Multiple Column vs Multiple Column Lookup - excel

I am after a formula to match a number of columns between two worksheets and return the last reference worksheets final column data. I know this is doable in VBA, but am looking for a formula method.
MainWorksheet:
User | Region | Country | City | Lookup
--------------------------------------------------
User1 | Europe | Italy | Rome | [formula here]
User2 | Americas | Brazil | Rio | [formula here]
ReferenceWorksheet:
Region | Country | City | Data
-----------------------------------
Europe | England | London | some data
Americas | Brazil | Rio | more data
Europe | Italy | Rome | some more data
The formula I am after should match each column in that particular row and add the Data cell value from the ReferenceWorksheet to the MainWorksheet.
eg. If (MainWorksheet.Region = ReferenceWorksheet.Region) &&
(MainWorksheet.Country == ReferenceWorksheet.Country) &&
(MainWorksheet.Region == ReferenceWorksheet.Region) Then
MainWorksheet.Column E = ReferenceWorksheet.Current Row:Data Column
I haven't found a cleancut way to do this using mutliple columns using VLOOKUP, INDEX(MATCH)) etc. Is there a way to filter within a function?
Any help is much appreciated!

I agree with vasek1, adding additional columns will simplify the formulas required but if you want to avoid extra columns there are [relatively] simple methods available.
Method 1 - do the same concatenation as vasek1....but within the formula, e.g. in E2
Main
=INDEX(Ref!D$2:D$100,MATCH(B2&"-"&C2&"-"&D2,Ref!A$2:A$100&"-"&Ref!B$2:B$100&"-"&Ref!C$2:C$100,0))
formula needs to be confirmed with CTRL+SHIFT+ENTER
Method 2 - a non-array version with LOOKUP
=LOOKUP(2,1/(Ref!A$2:A$100=B2)/(Ref!B$2:B$100=C2)/(Ref!C$2:C$100=D2),Ref!D$2:D$100)
Note that the first formula finds the first match, the latter the last. I assume that the reference data will only have a single instance of each region/country/city combination in which case they will both give the same results, but that isn't guaranteed in every situation.
To allow C2 to be "<>" meaning "any country" (as per comment) you can use this revised version of the LOOKUP formula
=LOOKUP(2,1/(Ref!A$2:A$100=B2)/((Ref!B$2:B$100=C2)+(C2="<>"))/(Ref!C$2:C$100=D2),Ref!D$2:D$100)
A similar change can be applied to the INDEX/MATCH version

A solution I use for this type of problem is to create an extra column to serve as the unique identifier for each table. So, in your case,
Main table: formula for key, assuming you start with column 1 = A, is
E2 = B2 & "(underscore)" & C2 & "(underscore)" & D2
User | Region | Country | City | Key | Lookup
--------------------------------------------------
User1 | Europe | Italy | Rome | Europe_Italy_Rome | [formula here]
User2 | Americas | Brazil | Rio | Americas_Brazil_Rio | [formula here]
Reference table: here, insert the extra column to the left so you can do a vlookup on it. Formula for Key in A2 is
A2 = B2 & "(underscore)" & C2 & "(underscore)" & D2
Key | Region | Country | City | Data
---------------------------------------------------------------------
Europe_England_London | Europe | England | London | some data
Americas_Brazil_Rio | Americas | Brazil | Rio | more data
Europe_Italy_Rome | Europe | Italy | Rome | some more data
Then, the lookup formula in the main table becomes very simple:
F2 = VLOOKUP(E2, ReferenceTable!$A$2:$E$4, 5, 0)
You can then hide the key columns from the user, if necessary. The advantage of this approach is that it keeps the formulas simple and is much easier to understand and update than writing VBA or a complicated formula.

Here's a simple example of multi-column MATCH (the kind of approach which often shows up when searching for this type of formula):
In E10:
=IFERROR(INDEX(E3:E5,MATCH(B10&C10&D10,$B$3:$B$5&$C$3:$C$5&$D$3:$D$5,0),1),"No Match")
Be sure to use Ctrl+Shift+Enter when entering the formula.
Posting this to note that it has an issue you should be aware of: the example above matches on:
B | Two | Blue
but it will also match on:
BT | wo | Blue

