Using MATCH() function with an unsorted list - excel

I'm having an issue with a spreadsheet formula that uses the MATCH() function.
=IFERROR(IF(LENB(Y2461)<> 0, "Complete", IF(LENB(Q2461)<> 0, IF(Q2461-$Y$1<MATCH($Y$1,R2461:X2461),"ON HOLD"), INDEX($R$4:$X$5,1,MATCH($Y$1,R2461:X2461)))),"ON HOLD")
This is the formula in the cell with the specific problem. I'm using match to look through a horizontal range of data and determine which column contains the most recent change, with exceptions for when the "Complete" column has a date, and the "ON HOLD" column has a date. Cell Y1 contains =TODAY(), so it checks each cell against today's date. The cells are formatted into dates, and are entered as dates from left to right. However, the entries can start again from an earlier column and leave the dates out of order.
The issue is, on only a few occurrences at a time, MATCH() will return a column that isn't the most recent. As far as I've been led to believe, and how it works for the other instances of this formula, is that it reads the array from right to left and stops at the first "highest" date.
The error is occurring on one row specifically, while the expected result works multiple times elsewhere on the sheet.
Am I using MATCH() wrong by assuming that it will read in a certain direction every time? Is there a different error in the code? Or is there a different way to get the result I've programmed it for?

MATCH with no third argument as you are using it is the same as MATCH with 1 or TRUE as third argument, which means that you can only guarantee that it will work OK if the range used - R2461:X2461 - is always in ascending order....but you say that isn't the case so I don't think you can guarantee the formula will work
Try using this version instead [revised as per comments]
=IFERROR(IF(LENB(Y2461)<> 0, "Complete", IF(LENB(Q2461)<> 0, IF(Q2461-$Y$1< MATCH(MAX(IF(R2461:X2461<=$Y$1,R2461:X2461)),R2461:X2461,0),"ON HOLD"), INDEX($R$4:$X$5,1,MATCH(MAX(IF(R2461:X2461<=$Y$1,R2461:X2461)),R2461:X2461,0)))),"ON HOLD")
confirmed with CTRL+SHIFT+ENTER
The logic of the alterations is that this revised MATCH part
=MATCH(MAX(IF(R2461:X2461<=$Y$1,R2461:X2461)),R2461:X2461,0)
will do the same as this part
=MATCH($Y$1,R2461:X2461)
whether R2461:X2461 is in ascending order or not - it finds the largest values which is <= to Y1 and gives you the position of the first instance.
Revised
If you want the rightmost date where the largest date <= today is duplicated then you can use this construction in place of MATCH
=MAX(IF(R2461:X2461<=$Y$1,COLUMN(R2461:X2461)-COLUMN(R2461)+1))
which would make the complete formula like this:
=IFERROR(IF(LENB(Y2461)<> 0, "Complete", IF(LENB(Q2461)<> 0, IF(Q2461-$Y$1< MAX(IF(R2461:X2461<=$Y$1,COLUMN(R2461:X2461)-COLUMN(R2461)+1)),"ON HOLD"), INDEX($R$4:$X$5,1,MAX(IF(R2461:X2461<=$Y$1,COLUMN(R2461:X2461)-COLUMN(R2461)+1))))),"ON HOLD")

Omitting the [match_type] from the syntax MATCH(lookup_value, lookup_array, [match_type]) may lead to unexpected results when the lookup_array is not sorted.
http://office.microsoft.com/en-gb/excel-help/match-function-HP010062414.aspx

Related

Why is =SUMIF(C5:C19,NOT(ISFORMULA(C5:C19))) returning zero?

I have a spreadsheet that I track my hours. Each cell initially is populated with a formula, i.e. =IF(WORKDAY(B24-1,1,holidays2019)=B24,OFFSET(C24,-1,2),0)
and then as the month progresses I enter my actual time.
In the following excerpt all values through 5/10/2019 are entered.
The formula =SUMIF(C5:C19,NOT(ISFORMULA(C5:C19))) shows zero. I do not understand why this does not work.
I appreciate any help! Column B in my spreadsheet corresponds to the dates shown below and Column C to the time entries.
Expected Result: 48.9
=SUMPRODUCT(J6:J20,--NOT(ISFORMULA(J6:J20)))
The key to this solution is the -- in front of the NOT(). A boolean that is processed by a math operator gets converted to 1 or 0. --, +0, -0, *1, /1 would have all worked to do the conversion. So now you wind up with an array of values you may want to sum being multiplied by an array of 1 and 0 to indicate the ones you want. The 1 are manual entry and the 0 are your formulas entries.
Now SUMPRODUCT performs array like calculations. As a result avoid using full column/row references inside it or you will wind up with a lot of excess calculations. Adjust the ranges in the answer to suit your needs.
Here's the MSDN definition of the Criteria in =SUMIF
criteria Required. The criteria in the form of a number, expression,
a cell reference, text, or a function that defines which cells will be
added. For example, criteria can be expressed as 32, ">32", B5, "32",
"apples", or TODAY().
Important: Any text criteria or any criteria that includes logical or
mathematical symbols must be enclosed in double quotation marks (").
If the criteria is numeric, double quotation marks are not required.
So, the reason, why your SUMIF returns 0 is, because none of the cells match the criteria, as they return a number and meanwhile they expect FALSE
Another issue here being, that the ISFORMULA will return TRUE, even when a range contains a single formula while all the rest has none. So basically you need to drag the formula down for each cell individually and sum them up only when a value is TRUE
Starting from cell D1:
=ISFORMULA(B1)
And then you can simply sum them up with the formula you provided.
=SUMIF(D1:D16,TRUE,C1:C16)
Obviously, you can hide the column D to make it more aesthetically pleasing.
Your formula fails because the criteria you're matching against, is TRUE/FALSE. Obviously the values in C5:C19 don't contain any booleans, so the sum is 0.
To solve this, you can add the correct criteria in cell D5 and below: =ISFORMULA(C5)
Then use =SUMIF(D5:D19,FALSE,C5:C19) to sum the values in column C.

Index Match returning incorrect values

I am using Index/Match to align some values in one spreadsheet to rates that I analyzed in another. I am using the same formula across multiple workbooks, and in one workbook the formula seems to work while in the other it doesn't. The change in workbooks is already accounted for, so I don't know why the formula structure doesn't seem to carry over.
For reference, here are the two formulas, respectively:
=INDEX('ubersuggest_Board Games.xlsx'!$E$2:$E$976,MATCH(J17,'ubersuggest_Board Games.xlsx'!$A$2:$A$976,0))
=INDEX('ubersuggest_Board Game magazine.xlsx'!$D$2:$D$510,MATCH(J18,'ubersuggest_Board Game magazine.xlsx'!$A$2:$A$283))
Here the formula seems to work, getting the values I want:
Formula no longer works:
Thanks for the help!
It's not returning incorrect values - it's returning exactly what your function says to. The problem is that the two formulas are not the same!
Closely comparing the two formulas, it's clear that you're missing an parameter at the end of the second formula, the MATCH_TYPE.
Match_type Behaviour
1 or omitted :
MATCH finds the largest value that is less than or equal to lookup_value. The values in the lookup_array argument must be placed in ascending order, for example: ...-2, -1, 0, 1, 2, ..., A-Z, FALSE, TRUE.
0 :
MATCH finds the first value that is exactly equal to lookup_value. The values in the lookup_array argument can be in any order.
-1 :
MATCH finds the smallest value that is greater than or equal to lookup_value. The values in the lookup_array argument must be placed in descending order, for example: TRUE, FALSE, Z-A, ...2, 1, 0, -1, -2, ..., and so on.
When you're having a problem with a formula, break it up into each smaller section so that you can see where the issue is.
For example, you could put the MATCH section of the formula in one cell, and the INDEX function in the next cell, referring to the value in the other cell. This would have made the issue easier to find.
More Information:
Office Support : MATCH Function

Can Vlookup return a formula in excel?

I am trying to use the VLOOKUP function in excel to return a formula. I've found plenty here on SO about using VLOOKUP but have a slightly different question.
I am trying to get the week's average temperature (from column B) before a specified day (in column C) that can be found in column A.
Put more simply:
If date in cell C2 exists in column A, return average from range in column B.
So far this is the closest I've got (thanks to other QAs on SO):
=VLOOKUP(C2, A1:B660, AVERAGE(B124:B130), FALSE)
However using the AVERAGE function in place of column number (which would usually be the argument used) does not seem to work.
I've attached a very simplified picture of my data:
If VLOOKUP is the wrong function to handle this what would be a better approach?
I'm running Excel 15.32 on a Mac.
EDIT:
Dummy data:
https://www.dropbox.com/s/rblk943k2zf71tw/dummy%20data.xlsx?dl=0
What about:
=AVERAGE(OFFSET($B:$B,MATCH($C2,$A:$A,0)-1,0,-7))
This assumes a header in row 1.
Find the matched date in column A from the entry in C2
Create an array of column B values, counting back a week from that point
Average that array.
You can fill this down column D, for example, and it will adjust as necessary.
One problem with the OFFSET function is that it is volatile, so all the formulas would recalculate if anything is changed on the worksheet.
The following, at least in later versions of Excel, should be non-volatile:
=AVERAGE((INDEX($A:$B,MATCH($C2,$A:$A)-6,2,1):INDEX($A:$B,MATCH($C2,$A:$A,0),2)))
I will leave it to you to handle the errors from checking dates in rows 2-6.
Use INDEX as a cell reference with MATCH locating the primary date and using that position as well as that position minus 6 for the range.
=AVERAGE(INDEX(B:B, MATCH(C2, A:A, 0)-6):INDEX(B:B, MATCH(C2, A:A, 0)))
I think what you are looking for is this:
=IF(COUNTIF(A1:A660,C2)=0,0,AVERAGE(B124:B130))
This says if C2 cannot be found in A1:B660, then return 0, otherwise return the AVERAGE(B124:B130).
I would recommend a different approach. Still using VLOOKUP, I would go with the below. However there will be an easier/more elegant way to get this done.
Use VLOOKUP to return a value if found. Really, you don't care about the value it returns.
=VLOOKUP(C2,A:B,2,FALSE)
Wrap in an IFNA to handle dates not found. Here I've got it to return -1.
=IFNA(VLOOKUP(C2,A:B,2,FALSE),-1)
Use an IF statement to work out an average if VLOOKUP returns something, and do something else if it's not found.
=IF(IFNA(VLOOKUP(C2,A:B,2,FALSE),-1)<>-1,AVERAGE(B124:B130),"do something else")

Vlookup returns N/A despite of existing match

I have two tables, table1 and table2. I execute VLOOKUP function in order to fill in 3 columns from table2 into table1.
For some reason, the formula doesn't work for the first row, and doesn't find the exact match from table2 even though it exists.
I made sure that both columns (for comparison) have the same format (General) and there is no extra spacing. Same conditions also apply for the rest of the records, and it works there properly.
table1 - you can see the missing matches for the first row.
table2 - you can see the match does exist, but it is not reflected in table1.
Is there any other reason why VLOOKUP can't find a match for a specific record?
Try directly evaluating equality for the two cells that you believe are equal, for instance if A2 is the value you are looking up and Sheet2!A100 is the value you think should match try this in a cell:
=(A2=Sheet2!A100)
If that returns false then you know that there is some formatting issue or error in your vlookup.
Also try Formulas / Evaluate Formula ribbon command to step through your vlookup in case that highlights something wrong.
Okay - Here's a doozy of a use-case. VLOOKUP and INDEX-MATCH were returning #N/A for values that were "apparently" equal. Cleaned my data with =TRIM(CLEAN(SUBSTITUTE(A1,CHAR(160)," "))) and that didn't work.
Then, I compared two cells that looked like they had matching values and they evaluated to FALSE (A1=B1 resulted in FALSE).
Then, as a last resort, I code checked each ASCII value for each character in the two cells and I found that the "-" in one cell was different from the "-" in the other cell. The first cell has the ASCII value 63 and the second cell had the ASCII value 45 for what looked like was the same "-". Turns out that 63 is a "short dash" and 45 is your standard dash or minus symbol.
The way to evaluate the ASCII codes for each character in a string is to combine the CODE function with the MID or RIGHT functions after testing the cells for length using the LEN function.
Examples:
LEN(A1) should equal LEN(B1)
For the first character in each cell:
CODE(A1) Code defaults to the first character on the left
CODE(MID(A1,2,1) yields the ASCII for the second character
CODE(MID(A1,3,1) yields the ASCII for the second character
and so on
If you have a lot of characters you can post an integer sequence next to your CODE-MID function and point the position argument to the related integer and just copy down or across
Or
You can look for the weird non-numeric character and just test that one for both cells.
Have observed scenarios like this where direct comparison fails (e.g. formula =A1=B1 resulted in FALSE) and yet length =LEN(A1)=LEN(B1) and letter by letter ASCI comparison (=CODE(A1,1,1), =CODE(A1,2,1), =CODE(A1,3,1), etc.) shows no difference.
What worked was to adjust the format of the lookup value inside the VLOOKUP.
e.g.
=VLOOKUP(A1, ARRAY, COL_NUM, FALSE) -> =VLOOKUP(TEXT(A1, "000"), ARRAY, COL_NUM, FALSE)
Here's an issue I encountered: my VLOOKUP formula returns the correct value (1) if I type in the value-to-look-up (1.016) directly in the formula, shown in cell F54.
However, if I referenced a value in column A as the value-to-look-up, the formula returned #N/A, as shown in cell F55.
(I was actually trying to VLOOKUP the current row's A value plus 0.015, i.e. VLOOKUP(A54+0.015, $A$3:$B$203, 2, FALSE))
Yet if I use the ROUND function, then the VLOOKUP formula works, as shown in F56.
I recently encountered the same issue and resolved it by changing the vlookup formula to =VLOOKUP([value to lookup], [lookup table], [column to return in the lookup table], False). Setting the last input argument to "false" forces Excel vlookup function to perform an exact match.

MATCH and LOOKUP returning unexpected values

UPDATE WITH ANSWER:
I misunderstood the operation of MATCH and LOOKUP; they apparently do not automatically select the last value.
The updated formula is as follows:
=IF(
ISNUMBER( MATCH(2,INDEX(1/($D2=$D$1:$D1),0)) ),
($A2+$B2) - (LOOKUP(2,1/($D2=$D$1:$D1),$A$1:$A1)+LOOKUP(2,1/($D2=$D$1:$D1),$B$1:$B1))
,0 )
The main differences are that MATCH is now MATCH(2,INDEX(1/($D2=$D$1:$D1),0)) and LOOKUP is now LOOKUP(2,1/($D2=$D$1:$D1),$A$1:$A1).
Thanks barry houdini and Nanashi for their help!
I am working on what was supposed to be a simple spreadsheet, but one of my formulas is giving me unanticipated results. A screenshot of my data can be seen below:
![Spreadsheet Screenshot][1]
In column C, I am trying to get the time difference between the previous data point with the same type and the current data point. My formula (formatted for easier reading, and taken at cell C11) is as follows:
=IF(
NOT( ISNA( MATCH($D11,$D$1:$D10,1) ) ),
($A11+$B11)-(
LOOKUP($D11,$D$1:$D10,$A$1:$A10)+LOOKUP($D11,$D$1:$D10,$B$1:$B10)
),FALSE)
The cell numbering changes for the appropriate cell–for example, C10 references $D10 and the range $D$1:$D9, etc.
The conditional (NOT( ISNA( MATCH($D11,$D$1:$D10,1) ) ) checks to make sure that in column C there is a previous value that equals the current one; otherwise it returns FALSE, as it does in rows 1 and 12.
The calculation ($A11+$B11)-(LOOKUP($D11,$D$1:$D10,$A$1:$A10)+LOOKUP($D11,$D$1:$D10,$B$1:$B10) takes the current row date and time and subtracts the date and time in the row corresponding with the previous instance of the same type (the LOOKUP function is supposed to return the last occurrence of a value in an array, according to the documentation).
My issue is this: after row 12, the MATCH and LOOKUP functions are all picking up row 11 as the last row in which column C has the value of 1. I've tried testing them separately, and both functions return their appropriate values from row 11. For example, putting the following formula in E16: =MATCH(1,$D$1:$D16,1) returned 11 when I would expect the value to be 16.
What am I doing wrong?
The problem here is that MATCH is not programmed to return the index of the latest matching value. That said, a formula that gets this for us will solve the problem.
Enter the following formula in C2 and drag down:
=MOD((B2)-INDEX(B:B,SUMPRODUCT(MAX(($D$1:$D1=D2)*ROW($D$1:$D1)))),1)
Broken down, this is what each part does:
=SUMPRODUCT(MAX(($D$1:$D1=D2)*ROW($D$1:$D1))) 'Returns the row of the latest match.
=INDEX(B:B, SUMPRODUCT...) 'Returns the matching cell in Column B.
=MOD(B2 - INDEX(...),1) 'Gets the absolute difference, no need to add A and B.
Result:
Let us know if this helps.
EDIT: Changed formula as per Barry's correction.
Neither MATCH nor LOOKUP will find the "last occurrence" as you require with unsorted data. Try these versions for last row/match:
=MATCH(2,INDEX(1/($D11=$D$1:$D10),0))
=LOOKUP(2,1/($D11=$D$1:$D10),$B$1:$B10)
....for your specific requirement you can get both date and time in one LOOKUP, e.g.
=$A11+$B11-LOOKUP(2,1/($D11=$D$1:$D10),$A$1:$A10+$B$1:$B10)
which explicitly uses the dates in column A - if you have data for every day, so you can always assume that change of day is to the next day then you can leave out the date references and use MOD like this:
=MOD($B11-LOOKUP(2,1/($D11=$D$1:$D10),$B$1:$B10),1)

Resources