我正在研究算法基础工具;请帮我解决以下问题。
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,直到我满足条件。
我试过阵列,我无法找到解决方案,任何帮助都会非常感激。我提前谢谢。
答案 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
而不是Keys
和ColNums
代替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