Automatically working out the average of filtered results - excel

I have a spreadsheet where column P has a score between 1-6
The cell O4 has the following formula: =AVERAGEIFS(P8:P5000,P8:P5000,"<>6",P8:P5000,"<>0")
This formula searches for the average of the score in column P excluding 6, blanks and 0
Column O has staff names e.g John, Mark, Tim.......
What i want to do is for Cell O4 to automatically calculate the average of the figures shown in column P after i have used the filter function to show only results of a selected staff member.
I was hoping excel might be able to do this automatically however cell O4 appears to still be showing the average of the whole column P regardless of whether i have filtered or not.
I was given the formula below on another forum but it seems to be giving slightly wrong results albeit only by a small amount but i need to have the results exact if possible. Any help appreciated.
=SUMPRODUCT(1-ISNUMBER(MATCH(P8:P100,{0,6},0)),SUBTOTAL(9,OFFSET(P8,ROW(P8:P100)-ROW(P8),0,1)))/SUMPRODUCT(1-ISNUMBER(MATCH(P8:P100,{0,6},0)),SUBTOTAL(2,OFFSET(P8,ROW(P8:P100)-ROW(P8),0,1)))

Maybe
{=AVERAGE(IF((P8:P5000<>6)*(P8:P5000<>0)*SUBTOTAL(103,INDIRECT("O"&ROW(8:5000))),P8:P5000))}
will do what you want. Assuming the Filter is on column O.
The 103 in SUBTOTAL will also exclude if rows are manually hidden. If this ist unwanted and it should only exclude hidden rows, if filtered, then use 3 instead.
This is an array formula. Input it into the cell without the curly brackets and then press [Ctrl]+[Shift]+[Enter] to create the array formula.

I would create a separate table in a new sheet with all unique staff members and then perform the calculation. This way, you can quickly compare values for all staff just by scanning the table instead of having to constantly update the filter to see the values for potentially dozens or hundreds of staff. You would add the staff name range and criteria to your AVERAGEIFS formula.
For your example:
Sheet 2
A B
--- ---
1 | Staff Average
2 | Bob =AVERAGEIFS(Sheet1!$P$8:$P$5000,Sheet1!$O$8:$O$5000,A2,Sheet1!$P$8:$P$5000,"<>6",Sheet1!$P$8:$P$5000,"<>0")
3 | Mary =AVERAGEIFS(Sheet1!$P$8:$P$5000,Sheet1!$O$8:$O$5000,A3,Sheet1!$P$8:$P$5000,"<>6",Sheet1!$P$8:$P$5000,"<>0")
4 | Joe =AVERAGEIFS(Sheet1!$P$8:$P$5000,Sheet1!$O$8:$O$5000,A4,Sheet1!$P$8:$P$5000,"<>6",Sheet1!$P$8:$P$5000,"<>0")

Related

How to create a dynamic formula to find the average of a set of values for a given vector

I am trying to create a formula that gives me the average of the last 12 entries in a given dataset depending on the associated vector.
Let's make an example:
I have in column F2,G2,H2 and I2 dates, Company1, Company2 and Company3 respectively. Then from row3 to row 33 I have months dates starting from May 2016.
Date Company1 Company2 Company3
May-16 2,453,845
Jun-16 13,099,823
Jul-16 14,159,037
Aug-16 38,589,050 8,866,101
Sep-16 63,290,285 13,242,522
Oct-16 94,005,364 14,841,793
Nov-16 123,774,792 7,903,600 41,489,883
Dec-16 93,355,037 12,449,604 69,117,105
Jan-17 47,869,982 13,830,712 83,913,764
Feb-17 77,109,905 10,361,555 68,176,643
The goal is to create a formula that, when I drag it down, correctly calculates the average of the last 12 values for a given company.
So for example i would have, say in table "B2:C5":
Company1 76,856,345
Company2 11,120,859
Company3 65,674,349
And, if a new Company4 is added to the list, then I just have to drag it down the formula, to calculate the average of the last 12 months for Company4.
Until now, I have came up with this formula:
=AVERAGE(LOOKUP(LARGE(IF(ISNUMBER(G:G),ROW(G:G)),ROW(INDIRECT("1:"&MIN(12,COUNT(G:G))))),ROW(G:G),G:G ))
This formula correctly calculates the average of a given column, considering only the last 12 values. The last step would be to come up with a formula that includes all the columns and then calculates the average for the given company.
Thanks!
I recommend that you use a named range to define your data in columns G:I. When a company is added, just modify the named range's specs. I used the name Target. Of course, you can replace it with $G:$I if you feel so inclined but I would rather recommend reducing the number of rows in the range, which is easier to manage when it is named.
Use the formula below to extract the company names from the first row of Target into the first column of your averages table. This is to ensure that the names are spelled identically in both locations.
=INDEX(Target,1,ROW()-2)
The number 2 indicates the number of rows above the row containing the formula. it is copied here from cell M3. There, ROW()-2 creates the number 1, counting sequentially as the formula is copied down.
Now I have the formula below in my cell N3 and copied down.
=SUM(INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0)))
The formula simply sums up the columns G, H, and I in 3 consecutive rows.
In the final step I inserted the range definition established above, meaning excluding the SUM() function, into your existing formula.
=AVERAGE(LOOKUP(LARGE(IF(ISNUMBER(INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0))),ROW(INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0)))),ROW(INDIRECT("1:"&MIN(12,COUNT(INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0))))))),ROW(INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0))),INDEX(Target,0,MATCH($M3,INDEX(Target,1,0),0))))

