Find and compare last two non zero values in a range - excel-formula

Would like to search range A1:G1 and compare the last two non zero values and return the word "Better" if the last value is higher than the second to last or "Worse" if the last value is lower than the second to last. Some cells may be empty. Example below.
45 6 7 0 4 Worse
1 45 65 0 0 Better

Use this formula:
=IF(INDEX(A1:G1,,AGGREGATE(14,6,COLUMN(A1:G1)/(A1:G1>0),2))>INDEX(A1:G1,,AGGREGATE(14,6,COLUMN(A1:G1)/(A1:G1>0),1)),"Worse","Better")
The AGGREGATE() function was introduced in excel 2010.
EDIT: Per the comments:
=IF(INDEX($E23:$CB23,,AGGREGATE(14,6,(COLUMN($E23:$CB23)-COLUMN($E:$E)+1)/($E23:$CB23>0),2))>INDEX($E23:$CB23,,AGGREGATE(14,6,(COLUMN($E23:$CB23)-COLUMN($E:$E)+1)/($E23:$CB23>0),1)),"Worse",IF(INDEX($E23:$CB23,,AGGREGATE(14,6,(COLUMN($E23:$CB23)-COLUMN($E:$E)+1)/($E23:$CB23>0),2))<INDEX($E23:$CB23,,AGGREGATE(14,6,(COLUMN($E23:$CB23)-COLUMN($E:$E)+1)/($E23:$CB23>0),1)),"Better","No Change"))

Related

How to return values from previous day or month?

I have a list of data for the month of feb and I want to return values of only those days for which data has been recorded.
Ex:
Defect 02/01 02/02 02/03 02/04
Missing clip
Wrong cable 3 5
Wrong BSN 5 9 6
Damaged harness 4 2 1
I want the formula to return the values and defect type for the date of 02/02
I want the formula to return only Wrong BSN and Damaged harness and the corresponding values for that.
Any help would be appreciated.
Thanks,
Kavya
You can use =HLOOKUP() to horizontally search for a specific term, and when the formula find the term, it'll return the occurrence in the nth row.
=HLOOKUP(what_ur_searching, where_ur_searching, which_row_should_return, exact_or_aprox_match)
It's important to say that HLOOKUP will match the first occurrence from left to right. In your example you have 02/03 two times, so if you try to return the 02/03 values, it'll return 9 and 1, instead of 6 and null.
Wrong BSN:
Write the following formula in any cell that you want, inside the same worksheet: =HLOOKUP("02/02",$A$1:$E$5,4;0)
Explaining:
Search in the first row of $A$1:$E$5, the occurrence of the term "02/02". If the formula find it, return the occurrence on the 4th line (where 1 is equal to the header and 4 is equal to the row number of "Wrong BSN" data). The 0 means that it's looking for the EXACT occurence of "02/02".
Damaged harness:
Write the following formula in any cell that you want, inside the same worksheet: =HLOOKUP("02/02",$A$1:$E$5,5;0)
Explaining:
Search in the first row of $A$1:$E$5, the occurrence of the term "02/02". If the formula find it, return the occurrence on the 5th line (where 1 is equal to the header and 5 is equal to the row number of "Damaged harness" data). The 0 means that it's looking for the EXACT occurence of "02/02".

Excel, Sumproduct, multiple conditions search in {}

