I am looking for a formula (or code) that finds a value in a column, then find the value in that row between dates, when multiple dates return the max, then returning the value to the left. I cannot use a helper column. I tried a couple of nested index/match formula's but without success...
For the below example:
Parameter 1: Find Fork in Column A
Parameter 2: In that row (4), find date between: 1 Jan 18 AND 5 Jan 18
Parameter 3: when multiple dates are found in that date range, return the max
Parameter 4: Return the value from column left of that date
Result: black in Column D.
A B C D E F G
1 ID Colour 1Date 1 Colour 2Date 2 Colour 3 Date 3
2 Plate Green 1-Jan-18 Red 23-Jan-18 L blue 14-Feb-18
3 Bowl Blue 6-Jan-18 Brown 28-Jan-18 Yellow/Green 19-Feb-18
4 Fork Yellow 2-Jan-18 Black 4-Jan-18 Turquoise 24-Feb-18
5 Knive Purple 16-Jan-18 White 7-Feb-18 Maroon 1-Mar-18
6 Spoon Pink 21-Jan-18 Orange 12-Feb-18 L pink 6-Mar-18
I hope it is possible! Many many thanks in advance.
Try this
where
I10 = ID to search for
I11 = Min Date (1 Jan 2018)
I12 = Max Date (5 jan 2018)
J10 = =MATCH($I$10,$A$1:$A$6,0) get the row number if the ID
=INDEX(INDEX($A$1:$G$6,$J$10,),
MATCH(
MAXIFS(INDEX($A$1:$G$6,$J$10,),
INDEX($A$1:$G$6,$J$10,),">="&$I$11,
INDEX($A$1:$G$6,$J$10,),"<="&$I$12
),
INDEX($A$1:$G$6,$J$10,),0
) - 1
)
were
INDEX($A$1:$G$6,$J$10,)get the data row for the ID (repeated several time in formula)
MAXIFS(...) get the maximum date meeting the >= and <= criteria
MATCH(MAXIF(...), [ID data row],0) get the column number for the date returned by the MAXIF
INDEX( [ID data row], MATCH(MAXIF(...), [ID data row],0) - 1)returns the color
Alternative Formula without MAXIFS
=INDEX(INDEX($A$1:$G$6,$J$10,),
MATCH(
MAX(IFERROR(({0,0,1,0,1,0,1})*(INDEX($A$1:$G$6,$J$10,)>=$I$11)*(INDEX($A$1:$G$6,$J$10,)<=$I$12)*(INDEX($A$1:$G$6,$J$10,)),0)),
INDEX($A$1:$G$6,$J$10,),0
) - 1
)
Enter as an Array Formula (complete with CtrlShiftEnter rather than just Enter)
I require your assistance on the following:
Lets say we got 3 different groups: (A,B,C)
And we have a few value ranges within each group:
(Eg. A has 0 - 100, 101 - 200 while B has 0 - 200, 201 - 400 and C has 0 - 300, 301 - 600.)
At the end, for each group that falls under whatever range they have, they will be assigned a final number.
(Eg.
[A,95] = 0.5 / [A,101] = 1.0
[B,95] = 1.5 / [B,205] = 3.0
[C,95] = 4.5 / [C,308] = 6.0)
Currently i have my index match formula as follows:
"=INDEX(finalnumber!F2:F29,MATCH(C11&C25,Group!A2:A29&valuerange!D2:D29,0))"
I keep getting a #N/A response.
I have also created an array table as follows:
enter image description here
Group Range Final Number
A 0 - 100 0.50
A 101 - 200 1.00
B 0 - 200 1.50
B 201 - 400 3.00
C 0 - 300 4.50
C 301 - 600 6.00
Pls help! Many thanks in advance!
You can use the following (you will need to tailor to your layout). I have assumed A and 95, for example, are in separate cells as you concatenate cells in your formula to do your lookup.
=IF(AND(ISERROR(INDEX(OFFSET(INDEX(C:C,H2),,,I2-H2+1,1),MATCH(VLOOKUP(G2,LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,TRUE),LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,0))),INDEX(A:A,COUNTA(A:A)+1)=F2,G2>=1*LEFT(INDEX(B:B,COUNTA(A:A)+1),FIND("-",INDEX(B:B,COUNTA(A:A)+1))-1),G2<=1*RIGHT(INDEX(B:B,COUNTA(A:A)+1),LEN(INDEX(B:B,COUNTA(A:A)+1)) - FIND("-",INDEX(B:B,COUNTA(A:A)+1)))),INDEX(C:C,COUNTA(A:A)+1),INDEX(OFFSET(INDEX(C:C,H2),,,I2-H2+1,1),MATCH(VLOOKUP(G2,LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,TRUE),LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,0)))
This is entered as an array formula with Ctrl+ Shift+ Enter
Formulas in helper cells (to keep overall formula more legible):
H2 is =MATCH(F2,A:A,0) ' finds the first match for the letter e.g. A
I2 is =MAX(IF(A:A=F2,ROW(A:A)-ROW(INDEX(A:A,1,1))+1)) ' finds the last match for the letter e.g. A. This is entered with Ctrl+ Shift+ Enter i.e. an array formula.
Data layout
Example run:
Notes:
You might want to wrap the whole thing in an IFERROR( formula, "") to hide any not found error messages.
I'm unclear why you require four separate worksheets for this operation. For simplicity in demonstrating, I've put your lookup table on the same worksheet as the values to lookup.
=SUMPRODUCT(I$2:I$7, (G$2:G$7=LEFT(A2))*(--REPLACE(H$2:H$7, FIND(" - ", H$2:H$7), 9, TEXT(,))<=--MID(A2, 3, 9))*
(--REPLACE(H$2:H$7, 1, FIND(" - ", H$2:H$7)+1, TEXT(,))>=--MID(A2, 3, 9)))
I have an excel file that has been uploaded here
http://www58.zippyshare.com/v/99974349/file.html
The formula works great except for a column with descending values.
=INDEX(
INDIRECT("'"&LOOKUP(B5,TblA)&"'!A6:A36"),
LOOKUP(9.99999999999999E+307,
SEARCH("-"&C8&"-","-"&INDIRECT("'"&LOOKUP(B5,TblA)&"'!C6:C36")&"-"),
ROW(C6:C36)-ROW(C6)+1))
Let me explain the excel file.
I have one main sheet 'Report' and 4 other sheets correspond to 4 age groups. - 4.2.0 to 4.7.30, 4.8.0 to 5.1.30, 5.2.0 to 5.7.30 and 5.8.0 to 6.1.30. Depending on the Age (B5) in the sheet 'Report', I select one of the 4 sheet to pick values from. I pick the correct sheet using a Table Name TblA which contains all sheet names and is defined from A24 to B27 in the sheet 'Report'.
In the sample sheet that is uploaded, B5 contains the value 5.7 which means we have to select the sheet 5.2.0 to 5.7.30.
Now from the sheet 5.2.0 to 5.7.30, I have to seek the respective Standard Score (1st column) for every Raw Score entered in 'Report'.
Here are the steps:
A. Enter Raw scores in sheet 'Report' C7 to C15
B. Search Respective sheet depending on age (B5 cell), in our case 5.2.0 to 5.7.30 since age is 5.7
C. Populate Standard score from Raw scores by picking the corresponding column in the 4 sheets. For example, if Raw Score of Col1 is 25 (C7), then pick the Standard score of Col1 from 5.2.0 to 5.7.30 and enter in D7 and so on.
D. This way all standard scores are filled in D7 to D15.
The formula works great except for D13 in sheet 'Report' since if you observe ColD in 5.2.0 to 5.7.30, it is in descending order.
How do I change the formula to accomodate this unique column?
Well, it's not really the order that's causing the error, it's because you don't have any results! The formula you use is trying to find -159- which it cannot find at all in the age sheet. You really need something to look into ranges, so that if you have 159, it will return a positive result when you try to match against 139-160.
I have made a formula building it from smaller ones, but when assembled, the repeating units make it daunting... Also, it's an array formula, so you need to use Ctrl+Shift+Enter for it to work as intended. You can still drag the formula down.
=INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),
IFERROR(
MATCH(
C7,
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)*1,
0
),
MATCH(
1,
IF(
1*LEFT(
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
),
FIND(
"-",
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)
)-1
)<=C7,
1,
0
)*
IF(
1*MID(
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
),
FIND(
"-",
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)
)+1,
100
)>=C7,
1,
0
)
,0
)
)
)
The single line version...
=INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),IFERROR(MATCH(C7,INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0))*1,0),MATCH(1,IF(1*LEFT(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))-1)<=C7,1,0)*IF(1*MID(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))+1,100)>=C7,1,0),0)))
You can notice that there are some repeating blocks, namely:
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36")
For the sheet name;
INDEX(
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)
Which is a larger block to make the formula a bit more flexible (it automatically picks the correct column e.g. if you change B8 Exclusion to Col1, the formula will automatically adjust itself)
If I call the first Sheet and the second Column, it becomes much shorter and perhaps easier to understand:
=INDEX(
Sheet,
IFERROR(
MATCH(
C7,
Column*1,
0
),
MATCH(
1,
IF(
1*LEFT(
Column,
FIND(
"-",
Column
)-1
)<=C7,
1,
0
)*
IF(
1*MID(
Column,
FIND(
"-",
Column
)+1,
100
)>=C7,
1,
0
)
,0
)
)
)
Or
=INDEX(Sheet,IFERROR(MATCH(C7,Column*1,0),MATCH(1,IF(1*LEFT(Column,FIND("-",Column)-1)<=C7,1,0)*IF(1*MID(Column,FIND("-",Column)+1,100)>=C7,1,0),0)))
Disclaimer: I'm not sure if there are any way to make this even shorter, but I guess that as long as it's working right now ^^
You can download your updated sheet here.
Explanation:
As I mentioned before, the formula is based off several smaller ones and quite a few repeats of those.
INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36")
As you already know (it's a variation of a part of your own formula), this gives the area containing all the different ages. Using it and the below, we get this:
INDEX(
INDIRECT('"&LOOKUP($B$5,TblA)&"'!B6:J36"),
0,
MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)
Into:
INDEX(
'Sheet'!B6:J36,
0,
MATCH(B7,'Sheet'!B5:J5,0)
)
Index will thus look into the range 'Sheet'!B6:J36, 0 indicates it will take any column(s) and MATCH(B7,'Sheet'!B5:J5,0) returns the nth column by taking the value of B7 (in the case of your spreadsheet, Col1) and looking it into 'Sheet'!B5:J5 which gives 1. The above will thus return the range 'Sheet'!B6:B36. Let's put it in the formula:
=INDEX(
'Sheet'!A6:A36,
IFERROR(
MATCH(
C7,
'Sheet'!B6:B36*1,
0
),
MATCH(
1,
IF(
1*LEFT(
'Sheet'!B6:B36,
FIND(
"-",
'Sheet'!B6:B36
)-1
)<=C7,
1,
0
)*
IF(
1*MID(
'Sheet'!B6:B36,
FIND(
"-",
'Sheet'!B6:B36
)+1,
100
)>=C7,
1,
0
)
,0
)
)
)
This formula is itself a giant INDEX formula, with range 'Sheet'!A6:A36 and row number as the big IFERROR group. The first part of the IFERROR() gets evaluated first:
MATCH(
C7,
'Sheet'!B6:B36*1,
0
)
This should be easy enough to understand. It looks for the raw score (from C7) into the range we obtained earlier, times 1 to convert everything to number (you can't look up numbers and text and expect a match). So that if there's an exact match of a number, it will return the row number of the found raw score and feed it to the INDEX(). For example, if the first row is returned, we get:
=INDEX('Sheet'!A6:A36,1)
Which is 'Sheet'!B6. If however there's no match (i.e. the raw score cannot be found), MATCH will return an error. And that's when the second part of the IFERROR comes into play:
MATCH(
1,
IF(
1*LEFT(
'Sheet'!B6:B36,
FIND(
"-",
'Sheet'!B6:B36
)-1
)<=C7,
1,
0
)*
IF(
1*MID(
'Sheet'!B6:B36,
FIND(
"-",
'Sheet'!B6:B36
)+1,
100
)>=C7,
1,
0
)
,0
)
This MATCH tries to find 1 within what seems to be two IFs; the first one being:
IF( 1*LEFT('Sheet'!B6:B36,FIND("-",'Sheet'!B6:B36)-1)<=C7 , 1 , 0)
FIND("-",'Sheet'!B6:B36)-1 gets the position of the last character before the - in the column 'Sheet'!B6:B36.
With those values, this FIND would return:
12-13 -> 2
145-155 -> 3
1567-1865 -> 4
The IF thus becomes:
IF( 1*LEFT('Sheet'!B6:B36,{2,3,4})<=C7 , 1 , 0)
Notice the braces here; they indicate an array and that's why this is an array formula. LEFT then extracts all the characters before the - (remember your other question, I answered with a technique very similar to this):
12-13 -> 2 -> 12
145-155 -> 3 -> 145
1567-1865 -> 4 -> 1567
Which is...
IF( 1*{12,145,1567}<=C7 , 1 , 0)
Again, 1* converts those to actual numbers because LEFT be default returns text characters. It's important here to do this because we're going to use the comparator <=, so that if the value to the left of C7 (the raw score), then the IF should return 1, else, it should return 0. Let's say that the raw score was 154. The results would be:
IF( {12,145,1567}<=154 , 1 , 0)
IF( {TRUE,TRUE,FALSE} , 1 , 0)
{1,1,0}
I just realised that the formula can be made a little shorter xD Anyway, we'll see that later. The next IF behaves in a similar fashion, but checks for the value at the right of the -:
IF( 1*MID('Sheet'!B6:B36,FIND("-",'Sheet'!B6:B36)+1,100)>=C7 , 1 , 0)
With...
FIND MID('Sheet'!B6:B36, X, 100)
12-13 -> 4 -> 13
145-155 -> 5 -> 155
1567-1865 -> 6 -> 1865
You can notice that this formula will stop working if you have something above 100 character long here. Anyway, the IF thus becomes:
IF( {13,155,1865}>=154 , 1 , 0)
IF( {FALSE,TRUE,TRUE} , 1 , 0)
{0,1,1}
Now that we have these, the MATCH from before becomes:
MATCH( 1 , {1,1,0}*{0,1,1} , 0)
Some simple math makes this into:
MATCH( 1 , {0,1,0} , 0)
And what is the position of the 1 in there? That's right, position 2!
Our original formula this becomes:
=INDEX( 'Sheet'!A6:A36 , IFERROR( #Error! , 2 ) )
So that if nothing was found at first, it will return an error (#N/A in this case) and instead return 2. =INDEX( 'Sheet'!A6:A36 , 2 ) gives 'Sheet'!A7.
And the slightly shorter version is:
=INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),IFERROR(MATCH(C7,INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0))*1,0),MATCH(1,(1*LEFT(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))-1)<=C7)*(1*MID(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))+1,100)>=C7),0)))
I actually removed the inner IFs, because (a>b)*(c>b) already returns 0s and 1s since TRUE multiplied by TRUE gives 1 in excel.
In Excel 2007 the formulae are returning a lot of circular reference warnings, so it may be worth adding a tag for your Excel version. Mine is Excel 2007 but with it the results you want seem achievable as below:
To shorten the formulae and reduce computation I have added in Report C5 "Table" and in D5 =VLOOKUP(B5,TblA,2,1).
I have also inserted a column immediately to the right of ColumnH ("ColD") in 5.2.0 to 5.7.30 and applied Text To Columns on Column H, with - as the delimiter.
I then applied to Report E7 and copied down to E15:
=INDEX(INDIRECT("'"&D$5&"'!A6:A36"),MATCH(C7,INDIRECT("'"&D$5&"'!"&CHAR(ROW()+59)&"6:"&CHAR(ROW()+59)&"36"),0))
and adjusted the 59s to 60s in the last three rows. Such adjustment would not be necessary if ColumnI were moved far enough to the right.
In E13 I changed the match from exact to next higher (final 0 to -1).
For Figures I cheated and changed K23 in 5.2.0 to 5.7.30 to 22 from 21-22, but such banding could, for other columns, be treated in much the same way as I did for ColD.