INDEX/MATCH with 4 columns - excel

I have an Excel file with 2 sheets - one sheet contains my items, prices, codes, etc. and the other sheet is for cross-matching with competitors.
I've included an Excel file and image below.
I want to be able to generate my code automatically when manually entering any of my competitor's codes. I was able to do INDEX/MATCH but I was only able to match with one column (I'm assuming they're all in one sheet to make it easier). Here is my formula:
=INDEX(C:C,MATCH(K2,E:E,0)
So this is looking only in E:E, when I tried to enter a different column such as C:C or D:D it returns an error.
I tried to do the MATCH as C:G but it gave an error right away.

The reason why match gave you error is because it's looking for an array and you put in multiple columns.
There is definitely a more elegant way to do this but this is the first one that I came up with.
=IFERROR(INDEX(B:B,MATCH(K2,C:C,0)),IFERROR(INDEX(B:B,MATCH(K2,D:D,0)),IFERROR(INDEX(B:B,MATCH(K2,E:E,0)),IFERROR(INDEX(B:B,MATCH(K2,F:F,0)),IFERROR(INDEX(B:B,MATCH(K2,G:G,0)),"")))))

Index/Match Combination
Please try this formula:
{=INDEX($B$2:$B$5,MATCH(1,(K2=$C$2:$C$5)+(K2=$D$2:$D$5)+(K2=$E$2:$E$5)+(K2=$F$2:$F$5)+(K2=$G$2:$G$5),0))}
Instruction: Paste the formula {without the curly brackets} to the formula bar and hit CTRL+SHIFT+ENTER while the cell is still active. This will create an array formula. Hence, the curly brackets. Please take note though that manually entering the curly brackets will not work.
Description:
The INDEX function returns a value or the reference to a value from within a table or range.1
The MATCH function searches for a specified item in a range of cells, and then returns the relative position of that item in the range.2
Syntax:
The INDEX function has two forms—Array and Reference form. We're going use the Reference form in this case.
INDEX(reference, row_num, [column_num], [area_num])1
MATCH(lookup_value, lookup_array, [match_type])2
Explanation:
To simplify, we're going to use this form:
INDEX(reference, MATCH(lookup_value, lookup_array, [match_type]))
The INDEX function returns a value from the reference My code column (B1:B5) based on the row_num argument, which serves as an index number to point to the right cell, and we're going to do that by substituting row_num with MATCH function.
MATCH function, on the other hand, returns the relative position of a value in competitorn column that matches the value in individual cells of the competitor code column.
To make it work with multiple lookup range, we're going to create arrays of boolean values (TRUE/FALSE, aka logical values) by comparing values from individual cells in competitor code column with values in individual competitorn columns. Now, we convert these boolean values into numerical values by performing a mathematical operation that does not alter its implied value (i.e. TRUE=1, FALSE=0). We're going to add these values directly to make it simple. The resulting array have four index with two possible values: 1 or 0. Since each item in MATCH's lookup_array is unique, then there can be only one TRUE or 1. The rest are FALSE or 0's. So, with that knowledge, we're going to use it as our lookup_value.
Let's dissect the formula:
=INDEX(B2:B5,MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0))
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},MATCH)
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},(2))
2 = MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0)
2 =MATCH(1,
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;TRUE;FALSE;FALSE},0))
OR
=MATCH(1,
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;1;0;0},0))
=========
{0;1;0;0},0))
2 = MATCH(1,{0;1;0;0},0))
I hope this answer is helpful.
References and links:
INDEX function
MATCH function
Create an array formula

Related

Is there a way to scan an entire column based on one cell in another column and pull out a value of the corresponding column?