I run into several postings on the internet (incl. stackowerflow) with code like this
=SUMPRODUCT((A1:A10="Marketing")*(B1:B10={"North","South"})*(C1:C10))
Conditions for search are neatly put into {}. I have 28 such conditions to search for, so I'm looking for a way to make the formula easier to read. If I try it, i get N/A.
Is there a trick I'm missing?
I'm aware that it can be written
(B1:B10="North") + (B1:B10="South")
but with 28 items it is going to be long.
Thank you in advance
EDIT1: (Disregard)
Tried Axel's suggestion
Simple example
- A B C D
1 1 2 3
2 1 2 2 3
3 2 4 4 6
4 3 6 6 9
=SUMPRODUCT((A2:A4={2,3})*(B2:D4))
Returns Sumproduct(({1,2,3}={2,3})*(B2:D4)) -> I still get N/A for last column when you continue in process
Same for
=SUMPRODUCT((A2:A4=A6:B6)*(B2:D4))
where A6:B6 is list of conditions
or
=SUMPRODUCT((A2:A4=testrange)*(B2:D4))
I'm trying to put all conditions within formula {"case1","case2",...} and so but can't make it work.
Edit 2:
Ok, I see the difference now.
Initial formula is column by column by column
What I'm trying to solve
Column A- list of accounts, I need to find 28 of them
Row 1 - months (conditions varies)
Range B2:AA462 - values
I can write it all with (A2:A462="account1")+(A2:A462="acount2")... up to 28 cases, but I'm asking whether there is a way to write it more simpler
Something like initial A2:A462={"North","South"}
Something like
=Sumproduct((A2:A462={"account1","account2",...})*(B1:AA1="June")*(B2:AA462))
Is there a way write this somehow?
EDIT 4:
Few weeks later inspired by Axel's inputs
=SUMPRODUCT(MMULT(--(A2:A7=G1:J1),ROW(1:4)/ROW(1:4))*(B1:E1=G4)*B2:E7)
Can be grown into
{=SUMPRODUCT(MMULT(--(A2:A7=TRANSPOSE(namedrange)),ROW(OFFSET(A1,0,0,COUNTA(namedrange)))/ROW(OFFSET(A1,0,0,COUNTA(namedrange))))*(B1:E1=G4)*(B2:E7))}
Ok, named range, has conditions within column, more natural way to keep a list of conditions you want to filter for. Also MMULT is now flexible, and counts number of conditions and adjust number of rows to multiply by.
Whole formula must be entered as array formula.
{"North","South"} is the array literal for a row vector. That means it is as if "North" and "South" is placed in juxtaposed cells in one row. So if "North" is in E1 and "South" is in F1, then the formula could also be:
=SUMPRODUCT((A1:A13="Marketing")*(B1:B13=E1:F1)*C1:C13)
With more criteria it could be:
=SUMPRODUCT((A1:A13="Marketing")*(B1:B13=E1:H1)*C1:C13)
It is important that the criterias are in a row vector (one row, multiple columns) since the B1:B13 is a column vector.
Answer to your Edit 2:
The approach:
=SUMPRODUCT(((A2:A462="account1")+(A2:A462="account2")+...+(A2:A462="account28"))*(B1:AA1="June")*B2:AA462)
, which will work, is different from (A2:A462={"account1","account2",...,"account28"}). The latter cannot work since it creates a matrix of 461 rows and 28 columns while the working one ((A2:A462="account1")+(A2:A462="account2")+...+(A2:A462="account28")) is only a vector of 461 rows in one column.
The equivalent could be:
=SUMPRODUCT(MMULT(--(A2:A462={"account1","account2",...,"account28"});ROW(1:28)/ROW(1:28))*(B1:AA1="June")*B2:AA462)
and if "account1","account2",...,"account28" are in AC1:BD1 then also:
=SUMPRODUCT(MMULT(--(A2:A462=AC1:BD1);ROW(1:28)/ROW(1:28))*(B1:AA1="June")*B2:AA462)
What is this doing? It uses MMULT to transform the matrix of 461 rows and 28 columns into a vector of 461 rows by multiplying the matrix with a row vector of 28 rows filled with 1.
So if there is a 1 in one of the 28 columns in each row of the matrix, then there will also be a 1 as the row value of the resulting vector of 461 rows.
Example:
Formula in H3:
=SUMPRODUCT(((A2:A7=G1)+(A2:A7=H1)+(A2:A7=I1)+(A2:A7=J1))*(B1:E1=G3)*B2:E7)
Formula in H4:
=SUMPRODUCT(MMULT(--(A2:A7=G1:J1),ROW(1:4)/ROW(1:4))*(B1:E1=G4)*B2:E7)
To be complete, there also would be an approach using SUMIF inside SUMPRODUCT which would be the better approach in my opinion.
So the Formula in H4 would be:
=SUMPRODUCT(SUMIF(A2:A7,G1:J1,INDEX(B2:E7,0,MATCH(G5,B1:E1,0))))
Your formula would be:
=SUMPRODUCT(SUMIF(A2:A462,AC1:BD1,INDEX(B2:AA462,0,MATCH("June",B1:AA1,0))))

Why does this formula to return the average the top n% return an error for some values?

