I have a big table like this (imagine round-robin result table) where both column and row are team names that First row will be exactly like First Column
Because the table is very big so it is hard to look up for value if I have to look for multiple values
So I'd like to create a table like this
Let's say I want to look up the first "?" in this small table. What formula can I use to look up A2(column)xA3(row) from the big table?
I hope I made it clear enough.
Any pointers or resource I could read online would be greatly appreciated.
I would break this down in two parts.
Get a lookup working for row values using VLOOKUP(). Here is an example: VLOOKUP($A3, BigTable!$A$2:$CW$101, 2, 0):
$A3: Lookup value to find. Dollar sign locks just the column so that when you drag the formula across A doesn't change
BigTable!$A$2:$CW$101: Range to find the result. Dollar sign completely locks the range so wont change
2: Column to bring back (For the time being it is always going to bring back second column)
0: Look for an exact match
Get a lookup working for the column values so that when the formula is copied across it automatically updates the column that it is looking for. I used MATCH() to find the position of the column value in BigTable. For example: MATCH(B$1, BigTable!$B$1:$CW$1, 0):
B$1: Column header to lookup up the position of in the BigTable. Dollar sign locks the row so when you move it down it remains as 1
BigTable!$B$1:$CW$1: Header column to look through
0: Look for an exact match
Finally put the two pieces of the formula together and check some of the values to make sure that it is working correctly: VLOOKUP($A2, BigTable!$A$2:$CW$101, MATCH(B$1, BigTable!$B$1:$CW$1, 0), 0)
This would then give you one formula to copy across the whole of the SmallTable to lookup up the relevant values in the BigTable.
http://www.contextures.com/xlFunctions03.html
Read example 3, it is exactly like my problem.. Thank #DirkReichel for suggesting Index function, so I could know where even to start.
Related
I have scoured the internet but come up empty.
I am looking for a formula that will be in a single cell (I don't want to have to fill it down the side of the table for instance) that will return the header of the first column that has a value in it, from left to right. If there's a value in the last cell of the first column, for instance, I want that header returned rather than moving to column 2.
I have tried nested xlookups and index/match combinations and just can't find anything that will be in a single cell.
Any help is appreciated!!
EDIT: Yup, let me be more clear. My apologies!
Here is an excerpt of my table. In this instance, I would want the result to be Sep-21 (a reference to the cell is also fine).
I know I can easily drag the formula in A1 down and pull the column header of the first cell in that row with a value. What I want is to reference this on another sheet, so I don't want to have to do that. I want one formula in one cell to pull this information, if possible. If I can't do it that simply, maybe I have to do some other wizardry and hide a row/column or something and fill the formula down that way and then pick the latest date, but I'd like to avoid that if possible. One cell would be much more elegant!
As for what I've tried, all my attempts are pretty messy and incomplete, so I don't know if it would be helpful to paste them here, but essentially I've tried to use an xlookup where the lookup_array is B2:D6, and then the return_array is the header, but that doesn't seem to work. I guess the lookup_array has to be a single column/row? Something like:
xlookup(ISBLANK(FALSE), B2:D6, B1:D1)
It's kind of like an inverse xlookup, lol.
EDIT2: I've done some more messing about and have come SO CLOSE! Now my problem is with structured references in a table and trying to exclude my first two columns.
First, the solution that does work without structured references (assuming the table starts in A1):
=IFERROR(INDEX(B1:D1,SUMPRODUCT(MIN(IF((B2:D6<>0)*(COLUMN(B2:D6)) > 0, ((B2:D6<>0)*(COLUMN(B2:D6)))))-COLUMN(A1))), "error")
But like I said, my structured references are getting in the way now. I want to pull all the data in my dynamic table, except for the first two columns.
I know this is a completely different problem now, my apologies for that.
The solution (assuming the table starts in A1):
=IFERROR(INDEX(B1:D1,SUMPRODUCT(MIN(IF((B2:D6<>0)*(COLUMN(B2:D6)) > 0, ((B2:D6<>0)*(COLUMN(B2:D6)))))-COLUMN(A1))), "error")
If your data is in row 2:
=INDEX(1:1, 1, MATCH("", 2:2,-1))
should work
Looking for something like a typical index match formula that can look to the right and return value to the left, but look at all columns in a range. Take below valid formula for example.
(Excel 2021.)
Finds A1's value in column D, and it returns value from column C.
=INDEX($C$1:$C$10,MATCH(A1,$D$1:$D$10,0))
In my ideal world I can Keep $D$1 and change $D$10 to $F$10 so it searches all columns D/E/F, and still returns C like below. However that does not work in our real world, any other ideas please? Thanks!
=INDEX($C$1:$C$10,MATCH(A1,$D$1:$F$10,0))
Update*
To clarify there are mix of letters and numbers. Also this table will be about 50k rows so hoping as simple as possible.
Also Column C will all be unique for sure, and D-F should be unique values but there is a chance a mistake and a few duplicates might be in.
You need MMUL() with INDEX(). Try below formula if you have Excel-365.
=FILTER(C1:C10,MMULT(--(D1:F10=A1),SEQUENCE(COLUMNS(D1:F1))))
For older version try
=INDEX($C$1:$C$10,LARGE(MMULT(--($D$1:$F$10=A1),TRANSPOSE({1,1,1}))*ROW($C$1:$C$10),1))
Since your INDEX/MATCH take from the same rows, you can first simplify your original search with
=XLOOKUP(A1,$D$1:$D$10,$C$1:$C$10)
XLOOKUP combines HLOOKUP and VLOOKUP with exact match being the default.
This will work for searching three rows
IFERROR(IFERROR(XLOOKUP(A1,$D$1:$D$10,$C$1:$C$10), XLOOKUP(A1,$E$1:$E$10,$C$1:$C$10)), XLOOKUP(A1,$F$1:$F$10,$C$1:$C$10))
We can name the columns colC, colD, colE, and colF and it becomes
IFERROR(IFERROR(XLOOKUP(A1,colD,colC), XLOOKUP(A1,colE,colC)), XLOOKUP(A1,colF,colC))
As with other lookups, this returns the first value or #N/A error.
This could be made more scalable for higher number of rows if we are allowed to add a column somewhere.
I have very basic user Excel knowledge. I have a spreadsheet where I keep track of reloading data. Each load I enter gets a unique load number that is calculated automatically with a formula, based on the caliber name and an incrementally increasing number. As of now, every load I enter gets a number, even if it's been repeated before. Popular loads that I repeat often are all the same except for the date and numbers of rounds made but currently will have different load numbers. Is there a way to skips these repeated loads and assign it the previous load number or not assign a load number at all, with a formula instead of manually?
I know this is asking for a great deal but I'd greatly appreciate any help! I'm certainly open to suggestions if this isn't even the best way to go about this.
Sample workbook at:
https://www.dropbox.com/s/v5y1ufxjiosmnap/My%20Reloading%20Data%20-%20Sample.xlsx?dl=0
Here's what I've tried so far:
In column Q2, combine all the criteria.
=C17&E17&F17&G17&H17&L17&M17&N17&P17
In column R2 look for duplicates.
=IF(COUNTIF($Q$2:$Q17, $Q17)>1, "Duplicate", "")
D2 is the Load # column.
=IF(R17="Duplicate","",(TEXT(C17,0)&"-"&TEXT(COUNTIF($C$2:C17,C17),"000")))
This will skip the duplicate loads and not give them a load # leaving the cell blank. I'd love to find and match what that load # should be and insert it. Also, when the sequential numbering resumes it acts as if it's counted the duplicate row. For instance D2 might look like:
9mm-001
9mm-002
(Skipped for duplicate and left blank, but would like it to find, match, and insert the duplicate load #)
9mm-004 (I'd like to to be 9mm-003)
You should be able to achieve this with a VLOOKUP formula or a combination of MATCH and INDEX.
VLOOKUP (Vertical Lookup) looks for a match in another cell and returns a value from an offset column. A non match, if you use FALSE as the last parameter, returns a #N/A error.
So, in D20 (for example) you could, using column Q as your determinant, use the following, assuming you had a copy of D in column R:
=IFERROR(VLOOKUP(Q20,Q$1:R19,2,FALSE),[value for newly found loadno])
What this formula does is calculates a VLOOKUP - if that doesn't find a record, calculate a new value. The VLOOKUP will look at the concatenated key in the current row Q column, search through all previous columns (note it is anchored at row 1, but not anchored for the bottom of the range so you can copy the formula), it uses the column 2 (Q is column 1, so R is column 2) for the result, and demands an exact match (FALSE). If it doesn't find one, return NA and let the second half of the IFERROR take over.
See how you go with this.
The MATCH INDEX may work better because you won't need the additional R column due to VLOOKUP only being able to look to the right of the key.
Here is an INDEX and MATCH solution - slightly harder to understand, but a more flexible solution.
=IFERROR(INDEX(D$1:D19,MATCH(Q20,Q$1:Q19,0)),[value for newly found load number])
I prefer this.
The outer function says return the nth value in the list. The inner MATCH function says find this value (Q20) in this list (Q1:Q19). The 0 as the third parameter of the MATCH function says the match has to be exact.
I have two columns with team names and two columns with corresponding stats. I need to go through the 2 columns and find the stats that match the team name, and they need to be in order. VLOOKUP, MATCH, and SEARCH don't seem to work with multiple columns. Does anyone know how this can be done?
Assuming in your picture, the "Home" title is in cell B2 then the following array formula can be put in the cells H3:L7 (array formulas need to be entered with Ctrl+Shift+Enter)
=IFERROR(OFFSET($D$1,-1+SMALL(IF(($B$3:$B$7=H$2)+($C$3:$C$7=H$2),ROW($B$3:$B$7),"X"),ROW()-ROW($2:$2)),--NOT((INDEX($B:$B,SMALL(IF(($B$3:$B$7=H$2)+($C$3:$C$7=H$2),ROW($B$3:$B$7),"X"),ROW()-ROW($2:$2)))=H$2))),"")
Let me break it down...
the logic is: OFFSET(top_of_results,row_number_that_has_Nth_team_score,0_or_1_for_home_or_away)
this is wrapped in an IFERROR in for where there isn't e.g. a 5th score for team A
using the array part IF(($B$3:$B$7=H$2)+($C$3:$C$7=H$2),ROW($B$3:$B$7),"X" we get an array of that has the ROW number if either (done using +) B or C have a value matching our team header (H$2) or an X otherwise
using SMALL(...,ROW()-ROW($2:$2)) we get the Nth smallest row, based on 1st being in row 3, 2nd in row 4 etc.
to get whether it is home or away, we check column B on our row to see if it matches --NOT((INDEX($B:$B,row_number_that_has_Nth_team_score-O)=H$2)) this gives 0 for home, 1 for away and this is used to offset the column
Hopefully it makes sense. Array formulas are very powerful, if a little confusing :-) I recommend CPearson's intro for more information.
Good luck!
TOP Table is Input, and bottom table is preview for required output.
For Each ID I need to find earliest datetime. I also need other information from other columns (please see image below).
My current solution is:
In Cell E2 =A2
Cell E3 drag down =IF(E2<>A3,IF(E1=A3,"",A3),"")
In Cell F2 drag down =IF(E2<>"",MIN(IF($A$2:$A$14=E2,$C$2:$C$14)),"") Ctrl+Shift+Enter
One more option without any intermediate calculations:
Select the whole range starting E2 and to the last row where IDs are located - for the sample given it's row 14, so select range E2:E14: =IFERROR(INDEX($A$2:$A$14,SMALL(IF(MATCH($A$2:$A$14,$A$2:$A$14,0)=ROW(INDIRECT("1:"&ROWS($A$2:$A$14))),MATCH($A$2:$A$14,$A$2:$A$14,0),""),ROW(INDIRECT("1:"&ROWS($A$2:$A$14))))),"") and press CTRL+SHIFT+ENTER instead of usual ENTER - this will define a Multicell ARRAY formula and will result in curly {} brackets around it (but do NOT type them manually!).
F2 (ID2): =IF(E2="","",SUMPRODUCT(--(E2=$A$2:$A$14),--(G2=$C$2:$C$14),$B$2:$B$14)) - normal formula.
G2 (Min Date): =IF(E2="","",MIN(IF(E2=$A$2:$A$14,$C$2:$C$14,2^100))) and press CTRL+SHIFT+ENTER instead of usual ENTER - this will define an ARRAY formula and will result in curly {} brackets around it (but do NOT type them manually!).
H2 (InCh): =IF(E2="","",INDEX($D$2:$D$14,SUMPRODUCT(--(E2=$A$2:$A$14),--(F2=$B$2:$B$14),--(G2=$C$2:$C$14),ROW(INDIRECT("1:"&ROWS($D$2:$D$14)))))) - normal formula.
Remarks:
To make the solution more compact and easy to read, define named range for ID column, and then reference other data columns using OFFSET.
ID2 values may not be unique - as they are on the sample for IDs 1...3.
Resulting set for Min Date should be formatted the same way as source Date row.
The key formula of the solution - is multicell monster which returns unique IDs without empty rows - as OP requested)
Sample file: https://www.dropbox.com/s/d2098updfh8djnf/MinDateIDs.xlsx
This is quite a challenge... I think I have found an approach that works. For the sake of clarity, I used a few helper columns. Also, I did not use any named ranges but stuck with the column-row indications. You might want to change that.
It looks like this:
and zooming in to the relevant columns:
Column F contains an array formula to filter out duplicates. An approach is explained here. The formula I used in F2 is
=INDEX($A$2:$A$14, MATCH(MIN(IF(COUNTIF($F$1:F1,$A$2:$A$14)=0, 1, MAX((COUNTIF($A$2:$A$14, "<"&$A$2:$A$14)+1)*2))*(COUNTIF($A$2:$A$14, "<"&$A$2:$A$14)+1)), COUNTIF($A$2:$A$14, "<"&$A$2:$A$14)+1, 0))
Use Ctrl-Shift-Enter to confirm as array formula. Drag this down or copy into column F. Then columns G and H contain the starting and ending indices of the duplicate ID values. This answer helped, please upvote it :-). The two formulas used are:
=MATCH(2,1/FREQUENCY($F2,$A$2:$A$14))
in G2, and
=FREQUENCY($A$2:$A$14,$F2)
in H2. Again, drag them down to get the full column filled. Next, column I is for clarification only -- and for sanity checking. It contains the desired minimum date from each sub-array. Column J substitutes that formula into a MATCH to find the actual index of the desired date.
=MIN(OFFSET($C$2:$C$14,$G2-1,0,1+$H2-$G2,1))
in I2 and
=$G2-1+MATCH(2,1/FREQUENCY(MIN(OFFSET($C$2:$C$14,$G2-1,0,1+$H2-$G2,1)), OFFSET($C$2:$C$14,$G2-1,0,1+$H2-$G2,1))
in J2. Finally, columns L, M and N index into the original set of data via
=INDEX(B$2:B$14,$J2)
in L2, which you can drag horizontally and then vertically.
When you are done, you can hide the helper columns, or fold everything into big formulas. Good luck with that... There might be an easier way to achieve this, but I did not find it.
If you want the value from column D in G then assuming that column C values are unique you could just use a VLOOKUP, i.e. in G2 copied down
=VLOOKUP(F2,C$2:D$14,2,0)
Per your picture, they're all in the same sheet. Just sort by ID, then Date (ascending). As you work your way down the ID column, each time the ID changes, you know you've found the row with the minimum Date for that specific ID. Create an extra column to signify where ID changes occur, and filter for those rows (hide the column if you so desire).
And... voila.
Know this link is old, but there is a much shorter and easier way!
How about using a pivot table using the Minimum as field setting and then do a =GETPIVOTDATA() to get the information back!
Seems a lot simpler as these formulas!
Actually, I just realized I've been overthinking this...Excel keeps the top item and removes all that follow when removing duplicates.
So if you are going to create an extra working table anyway, why not just copy the range/columns you want to keep, then use the basic sort.
Sort first by ID, then by the column you want as the second filter. Be sure the sorts are in the order you want (e.g. newest to oldest, oldest to newest, A to Z, Largest to smallest, etc).
Once the data is sorted, remove duplicates based on ID. You are left with all of your columns of data, filtered by newest/oldest/largest/smallest per individual.
This worked for my table with 30,000+ records, filtered down to 1500 unique individuals with most recent (plus associated amount), and with a second filter, the largest (plus associated date) for each person.