A
B
C
D
4
1
6
5649
3
8
10
9853
5
2
7
1354
I have two worksheets, for example column A in sheet 1 and columns B-D in sheet 2.
What I want to do is to take one value in Column A, and scan both columns B and C and it is between those two values, then display the corresponding value from column D in a new worksheet.
There could be multiple matches for each of the cell in column A and if there is no match, to skip it and not have anything displayed. Is there a way to code this and somehow create a loop to do all of column A? I tried using this formula, but I think it only matches for each row and not how I want it to.
=IF(AND([PQ.xlsx]Sheet1!$A2>=[PQ.xlsx]Sheet2!$B2,[PQ.xlsx]Sheet1!$A2<[PQ.xlsx]Sheet2!$C2),[PQ.xlsx]Sheet2!$D$2,"")
How do I do this?
Thank you.
I'm not positive if I understood exactly what you intended. In this sheet, I have taken each value in A:A and checked to see if it was between any pair of values in B:C, and then returned each value from D:D where that is true. I did keep this all on a single tab for ease of demonstration, but you can easily change the references to match your own layout. I tested in Excel and then transferred to this Google Sheet, but the functions should work the same.
https://docs.google.com/spreadsheets/d/1-RR1UZC8-AVnRoj1h8JLbnXewmzyDQKuKU49Ef-1F1Y/edit#gid=0
=IFERROR(TRANSPOSE(FILTER($D$2:$D$15, ($A2>=$B$2:$B$15)*($A2<=$C$2:$C$15))), "")
So what I have done is FILTEREDed column D on the two conditions that Ax is >= B:B and <= C:C, then TRANSPOSED the result so that it lays out horizontally instead of vertically, and finally wrapped it in an error trap to avoid #CALC where there are no results returned.
I added some random data to test with. Let me know if this is what you were looking at, or if I misunderstood your intent.
SUPPORT FOR EXCEL VERSIONS WITHOUT DYNAMIC ARRAY FUNCTIONS
You can duplicate this effect with array functions in pre-dynamic array versions of Excel. This is an array function, so it has be finished with SHFT+ENTER. Put it in F2, SHFT+ENTER, and then drag it to fill F2:O15:
=IFERROR(INDEX($D$2:$D$15, SMALL(IF(($A2>=$B$2:$B$15)*($A2<=$C$2:$C$15), ROW($A$2:$A$15)-MIN(ROW($A$2:$A$15))+1), COLUMNS($F$2:F2))),"")
reformatted for easier explanation:
=IFERROR(
INDEX(
$D$2:$D$15,
SMALL(
IF(
($A2>=$B$2:$B$15)*($A2<=$C$2:$C$15),
ROW($A$2:$A$15) - MIN(ROW($A$2:$A$15))+1
),
COLUMNS($F$2:F2)
)
),
"")
From the inside out: ROW($A$2:$A$15) creates an array from 2 to 15, and MIN(ROW($A$2:$A$15))+1 scales it so that no matter which row the range starts in it will return the numbers starting from 1, so ROW($A$2:$A$15) - MIN(ROW($A$2:$A$15))+1 returns an array from 1 to 14.
We use this as the second argument in the IF clause, what to return if TRUE. For the first argument, the logical conditions, we take the same two conditions from the original formula: ($A2>=$B$2:$B$15)*($A2<=$C$2:$C$15). As before, this returns an array of true/false values. So the output of the entire IF clause is an array that consists of the row numbers where the conditions are true or FALSE where the conditions aren't met.
Take that array and pass it to SMALL. SMALL takes an array and returns the kth smallest value from the array. You'll use COLUMNS($F$2:F2) to determine k. COLUMNS returns the number of columns in the range, and since the first cell in the range reference is fixed and the second cell is dynamic, the range will expand when you drag the formula. What this will do is give you the 1st, 2nd, ... kth row numbers that contain matches, since FALSE values aren't returned by SMALL (as a matter of fact they generate an error, which is why the whole formula is wrapped in IFERROR).
Finally, we pass the range with the numbers we want to return (D2:D15 in this case) to INDEX along with the row number we got from SMALL, and INDEX will return the value from that row.
So FILTER is a lot simpler to look at, but you can get it done in an older version. This will also work in Google Sheets, and I added a second tab there with this formula, but array formulas work a little different there. Instead of using SHFT+ENTER to indicate an array formula, Sheets just wraps the formula in ARRAY_FORMULA(). Other than that, the two formulas are the same.
Since FALSE values aren't considered, it will skip those.

How do I use INDIRECT inside an Excel array formula?

