Excel VBA根据相对范围的最小值到最大值查找范围内的单元格地址
我正在研究算法基础工具;请帮助我解决以下问题。Excel VBA根据相对范围的最小值到最大值查找范围内的单元格地址
1.首先我根据一个标准(动态)找到行号。假定行数为5,它已设定值的来源:(:F1 B1)
3.Then我需要找到列号(B5 F5)
Set FindRow = SearchRange.Find(Sheet1.Cells(xRow, 2).Text, LookIn:=xlValues, lookat:=xlWhole)
MyRow = FindRow.Row
2.I具有数值头,即MyCol是最小值单元格的列号(B1:F1)
4.然后我测试一个标准,If Cells(MyRow,MyCol)="ABC" Then
测试失败,我需要再找到下一个最小值(B1:F1)和列号,即MyCol,直到我符合条件。
我试过阵列,我无法找到解决方案,任何帮助将不胜感激。我提前致谢。
如果我理解正确,您需要的是索引排序。许多语言都将索引排序作为标准函数提供。 VBA既没有标准排序也没有索引排序。
使用传统的数组排序,值在数组内排序。例如:假设我有值的数组:
A D B E C
如果我传递数组排序,则返回:
A B C D E
但有时你可以在阵列不排序。在你的情况下,数组是一系列的列标题。您无法对这些标题进行排序,因为它们属于它们的列。您必须对列进行排序,因为列的顺序意味着某些内容,所以最好不切实际并且可能不可接受。
有了一个索引排序,您创建阵列按键和指标:
Keys A D B E C
Indices 1 2 3 4 5
这两个数组传递给叶键不变,排序排序指标给:
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
谢谢托尼! – Manish
@Manish。不用谢。注意:我有一个使用相同技术的快速排序实现。在大多数情况下,快速排序是最快的排序,但它更难以理解。我的实现可以为54,000行工作表创建键和索引,并在1.5秒内对索引进行排序。如果需要对大数组进行排序索引,请记住这一点。 –
请从您的方法发布代码。 – Limak