Find value in another table, return row index - excel

I'm inexperienced in Excel functions and need some help with the following scenario:
Table I has 2 columns:
X Y
3.2 result
4.7 result
1.2 result
Table II has these columns:
A B C D
1 1.2 0.0 2.3
2 4.1 3.2 0.0
3 0.0 4.7 0.0
I will try to illustrate what I want to do in C++/C#/Java programming syntax:
In Y[1] I want to store:
foreach (int value in TableII) //look for X[1] in Table 2
if( value == X[1] ){ //when you find it,
return A[value.rowNumber]; //return the corresponding value from A
//break;
}
In other words, I want to find X[1] in table II (it will always be there, and always just once), and return the corresponding value from column A[of the same index as the match].
I've looked at HLOOKUP but there's more to it that just one command. Please help.
[EDIT]
I've tried this =INDEX(Column1,IFERROR(MATCH(I2,Column2,0),IFERROR(MATCH(I2,Column3,0),IFERROR(MATCH(I2,Column4,0),IFERROR(MATCH(I2,Column5,0),IFERROR(MATCH(I2,Column6,0),IFERROR(MATCH(I2,Column7,0),IFERROR(MATCH(I2,Column8,0),MATCH(I2,Column9,0)))))))))
But I get the "more levels of nesting than are allowed in the current file format" error. If I remove just one IFERROR(MATCH(I2,Column8,0), then it works. But I need Columns 2 to 9, with Column1 holding the index.
I thought Excel 2007 and 2010 do not have nesting limits any more. What gives?
(For anyone new to Excel reading this, "Column1" etc. are made by selecting the column, right clicking on the selection, and "Define Name".)
[EDIT2]
So I "solved" my nesting problem by dividing the formula into 2 parts, with a +, having the ifs return 0 in case there's no match in either side. This way you either have something + 0 or 0 + something, so it works.
Here's the formula I'm using right now:
=INDEX(Column1, IFERROR(MATCH(I3,Column2,0),IFERROR(MATCH(I3,Column3,0),IFERROR(MATCH(I3,Column4,0),IFERROR(MATCH(I3,Column5,0),IFERROR(MATCH(I3,Column6,0),IFERROR(MATCH(I3,Column7,0),0))))))
+
IFERROR(MATCH(I3,Column8,0),IFERROR(MATCH(I3,Column9,0),0))
)
I've accepted Chris' answer, as he did most of the work, but I would still like to know if my workaround is good practice and if there isn't a shorter/better way to do this.
Thank you.

Here's a possible formula for Y (assumes table I is located in columns G:H)
=INDEX($A:$A,IFERROR(MATCH(G2,$B:$B,0),IFERROR(MATCH(G2,$C:$C,0),MATCH(G2,$D:$D,0))))
Note the IsError function was introduced in Ecel 2007
If your tables are actually defined as excel tables you can use
=INDEX(Table2[Column1],IFERROR(MATCH([#X],Table2[Column2],0),IFERROR(MATCH([#X],Table2[Column3],0),MATCH([#X],Table2[Column4],0))))
(substitute your own table and column names)

If your values are unique, you can use the following formula without having to do any nesting:
=INDEX(column1,SUMPRODUCT((Table2=G24)*ROW(Table2)))

Related

switch function Excel

I am working on an Excel switch funciton but something is not working.
I have 2 tables. This is my table 1 -
And this is my Table 2 -
Now, what is want is - when the table 1 "Pick value" Column has a value of A it should enter code herepick the value from Table 2 column value A Value when the value is B, it should pick B Value, else C value from the corresponding field.
That IS WHY I am using this switch query in Excel -
=SWITCH([Pick Value];"A";Table2[A Value];"B";Table2[B Value];Table2[C Value];)
But it is not working -
Anyone knows what I am doing wrong here!
Here is a SWITCH version also using XLOOKUP:
=XLOOKUP([#ID];Table2[ID];SWITCH([#[Pick Value]];"A";Table2[A Value];"B";Table2[B Value];"C";Table2[C Value]))
Use FILTER:
=#FILTER(CHOOSE(MATCH([#Pick Value];{"A";"B";"C"};0);Table2[A Value];Table2[B Value];Table2[C Value]);Table2[ID]=[#ID])
INDEX/MATCH
If you don't have 365, you can use one of the following formulas.
Comma
Array formula (CRTL+SHIFT+ENTER):
=IFERROR(INDEX(Table2[#[A Value]:[C Value]],MATCH([#[Pick Value]],LEFT(Table2[[#Headers],[A Value]:[C Value]],1),0)),"")
or if using "A","B","C" explicitly (ENTER):
=IFERROR(INDEX(Table2[#[A Value]:[C Value]],MATCH([#[Pick Value]],{"A","B","C"},0)),"")
Semi Colon
Array formula (CRTL+SHIFT+ENTER):
=IFERROR(INDEX(Table2[#[A Value]:[C Value]];MATCH([#[Pick Value]];LEFT(Table2[[#Headers];[A Value]:[C Value]];1);0));"")
or if using "A","B","C" explicitly (ENTER):
=IFERROR(INDEX(Table2[#[A Value]:[C Value]];MATCH([#[Pick Value]];{"A";"B";"C"};0));"")

Specifying search direction in Excel VLOOKUP() function

There are many great answers on Stack Overflow describing how to use Excel's VLOOKUP() function. A few that I researched prior to asking this question are here:
Using VLOOKUP()
Excel Vlookup Function
using lookup , vlookup formula
It looks like VLOOKUP(), by default, returns the first matching entry in a table (i.e. "top-first" search). I have a need to instead return the last entry in a table (i.e. "bottom-first" search) -- is there a way to specify search direction using the VLOOKUP() function or, barring that, an alternative function that works like VLOOKUP() but allows one to specify search direction?
EDIT:
Here is a sample of my data. I have network traffic where I am trying to calculate timestamp differences between packets with the same identifiers.
Packet ID Timestamp (ms)
A 0.0
B 1.0
C 2.0
C 3.0
A 4.0
B 5.0
. .
. .
. .
and I need to calculate the timestamp differences similar to below
Packet ID Timestamp (ms) Timestamp Difference (ms, packet ID basis)
A 0.0 0.0
B 1.0 0.0
C 2.0 0.0
C 3.0 1.0 (i.e. "3.0 - 2.0")
A 4.0 4.0 (i.e. "4.0 - 0.0")
B 5.0 4.0 (i.e. "5.0 - 1.0")
C 6.0 3.0 (i.e. "6.0 - 3.0")
. . .
. . .
. . .
To accomplish this, I am trying to create a VLOOKUP() on Packet ID to find the timestamp of the directly previous packet with that same ID.
From this page, you should be able to use:
=LOOKUP(2,1/(A2:A12=D2),B2:B12)
and to ignore zeroes you can use this CSE formula (enter with CTRL+SHIFT+ENTER)
=LOOKUP(9.99999999999999E+307,IF(A2:A12=D2,IF(ISNUMBER(B2:B12),B2:B12)))
(Adjusting ranges as necessary)
Why not create your own VLOOKUP() UDF?
Function VLOOKUP2(lookupVal, tblArray As Range, colIndex As Long)
Dim r As Long
r = tblArray.Find(What:=lookupVal, SearchDirection:=xlPrevious).Row
VLOOKUP2 = tblArray(r, colIndex)
End Function
Disclaimer: The extent of my testing is what you see in the below image.
As #tim says, it usually is best to use unique values as indices so that you don't have problems when it is sorted. If this is something that is not an index (e.g., a date) then this is fine.
I would use an array formula (hit ctrl, shft, enter to add the curly braces, instead of just enter):
{=INDEX(K34:K38,LARGE(IF(K34:K38="a",ROW(K34:K38),),1)-ROW(K34)+1)}
Here's the breakdown:
INDEX(<<target column range>>,
#Compare all the recorded row numbers, and get the largest
LARGE(
#For each item in the column, check to see if it matches the
#search value
IF(<<column range to search>> = <<value to search>>,
#if it does, record its row number
ROW(<<column range to search>>),
)
)
#since we are getting the absolute row number (not relative to the
#target column, we need to calculate an offset
-ROW(<<start item>>)
#excel ranges start at 1 and not 0 so we have to correct the offset
+1
)

Excel If Else Formula comparing string values

First I'm no Excel formula guru..
I want to write a formula that is comparing 4 possible string values
such as: Up, Down, Left, Right
pseudocode would be say:
if a1="Up" and a2="Down" then 1.1
else if a1="Left" and a2="Right" then 1.1
else if a1="Left" and a2="Down" then .95
else if a1 = a2 then 1
I'd cover all the permutations..
I view it as 6 nested if tests
4 items to test/compare
6 tests emerge
1x2,1x3,1x4,2x3,2x4,3x4
=IF(1=2,do this,if(1=3,do this,if(1=4,do this,if(2=3,do this,if(2=4,do this,if(3=4,do this,value if every test fails))))))
I THINK Excel has a limit of 7 nested if formulas or perhaps even formulas in general.
Perhaps you're looking for something like this?
=IF("Test1"="","Equal1
","")&IF("Test2"="","Equal2
","")&IF("Test3"="","Equal3
","")&IF("Test4"="","Equal4
","")
Borrowed from basically the same question on SuperUser.

Return a row number that matches multiple criteria in vbs excel

I need to be able to search my whole table for a row that matches multiple criteria. We use a program that outputs data in the form of a .csv file. It has rows that separate sets of data, each of these headers don't have any columns that are unique in of them self but if i searched the table for multiple values i should be able to pinpoint each header row. I know i can use Application.WorksheetFunction.Match to return a row on a single criteria but i need to search on two three or four criteria.
In pseudo-code it would be something like this:
Return row number were column A = bill & column B = Woods & column C = some other data
We need to work with arrays:
There are 2 kinds of arrays:
numeric {1,0,1,1,1,0,0,1}
boolean {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
to convert between them we can use:
MATCH function
MATCH(1,{1,0,1,1,1,0,0,1},0) -> will result {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
simple multiplication
{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}*{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE} -> will result {1,0,1,1,1,0,0,1}
you can can check an array in the match function, entering it like in the picture below, be warned that MATCH function WILL TREAT AN ARRAY AS AN "OR" FUNCTION (one match will result in true
ie:
MATCH(1,{1,0,1,1,1,0,0,1},0)=TRUE
, YOU MUST CTR+SHIFT+ENTER !!! FOR IT TO GIVE AN ARRAY BACK!!!
in the example below i show that i want to sum the hours of all the employees except the admin per case
we have 2 options, the long simple way, the complicated fast way:
long simple way
D2=SUMPRODUCT(C2:C9,(A2=A2:A9)*("admin"<>B2:B9)) <<- SUMPRODUCT makes a multiplication
basically A1={2,3,11,3,2,4,5,6}*{0,1,1,0,0,0,0,0} (IT MUST BE A NUMERIC ARRAY TO THE RIGHT IN SUMPRODUCT!!!)
ie: A1=2*0+3*1+11*1+3*0+2*0+4*0+5*0+6*0
this causes a problem because if you drag the cell to autocomplete the rest of the cells, it will edit the lower and higher values of
ie: D9=SUMPRODUCT(C9:C16,(A9=A9:A16)*("admin"<>B9:B16)), which is out of bounds
same as the above if you have a table and want to view the results in a diferent order
the fast complicated way
D3=SUMPRODUCT(INDIRECT("c2:c9"),(A3=INDIRECT("a2:a9"))*("admin"<>INDIRECT("b2:b9")))
it's the same, except that INDIRECT was used on the cells that we want not be modified when autocompleting or table reorderings
be warned that INDIRECT sometimes give VOLATILE ERROR,i recommend not using it on a single cell or using it only once in an array
f* c* i cant post pictures :(
table is:
case emplyee hours totalHoursPerCaseWithoutAdmin
1 admin 2 14
1 him 3 14
1 her 11 14
2 him 3 5
2 her 2 5
3 you 4 10
3 admin 5 10
3 her 6 10
and for the functions to check the arrays, open the insert function button (it looks like and fx) then doubleclick MATCH and then if you enter inside the Lookup_array a value like
A2=A2:A9 for our example it will give {TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE} that is because only the first 3 lines are from case=1
Something like this?
Assuming that you data in in A1:C20
I am looking for "Bill" in A, "Woods" in B and "some other data" in C
Change as applicable
=IF(INDEX(A1:A20,MATCH("Bill",A1:A20,0),1)="Bill",IF(INDEX(B1:B20,MATCH("Woods",B1:B20,0),1)="Woods",IF(INDEX(C1:C20,MATCH("some other data",C1:C20,0),1)="some other data",MATCH("Bill",A1:A20,0),"Not Found")))
SNAPSHOT
I would use this array* formula (for three criteria):
=MATCH(1,((Range1=Criterion1)*(Range2=Criterion2)*(Range3=Criterion3)),0)
*commit with Ctrl+Shift+Enter

Case Function Equivalent in Excel

I have an interesting challenge - I need to run a check on the following data in Excel:
| A - B - C - D |
|------|------|------|------|
| 36 | 0 | 0 | x |
| 0 | 600 | 700 | x |
|___________________________|
You'll have to excuse my wonderfully bad ASCII art. So I need the D column (x) to run a check against the adjacent cells, then convert the values if necessary. Here's the criteria:
If column B is greater than 0, everything works great and I can get coffee. If it doesn't meet that requirement, then I need to convert A1 according to a table - for example, 32 = 1420 and place into D. Unfortunately, there is no relationship between A and what it needs to convert to, so creating a calculation is out of the question.
A case or switch statement would be perfect in this scenario, but I don't think it is a native function in Excel. I also think it would be kind of crazy to chain a bunch of =IF() statements together, which I did about four times before deciding it was a bad idea (story of my life).
Sounds like a job for VLOOKUP!
You can put your 32 -> 1420 type mappings in a couple of columns somewhere, then use the VLOOKUP function to perform the lookup.
Without reference to the original problem (which I suspect is long since solved), I very recently discovered a neat trick that makes the Choose function work exactly like a select case statement without any need to modify data. There's only one catch: only one of your choose conditions can be true at any one time.
The syntax is as follows:
CHOOSE(
(1 * (CONDITION_1)) + (2 * (CONDITION_2)) + ... + (N * (CONDITION_N)),
RESULT_1, RESULT_2, ... , RESULT_N
)
On the assumption that only one of the conditions 1 to N will be true, everything else is 0, meaning the numeric value will correspond to the appropriate result.
If you are not 100% certain that all conditions are mutually exclusive, you might prefer something like:
CHOOSE(
(1 * TEST1) + (2 * TEST2) + (4 * TEST3) + (8 * TEST4) ... (2^N * TESTN)
OUT1, OUT2, , OUT3, , , , OUT4 , , <LOTS OF COMMAS> , OUT5
)
That said, if Excel has an upper limit on the number of arguments a function can take, you'd hit it pretty quickly.
Honestly, can't believe it's taken me years to work it out, but I haven't seen it before, so figured I'd leave it here to help others.
EDIT: Per comment below from #aTrusty:
Silly numbers of commas can be eliminated (and as a result, the choose statement would work for up to 254 cases) by using a formula of the following form:
CHOOSE(
1 + LOG(1 + (2*TEST1) + (4*TEST2) + (8*TEST3) + (16*TEST4),2),
OTHERWISE, RESULT1, RESULT2, RESULT3, RESULT4
)
Note the second argument to the LOG clause, which puts it in base 2 and makes the whole thing work.
Edit: Per David's answer, there's now an actual switch statement if you're lucky enough to be working on office 2016. Aside from difficulty in reading, this also means you get the efficiency of switch, not just the behaviour!
The Switch function is now available, in Excel 2016 / Office 365
SWITCH(expression, value1, result1, [default or value2, result2],…[default or value3, result3])
example:
=SWITCH(A1,0,"FALSE",-1,"TRUE","Maybe")
Microsoft -Office Support
Note: MS has updated that page to only document the behavior of Excel 2019. Eventually, they will probably remove references to 2019 as well... To see what the page looked like in 2016, use the wayback machine:
https://web.archive.org/web/20161010180642/https://support.office.com/en-us/article/SWITCH-function-47ab33c0-28ce-4530-8a45-d532ec4aa25e
Try this;
=IF(B1>=0, B1, OFFSET($X$1, MATCH(B1, $X:$X, Z) - 1, Y)
WHERE
X = The columns you are indexing into
Y = The number of columns to the left (-Y) or right (Y) of the indexed column to get the value you are looking for
Z = 0 if exact-match (if you want to handle errors)
I used this solution to convert single letter color codes into their descriptions:
=CHOOSE(FIND(H5,"GYR"),"Good","OK","Bad")
You basically look up the element you're trying to decode in the array, then use CHOOSE() to pick the associated item. It's a little more compact than building a table for VLOOKUP().
I know it a little late to answer but I think this short video will help you a lot.
http://www.xlninja.com/2012/07/25/excel-choose-function-explained/
Essentially it is using the choose function. He explains it very well in the video so I'll let do it instead of typing 20 pages.
Another video of his explains how to use data validation to populate a drop down which you can select from a limited range.
http://www.xlninja.com/2012/08/13/excel-data-validation-using-dependent-lists/
You could combine the two and use the value in the drop down as your index to the choose function. While he did not show how to combine them, I'm sure you could figure it out as his videos are good. If you have trouble, let me know and I'll update my answer to show you.
I understand that this is a response to an old post-
I like the If() function combined with Index()/Match():
=IF(B2>0,"x",INDEX($H$2:$I$9,MATCH(A2,$H$2:$H$9,0),2))
The if function compare what is in column b and if it is greater than 0, it returns x, if not it uses the array (table of information) identified by the Index() function and selected by Match() to return the value that a corresponds to.
The Index array has the absolute location set $H$2:$I$9 (the dollar signs) so that the place it points to will not change as the formula is copied. The row with the value that you want returned is identified by the Match() function. Match() has the added value of not needing a sorted list to look through that Vlookup() requires. Match() can find the value with a value: 1 less than, 0 exact, -1 greater than. I put a zero in after the absolute Match() array $H$2:$H$9 to find the exact match. For the column that value of the Index() array that one would like returned is entered. I entered a 2 because in my array the return value was in the second column. Below my index array looked like this:
32 1420
36 1650
40 1790
44 1860
55 2010
The value in your 'a' column to search for in the list is in the first column in my example and the corresponding value that is to be return is to the right. The look up/reference table can be on any tab in the work book - or even in another file. -Book2 is the file name, and Sheet2 is the 'other tab' name.
=IF(B2>0,"x",INDEX([Book2]Sheet2!$A$1:$B$8,MATCH(A2,[Book2]Sheet2!$A$1:$A$8,0),2))
If you do not want x return when the value of b is greater than zero delete the x for a 'blank'/null equivalent or maybe put a 0 - not sure what you would want there.
Below is beginning of the function with the x deleted.
=IF(B2>0,"",INDEX...
If you don't have a SWITCH statement in your Excel version (pre-Excel-2016), here's a VBA implementation for it:
Public Function SWITCH(ParamArray args() As Variant) As Variant
Dim i As Integer
Dim val As Variant
Dim tmp As Variant
If ((UBound(args) - LBound(args)) = 0) Or (((UBound(args) - LBound(args)) Mod 2 = 0)) Then
Error 450 'Invalid arguments
Else
val = args(LBound(args))
i = LBound(args) + 1
tmp = args(UBound(args))
While (i < UBound(args))
If val = args(i) Then
tmp = args(i + 1)
End If
i = i + 2
Wend
End If
SWITCH = tmp
End Function
It works exactly like expected, a drop-in replacement for example for Google Spreadsheet's SWITCH function.
Syntax:
=SWITCH(selector; [keyN; valueN;] ... defaultvalue)
where
selector is any expression that is compared to keys
key1, key2, ... are expressions that are compared to the selector
value1, value2, ... are values that are selected if the selector equals to the corresponding key (only)
defaultvalue is used if no key matches the selector
Examples:
=SWITCH("a";"?") returns "?"
=SWITCH("a";"a";"1";"?") returns "1"
=SWITCH("x";"a";"1";"?") returns "?"
=SWITCH("b";"a";"1";"b";TRUE;"?") returns TRUE
=SWITCH(7;7;1;7;2;0) returns 2
=SWITCH("a";"a";"1") returns #VALUE!
To use it, open your Excel, go to Develpment tools tab, click Visual Basic, rightclick on ThisWorkbook, choose Insert, then Module, finally copy the code into the editor. You have to save as a macro-friendly Excel workbook (xlsm).
Even if old, this seems to be a popular questions, so I'll post another solution, which I think is very elegant:
http://fiveminutelessons.com/learn-microsoft-excel/using-multiple-if-statements-excel
It's elegant because it uses just the IF function. Basically, it boils down to this:
if(condition, choose/use a value from the table, if(condition, choose/use another value from the table...
And so on
Works beautifully, even better than HLOOKUP or VLOOOKUP
but... Be warned - there is a limit to the number of nested if statements excel can handle.
Microsoft replace SWITCH, IFS and IFVALUES with CHOOSE only function.
=CHOOSE($L$1,"index_1","Index_2","Index_3")
Recently I unfortunately had to work with Excel 2010 again for a while and I missed the SWITCH function a lot. I came up with the following to try to minimize my pain:
=CHOOSE(SUM((A1={"a";"b";"c"})*ROW(INDIRECT(1&":"&3))),1,2,3)
CTRL+SHIFT+ENTER
where A1 is where your condition lies (it could be a formula, whatever). The good thing is that we just have to provide the condition once (just like SWITCH) and the cases (in this example: a,b,c) and results (in this example: 1,2,3) are ordered, which makes it easy to reason about.
Here is how it works:
Cond={"c1";"c2";...;"cn"} returns a N-vector of TRUE or FALSE (with behaves like 1s and 0s)
ROW(INDIRECT(1&":"&n)) returns a N-vector of ordered numbers: 1;2;3;...;n
The multiplication of both vectors will return lots of zeros and a number (position) where the condition was matched
SUM just transforms this vector with zeros and a position into just a single number, which CHOOSE then can use
If you want to add another condition, just remember to increment the last number inside INDIRECT
If you want an ELSE case, just wrap it inside an IFERROR formula
The formula will not behave properly if you provide the same condition more than once, but I guess nobody would want to do that anyway
If your using Office 2016 or later, or Office 365, there is a new function that acts similarly to a CASE function called IFS. Here's the description of the function from Microsoft's documentation:
The IFS function checks whether one or more conditions are met, and returns a value that corresponds to the first TRUE condition. IFS can take the place of multiple nested IF statements, and is much easier to read with multiple conditions.
An example of usage follows:
=IFS(A2>89,"A",A2>79,"B",A2>69,"C",A2>59,"D",TRUE,"F")
You can even specify a default result:
To specify a default result, enter TRUE for your final logical_test argument. If none of the other conditions are met, the corresponding value will be returned.
The default result feature is included in the example shown above.
You can read more about it on Microsoft's Support Documentation

Resources