Index Match with Multiple Criteria while looking for a certain string - excel

A B C
1 Name Last Name ID
2 Ben Dafflin ID1001
3 Yu Yiin ID1002
5 Max Gray ID1003
6 John Carl Flit ID1004
Situation 1 : Index Match with wildcards "*" (Working Fine!)
Formula : =INDEX($C:$C,MATCH("*John*",$A:$A,0))
Result : ID1004
Situation 2 : Index Match with multiple criteria (Working Fine!)
Formula : =IFERROR(INDEX(D:D,MATCH(1,(B:B="Flit")*(C:C="John Carl"),0)),"")
Result : ID1004
Problem:
In situation 2, if it only looks for cells with "Carl" or "*Carl*" it doesn't work. Any suggestion how will I use the situation 2 having an index match with multiple criteria but can still look for cells that contains such specific string.

To have your 2nd formula return a value, you just need to reference the correct columns: =IFERROR(INDEX(C:C,MATCH(1,(B:B="Flit")*(A:A="John Carl"),0)),"")
If you want to use wild cards with MATCH where you have multiple criteria, you can try:
=INDEX(C:C,MATCH(1,1/(ISNUMBER(SEARCH("*Carl*",A:A))*(B:B="Flit")),0))
If you have Office 365
=FILTER(C:C,ISNUMBER(SEARCH("*Carl*",A:A))*(B:B="Flit"))

Lookup when Matching to Multiple Columns
There's another way to approach this, which is simpler and may well be a better fit:
{=INDEX(C:C,MATCH("*CarlFlit",A:A&B:B,0))}
The above is of course an array formula (hence the opening { and closing })
a) The array matched is the rows of columns A and B concatenated into single strings
b) This specific example is of course looking for (*wild-carded) *CarlFlit
c) Which of course, could be any combination of values and valid MATCH wildcards
If the values being looked for are in cells (rather than hardcoded into the formula) simply refer to those cells:
{=INDEX(C:C,MATCH(E2&F2,A:A&B:B,0))}
To add checking for no-match (using first example above):
{=IF(ISNUMBER(MATCH("*CarlFlit",A:A&B:B,0)),INDEX(C:C,MATCH("*CarlFlit",A:A&B:B,0)),"Not Found")}
Additional information
The formula above can be expanded to accommodate matching across any number of columns.
o Simply & in each additional column (in whatever order suites your purpose).
For performance reasons, it's not a good idea to have lookup functions looking at entire columns.
a) Better to use (e.g.) {=INDEX($C$1:$C$1000,MATCH("*CarlFlit",$A$1:$A$1000&$B$1:$B$1000,0))}.
b) Where 1000 is of course an example last row in your lookup range.

Related

How would I return a partial string to a calculated column based on a look up table

