问题
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?
回答1:
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.
回答2:
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 ) ), "" )
It's an FormulaArray
returning all matches for several items
All merits go to @Grade'Eh'Bacon for his great work on the subject.
回答3:
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.
来源:https://stackoverflow.com/questions/31222926/can-match-function-in-an-array-formula-to-return-multiple-matches