What you need is typically called a Multiple Lookup.
This was asked a few times, under various forms.
I have compiled here a list of such posts.
(This one is in the list)
There are many possible solutions for that.
The one I found most robust is shown here.
Adapted to this case, the formula in E3 would be
=INDEX(Ref!D:D,SUMPRODUCT(--(Ref!A:A=B3),--(Ref!B:B=C3),--(Ref!C:C=D3),ROW(Ref!D:D)),0)
and copy downward.

Related

Find in which columns lies the text?

Thanks for reading this!
Lets say we have 2 columns in this workbook called "Data":
| Column A | Column B |
| -------- | -------------- |
| Joshua | Noah |
| Daniel | Joshua |
In another workbook, I want the user to input some random name in a cell.
Below that cell, I want to be able to show him/her, in which column that name lies. E.g. if he types "Joshua", I want to be shown below:
||
|--|
|Column A|
|Column B|
I prefer using a formula, instead of VBA, as it would mess with my not-so-experienced end-user!
Notes: See below my attempt if you find it useful:
(1) I tried that using a nested IF + FILTER functions inside, but the IF returns only the first TRUE column, like this:
| |
|------|
| Column A |
| Column A |
Here is my actual formula, where I'm referring to split ranges in sheet "6", where I have 4 columns:
IF(NOT(ISERROR(FILTER('6'!B4#,ISNUMBER(SEARCH($F$4,'6'!B4#))))),'6'!$B$1,
IF(NOT(ISERROR(FILTER('6'!D4#,ISNUMBER(SEARCH($F$4,'6'!D4#))))),'6'!$D$1,
IF(NOT(ISERROR(FILTER('6'!F4#,ISNUMBER(SEARCH($F$4,'6'!F4#))))),'6'!$F$1,
IF(NOT(ISERROR(FILTER('6'!H4#,ISNUMBER(SEARCH($F$4,'6'!H4#))))),'6'!$H$1,""))))
You could use:
Formula in D2:
=FILTER(TRANSPOSE(A1:B1),MMULT(--(TRANSPOSE(A2:B3)=D1),SEQUENCE(ROWS(A2:B3),,,0)),"")
You can get the column numbers with this formula (original data on worksheet "10")
=AGGREGATE(15,6,1/('10'!A:D="Joshua")*COLUMN('10'!A:D),SEQUENCE(COUNTIF('10'!A:D,"Joshua")))
Although I suggest reducing the range references from full columns to something shorter to reduce calculation times.
With Office 365, you can convert the column number to the letter with this:
=LET(col,AGGREGATE(15,6,1/('10'!A:D="Joshua")*COLUMN('10'!A:D),SEQUENCE(COUNTIF('10'!A:D,"Joshua"))),
adr,ADDRESS(1,col,2),
"Column " & LEFT(adr,FIND("$",adr)-1))

Sum All VLOOKUP Matches

I have a sheet where I am recording what I eat:
Another where I keep an index of values to lookup
I tried
=SUM(VLOOKUP('Sheet1'!A2:A11,'Sheet2'!A2:E11,2,FALSE))
but that only returned the first match, so then I tried
=SUMPRODUCT(SUMIF('Sheet1'!A2:A11,'Sheet2'!A2:A11,'Sheet2'!B2:B11))
but that isn't working either.
does anyone have a solution, where I can also multiply the value of the return match by the # of servings in the first sheet?
Thanks!
If you want a single output of calories through SUMPRODUCT then you can use
=SUMPRODUCT(B2:B11*IFERROR(VLOOKUP(A2:A11,Sheet2!A2:B11,2,0),0))
If you are sure that all entries on Sheet 1 can be located on Sheet 2 then you can drop IFERROR portion like
=SUMPRODUCT(B2:B11*VLOOKUP(A2:A11,Sheet2!A2:B11,2,0)).
Beware that if a value is not found in Sheet 2 then formula will produce wrong result as IFERROR will multiply the serving quantity with 0.
I combine 2 tables into one sheet, Table 1 housed in Column A & B and Table 2 housed in Column D & E
In G2, "Total Serving Colories" enter formula :
=SUMPRODUCT(VLOOKUP(T(IF({1},A2:A12)),D2:E12,2,FALSE)*B2:B12)
It's not super-clear what you're trying to get at. But defining the "Calories Per Serving" in a range called "cals",
+---+---------+-----+--------------------------------+
| | A | B | C |
+---+---------+-----+--------------------------------+
| 1 | egg | 3 | =(VLOOKUP(A2,cals,2,FALSE))*B2 |
| 2 | oatmeal | 1.5 | =(VLOOKUP(A3,cals,2,FALSE))*B3 |
| 3 | shrimp | 2 | =(VLOOKUP(A4,cals,2,FALSE))*B4 |
+---+---------+-----+--------------------------------+
Results in:

Find Matching Word, or Number, in a Column and return corresponding rows

I'm not sure how well I'm going to articulate this, but hopefully, it makes sense.
I have a Google Sheet that houses 3 tabs, 2 of which hold data while the 3rd is an overview of the 2. I'm trying to create a small search formula to easily find specific data from 1 of the 2 sheets.
Here is how one sheet looks:
A B C D
1| Name | Number | Type | Role
--------------------------------------------
2| John Doe | 012345 | Tech | MKT
3| Jane Doe | 012445 | Business | DEV
4| Jane Doe | 012445 | Business | MKT
5| Arthur | 015475 | Home | SALE
6| Arthur | 011111 | Tech | MKT
And there are about 250 rows.
What I'm trying to do is see if a specific column matches the search term added to the primary sheet.
E.g: "Arthur" in Column 1 ("Arthur" A2:A5). And, if it exists, return the data from each column in the corresponding row.
E.g: Data returned would be:
A5 (Arthur), B5 (015475), C5 (Home), D5 (Sale)
Currently, I'm using the following formula in the main sheet which searches column A in Sheet 2 (A1 is the cell where I'm typing the name, e.g: Arthur) and outputs the first row:
=Vlookup(A1,Sheet2!$A$1:$K$200,1,False)
If there is a Match, the contents of that Cell is output. In this case, Arthur.
So, is there any way of extending this to also get the contents of all Cells in the matching Row?
But, I need to ensure it's going to be compatible in the event that this file is opened in MS Excel.
Thanks
EDIT: I've managed to solve my own problem:
=IFERROR(INDEX(Sheet2!$A$1:$K$20,SMALL(IF(Sheet1!$A$1:$K$20=A2,ROW($A$1:$K$20)-ROW($C$1)+1),ROWS(A$1:K1))),"False")
However, this does not work for Duplicates.
Let's so, there are 2 Arthurs, this will only return the corresponding row for the last instance of Arthur it finds. Is there a way to have it return all of them.
Please find the below formula & the image. Hope the formula will solve your issue.If still, the problem exists please share a Sample sheet with some Sample data. I will try to resolve your issue.
Formula - =QUERY(A3:D8,"Select A,B,C,D where A = '"&F2&"'",0)
Image for reference -
If you want to include the headers please replace 0 with 1.
The simplest is the filter function. Please try:
=filter('Sheet1'!A:D, A:A = "Arthur")
Or a query function.
NOTE! query and filter are not compatible with excel.
For excel you may adopt this formula for your needs:
=INDEX('Sheet1'!B$1:B$500, SMALL(IF("Arthur"='Sheet1'!$A$1:$A$500, ROW('Sheet1'!$A$1:$A$500)-ROW('Sheet1'!$A$1)+1), ROW('Sheet1'!1:1)))
Drag it down and right to adjust the result.

Transponse just some columns in excel

I have a worksheet with columns similar to the below
name | id | contact | category | week 1 | week 2 | week 3 | ... |week 52
What I need to do is transpose the 'week' columns into rows, so I end up with:
name | id | contact | category | week
With an entry for each week as a row in the s/sheet - thus making a long list on rows with the column data for each week.
example current format:
jones | 12345 | simon | electronics | 100 | 120| 130| 110 | ..........150
Required format
jones | 12345 | simon | electronics | 100
jones | 12345 | simon | electronics | 120
jones | 12345 | simon | electronics | 130
jones | 12345 | simon | electronics | 110
...
jones | 12345 | simon | electronics | 150
I have tried the usual excel transpose (via paste) but cannot get the first few columns to stay static, whilst transposing the week columns
Ideally I would like to achieve this within excel, but I can import the data into a mysql database and use that if the solution would be easier that way
Hope this makes sense
[added examples]
I would do the work on a second sheet, which uses the INDIRECT function to do the lookups for you:
http://www.excelfunctions.net/Excel-Indirect-Function.html
Start by setting up some indexes on the new sheet - we will use these to indirectly look up into the original sheet and pull the data across.
I would count up to 52 again and again in column A, starting with a 1 in A2, and using this formula below:
=if(A2=52,1,A2+1)
This would be my count of the weeks per person.
In column B, I would count my people, starting with a 1 in B2, and using this formula:
=if(A3=1,B2+1,B2)
This gives me the row and column offsets to use in the INDIRECT function to fetch the data from your original sheet.
Now the fun part - matching these row and column offsets to your actual data.
Lets assume your original data is in a sheet called "original". This is where we need to look up the data.
We will map the original column A into the new sheet's column C. So C2 can hold this formula:
=indirect("original!R"&($B2+1)&"C1",false)
What you are doing there is looking in the row that you calculated in the B column (formula above), and looking in the first column of that row (i.e. column A) - this is where the Name is stored.
Similarly, the "id", "contact" and "category" columns get mapped to new sheet columns D, E, F, using modifications of that formula:
=indirect("original!R"&($B2+1)&"C2",false)
=indirect("original!R"&($B2+1)&"C3",false)
=indirect("original!R"&($B2+1)&"C4",false)
Only the column offset gets changed in these updates.
To pull the weekly data across, we use a similar formula; the difference is that now we get to use the newly calculated column A, where we counted up from 1 to 52 over and over.
So G2 becomes:
=indirect("original!R"&($B2+1)&"C"&(4+$A2),false)
Copy this all down as far as you need, and hide columns A and B.

Counting the number of older siblings in an Excel spreadsheet

I have a longitudinal spreadsheet of adolescent growth.
ID | CollectionDate | DOB | MOTHER ID | Sex
1 | 1Aug03 | 3Apr90 | 12 | 1
1 | 4Sept04 | 3Apr90 | 12 | 1
1 | 1Sept05 | 3Apr90 | 12 | 1
2 | 1Aug03 | 21Dec91 | 12 | 0
2 | 4Sept04 | 21Dec91 | 12 | 0
2 | 1Sept05 | 21Dec91 | 12 | 0
3 | 1Aug03 | 30Jan89 | 23 | 0
3 | 4Sept04 | 30Jan89 | 23 | 0
This is a sample of how my data is formatted and some of the variables that I have. As you can see, since it is longitudinal, each individual has multiple measurements. In the actual database there are over 10 measurements per individual and over 250 individuals.
What I am wanting to do is input a value signifying the number of older brothers and older sisters each individual has. That is why I have included the Mother ID (because it represents genetic relatedness) and sex. These new variable columns would just say how many older siblings of each sex each individual has. Is there a formula that I could use to do this quickly?
=COUNTIFS($B:$B,"<>"&$B2,$H:$H,$H2,$AI:$AI,$AI2,$J:$J,"<"&$J2)
Create a column named Distinct with this formula
=1/COUNTIF([ID],[#ID])
Then you can find all the older 0-sexed siblings like this
=SUMPRODUCT(([DOB]>[#DOB])*([MOTHERID]=[#MOTHERID])*([Sex]=0)*([Distinct]))
Note that I made the data a Table and used table notation. If you're not familiar [COLUMNNAME] refers to the whole column and [#COLUMNNAME] refers to the value in that column on the current row. It's similar to saying $A:$A and A2 if you're dealing with column A.
The first formula gives you a value to count that will always result in 1 for a particular ID. So ID=1 has three lines and Distinct will result in .33333 for each line. When you add up the three lines you get 1. This is similar to a SELECT DISTINCT in Sql parlance.
The SUMPRODUCT formula sums [Distinct] for every row where the DOB is greater than the current DOB, the Mother is the same as the current Mother, and the Sex is zero.
I have a possible solution. It involves adding two columns -- One for "# older siblings" and one for "unique?". So here are all the headings I have currently:
A -- ID
B -- CollectionDate
C -- DOB
D -- MOTHER ID
E -- Sex
F -- # older siblings
G -- unique?
In G2, I added the following formula:
=IF(A2=A1,0,1)
And dragged down. As long as the data is sorted by ID, this will only display "1" once for each unique person.
In F2, I added the following formula:
=COUNTIFS(G:G,"=1",D:D,"="&D2,C:C,"<"&C2)
And dragged down. It seemed to work correctly for the sample data you provided.
The stipulations are:
You would need the two columns.
The data would need to be sorted by ID
I hope this helps.
You need a formula like this (for example, for row 2):
=COUNTIFS($A:$A,"<>"&$A2,$E:$E,$E2,$D:$D,$D2,$C:$C,"<"&$C2)
Assuming E:E is column for sex, D:D is column for mother ID and C:C is column for DOB.
Write this formula in H2 cell for example and drag it down.

Resources