[英]Excel VBA Find cell address in range based on min to max value of correspoding range
我正在研究基於算法的工具; 請協助我解決以下問題。
1.首先,我根據一個條件(動態)找到行號。 假設行號是5,並且它有一組Value From(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
測試一個條件, 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
這兩個數組都傳遞給使Key保持不變並對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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.