In another thread here the suggestion was made to use:
-AVERAGEIF(A2:A10,">"&PERCENTILE(A2:A10,0.7))
to return the average of the top n% of the values in the specified range.
This seems to work most, but not all, of the time.
For example if I start with a column of twenty empty cells and insert 75,69,75,56,75,73 as the first six values,
the formula returns a #DIV/0! error for .8, but not .7.
However, changing the leading 75 to 74 returns a non-error result for either .7 or .8 .
Our of around 40 instances of use in a sheet, this was the only set of inputs that returned an error.
Is this the correct behavior of this construction when evaluating properly, or a problem in Excel?
Igrore - I can't get the values in the question to formated properly.
The reason its failing on you is that the 70th percentile of the 6 numbers you have choosen is 75. As such when you go through your data there is no number greater than 75. so you wind up with an empty array.
I am not a stats person but one potential solution would be to change the > to >= in which case it would grab all number also equal to the 70th percentile. If that is not acceptable you could wrap the whole thing in an IFFERROR formula:
=IFERROR(YOUR FORMULA,"nothing greater than the X percentile")
So in your case it is merely a special case where all the number in the array were equal or less then your cut off point. Changing the 75 to 74 changes the result of the 70th percentile.

Excel Condition missplacing

I am trying to make an average of multiple cells, and I want to ignore to zero cells.
Here is my formula =IFERROR(AVERAGEIF(L4:L10;L12:L18;L20:L26;L28:L34;L36:L37);"") and I don't know where to put the condition to ignore zero "<>0" . Am I doing something wrong?
Assuming you only have positive values and zeroes you can average without zeroes, for non-contiguous ranges using this syntax
=IFERROR(SUM(L4:L10;L12:L18;L20:L26;L28:L34;L36:L37)/INDEX(FREQUENCY((L4:L10;L12:L18;L20:L26;L28:L34;L36:L37);0);2);"")
The FREQUENCY part gives you a two element array, one being the count of zeroes, the other the count of positive values, INDEX then retrieves the second of those (the number of positive values), so if you divide the sum by that count you get the average excluding zeroes. FREQUENCY function (unlike AVERAGEIF) accepts a non contiguous range argument (a "union")
....but if you can identify which rows to exclude by using values in another column then it's easier with AVERAGEIFS, e.g. if on the excluded rows, e.g. in K11, K21, K35 etc. they all have the value "Total" you can use this version:
=IFERROR(AVERAGEIFS(L4:L37;L4:L37;"<>0";K4:K37;"<>Total");"")
adjust depending on the exact text, wildcards are possible
Here is another way using SUMIF and COUNTIF.
Example data:
Values
1
-3
0
5
777
3
0
0
8
text
4
5
6
0
6
7
Formulas:
B18=SUMIF(A2:A17,"<>0",A2:A17)-SUM(A6,A11,A15)
B19=COUNTIF(A2:A5,"<>0")+COUNTIF(A7:A10,"<>0")+COUNTIF(A12:A17,"<>0")
B20=B18/B19

Combining LOOKUP and OFFSET

I would like to offset the last entry in my data by one week. For example, I just created this example data:
day value
1 4
2 3
3 5
4 6
5 1
6 3
7 9
8 5
To find the last entry in the dataset, I use the lookup function:
=LOOKUP(9.99E+307,b1:b10)
which will return the value 5. (In case that notation is not familiar, 9.99E+307 is the largest number that can be written in Excel).
I would like then to compare this value to last week's value, and thus offset the last entry by 7. I see that OFFSET asks for: offset(reference,rows,cols) but using:
=OFFSET(LOOKUP(9.99E+307,b1:b10),-7,0)
does not seem to work (it returns an error).
What could be the problem?
#user3561813 has explained why, a solution might be:
=INDEX(B:B,MATCH(1E+100,B:B)-7)
MATCH finds the position (row number) of last entry in ColumnB, -7 steps up seven rows and INDEX finds the content of that row in ColumnB.
You could also use a single LOOKUP function with the "return vector" offset by 7 rows, e.g.
=LOOKUP(9.99E+307,B8:B100,B1:B93)
Why not change the lookup to look for the last day in the list?
This formula will return the last day value (8 in your data above):
=LOOKUP(9.99E+307,A1:A10)
You can then use this formula to return the last value for that day (5 in your data above):
=VLOOKUP(LOOKUP(9.99E+307,A1:A10),A1:B10,2,FALSE)
If you wanted to get the value for 7 days earlier just subtract 7 from the results of the LOOKUP formula like this (will return 4 - day 1 value in your data above):
=VLOOKUP(LOOKUP(9.99E+307,A1:A10)-7,A1:B10,2,FALSE)
The Reference is the OFFSET function refers to a Range object (a cell). The result of your Lookup function is a numeric value, in this case 5. You can't OFFSET a numeric value.
Have you considered using VBA?

Resources