Excel VBA根据对应范围的最小值到最大值查找范围内的单元格地址

时间:2016-11-05 11:11:45

标签: excel-vba multidimensional-array vba excel

我正在研究算法基础工具;请帮我解决以下问题。

1.首先,我根据一个标准(动态)找到行号。假设行号为5,它的值为(B5:F5)

Set FindRow = SearchRange.Find(Sheet1.Cells(xRow, 2).Text, LookIn:=xlValues, lookat:=xlWhole)    
MyRow = FindRow.Row

2.我有带数值的标题(B1:F1)

3.然后我需要找到列号,即MyCol是(B1:F1)中最小值单元格的列号

4.然后我测试了If Cells(MyRow,MyCol)="ABC" Then测试失败的一个标准,我又需要去找(B1:F1)和列号中的下一个最小值,即MyCol,直到我满足条件。

我试过阵列,我无法找到解决方案,任何帮助都会非常感激。我提前谢谢。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您需要的是索引排序。许多语言提供索引排序作为标准函数。 VBA既没有排序也没有索引排序作为标准。

使用传统的数组排序,值在数组中排序。例如:假设我有一个包含值的数组:

A     D     B     E     C

如果我将该数组传递给某个排序,则返回为:

A     B     C     D     E

但有时你无法对数组进行排序。在您的情况下,该数组是一系列列标题。您无法对这些标题进行排序,因为它们属于列。您必须对列进行排序,这些列最好是不切实际的,也可能是不可接受的,因为列的顺序将意味着什么。

使用索引排序,您可以创建数组键和索引:

Keys    A     D     B     E     C
Indices 1     2     3     4     5

这两个数组都传递给不改变Keys的排序,并对Indices进行排序以给出:

Indices 1     3     5     2     4

使用常规排序,您可以将排序的条目作为Array(1)进行访问。 Array(2)等等。使用索引排序,您可以将排序的条目作为Array(Indices(1))进行访问。 Array(Indices(2))等等。

通过索引来获取已排序的条目起初可能有点难以理解,直接进入源数组无疑是个小问题。

下面我给你一个索引插入排序。插入排序简单易懂,但大量条目速度慢。您只需要排序五个条目,因此其性能可以接受。查看"插入排序"的Wiki条目。用于图示演示它是如何工作的。

DemoSortColumnHeadings显示了如何使用排序以及如何访问列标题。我使用名称ColHeads而不是KeysColNums代替Indices,因为我相信这会使DemoSortColumnHeadings更容易理解。已排序的ColNums包含所需序列中的列号。排序后,不再需要数组ColHeads

最后一点。 VBA是我所知道的唯一一种允许您指定数组下限和上限的语言。大多数语言要求下限为零。我利用这个来定义数组的尺寸为(2到6)而不是(0到4)。这就是数组ColNums中的值是列号的原因。对于大多数语言,我需要ColNums(N)+2来获取列号。

Option Explicit
Sub DemoSortColumnHeadings()

  Const ColFirst As Long = 2  ' Column B = column 2
  Const ColLast As Long = 6   ' Column F = column 6

  Dim ColCrnt As Long
  Dim ColNums() As Long
  Dim InxColNum As Long
  Dim ColHeads() As String

  With Worksheets("Test data")

    ReDim ColHeads(ColFirst To ColLast)
    ReDim ColNums(ColFirst To ColLast)

    For ColCrnt = ColFirst To ColLast
      ColHeads(ColCrnt) = .Cells(1, ColCrnt).Value
      ColNums(ColCrnt) = ColCrnt
    Next


    Debug.Print "Initial sequence"
    Debug.Print "|";
    For ColCrnt = ColFirst To ColLast
      Debug.Print .Cells(1, ColCrnt).Value & "|";
    Next
    Debug.Print

    Call InsertionSort(ColNums, ColHeads)

    Debug.Print "Final sequence"
    Debug.Print "|";
    For InxColNum = LBound(ColNums) To UBound(ColNums)
      ColCrnt = ColNums(InxColNum)
      Debug.Print .Cells(1, ColCrnt).Value & "|";
    Next
    Debug.Print

  End With


End Sub
Public Sub InsertionSort(ByRef Indices() As Long, ByRef Keys() As String)

  Dim Found As Boolean
  Dim I As Long
  Dim InxIFwd As Long
  Dim InxIBack As Long

  For InxIFwd = LBound(Indices) + 1 To UBound(Indices)
    I = Indices(InxIFwd)  ' Save value of current entry in Indices
    ' Find first entry back, if any, such that Keys(I) >= Keys(Indices(InxIBack))
    ' If Keys(I) < Keys(Indices(InxIBack)), set Indices(InxIBack+1) to
    ' Indices(InxIBack). That is move indices for keys greater that Keys(I) down
    ' Indices leaving a space for I nearer the beginning.
    Found = False
    For InxIBack = InxIFwd - 1 To LBound(Indices) Step -1
      If Keys(I) >= Keys(Indices(InxIBack)) Then
        ' Keys(I) belongs after Keys(Indices(InxIBack))
        Indices(InxIBack + 1) = I
        Found = True
        Exit For
      End If
      Indices(InxIBack + 1) = Indices(InxIBack)
    Next
    If Not Found Then
      ' Insertion point for I not found so it belongs at beginning of Indices
      Indices(LBound(Indices)) = I
    End If
  Next

End Sub