Can MATCH function in an array formula to return m

2019-02-20 20:03发布

I tried to use the MATCH function in an array formula to return multiple matches (by default it only returns the first match). However, this doesn't seem to work. How can I solve this problem without a complex, unreadable formula?

3条回答
狗以群分
2楼-- · 2019-02-20 20:42

How about this, without VBA? [entered on cell C9 as an array formula with CTRL + SHIFT + ENTER, where your searched column is A9:A24, and your search terms are in B1:B4], and dragged down to find multiple hits?

=SMALL(IFERROR(MATCH($B$1:$B$4,$A$9:$A$24,0),""),ROW()-ROW($C$8))

This first uses the array formula to show each 'hit' for any of the search terms matched in the searched column, and then using the Small function with reference to the current cell's row, it returns the earliest hit, then the 2nd hit, then the 3rd hit, etc.

Beyond this point, the reference points to the searched array can be used as needed (converted to the row location of an index function, etc.).

EDIT On further review of the results from this formula, it only returns a single hit for each search term, even if that search term appears multiple times. To resolve this, I first used the formula:

=SMALL(IF($A$9:$A$24=$B$1,ROW($A$9:$A$24),""),ROW()-ROW($E$8))

This shows each hit for a match of the search term found in B1. Here is where I am stuck. I could only figure out how to resolve with the admittedly manual:

=SMALL(IF($A$9:$A$24={"a","b","c"},ROW($A$9:$A$24),""),ROW()-ROW($E$8))

Any suggestions on how to improve to allow multiple hits for multiple terms?

EDIT - Additional option

Okay, I've determined another method of picking up multiple hits. This one relies on considering the location of the previous matches already made. Depending on what you want your result vector to look like (which was never specified by the OP), the results from this are clean but the formula is fairly messy.

The first cell looks like this, in cell H9: =ADDRESS(MIN(IFERROR(MATCH($B$1:$B$4,$A$9:$A$24,0),""))+ROW($A$8),1)

This shows the address of the first cell which matches any of the search terms, using the formula noted further above.

The cell below that (and every cell after that), has this (also an array formula):

=ADDRESS(MIN(IFERROR(MATCH($B$1:$B$4,INDIRECT(ADDRESS(ROW(INDIRECT(H9))+1,1)):$A$25,0),""))+ROW(INDIRECT(H9)),1)

This picks up the address of the cell found in the row above (adding 1 row to avoid re-hitting the same term), and from that new search column from that point to the end point (adding 1 row so that it properly stops at the last ending hit), it re-searches for any of the terms.

This one is again, not that clean [Yes I know there are some improvements I could make to determining what the search should be - either using the text manipulation functions or even doing a relative name reference that changes as you move down the column], but it is automated and, I would argue, cleaner than a VBA module. Especially as, depending on what you want your result vector to be, this could be much simpler.

查看更多
看我几分像从前
3楼-- · 2019-02-20 20:44

Working\developing on the formulas posted by @Grade'Eh'Bacon ended up with this formula to retrieve all the results of a match function with several matches for several items.

Assuming input range is B2:B17 and the range with the items to match is F3:F5 enter this FormulaArray in H3

=IFERROR( SMALL( IF( $B$3:$B$17 = TRANSPOSE( $F$3:$F$5 ),
 1 + ROW( $B$3:$B$17 ) - ROW( $B$3 ), "" ), ROWS($2:2  ) ), "" )

enter image description here

It's an FormulaArray returning all matches for several items

All merits go to @Grade'Eh'Bacon for his great work on the subject.

查看更多
We Are One
4楼-- · 2019-02-20 20:48

It is not possible with the built-in MATCH, however, using a VBA macro, you can achieve this:

Public Function MATCH_RANGE(values As Variant, ary As Variant, match_type As Integer)
    Dim i As Integer
    Dim elementCount As Integer
    Dim result()
    Dim value As Variant

    Dim arySize As Integer
    arySize = UBound(ary.Value2, 1)

    Dim valueSize As Integer
    valueSize = UBound(values.Value2, 1)

    ReDim result(0 To arySize, 0 To 1)

    elementCount = 0

    For i = 1 To arySize
        For j = 1 To valueSize
            value = values(j, 1)
            If (match_type = -1 And ary(i, 1) <= value) Or (match_type = 0 And ary(i, 1) = value) Or (match_type = 1 And ary(i, 1) >= value) Then
                result(elementCount, 0) = i
                elementCount = elementCount + 1
            End If
        Next j
    Next i

    For i = elementCount To arySize
        result(i, 0) = -100000000
    Next i

    MATCH_RANGE = result
End Function

This function both returns multiple matches and allows you to pass a range of multiple values that you want matched. I've found this useful a number of times. Feedback welcome to help improve this.

NOTE: You must spread this formula across a few cells using an array-formula (CRTL-SHIFT-ENTER), in order to see the multiple matches.

查看更多
登录 后发表回答