简体   繁体   English

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

[英]Excel VBA Find cell address in range based on min to max value of correspoding range

I am working on algorithm base tool; 我正在研究基于算法的工具; Kindly assist me for below problem. 请协助我解决以下问题。

1.First I find row number based on one criteria (Dynamic). 1.首先,我根据一个条件(动态)找到行号。 Assume row number is 5 and it has set of Value From (B5:F5) 假设行号是5,并且它有一组Value From(B5:F5)

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

2.I have header with numeric value(B1:F1) 2.我有带数字值的标题(B1:F1)

3.Then I need to find column number, ie MyCol is column number of minimum value cell in (B1:F1) 3.然后我需要找到列号,即MyCol是(B1:F1)中最小值单元格的列号

4.Then I test one criteria with If Cells(MyRow,MyCol)="ABC" Then test fail and again I need go and find next Minimum value in (B1:F1) and column number, ie MyCol, Until I Meet the condition. 4.然后,我使用If Cells(MyRow,MyCol)="ABC" Then测试一个条件, If Cells(MyRow,MyCol)="ABC" Then测试失败,再次需要在(B1:F1)和列号中找到下一个最小值,即MyCol,直到满足条件。

I tried array, I am not able to find solution, Any help would be much appreciated. 我试过数组,我找不到解决方案,任何帮助将不胜感激。 My Thanks in advance. 提前谢谢。

If I understand correctly, what you need is an indexed sort. 如果我理解正确,那么您需要的是索引排序。 Many languages provide an indexed sort as a standard function. 许多语言都将索引排序作为标准函数提供。 VBA has neither a sort nor an indexed sort as standard. VBA既没有排序标准也没有索引排序标准。

With a conventional array sort, values are sorted within the array. 使用常规的数组排序,值将在数组内排序。 For example: suppose I have an array with values: 例如:假设我有一个带有值的数组:

A     D     B     E     C

If I pass that array to a sort, it is returned as: 如果我将该数组传递给排序,则返回为:

A     B     C     D     E

But sometimes you cannot sort the array. 但是有时您无法对数组进行排序。 In your case, the array is a range of column headings. 在您的情况下,数组是一系列列标题。 You cannot sort those headings because they belong with their columns. 您无法对这些标题进行排序,因为它们属于其列。 You would have to sort the columns which is at best impractical and probably unacceptable since the sequence of columns will mean something. 您将不得不对列进行排序,这是最不切实际的,并且可能是不可接受的,因为列的顺序将有意义。

With an indexed sort, you create arrays Keys and Indices: 使用索引排序,您可以创建数组键和索引:

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

Both these arrays are passed to the sort which leaves Keys unchanged and sorts Indices to give: 这两个数组都传递给使Key保持不变并对Indices进行排序的排序,以给出:

Indices 1     3     5     2     4

With the regular sort, you access the sorted entries as Array(1) . 使用常规排序,您可以将已排序的条目作为Array(1) Array(2) and so on. Array(2)等。 With an indexed sort, you access the sorted entries as Array(Indices(1)) . 通过索引排序,您可以以Array(Indices(1))形式访问排序后的条目。 Array(Indices(2)) and so on. Array(Indices(2))等。

Going via an index to get the sorted entries can be a little difficult to understand at first and it is undoubtedly fiddlier that going directly to the source array. 刚开始时,通过索引来获取排序的条目可能有点困难,并且直接转到源数组无疑是摆弄。

Below I have given you an indexed Insertion Sort. 下面,我为您提供了索引化的插入排序。 An Insertion Sort is simple and easy to understand but is slow with large numbers of entries. 插入排序很简单易懂,但是输入大量条目却很慢。 You only have five entries to sort so its performance is acceptable. 您只有五个条目可以排序,因此其性能是可以接受的。 Look at the Wiki entry for "Insertion Sort" for a pictorial demonstration of how it works. 在Wiki上的“插入排序”条目中查看其工作方式的图形演示。

Macro DemoSortColumnHeadings shows how to use the sort and how to access the column headings. DemoSortColumnHeadings展示了如何使用排序以及如何访问列标题。 I have used the name ColHeads instead of Keys and ColNums instead of Indices because I believe this will make DemoSortColumnHeadings easier to understand. 我使用名称ColHeads代替Keys ,使用ColNums代替Indices因为我相信这将使DemoSortColumnHeadings更加容易理解。 The sorted ColNums contains the column numbers in the sequence you require. 排序的ColNums包含您所需顺序的列号。 After the sort, the array ColHeads is no longer required. 排序后,不再需要数组ColHeads

One last point. 最后一点。 VBA is the only language I know which allows you to specify both the lower bound and the upper bound of an array. VBA是我所知道的唯一一种语言,它允许您指定数组的下限和上限。 Most languages require the lower bound to be zero. 大多数语言要求下限为零。 I have taken advantage of this to define the dimensions of the arrays as (2 to 6) and not (0 to 4). 我利用此优势将数组的尺寸定义为(2到6)而不是(0到4)。 This is why the values in array ColNums are column numbers. 这就是为什么数组ColNums中的值是列号的原因。 With most languages, I would have needed ColNums(N)+2 to get the column number. 对于大多数语言,我将需要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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM