Logic behind last evaluation step of a LOOKUP formula to find last non empty value in a row. - excel

I want to get last non empty cell from every row for further operations. Searching Net I came across a LOOKUP formula which can do this job fine. I have alpha as well as numeric data in the rows.
Sample Data is shown below.
ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8 ID9 ID10 ID11
a1 a2 a3 a4 a5 23 24 25 25
23 NN 67 99 200001 ss p1 23 rq 3
I am using the following formula in L4 which gives correct results that is 3 in L4. Similar formula for row 2 gives result of 25 in L2.
To understand the formula I carried out Formula Evaluation but I am not getting the logic of last step as how it translates to final result.
=LOOKUP(2,1/(A4:K4<>""),A4:K4)
LOOKUP(2,{1,1,1,1,1,1,1,1,1,#DIV/0!,1},A4:K4)
After this step result that is the last non empty value of Row 4 comes i.e. 3
Can someone explain how this line is finally translating into the result step by step.

Basically taking the below formula as an example
=LOOKUP(2,1/(A1:D1<>""),A1:D1)
With data in A1:D1
A1 B1 C1 D1
1 2 3
The formula will populate as follows
=LOOKUP(2,{1,1,1,#DIV/0!},{1,2,3,0})
The way this works is quite simple.
1/(A1:D1<>"") creates an array of 1's and #DIV\0!
1 where the cell is not blank
#DIV/0 where the cell is blank
Then the lookup formula looks for a 2 in this array , which it cant find, but it will always return the position of then last NON ERROR value in the context of an array filled with 1's and #DIV/0!, which would be the 3rd position in the array, The LOOKUP formula then returns the 3rd position of the last argument array in the formula A1:D1 , which is 3

This approach finding the last filled cell uses the vector form of LOOKUP. In
=LOOKUP(2,{1,1,1,1,1,1,1,1,1,#DIV/0!,1},A4:K4) the 2 is the lookup_value, the array {1,1,1,1,1,1,1,1,1,#DIV/0!,1} is the lookup_vector and the A4:K4 is the result_vector.
The vector form of LOOKUP looks in a lookup_vector for the lookup_value and returns the value from the same position in the result_vector.
If the LOOKUP function can't find the lookup_value directly in the lookup_vector, the function matches the largest value in lookup_vector that is less than or equal to lookup_value. If multiple equal values are in the array, which are the largest which are less than or equal to lookup_value, the position of the last is taken. In this case it matches the last 1 since this is the largest value in lookup_vector that is less than or equal to 2.
But for this to do, there is the rule, that the values in lookup_vector must be placed in ascending order. And this is the not documented feature with this approach. It seams as if the #DIV/0! errors within lookup_vector does not contradict that rule. But since the source is not open, we can't be absolutely sure about this. But this approach is used sucessfully so often, that we can be very sure.

Related

How to sum values from column B by choosing multiple different values from column A?

A 1
B 2
C 3
I want add number by choosing alphabet, and like if choose A & B in formula then cell must show sum value 3 and even if I shuffle the alphabet upside downside it still show the 3 by analyzing alphabet.
I first checked which of the key values are present in the user-provided input string. I made a new column where I assigned an extra value of 0 to those that are not present in the input string, and a value of 1 to those that are. I then multiplied that binary column with the corresponding value, and then summed them all up.
I started with FIND(), which will tell you where the value of the key letter starts in the input string. E.g., =FIND("A", "BAC") will return 2, because "A" starts in the second position of "BAC".
This will return an error if the string can't be found, so I surrounded the output of the FIND() with IFERROR(). IFERROR takes in an expression and lets you specify what you want the output to be if the expression returns an error. I set the error output value to be '0'.
I then surrounded all of that with an IF() statement. If the value is 0, leave it as 0. If it's greater than 0, set it to be 1.
This IF(IFERROR(FIND())) expression will produce a 0 or a 1 for each key letter, which you can then multiply with that key's value to obtain how much that key contributes to the final sum. And then it can all be added up neatly.
Screenshot of final spreadsheet
The important cell formulas are:
C1: (whatever your input string is)
C2: =SUM(C5:C7)
A5: A
A6: B
A7: C
B5: 1
B6: 2
B7: 3
C5: =IF(IFERROR(FIND(A5,$C$1),0)>0,1,0)*B5
C6: =IF(IFERROR(FIND(A6,$C$1),0)>0,1,0)*B6
C7: =IF(IFERROR(FIND(A7,$C$1),0)>0,1,0)*B7

To filter multiple columns with a condition on the results

I am trying to find a way of highlighting a result with multiple conditions. I have no knowledge of pivot tables. I would rather use a formula or macros. The table is organised by Dealer.
Acc NAME Add Dealer Total
68687 Sara 11 Wood 111A 0
68687 Sara 11 Wood 111A 0
32187 Sara 11 Wood 111A 0
12345 Tom 10 Main 7878C 2
12345 Tom 10 Main 7878C 2
54321 Tom 10 Main 7878C 2
My table is similar to the one above. I want to select where the Total is greater than 0 & for each Dealer each unique Account number with the lowest Account number highlighted somehow.
So the results I want for the table above would be: Dealer 7878C, Accounts 12345, 54321.
12345 being the lower of the two, it is highlighted.
I don't mind copying the results onto another sheet, as I don't want to remove any data from the sheet. I started by just filtering the Totals for >0 and I was thinking of trying to filter for unique values in Account but its the next step that I am stuck on. A countifs formula?
The sheet is quite large and I'm just not sure which is the best way to try and do it.
Thanks for any help.
There's a nice but complicated way to do it.
With your original data:
With changed data:
As you can see I've placed your data in A1:E7.
I use two array formulas, one for the Dealer in G2:G5 and one for the Accounts H2:N5. The Dealer formula is vertical, and the Accounts formula is horizontal.
For the dealers put this array formula in G2 (press Ctrl+Shift+Enter to enter it):
=IFERROR(INDEX($D$2:$D$7,SMALL(IF(($E$2:$E$7>0)*(COUNTIF($G$1:$G1,$D$2:$D$7)=0),ROW($D$2:$D$7)-1),ROW($G$1:$G1))),"")
Now copy G2 down to G3:G5 to get the rest of the relevant dealers.
For the accounts put this array formula in H2:
=IFERROR(SMALL(IF(($D$2:$D$7=$G2)*(COUNTIF($G2:G2,$A$2:$A$7)=0),$A$2:$A$7),1),"")
Now copy H2 to the right, I2:N2, and down to H3:N5.
To make the first accounts bold I simply make the H column formatted as Bold.
You can copy these formulas farther as needed. Note that the locations are important. If you want to place the formulas elsewhere you'll need to change the references accordingly.
Formulas explained
What these formulas do is check for your conditions, and then get the smallest value that hasn't been retrieved yet, in the upper / left most cells.
The two formulas are mostly the same, apart from the fact that in the account numbers we can use the actual numbers, and with the dealer we use the row number instead.
The dealer formula from the inside out:
The conditions are set in the IF part of the formula, with a multiplier * as a logical AND (TRUE*TRUE=TRUE FALSE*TRUE=FALSE).
The first condition in IF(($E$2:$E$7>0)*(COUNTIF($G$1:$G1,$D$2:$D$7)=0),... checks for the row's Total value to be greater than zero, the second condition checks that the dealer is not already present in the G column. The second condition is irrelevant in the first cell, but in the second cell G3 it becomes COUNTIF($G$1:$G2,... which returns more than 0 if the dealer already exists, and evaluate to FALSE.
If the conditions are met the IF returns the dealer's index by using its row minus 1 ROW($D$2:$D$7)-1, which returns 1 for the first etc. as the starting row is 2. Otherwise it returns FALSE which is ignored.
The SMALL function returns the k-th smallest item. It ignores the FALSE items, and in our case returns the k-th smallest index that meets the conditions (Total>0 and not already present in the results). SMALL(...,ROW($G$1:$G1) in the first cell return the first item. ROW($G$1:$G2) in the second cell G3 evaluates to 2 and returns the second smallest item, and so forth.
The INDEX function simply returns the dealer from the data according to the index.
And finally, the IFERROR is there only to hide the errors when the end of the results is reached.
based on your sample data and assuming a header row in row 1 and the left column being column A.
=COUNTIF($A$2:A2,A2)
place that in F2 and copy down. Then do a filter on the helper column =1

First non blank value in a row, where row number is dynamic

I have a range say A1:E5 in Excel and now in this column has values and some are null. My question is I will give the row number dynamically to the function and for that row the function should give me the first non blank value?
1 2 3
Row1 23
Row2 67
When i give 2 it should return 67, when i give 1 it should give 23?
Try this:
=INDEX($A$1:$E$5,H1,AGGREGATE(15,6,COLUMN($A$1:$E$5)/((ROW($A$1:$E$5)=H1)*($A$1:$E$5<>"")),1))
So the AGGREGATE() Function is Creates an array of Column numbers and Errors. When the Row number does not match H2 and/or the cell is empty it will return a divide by 0 error.
The first part of the AGGREGATE function 15 tells it we are looking for the small. The second, 6, tell it to ignore the errors, so no we have an array of only those column number that did not error. In H2's case it has an array of {2,3,4,5} from which it sends back the smallest to the Index Function.
The Index Function has three parts. The first is the Range. The second the row of that range, hence the H1. The third is the column Which we get From the Aggregate Function. In this case it would return 2 because it is the smallest.
So the Value that is at row 2 and column 2 in the range selected is 23.

Formula returning Column A value for row containing MAX value of a range

Assume I have the following table:
A B C
1 Week 1 Week 2
2 Melissa 114.7 82.8
3 Mike 105.5 122.5
4 Andrew 102.3 87.5
5 Rich 105.3 65.2
The names are in column A, the Week values are in Row 1. (So A1 is blank, B1 = Week 1, and A2 = Melissa.)
I'm trying to build a formula that looks at all the values in a known range (in this example, B2:C5), chooses the highest value of the bunch (here, 122.5) and returns the name of the person from Column A that got that value. If I use this formula, it works for the values in range B2:B5:
=INDEX(A2:A5,MATCH(MAX(B2:B5),B2:B5,0))
That returns Melissa but if I expand the range to include more than just column B's values, I get an #N/A returned:
=INDEX(A2:A5,MATCH(MAX(B2:C5),B2:C5,0))
The weird part (to my simple brain) is that the MATCH portion of the formula works fine, if I just put in this formula, it returns the highest value of 122.5 from C3:
=MAX(B2:C5,B2:C5,0)
So clearly something it going wrong when I'm using either the MATCH or INDEX commands.
Hopefully this makes sense and someone can point out my error?
Try this:
=INDEX(A:A,MAX((B2:C5=MAX(B2:C5))*ROW(B2:C5)))
This is an array formula and must be confirmed with Ctrl+Shift+Enter.
Note: Match can only search one vector at a time. It can be one row or one column or one array. It cannot be two or more rows or columns or a 2D array.
Do it "twice"? Please try:
=INDEX(A2:A5,IFERROR(MATCH(MAX(B2:C5),B2:B5,0),MATCH(MAX(B2:C5),C2:C5,0)))
If you are going to have up to 52/53 weeks to cope with I'd suggest instead inserting a helper column with the MAX for each row. Make that an new (inserted) ColumnA (say =MAX(C2:BC2) etc.) and a simple VLOOKUP should serve, say:
=VLOOKUP(MAX(A:A),A:B,2,0)

Using COUNTIFS for a series of values at once

Working a step higher then COUNTIFS, I appose a challenge to write a formula without VBA code. The basic data is combined from 1000s of rows with:
Column A: rows with values from 1 to 3
Column B: rows with values from 1 to 250.
For this purpose lets say, we are looking at all cells of value "1" in column A, that suit value "5" in column B. To find all matches, we'd use COUNTIFS command.
1 1
2 5
1 5
1 7
1 10
3 45
2 12
1 2
2 1
=COUNTIFS(A1:A9;1;B1:B9;5)
The answer here is 1.
Next thing, the "5" in column B belongs to a group, e.g. group from 1 to 9. What would the best way be, to count all the matches in this example, so that for all "1"'s in column A, we'd have to find all matches with values from 1 to 9 in column B?! In the upper example that would result in "4". The obvious solution is with a series of IF commands, but that's unefficient and it easy to make a mistake, that get's easily overseen.
=COUNTIFS(A1:A9;1;B1:B9;"<="&9)
Works only as the upper limit. If I give the third criteria range and condition as ">="&1 it does not work - returns 0.
Gasper
Where the data is in A1:B9, using a lookup table in D1:E10 with letters A-J in column D and numbers 0 to 9 in column E and the following formula in B11 referencing letters entered in A11 and A12:
=COUNTIFS(A1:A9,1,B1:B9,">="&VLOOKUP(A11,$D$1:$E$10,2,FALSE),B1:B9,"<="&VLOOKUP(A12,$D$1:$E$10,2,FALSE))
works, changing the letters in A11 and A12 gives the correct count according to what they correspond to in the looku in D1:E10.
When you say give third criteria range do you mean:
=COUNTIFS(A1:A9;1;B1:B9;"<="&9,B1:B9;">=1")
If so then try:
=COUNTIFS(A1:A9;1;B1:B9;AND("<="&9,;">=1"))
ie have two conditional ranges with the second range having both conditions combined with AND()
Maybe what you want(ed) is:
=COUNTIFS(A:A;1;B:B;">=1";B:B;"<=9")
Almost there. I noticed that three criteria ranges and conditions work only if I use "=" sign in a condition. As soon as I use
=COUNTIFS(A1:A9;1;B1:B9;"<="&9,B1:B9;">=1")
it returns 0. My goal is to eventualy replace the number in a condition with a VLOOKUP command, so the final equation should be smth like
=COUNTIFS(A1:A9;1;B1:B9;"<="&VLOOKUP(...),B1:B9;">=VLOOKUP(...)")
But the "<" and ">" signs mess with this. Still looking for a solution.
This is my entire line, if it offers any further indication. The AND() commands is at the end - and it still results in 0
=COUNTIFS(INDIRECT(CONCATENATE("baza!$";SUBSTITUTE(ADDRESS(1;MATCH("card_type_id";baza!$A$1:$AAA$1;0);4);"1";"");"$2:$";SUBSTITUTE(ADDRESS(1;MATCH("card_type_id";baza!$A$1:$AAA$1;0);4);"1";"");"$15000"));IF(C6="računska";1;0);INDIRECT(CONCATENATE("baza!$";SUBSTITUTE(ADDRESS(1;MATCH(IF($C$4="CC_SI_klasifikacija";"building_classification_id";0);baza!$A$1:$AAA$1;0);4);"1";"");"$2:$";SUBSTITUTE(ADDRESS(1;MATCH(IF($C$4="CC_SI_klasifikacija";"building_classification_id";0);baza!$A$1:$AAA$1;0);4);"1";"");"$15000"));AND("<="&VLOOKUP($C$5;$K$203:$N$223;4;FALSE);">="&VLOOKUP($C$5;$K$203:$N$223;3;FALSE)))

Resources