Extract part of a list given start value in excel - excel

I want to extract part of a list given the starting value found by means of index/match combinations or the vlookup function. However, hence only the initial value is returned but subsequent values in the list are also of interest and should follow this initial found value. Is there a way of combining functions that return sub-arrays? Thank you in advance for the help. Best Regards, Oliver

Say we have data like:
and we wanted the UK people, VLOOKUP() would only return William. If we want more than just William, then in C1 enter:
UK
and in C2 enter the array formula:
=IFERROR(INDEX($B$2:$B$22, SMALL(IF(C$1=$A$2:$A$22, ROW($A$2:$A$22)-MIN(ROW($A$2:$A$22))+1, ""), ROW(A1))),"")
and copy down:
Array formulas must be entered with Ctrl + Shift + Enter rather than just the Enter key.

1. Incrementing Row/Column Count Options
1a. Start Value, Sub-List Length
Let us assume this sample data and result format:
A B C D
---------------------------------------------
1|John Start Value Amy Amy
2|Jane Sub-List Length 3 Amber
3|Amy Chris
4|Amber
5|Chris
6|Dan
7|Bob
You can achieve this by using the following formula and autofilling down:
=IFERROR(INDEX($A:$A,(MATCH($C$1,$A:$A,0))+IF(ROWS($1:1)<=$C$2,ROWS($1:1)-1,#VALUE!)),"")
1b. Start Value, End Value
Sample data and result format:
A B C D
---------------------------------------------
1|John Start Value Amy Amy
2|Jane End Value Dan Amber
3|Amy Chris
4|Amber Dan
5|Chris
6|Dan
7|Bob
Use this formula and autofill down:
=IFERROR(INDEX($A:$A,(MATCH($C$1,$A:$A,0))+IF(ROWS($1:1)<=(MATCH($C$2,$A:$A,0)-MATCH($C$1,$A:$A,0)+1),ROWS($1:1)-1,#VALUE!)),"")
1c. Start Value, End of list
Sample data and result format:
A B C D
---------------------------------------------
1|John Start Value Chris Chris
2|Jane Dan
3|Amy Bob
4|Amber
5|Chris
6|Dan
7|Bob
Use this formula and autofill down:
=IFERROR(INDEX($A:$A,(MATCH($C$1,$A:$A,0))+IF(ROWS($1:1)<=(COUNTA($A:$A)-MATCH($C$1,$A:$A,0)+1),ROWS($1:1)-1,#VALUE!)),"")
Note: for options 1a - 1c if you wish to have a horizontal list result replace ROWS($1:1) with COLUMNS($A:A) and autofill to the right
2. Using a Predefined Array:
Note: These options requires you to select the range you want the values to be in, and then use ctrl + shift + enter to enter the data.
2a. Vertical Sublist, Fixed Length:
Sample data and result format, with fixed length of 4
A B C D
---------------------------------------------
1|John Start Value Amy Amy
2|Jane Amber
3|Amy Chris
4|Amber Dan
5|Chris
6|Dan
7|Bob
Select cells D1:D4 and enter in this formula:
=INDEX($A:$A,MATCH($C$1,$A:$A,0)+TRANSPOSE({0,1,2,3}))
Then use ctrl + shift + enter
2b. Horizontal Sublist, Fixed Length:
Sample data and result format, with fixed length of 4
A B C D E F G
----------------------------------------------------------
1|John Start Value Amy Amy Amber Chris Dan
2|Jane
3|Amy
4|Amber
5|Chris
6|Dan
7|Bob
Same as last formula without TRANSPOSE and selecting cells D1:G1:
=INDEX($A:$A,MATCH($C$1,$A:$A,0)+{0,1,2,3})
Again, use ctrl + shift + enter
Note: To increment the length add additional values to the array {0,1,2,3, ...}

Related

Excel find last match from two tables

I'm looking for a way to find the last instance on an entry in the columns A,B and get the corresponding values from columns C,D
In the example below value for Henry is 1374 and value for Amy is 1124
Name1 corresponds to Value1 and Name2 corresponds to Value2.
Is there a formula to find the last entry from both columns Name1 and Name2 and return the corresponding Value1 or Value2
Raw data pasted below:
Name1 Name2 Value1 Value2
Sara Amy 1265 1241
John Sara 1142 1214
Amy Henry 1295 1121
Amy John 1175 1323
Sara John 1085 1251
Sara Henry 1242 1374
Amy Sara 1124 1055
Slightly shorter:
= INDEX($C$1:$D$8,MAX(IF($A$1:$B$8=A10,ROW($A$1:$B$8))),MATCH(A10,
INDEX($A$1:$B$8,MAX(IF($A$1:$B$8=A10,ROW($A$1:$B$8))),0),0))
Note this is an array formula, so you must press Ctrl+Shift+Enter rather than just Enter after typing the formula.
See below for working example.
Assumptions:
Data Grid is in cells A1:D8.
Values "Henry" & "Amy" are in cell A10 & A11 respectively.
Formula implementation:
In cell B10 following formula is implemented.
Alternative 1:
=INDEX($C$2:$D$8,MAX(IFERROR(LOOKUP(2,1/($A$2:$A$8=A10),ROW($A$2:$A$8)),-1),IFERROR(LOOKUP(2,1/($B$2:$B$8=A10),ROW($B$2:$B$8)),-1))-1,IF(IFERROR(LOOKUP(2,1/($A$2:$A$8=A10),ROW($A$2:$A$8)),-1)>IFERROR(LOOKUP(2,1/($B$2:$B$8=A10),ROW($B$2:$B$8)),-1),1,2))
Alternative 2 (slightly shorter than 1):
=INDEX($C$2:$D$8,LOOKUP(2,1/SEARCH(A10&",",$A$2:$A$8&","&$B$2:$B$8&",",1),ROW($A$2:$A$8))-1,IF(IFERROR(LOOKUP(2,1/($A$2:$A$8=A10),ROW($A$2:$A$8)),-1)>IFERROR(LOOKUP(2,1/($B$2:$B$8=A10),ROW($B$2:$B$8)),-1),1,2)).
To be copied down as much needed.
Notice -1 value after MAX() function which is used to adjust row number. It should be always n-1 considering data starts at nth row.
I've been trying to remember another method I've seen for 2d lookup (I can't find the link any more). It's basically like this
=INDIRECT(TEXT(MAX((ROW($A$2:$B$8)*100+COLUMN($A$2:$B$8))*($A$2:$B$8=A10))+2,"R0C00"),FALSE)
entered as an array formula using CtrlShiftEnter.
So the idea is that you generate a number from the row and column where the last occurrence of the name is located (so for Henry it would be 702).
The you format it to give R7C02 and feed this in to an indirect to give the reference to the cell in RC notation. The column plus 2 gives the cell that you want.
You might notice that this would fail if column>99, but you can make the multiplier as big as you want.

Pick multiple values from list and ignore empty cells

I have the following Excel spreadsheet:
A B C D E F G
1 USER1 USER2 MICHAEL SANDRA JAMES CAITLIN
2 Product A Michael James Michael James
3 Product B Sandra Caitlin Sandra Caitlin
4 Product C James Caitlin James Caitlin
5 Product D Michael Sandra Michael Sandra
In Columns D:G 4 users of a product are listed. If a product is used by a User his/her name appears in Cells D2:G5. If he/she does not use the product the cell remains empty.
In Columns B:C I want to achieve now that the emtpy cells are eliminated and the maximum 2 Users are listed.
Do you know any formula that can go through the Cells D2:G5 to pick the 2 Users and show them in Columns B:C?
I don't know of any quick formula that you can use.
You are probably best off using VBA. You could write something compact and concise in there. VBA is definitely the way to go if your matrix is going to grow in size.
However, if you insist on doing it in Excel with available formulas, AND the matrix remains relatively small, here is one way to do it:
You will need column H and I for "Mask" information. You can hide these columns in the finished worksheet.
A B C D E F G H I
1 USER1 USER2 MICHAEL SANDRA JAMES CAITLIN MASK1 MASK2
2 Product A Michael James Michael James 1010 10
3 Product B Sandra Caitlin Sandra Caitlin 101 1
4 Product C James Caitlin James Caitlin 11 1
5 Product D Michael Sandra Michael Sandra 1100 100
In cell H2, You can create the first Mask:
=IF(D2 <> "",1000,0)+IF(E2 <> "",100,0)+IF(F2 <> "",10,0)+IF(G2 <> "",1,0)
This is a positional Mask which puts a 1 in each numeral column where data exists.
In cell B2 for USER1, you can put the nested IF formula:
=IF(H2>=1000,D2,IF(H2>=100,E2,IF(H2>=10,F2,IF(H2>=1,G2,""))))
This uses the Mask to find the first occurrence of data and place it in the USER1 column.
Finding the second user is a little more tricky. But all we have to do is create a second Mask in column I. In cell I2 you can use this formula:
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
Let me break that formula down for you. We want to convert the first Mask in H2 to text so that we can trim off the first character (which corresponds to USER1) because, we don't need USER1 data anymore. Using TEXT(H2,0)
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
^^^^^^^^^^
But to do a right trim that removes the right most character, we need the length of the same text string minus 1. LEN(TEXT(H2,0))-1
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
^^^^^^^^^^^^^^^^^
Using those in a RIGHT function gives us our new Mask which removes USER1.
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
But we can't do math on a text string, so we have to convert it back to a number using the Value function.
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
That's our new Second Mask that we can use to find USER2. However, we need to test for error values as well. If all the cells are blank, it will have an error since you can't have a length of 0 in a Right function. So we need to test if the length of the text is greater than 1. LEN(TEXT(H2,0))>1
=IF(LEN(TEXT(H2,0))>1,VALUE(RIGHT(TEXT(H2,0),LEN(TEXT(H2,0))-1)),0)
^^^^^^^^^^^^^^^^^
Encase that all in an If statement and you now have your new Mask for USER2.
Now it's a simple nested IF formula for cell C2 by using the Mask in cell I2:
=IF(I2>=100,E2,IF(I2>=10,F2,IF(I2>=1,G2,"")))
We were able the toss out the test for 1000 since we know that would have been caught for USER1.
Now just copy the cells B2, C2, H2, and I2 down three more rows and all of your data will appear.
You can hide columns H and I if you'd like.
So, all in all, it's not that difficult (if your matrix remains small). There are only 4 formulas needed to make this work. And they are only of moderate complexity.
But once again, if your matrix is eventually going to grow in size, it will definitely be better to write this all in VBA.
Hope this helped. :)
It is possible without a formula though might be a bit tedious without VBA or similar (though not tagged that way):
Insert enough extra columns between C and D to be able to copy all of D:G into C.
Copy what was D:G into C and move what was the content of D:G out of the way (to other rows or other sheet/book).
Select the populated rows in C:F (or equivalent), HOME > Editing > Find & Select, Go To Special..., Blanks (only) OK.
Right click one of the selected cells and Delete..., Shift Cells left, OK.
Copy what was D:G back to E2.
The chosen two will be those furthest to the left.

Sumproduct matching values in excel

I have two excel tables:
A B C D E
1 John 10 Mark 2
2 Tommy 20 Tommy 3
3 Jane 15 John 4
4 Kate 2
5 Jane 1
Is there a function to sumproduct values in colum B with those values in column E which match by name, i.e. 10*4 + 20*3 + 15*1 ?
You can use sumif for this and just sum up the results when you are done:
=B1 * sumif(D:D, A1, E:E)
Copy that down your sheet, and then add up the totals.
If you don't want a ton of formulas hanging out on your sheet, you could convert this to a CSE/Array formula:
=SUM($B$1:$B$3*SUMIF(D:D, $A$1:$A$3,E:E ))
Just enter that in and hit Ctrl+Shift+Enter to enter it. It will get curly braces around it, which means it's an Array formula.
Since you asked about sumproduct, we could use SUMPRODUCT
=SUMPRODUCT(($A$1:$A$5=A1)*$B$1:$B$5)*SUMPRODUCT(($D$1:$D$5=A1)*$E$1:$E$5)
Now that is assuming there are no repeats (all names are unique). In the event that names are not unique you will have those numbers added together then multiplied.
After you apply that to a column and copied down appropriately, lets say F1 to F3, in F5 you could get your final answer using:
=SUM(F1:F3)

SUMIF for first 5 cells meeting criteria

Simple Excel Table such as
A B
1 John 5
2 John 7
3 John 9
4 Jill 25
5 John 21
6 John 22
7 Jill 50
8 John 100
9 John 2000
10 Jack 4
Using SUMIF, we can return the total assigned to John.
=SUMIF(A:A,"John",B:B)
Is there a way to return only the first 5 values that match the criteria? Or is there a way to return the 5 smallest values for John? Either would work.
Oh well. I'll go ahead and presume that you have Excel 2010 or later.
With e.g. "John" in D1, enter this formula in E1:
=SUMIFS($B$1:$B$10,$A$1:$A$10,D1,$B$1:$B$10,"<="&AGGREGATE(15,6,$B$1:$B$10/($A$1:$A$10=D1),5))
Copy down to give similar results for names in D2, D3, etc.
Regards
Formula:
=IF(COUNTIF($A$1:A1,A1)<=5,SUMIF($A$1:A1,A1,$B$1:B1),"")
The last value shown for each person will be the sum of the first (up to)5 values for that person. Just copy and paste values then sort.
Your sample data would show the same result for either the first 5 or lowest 5 as John's numbers are in ascending order. If that is not always the case or if you need to provide compatibility to versions of Excel earlier than 2010 I would offer the following. Note that in my sample image, I've resorted the numerical values in descending order to illustrate the difference.
For John's first 5 values (E2 in the sample image):
=SUM(INDEX(($B$2:$B$11)*($A$2:$A$11=D2)*(ROW($1:$10)<=SMALL(INDEX(ROW($1:$10)+($A$2:$A$11<>D2)*1E+99,,), 5)),,))
For John's lowest 5 values (F2 in the sample image):
=SUMPRODUCT(SMALL(INDEX(($B$2:$B$11)+($A$2:$A$11<>D2)*1E+99,,),ROW($1:$5)))
These are standard formulas. Any array processing is supplied by INDEX and/or SUMPRODUCT. Ctrl+Shift+Enter is not required. Some form of error control may be necessary when there are less than 5 matching values; a simple IF(COUNTIF(), <formula>) would suffice. When transcribing these type of formulas it is important to note that ROW(1:10) is the position within B2:B11 or A2:A11, not the actual row on the worksheet.
 
                  
In C1 enter:
=IF(A1="John",1,0)
In C2 enter:
=IF(A2="John",1+MAX($C$1:C1),0)
and copy down. Then use:
=SUMPRODUCT((A:A="John")*(B:B)*(C:C<6))
.
Assuming John in D1 you can get the sum of the 5 smallest values for John with this array formula
=SUM(SMALL(IF(A$1:A$100=D1,B$1:B$100),{1,2,3,4,5}))
confirm with CTRL+SHIFT+ENTER and copy down for to work for all names in the list

Excel Find Nth Instance of Multiple Criteria

I have 3 columns of data. Col A contains Names, Col B contains a client ID, Col C contains a date.
I'm trying to figure out how to write a formula that will find the top 2 and top 3 instances of a specific Name in Col A and client ID in Col B and return the value in Col C.
Trying to avoid using VBA, but not sure if this is doable.
So for example data looks like this and I would want to return that Sam dealt with Client ABC the 2nd time around on 12/16.
Sam ABC 12/3
Adam XYZ 12/5
John DEF 12/9
Sam ABC 12/16
Adam HIJ 12/18
Assuming
your headers are in A1:C1
your data starts from A3 (yes, not A2)
You enter the name in G2 & Client ID in G3 & you want the list of
dates starting from G5
Enter these formula/values:
A2: =G2
B2: =G3
C2: =0
G5:
=IFERROR(INDEX(($A$2:$A$500=$G$2)*($B$2:$B$500=$G$3)*($C$2:C$500),MATCH(0,COUNTIF($G$4:G4,($A$2:$A$500=$G$2)*($B$2:$B$500=$G$3)*($C$2:C$500)),0)),"End")
(Formula in G5 is an array formula; confirm this with Ctrl+Shift+Enter)
Drag the formula in G5 down until you see 'End'
Value in cell G5 will always be 0 or '1/0' based on your formatting.
The list of dates corresponding to the name & client ID combination will start from G6.
Let me see if I understood your need. Correct me if I'm wrong.
You want to be able to inform a Name and a Client ID and have Excel tell you the last 3 occurrences of that combination?
By "top 2 and top 3 instances of a specific name" I'm assuming you mean the top 2 and 3 dates found for that specific name and ID.
If so, try this:
Supposing you have your example data table starting at Cell A1 and ending at Cell C6 (including column headers) and that you'll enter the name in F1 and Client ID on F2
A B C
1 Name Client ID Date
2 Sam ABC 12/3
3 Adam XYZ 12/5
4 John DEF 12/9
5 Sam ABC 12/16
6 Adam HIJ 12/18
Type this formula where you want to return the date of the last occurrence:
=IFERROR(LARGE(IF($A$2:$A$6=$F$1,IF($B$2:$B$6=$F$2,$C$2:$C$6)),1),"-")
This should be entered as an Array Formula, so don't forget to press CTRL + SHIFT + ENTER or it'll not work.
To bring the 2nd last occurrence on another cell, just copy and paste the formula and change the number 1 to 2 (as indicated below):
=IFERROR(LARGE(IF($A$2:$A$6=$F$1,IF($B$2:$B$6=$F$2,$C$2:$C$6)),2),"-")
If you typed 'Sam' on F1 and 'ABC' on F2, this formula would return '12/16' as the last occurrence, '12/3' as the 2nd last occurrence and a dash (-) as the 3rd last occurrence, since there isn't one.
Of course, you'll have to adjust the ranges and other cell references accordingly in your real data set.
Hope this helps.

Resources