I need to parse cell for partial string match equal to any of the items in the look up table and return the first match (It would also be nice if it can return multiple matches if there happened to be more than 1 country in the comma separated cell * not required as this would be rare and can be covered by Multi country if needed*)
=IFS(SEARCH(L3,[#Tags]),SEARCH(L4,[#Tags]),SEARCH(L5,[#Tags]),SEARCH(L6,[#Tags])) result in errors I've also tried it using nested IF statements . I've also tried find in place of search
See link for example of Data set : Link
You may benefit from SUMPRODUCT and INDEX:
Formula in column D is:
=INDEX($I$2:$I$5;SUMPRODUCT(COUNTIF(B2;"*"&$I$2:$I$5&"*")*ROW($I$2:$I$5))-1)
Because ROW returns the row number related to whole worksheet but data starts at row 2, you need to substract minus 1.
Also, if you have Excel 365, probably you can use advanced functions to return more than 1 entry.
See if the following works for you:
Formula in D2:
=LOOKUP(99^99,SEARCH(","&Table2[Countries]&",",","&[#Tags]&","),Table2[Countries])

Excel: If, Search and match data from 3 different tables

I'm trying to search and match data from 3 different tables which are connected through an id and if the outcome is 1 of 5 options, then it is Yes or NO
see picture below for example. the yellow column should be filled it. the picture shows what the result should be.
Just some nested INDEX & MATCH could work for you:
=IFERROR(INDEX(K$3:K$7,MATCH(INDEX(H$3:H$7,MATCH(INDEX(E$3:E$7,MATCH("*"&A3&"*",D$3:D$7,0)),G$3:G$7,0)),J$3:J$7,0)),"")
MATCH allows the use of a wildcard and is at least as fast as VLOOKUP would be but usually faster!
You can do it like this:
Here's the code if you want to copy/paste & try it out:
=IF(VLOOKUP(VLOOKUP("*"&A3&"*", $D$3:$E$7, 2,FALSE), $G$3:$H$7, 2, FALSE) < 4, "Yes", "No")
I guess the biggest difference is that it will say "N/A" instead of "Empty" when there is no match.
Sapman.
Here's my suggestion to your particular case:
=IFERROR(VLOOKUP(VLOOKUP(IF(MIN(IF((LEN(SUBSTITUTE($D$2:$D$6,A2,""))-LEN($D$2:$D$6))<>0,ROW($D$2:$D$6)-1))=0,"",INDEX($E$2:$E$6,MIN(IF((LEN(SUBSTITUTE($D$2:$D$6,A2,""))-LEN($D$2:$D$6))<>0,ROW($D$2:$D$6)-2)))),$G$2:$H$6,2,FALSE),$J$3:$K$7,2,FALSE),"EMPTY")
It is based on the following logic:
first we take a value from Table A and remove it from Table B
then we check the length of the resulting string, if it's now different (i.e. LEN(XXACA)=5, LEN(XX)=2)
if it's different, we return the ROW number minus 2 (as your tables have two header rows)
then we use INDEX/MATCH to return the value of that row in Table B
then we do VLOOKUP twice to get data from Table C and Table "If/Then"
There are several error-handling parts as well which esure that you get the result you requested.

Three Dimensional Lookup Using INDEX/MATCH

This was taken and improved slightly from Question that has since been deleted
For those who can see deleted posts, it was taken from here: https://stackoverflow.com/questions/39793322/three-dimensional-lookup-no-concatenate-or-named-ranges-excel
I'm trying to do a three dimensional lookup without named ranges or concatenates. Simplified, my data is on the form:
Column1 Column2 Column3
Scott
P 1 2 3
M 4 5 6
N 7 8 9
George
P 10 11 12
M 13 14 15
N 16 17 18
I now want to search for a specific Name and then for a specific letter within that names table, I then want to match this row number with a specific column.
I tried a simple INDEX/MATCH:
=INDEX(A:D,MATCH("M",A:A,0),MATCH("Column1",1:1,0))
And that works for the fist name but not any others as it finds the first instance of M.
How do I modify it to look for a different name?
I have answered below, but want to see if someone has a better solution.
I used an IF() statement array formula to find what the P row number was after the George row... I also needed to use the MIN() function to get the first P row number after the name.
Beyond that, it's a simple INDEX() function.... that racked my brain for over an hour :).
=INDEX($A$1:$D$9,MIN(IF((ROW(A1:A9)>MATCH($F$4,A1:A9,0))*(A1:A9=$F$5),ROW(A1:A9),"")),MATCH($F$6,$A$1:$D$1,0))
Don't Forget!
Use Ctrl+Shift+Enter when finishing the formula, so it gets evaluated as an array formula.
You can use two other INDEX/MATCH's inside the first MATCH to set the lookup range. Then you simply need to add the MATCH() to find the absolute position of the name.
=INDEX(A:D,MATCH($H$4,INDEX(A:A,MATCH($H$3,A:A,0)):INDEX(A:A,MATCH($H$3,A:A,0)+4),0)+MATCH($H$3,A:A,0)-1,MATCH($H$5,$1:$1,0))
This one works better and does not have a size constraint:
=INDEX(A:D,MATCH(F4,INDEX(A:A,MATCH(F3,A:A,0)):A1040000,0)+MATCH(F3,A:A,0)-1,MATCH(F5,A1:D1,0))
You can do this just by adding the results of two matches together. One match for the names plus one match for the letter equals the total row.
=INDEX(A:D,MATCH(G5,A3:A5,0)+MATCH(G3,A:A,0),MATCH(G4,1:1,0))
In other words: Index(All of the Data, Match(Name, In name column, exact) + Match(Letter, In letter column, exact), Match(Column name, in Column row, exact)
Screen capture of working sheet
My answer attempts the general case with only one caveat:
That a letter is single character text, and a name is more than 1 character. Otherwise i feel there is no difference logically between letters and names, and it is then impossible to really do...
RE-EDIT for better function construction:
{=INDEX($A$1:$D$17, MATCH($H$3,$A1:$A17, 0)+MATCH($H$4, INDEX($A1:$A17, MATCH($H$3,$A1:$A17, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A1:$A17, 0)+POWER(SQRT(IF(LEN($A$1:$A$17)>1, ROW($A$1:$A$17), 0)-MATCH($H$3,$A$1:$A$17, 0)), 2)-1, ROWS($A$1:$A$17)), 2)), 0)-1, MATCH($H$5, $A$1:$D$1, 0))}
This uses an array formula along column A, and checks if the length is > 1 and throws the row nums into an array, with letters given a 0.
Then match row of unique name(e.g. George) is subtracted from each.
We then use a min(of all other name rows, with the last data row as the final default - SMALL function with 2 parameter) to find the next name row(or last data row if there is no following name).
Rest is standard index/match etc.
It will correctly return #N/A if there is no such letter under the chosen name...
My dataset is A1:A17, and the formula could use A:A instead each time, but the array calc inside the IF needs the A1:A17 for speed.
EDIT for better function construction:
If we wanted to avoid editing the formula when the data length changes, then we could let full column references of A:A go through the entire construction(and lose speed/efficiency) with the last data row in colA calculated via ROWS(A:A):
Re-edit:
{=INDEX($A:$D, MATCH($H$3,$A:$A, 0)+MATCH($H$4, INDEX($A:$A, MATCH($H$3,$A:$A, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A:$A, 0)+POWER(SQRT(IF(LEN($A:$A)>1, ROW($A:$A), 0)-MATCH($H$3,$A:$A, 0)), 2)-1, ROWS($A:$A)), 2)), 0)-1, MATCH($H$5,1:1, 0))}
It really depends on the setup...
Edit again for version which takes blanks as separators for names
If you want to use blanks as the separator for names, where no blanks are in the data results, but blanks appear in columns B to D where there is a name, then a tiny change in the above formulae will result in this:
=INDEX($A$1:$D$17, MATCH($H$3,$A$1:$A$17, 0)+MATCH($H$4, INDEX($A:$A, MATCH($H$3,$A:$A, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A:$A, 0)+POWER(SQRT(IF($B$1:$B$17="", ROW($A$1:$A$17), 0)-MATCH($H$3,$A$1:$A$17, 0)), 2)-1, ROWS($A$1:$A$17)), 2)), 0)-1, MATCH($H$5, $A$1:$D$1, 0))
This means that the names and letters do not have to be any specified length, but just one proviso is that blanks appear in the row with the name.
A small amendment to the condition to find the end range to search for the letter by replacing this: SQRT(IF(LEN($A$1:$A$17)>1, with this:
SQRT(IF($B$1:$B$17="",
I would use the area (4th parameter) of Index(). Below is a screenshot of test data. This example assumes the same columns and keys are sorted and consistent.
This works by using (Range1,Range2) as the first parameter of index. For the 4th parameter of index, use N for which area in the () you want Index to return.
I think this may be slightly tidier, and a little easier to modify maybe.
=INDEX(OFFSET(INDIRECT("A"&MATCH($H$3,$A:$A,0),TRUE),0,0,4,4),MATCH($H$4,$A:$A,0),MATCH(H5,$1:$1,0))
Using offset to create the range first, we're able to use the name from H3 to set that up, and then beyond that we are just indexing within that new range.
Now this is still dependendent on staying in Column A for the names.
Assuming the format of the data is always Name then P, M and N this formula does the work:
=INDEX($A:$D,
MATCH($H$3,$A:$A,0)
+LOOKUP($H$4,{"P",1;"M",2;"N",3}),
MATCH($H$5,$1:$1,0))
This solution works on almost all conditions. One restriction I found is when one of the subjects (Names) does no have data for any of the details (letters), but as of now the same occurs with all the other answers.
The formula assumes the data is located at B6:F30 (in order to ensure it can be applied regardless of the source range location).
The formula uses the Index\Match functions:
First, a MATCH to retrieve the position of the Name:
MATCH($H8,$B$6:$B$30,0)
With that info it uses INDEX to build a range that is used to obtain the position of the Detail (letter) using a second MATCH Function:
+ MATCH($I8,INDEX($B$6:$B$30, 1 + MATCH($H8,$B$6:$B$30,0))
:INDEX($B$6:$B$30,ROWS($B$6:$B$30)),0),
Adding the results of the first and second MATCH functions obtains the position of the Name`Detail` combination and uses it in an Index to the entire data. The position of the Data Column required is obtained with a Match:
INDEX($B$6:$F$30, 1st.MATCH + 2nd.MATCH,
MATCH(J$6,$B$6:$F$6,0))
With the results located at G6:L30 enter this formula in J8 then copy to J8:L30:
= INDEX( $B$6:$F$30,
MATCH( $H8, $B$6:$B$30, 0)
+MATCH( $I8, INDEX( $B$6:$B$30 , 1 + MATCH( $H8, $B$6:$B$30 ,0))
: INDEX( $B$6:$B$30, ROWS($B$6:$B$30) ),0),
MATCH( J$6, $B$6:$F$6, 0)),"")
This solution works in all conditions discussed so far (let me know of any condition that it does not work and I’ll try to cover it).
I’m posting this as a separated answer as the formulas applied in prior answer rightly apply to the conditions stated in them, as such they will be useful to users with those specific scenarios, so they don’t need to apply these long formulas.
This formula assumes the data is located at B6:E30 (in order to ensure it can be applied regardless of the source range location).
This formula uses the Index\Match functions and it’s a Formula Array.
FormulaArrays are entered pressing [Ctrl] + [Shift] + [Enter] simultaneously, you shall see { and } around the formula if entered correctly
Syntax:
=IFERROR(INDEX(DataRng,
MATCH(Value1,NamesRng,0)
+IFERROR(MATCH(Value2,INDEX(NamesRng,
1+MATCH(Value1,NamesRng,0))
:INDEX(NamesRng, IFERROR(MATCH(Value1,NamesRng,0)
+MATCH("#",IF((INDEX(Col1Rng,1+MATCH(Value1,NamesRng,0))
:INDEX(Col1Rng,ROWS(NamesRng)))="","#","!"),0),
ROWS(NamesRng))),0),NA()),MATCH(ValCol,DataHdr,0)),"")
Arguments:
Assuming the data is located at B6:E30.
Value1= Name to be found in Data, i.e. George, Scott, etc.
Value2= Detail to be found in Data, i.e. Detail1, Detalle2, etc.
ValCol = Column to be found in Data i.e. Column1, Column2, etc.
DataRng= $B$6:$E$30
DataHdr= $B$6:$E$6
NamesRng= $B$6:$B$30
Col1Rng= $C$6:$C$30
1st MATCH: Retrieves the position of the Name:
MATCH(Value1,NamesRng,0)
2nd MATCH: Retrieves the end position of the Name’s corresponding Details, which is determined by a blank value in column C or the end of the data range:
MATCH("#",IF((INDEX(Col1Rng, 1 + 1stMATCH)
:INDEX(Col1Rng,ROWS(NamesRng)))="","#","!"),0),
Builds a Range (vRange): With the Names's Details using the 1st and 2nd match functions. If 2nd Match returns an error then it uses the last row of the Data range:
INDEX(NamesRng, 1 + 1stMATCH )
:INDEX(NamesRng, IFERROR( 1stMATCH + 2ndMATCH, ROWS(NamesRng)))
3rd MATCH: Retrieves the position of the Detail within the vRange. It returns #NA if the combination is not present.
IFERROR(MATCH(Value2, vRange,0), NA())
Adding the results of the 1st and 3rd match functions obtains the Row index of the Name`Detailcombination or#NAif no found.
The Column index is obtained with a Match from the Header of the Data.
It then applying the INDEX function to the Data Range returns the value of theName\Detail\Columncombination.
If theName\Detail` combination is not found it returns blank.
=IFERROR( INDEX( DataRng, 1stMATCH + 3rdMATCH, MATCH(Column,DataHdr,0)),"")
With the results located at H6:L37 enter this Formula Array in J8 then copy to K8:L37 and to J9:L37:
=IFERROR( INDEX($B$6:$E$30,
MATCH($H8,$B$6:$B$30,0)
+IFERROR( MATCH($I8, INDEX($B$6:$B$30,
1+MATCH($H8,$B$6:$B$30,0))
:INDEX($B$6:$B$30, IFERROR(MATCH($H8,$B$6:$B$30,0)
+MATCH("#", IF((INDEX($C$6:$C$30,1+MATCH($H8,$B$6:$B$30,0))
:INDEX($C$6:$C$30,ROWS($B$6:$B$30)))="","#","!"),0),
ROWS($B$6:$B$30))),0),NA()),
MATCH(J$6,$B$6:$E$6,0)), "")
Wow... So many solutions already.
I think a simpler solution could be using offset to get a more generic answer.
=INDEX($A$1:$D$9, MATCH($G$3,OFFSET($A$1,MATCH($G$2,$A$1:$A$9,0),0,3,1),0)+MATCH($G$2,$A$1:$A$9,0), MATCH($G$4,$B$1:$D$1,0)+1)
The only variable to look for is 3 which is the number of M/N/P options present because that will affect the number of rows. Otherwise, the solution works fine in all possible scenarios and different orders.
When I have more than two inpunts for a data search I prefer to have the data organized as shown in the figure, so that I can use a pivot table and get it to organize the data in rows and columns as I like.
Then I use GETPIVOTDATA to search for a value.
Cell G9 contains this formula:
=GETPIVOTDATA("Value";$F$3;"Name";G15;"Letter";G16;"Column";G17)

Excel: match two columns and output third ... AND... there are multiple instances in each column

Working off a previous post:
Excel match two columns and output third
I have values in column A that are not unique and values in column B that are not unique, but together column A and B produce unique combinations:
A B C
1 Red Car Result#1
2 Blue Boat Result #2
3 Red Boat Result #3
4 Green Car Result #4
Let's say I want to find a match where Column A = Red and Column B = Boat which should return the corresponding value in Column C which should be Result #3.
Using the previous post's solution:
=IF(MATCH("Red",A1:A4,0)=MATCH("Boat",B1:B4,0),INDEX(C1:C4,MATCH("Boat",B1:B4,0)),0)
This would actually return value the first match for Boat in column B which would be result#2 rather than the intended result#3 where the match was true.
Any ideas on how to modify or write a function that would specify to retrieve information relative to specifically where the match was true (without using VBA)?
I've thought of a possible work around by creating another column that combines Col A and B to make a unique identifier but I was hoping to avoid that.
Thanks! Really appreciate it and sorry about the table formatting. I'm still very new at this.
You can retrieve a two column match using the AGGREGATE function to force anything that does not match into an error and ignore the errors.
      
The formula in E6 is,
=IFERROR(INDEX(C$1:C$99,AGGREGATE(15,6,ROW($1:$99)/((A$1:A$99="red")*(B$1:B$99="boat")), ROW(1:1))), "")
You are actually using the SMALL sub-function of the AGGREGATE function so you can get the second, third, etc. successive matches by increasing the k paramter. I done this above by using ROW(1:1) which equals 1 but will increase to 2, 3, etc as the formula is filled down.
Creating a third column is the most efficient solution. However if you absolutely have to avoid it, you could use a complicated formula like this:
=INDEX($C$1:$C$6,MATCH(A11,$A$1:$A$6,0) + MATCH(B11,OFFSET($A$1,MATCH(A11,$A$1:$A$6,0)-1,1,COUNTA($A$1:$A$6)-MATCH(A11,$A$1:$A$6,0),1),0)-1)
But the condition is that the lookup table is sorted for both column 1 and 2.

How to COUNTIFS with an array of criteria and match NOT condition?

My data table is like the image above. I can easily count the number of Male participants in group B or C using this array formula:
=SUM(COUNTIFS($B:$B, $E3, $C:$C, $F3:$F4))
The result is 3 as expected. However I'm gonna do the reverse thing, that is count the number of Male participants in NOT group B or C. The result should be 1 but currently I'm stuck at this.
Can anybody show me a way please (preferably not just counting the number of all Male participants and then do a subtraction)? I have even tried to change the values in the Group to something like <>B and <>C but it just doesn't work.
As you only have 2 in the group you can easily use COUNTIFS with 2 separate criteria, i.e.
=COUNTIFS($B:$B,$E3,$C:$C,"<>"&$F3,$C:$C,"<>"&$F4)
but clearly that might not be desirable for a large group, so you could use SUMPRODUCT like this to reference the group once
=SUMPRODUCT(($B:$B=$E3)*ISNA(MATCH($C:$C,$F3:$F4,0)))
ISNA will exclude matching rows - to include use ISNUMBER
You can replace F3:F4 with any single row or column of values
Note: whole columns with SUMPRODUCT will work (post Excel 2003) but is undesirable as Jerry says
Hmm, the thing with the formula right now is that the first COUNTIFS (for F3) will return 2 and the second COUNTIFS (for F4) will return 3, which SUM converts into 5 when you try:
=SUM(COUNTIFS($B:$B, $E3, $C:$C, "<>"&$F3:$F4))
I would suggest using SUMPRODUCT instead:
=SUMPRODUCT(($B:$B=$E3)*($C:$C<>$F3)*($C:$C<>$F4))
And maybe make the range smaller since this can take some time (you don't need to insert this as an array formula).
Otherwise, another option would be to count all the Males, and then subtract the counts for group B and subsequently C:
=COUNTIF($B:$B, $E3)-SUM(COUNTIFS($B:$B, $E3, $C:$C, $F3:$F4))

Resources