Frage

Here is an image, followed by description of data enter image description here

Description of Columns:

  • Column A (Key) is strictly increasing sequence of decimals
  • Column B (Group) represents a group the value in A belongs to.
  • Column C (Data) is assorted data

Inputs (in column F)

  • Exact Group number in i.e. {1, 2, 3, 4} in F4
  • A decimal value (unrestricted), call it DecimalValue, in F5

Task

Find row that belongs to the given Group, where ABS(Key - DecimalValue) value is minimized. Return Data from that row.

  • Ideally looking for an Excel-only solution, using INDEX, VLOOKUP, ABS, and the like.

This question is similar to my previous question, but different enough (involves a new Groupcolumn), where via comments it was determined that it is best to ask a new question, rather than try to update / modify the existing question:

Display Row Values based on Nearest Numeric Match of Key

Adding correction for Group column, if it is possible is what I am after, hence the title reflects that concern.

(Incomplete Solution - does not consider Group column)

=INDEX(C4:C33,MATCH(MIN(ABS(A4:A33-F5)),ABS(A4:A33-F5),0))
War es hilfreich?

Lösung

Give this a go...it seems to work on my test sheet. Be sure to adjust the ranges to suit your situation. Again, this is an array formula and needs to be confirmed with Ctrl+Shift+Enter:

=INDEX(C2:C7,MATCH(MIN(ABS((B2:B7=F4)*A2:A7-F5)),ABS((B2:B7=F4)*A2:A7-F5),0),0)

It works by zeroing out keys that don't match your group assignment (that's the (B2:B7=F4)*A2:A7-F5) part. So only keys w/ valid groups have some number to be used to match to the data column.

Hope that helps explain it. You can also utilize the "Evaluate Formula" function on the Formulas toolbar to see it in action.

Note - it seems to return the 1st data value if 0 is used as the closest value (regardless of group selection). Not sure how to get around that...

Andere Tipps

Here is sous2817's answer adjusted to avoid the problem of getting the wrong result when entering 0:

=INDEX(Data,MATCH(MIN(IFERROR(ABS(IF(GroupNo=Group,1," ")*Key-DecimalValue),
" ")),IFERROR(ABS(IF(GroupNo=Group,1," ")*Key-DecimalValue)," "),0))

The explanation for how it works is the same. The problem is avoided by replacing zeroes with errors.

Note that Key is the key column, GroupNo is the Group number column, Data is the data column, Group is the designated group for searching, and DecimalNumber is the number entered for searching.

EDIT: As discussed in comments below, this formula can be made much more readable by using a named range (AKA named formula). Set a named range searchRange equal to:

IFERROR(ABS(IF(GroupNo=Group,1," ")*Key-DecimalValue)," ")

Then the formula becomes:

=INDEX(Data,MATCH(MIN(searchRange),searchRange,0))

This has the added benefit of less Excel overhead, since the named formula only gets calculated once (whereas in the other version, it is calculated every time it appears).

You should be able to do as follows

Function getLastRow()
    Dim i As Integer
    Dim l_row As Integer
    For i = 1 To 35
        If Sheet1.Cells(Rows.Count, i).End(xlUp).Row > l_row Then
            l_row = Sheet1.Cells(Rows.Count, i).End(xlUp).Row
        End If
    Next i
    getLastRow = l_row
End Function
Sub data_lookup
    Dim last_row As Integer
    Dim lcell as Range
    Dim col_a_lookup As Double
    Dim col_b_lookup AS Double
    Dim row_collection As New Collection
    Dim variance AS Double
    Dim closest_row AS Integer

    col_b_lookup = 0.04
    col_a_lookup = 8
    variance = 50

    last_row = getLastRow
    'Find All the Cells that match your lookup value for column B
    For Each lcell in Sheet1.Range("$B$2", "$B$" & last_row)
       If lcell.value = col_b_lookup Then
          row_collection.Add lcell
       End If
    Next lcell
    'Loop through the collection created above to find the closest absolute value to
    'your lookup value for Column A 
    For Each lcell in row_collection
        If Abs(Sheet1.Cells(lcell.row,"A") - col_a_lookup) < variance then
            variance = Abs(Sheet1.Cells(lcell.row,"A") - col_a_lookup)
            closest_row = lcell.row
        End If
    Next lcell
    'Return Results 
    If closest_row > 0 Then
        Msgbox "Closest Data: " & Sheet1.Cells(closest_row,"G")
    Else
        Msgbox "Cannot Locate"
    End If
End Sub

Obviously you will have to set col_a_lookup and col_b_lookup to the values specified and I am sure you want to change the Msgbox. But this should help you on your way.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top