Excel look up value in array, return next value

I would like to look up a value in a range and return the value in the next row, but can't quite figure out how to do this. I especially would like to do this with formulas rather than VBA, and preferably with built-in formulas than custom (VBA) formulas, due to macro security issues.
I'm using Excel 2010. My workbook has two worksheets, "assessment" and "lookup". In lookup, I have lookup tables.
"lookup" looks something like:
Column A Column B Column C
1 Sales Engineering Manufacturing
2 Alice Bobbie Charlie
3 Dawn Edgar Frank
4 George Holly Isabel
In "assessment," I have some some drop downs from which users select one name from each column in "lookup." Based on some other criteria, I then rank these and create a new, sorted list (using INDEX() and MATCH()) that produce the selected name and corresponding column name a new sort order
Column A Column B
10 Engineering Edgar
11 Sales Alice
What I'd like is to return the name from the next row.
Column C
10 Holly
11 Dawn
But I'm having real trouble figuring out how to get there.
Assuming lookups is located at B2:D5 (change as required) and the result data is at F2:H3 (change as required) enter this formula in cell H2 then copy down.
=INDEX(
INDEX($B$2:$D$5,0,MATCH($F2,$B$2:$D$2,0)),
1+MATCH($G2,
INDEX($B$2:$D$5,0,MATCH($F2,$B$2:$D$2,0)),0))

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

return the nearest number value above current cell within a list in Excel 2010

This is a little difficult to explain but I have a list of data, all in one column, that contains a department number and then below each department number is a long list of brands that correspond to that department number. So within this list there are multiple departments with brands listed underneath them.
My goal is to somehow return the value of the department next to each brand but because the department number is located above the list of brands and the data is changing each time I repull the report, the row numbers will not remain them same and there may be duplicate brand names, and I cannot figure out what formula to use because it is all contained in one column.
I need to come up with some type of formula that doesn't just search, but returns the value of the next number or value above the current cell and skips all of the text or blanks in between so it will grab the department number above it. Is there a way to do this or a better way to accomplish the goal of assigning each brand to the department above it while allowing for changing data each time I pull the report?
I tried replacing all of the text with 0's or blanks and then used the indirect function to say: =IF(BG24="",INDIRECT("BF" & ROW() - 1),""), but I assumed it would continue to loop and skip the zeroes or blanks until it found a number, but it did not, it just returned the zero value.
If I understand your problem correctly, the following formula should do it. Put it in cell B2. In cell A1, I'm assuming that there's the department number.
=IF(ISERROR(A1*1), IF(ISERROR(A2*1), B1, ""), A1)
This will work for a table like the following where no brands are numbers only:
1
Brand1
Brand2
2
Brand1
Brand2
To become:
1
Brand1 1
Brand2 1
2
Brand1 2
Brand2 2

Excel function for ranking duplicate values

I have an excel sheet containing two columns of data that I'd like to rank.
Suppose we have the following:
A B
Franz 58
Daniel 92
Markus 37
Jörg 58
I would like a formula to rank the above data based on column B, and where there are duplicate values (Franz and Jörg) to put the alphabetical name first. What I have at the moment is simply duplicating Franz twice:
=INDEX(Name,MATCH(A2,Points,0))
Can someone advise me of formula / code that will rank the data and arrange duplicate values alphabetically?
Thanks
I would add a helper column in next to your data to help out with ties.
so in column C use
=B1+1/COUNTIF($A$1:$A$4,"<="&A1)/10
This will add on a decimal ranking system based on the name. This assumes that your numbers in column B do not have decimal places, if they do then you will need to increase the 10 on the end of the formula to account for it ie: for 2 decimal places use 1000, 3 : 10000 etc
Use this formula to get the first name
=INDEX(name,MATCH(LARGE(points,1),points,0))
adjust the 1 to 2 for the second name etc
EDIT had the sign around the wrong way
This will rank your data and will not repeat duplicates too:
In C2:
=SUM(1*(b2>$b$2:$b$5))+1+IF(ROW(b2)-ROW($b$2)=0,0,SUM(1*(b2=OFFSET($b$2,0,0,INDEX(ROW(b2)-ROW($b$2)+1,1)-1,1))))
CTRL+SHIFT+ENTER to turn it into an array
Drag these down to C5 and it will not duplicate rank where the name is the same, it will rank them alphabetically if they are the same.
Then if you wanted to order them automatically in order of top performer/score you then do this:
Putting this in E2:
=INDEX(A2:A5,MATCH(LARGE(C2:C5,ROW()-1),C2:C5,0))
...and drag down
Then use a vlookup on your data to return the score putting this in F2:
=vlookup(E2,A2:C5,2,false)
...and drag down
This should give you a table of highest scoring people in score order.
Assuming A2 is the first of the ranked points scores try this version
=INDEX(Name,SMALL(IF(A2=Points,ROW(Points)-MIN(ROW(Points))+1),COUNTIF(A$2:A2,A2)))
confirmed with CTRL+SHIFT+ENTER and copied down
Requires the Name list to be sorted because names with duplicate scores will be listed in the order shown

Resources