简体   繁体   中英

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). Assume row number is 5 and it has set of 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)

3.Then I need to find column number, ie MyCol is column number of minimum value cell in (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.

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.

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:

Indices 1     3     5     2     4

With the regular sort, you access the sorted entries as Array(1) . Array(2) and so on. With an indexed sort, you access the sorted entries as Array(Indices(1)) . Array(Indices(2)) and so on.

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.

Macro DemoSortColumnHeadings shows how to use the sort and how to access the column headings. I have used the name ColHeads instead of Keys and ColNums instead of Indices because I believe this will make DemoSortColumnHeadings easier to understand. The sorted ColNums contains the column numbers in the sequence you require. After the sort, the array ColHeads is no longer required.

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. 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). This is why the values in array ColNums are column numbers. With most languages, I would have needed ColNums(N)+2 to get the column number.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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