The situation
In the sheet "Planning" I have an area that contains pairs of sessions (strings) and hours (numbers) in adjacent cells (e.g. D11 and E11, I12 and J12 etc.) One session can occur multiple times.
D11:E11 is | Foo | 8 |
I12:J12 is | Foo | 4 |
In another sheet, I want to find a session in the Planning sheet and return an array with all the hours booked on that session (to calculate a total)
I use an array formula with a conditional and intend to use the SMALL function to retrieve the results from the array
The problem
The following formula returns all the correct references to hours booked on "Foo", so far so good.
=IF(Planning!$D$11:$CV$18="Foo";ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"))
{"Planning!$E$11"\FALSE\FALSE\FALSE\FALSE\"Planning!$J$12"}
However, if I use the INDIRECT function to retrieve the values of those references, they always return the value of the first reference in the array ("Planning!$E$11")
=IF(Planning!$D$11:$CV$18="Foo";INDIRECT(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning")))
{8\FALSE\FALSE\FALSE\FALSE\8}
How do I retrieve the correct values? Or should I tackle the problem in a whole different way?
Screenshots
The planning sheet
The overview I want
Since I was mainly interested in the total of planned hours, I eventually used the following formula:
=SUM(SUM(INDIRECT(IF(Planning!$D$11:$CV$18="Foo";(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"));"$U$19"))))
IF: Create the array with references to the Planning sheet if the string is found. If it's not found, add the reference $U$19.
Using INDIRECT, replace all references with the values in the Planning sheet. $U$19 contains the value 0.
Then use SUM twice to sum up all the values. I don't know why, but see
Is it possible to have array as an argument to INDIRECT(), so INDIRECT() returns array?
https://superuser.com/questions/1196243/simplify-a-sum-of-indirect-cell-values
Indirect doest work in most array formulas. If you give it a string that refers to an array, like "A1:A10" it it returns those cells as expected but thats about it. You can use that array as the input to another function but you cant send an array output from another function to INDIRECT(). (Or at least i have not figured out a way)
Try using the INDEX function with the ROW function.
INDIRECT("A1:A10") is similar to
INDEX(A:A,ROW(A1:A10))
However the former is less flexible.
Comsider:
INDEX(A:A,FILTER(ROW(A1:A10),NOT(ISBLANK(A1:A10))*ISNUMBER(A1:A10)))
This returns an array containing the numerical values in the range but does not treat an empty cell as zero. Watch your order of operations and parenthesis.
The product NOT(ISBLANK(A1:A10)*ISNUMBER(A1:A10) is the inner product of two vectors of boolean values.
ROW(A1:A10) creates a vector of row values of the of the elements in that range. Then filter throws out any where the corespinsing element of the boolean vector is 0. Index then returns an array of values of the cells in its range coresponding to those rows. The range given to INDEX could be any row in fact. Not just the one your selecting on. Using the entire column (for example A:A) allows excel to automatically update the references if you move the source data, for instance if you insert a header row. If you use a specific range you will need to add an offset to the row value and it will not automatically update refernces. (Without a far more complex formula)

Condensing a large formula

I was wondering if anyone could enlighten me on a way to condense/shorten this formula:
=IF(ISNUMBER(SEARCH("Kirkintilloch",B2)),"BRN01",IF(ISNUMBER(SEARCH("Tweacher",B2)),"BRN01",IF(ISNUMBER(SEARCH("Lenzie",B2)),"BRN01",IF(ISNUMBER(SEARCH("Bishopbrigg",B2)),"BRN03",IF(ISNUMBER(SEARCH("Torrance",B2)),"BRN03",IF(ISNUMBER(SEARCH("Bearsden",B2)),"BRN04",IF(ISNUMBER(SEARCH("Milngavie",B2)),"BRN04")))))))
Column B will contain an address which will be from one of these seven towns.
The reason I didn't do an IF then Lookup was that the result I want to return is not unique, I.e. Kirkintilloch & Torrance both need to return a result of BRN01.
If it's not possible to simplify this then no worries. It would just save me a lot of work in a larger piece of work with many more possible outcomes.
This is an array formula - confirm it with Ctrl+Shift+Enter while still in the formula bar:
=INDEX(Towns,SMALL(IF(ISNUMBER(SEARCH(INDEX(Towns,0,2),B2)),INDEX(Towns,0,1)),1),3)
Breaking this down:
First you need to create a named range (I called mine "Towns") that contains the array of an index, the town name and the desired return "BRN**" (you could make this a simple range and just reference that but I entered the actual array by selecting the range in formula, highlighting it and using F9 to calculate)
Now that you have this array, I use Index providing 0 for the row argument to return all rows so that I can equate against just a single column at a time.
IF(ISNUMBER(SEARCH(INDEX(Towns,0,2),B2)),INDEX(Towns,0,1))
As this is an array formula, each row is assessed individually and the results (first column when a match is found - index of the array) returned as an array, like so: {FALSE;FALSE;3;FALSE;FALSE;FALSE;FALSE}
I then use SMALL() to catch the lowest number or the first match to feed another index for the third column.

Match function parts in Excel 2016

I have this function:
MATCH(1,(PositionParameter[[#All],[Position Revised]]=$C94)asterisk(PositionParameter[[#All],[Campus Type Short]]=G$3)asterisk(PositionParameter[[#All],[Campus Num Arbitrary]]=G$1),0))
and I can't figure out what it does. I don't know what the asterisks are for. PositionParameter is the name of the worksheet, Position Revised is the name of a column, Campus Type Short is the name of a column, and Campus Num Arbitrary is the name of a column. There is suppose to be an asterisk between the first PositionParameter() and the second PositionParameter(). There is supposed to be another asterisk between the second PositionParameter() and the third PositionParameter(), but it is rendered as an italic. I took the asterisk out and spelled it out. The tooltip tells me this is suppose to return some sort of array, but I can't figure out its components. Can someone explain the asterisks to me? I would appreciate it.
Thanks,
Howard Hong
Your formula returns a single value - the relative position of the first row in the data where all three conditions are met.
It works like this:
Each of these three conditional statements:
PositionParameter[[#All],[Position Revised]]=$C94
PositionParameter[[#All],[Campus Type Short]]=G$3
PositionParameter[[#All],[Campus Num Arbitrary]]=G$1
.....returns an array of TRUE/FALSE values. Multiplying these three arrays together produces a single array of 1/0 values, 1 when all conditions are met in a row, 0 otherwise. This array forms the "lookup array" of the MATCH function
The "lookup value" is 1 so that value is looked up in the lookup array and the result of the MATCH function is the position of the first 1, which corresponds to the first row where all conditions are satisfied.
If there are no rows which meet all three conditions then the result is #N/A
Note that the zero at the end is the third parameter of the MATCH function - zero menas that an exact match must be found.
This is an "array formula" which needs to be confirmed with CTRL+SHIFT+ENTER
Often you would use this in conjunction with INDEX function to return a value from another column in the first row where conditions are satisfied, e.g. using normal cell references
=INDEX(A:A,MATCH(1,(B:B="x")*(C:C="y"),0))
That formula will return the value from column A in the first row where the two specified conditions are met (col B = "x"and col C = "y")
Well, asterisk could be a multiplication symbol or it could be a wildcard in Match. By the looks of the placement, I'd say it's multiplying data from an array or table.
And, um... I don't know what the asterisks are for but I took the asterisk out and spelled it out? Why would you do that? Was it working before you changed it? Where did you find this formula?
Please read [mcve]. Without sample data or other information about the purpose of the formula, I will take a wild guess:
Paste this into the cell:
=MATCH(1,(PositionParameter[[#All],[Position Revised]]=$C94)*(PositionParameter[[#All],[Campus Type Short]]=G$3)*(PositionParameter[[#All],[Campus Num Arbitrary]]=G$1),0))
. . . and assuming it's supposed to be an array, instead of hitting Enter on that cell:
hit: Ctrl+Shift+Enter to create an array formula.
Besides the link above, here is some other reading & practice for you:
Create an array formula
MATCH function
I think certains applications replace certain symbols (that aren't allowed in the application] with words when copying and pasting from Excel to them, but without more information about what happened, I can't say for sure what happened.
Assuming that the * are real and that the formula is entered as an array formula then it should return an array of 0s and 1s.
The formula is looking for Position Revised=C94 AND Campus Type Short =G3 AND Campus Num Arbitrary = G1
It will return a 1 for each row that matches all these conditions and a 0 for each row that does not.
If no rows match the conditions it will return #N/A

IF Values match return true

I am trying to get some code working but when I change a target cell into a range of cells I get an error #VALUE!
this code works
=IF(AND(A1=Sheet2!A2,B1=Sheet2!B2),"TRUE","FALSE")
but if I add a range I get #VALUE! Error
=IF(AND(A1=Sheet2!A2:A10,B1=Sheet2!B2:B10),"TRUE","FALSE")
Update : Here is an example of what I am trying to achieve
Any help would be much appreciated
Many Thanks,
And
Different approach from your logic statement. Instead it looks through your table and match the name with the row and the column with the date selected and the pulls the value at that location.
=INDEX($B$7:$G$8,MATCH($B3,$A$7:$A$8,0),MATCH(C$1,$B$6:$G$6,0))
IMPORTANT: The names in you B3:B4 area have to be unique and spelled identical to your A7:A8 area. That included trailing or leading spaces that you may accidentally drop in.
Adjust reference ranges to match your need if tables are on different sheets of your workbook.
THIS IS AN ARRAY FORMULA - Hit Ctrl+Shift+Enter While still in the formula bar
=INDEX(B2:B10,SMALL(IF(A2:A10=A1,IF(B2:B10="ONCALL",ROW(A2:A10)-1)),1))
=INDEX(B2:B10, - Look through B2:B10 and return the row number calulcaulated by:
SMALL(IF(A2:A10=A1,
IF(B2:B10="ONCALL",
ROW(A2:A10)-1)),1))
This is building an array of row numbers minus 1 where both IF statements are true (Date matches and "ONCALL" present), SMALL then returns the nth value in ascending order - I have asked for the 1st match (or the smallest row number) which INDEX then uses to return the result.

Resources