I am trying to write a formula in Excel which will count how many times we have sold less than 50 of a particular product. For example, here is a day's sales:
Order | Product | Qty
1 | A | 5
2 | A | 5
3 | A | 5
4 | B | 30
5 | C | 75
I want a formula in a cell which says how many times we have a requirement for less than 50 of a certain product. So in the example above, there is a total of 15 As, 30 Bs and 75 Cs, so 2 of those are less than 50.
I think it will need to be an array function of COUNTIF and SUM, but can't figure it out.
You could use this formula:
=SUMPRODUCT(--(IF(ROW($B$2:$B$10)=MATCH($B$2:$B$10,$B$1:$B$10,0),SUMIF($B$2:$B$10,$B$2:$B$10,$C$2:$C$10),"")<50))
Note: It's an array formula and must be entered through Ctrl+Shift+Enter
Product order placement can be randomized and does not have to be in order.
Another way
=SUMPRODUCT((SUMIF(B2:B10,B2:B10,C2:C10)<50)/COUNTIF(B2:B10,B2:B10))
Maybe something like that will help:
=SUMPRODUCT(--IF($B$2:$B$11<>$B$1:$B$10,SUMIF($B$2:$B$11,$B$2:$B$11,$C$2:$C$11)<50,0))
Note that this is an array formula so needs to be entered with Ctrl+Shift+Enter. Data needs to be sorted by Product (i.e. product A cannot appear in random rows, like row 2, 20 and 100; it needs to be grouped together).
Result:
Related
In Excel, I have a table as follows, which shows pricing based on volume.
If you buy up to 4 items per month, the unit price is $100, 5 to 8 is $90, 9 to 20 is $80, anything above 20 is $50.
A | B | C
----------------
1 | 4 | 100
5 | 8 | 90
9 | 20 | 80
21| 1000 | 50
I have my monthly purchase volumes in another column, say d:
D
--
3
6
2
4
3
10
7
7
10
2
I need to find the unit prices (C column values) based on this series falling between the values of A and B columns. I know I can use a compound if statement like =IF(AND(D$1>=A1,B1>=D$1),C1,0) ... but since my pricing table is actually much larger than my example, this approach becomes convoluted. How can I do this with a Vlookup in an elegant way?
I'd go with the following in E1:
=INDEX(C$1:C$4,MATCH(D1,A$1:A$4))
which, at worst should be just as fast as VLOOKUP but at best is much faster.
This can be done by dragging the following formula down to cover the full column D:
=LOOKUP(2,1/($A$2:$A$5<=D2)/($B$2:$B$5>=D2),$C$2:$C$5)
This will take each D value, compare with A and B, locate which bucket it falls into, and pull the C value. If not found, will return an N/A.
Here is an approach using SUMIFS:
=SUMIFS($C$1:$C$4,$A$1:$A$4,"<="&E1,$B$1:$B$4,">="&E1)
I started to get a headache around my problem that I cannot figure out for the love of me.
There are unknown amounts of column if that makes any difference, but basically each row needs to be compared to the previous one and ONLY when the previous value is greater, the difference between them gets added to the sum.
So for example I have this table
| A |
--|-----|
1 | 100 |
2 | 90 |
3 | 80 |
4 | 100 |
5 | 70 |
6 | 20 |
7 | 100 |
...
Expected result: 100, derived from ((100-90) + (90-80) + (100-70) + (70-20))
I have spent a whole day browsing every single excel tutorial page and cannot find a single helpful answer. Please help :(
Formula for Cell B2: (pull down through the rows).
=IF(A1>B1;A1-B1;0)+B1
Logic: If previous value is larger than current value, add the difference to the total.
If you want to do it in one formula, a basic way would be two use two ranges offset by one cell:
=SUMPRODUCT((A1:A6-A2:A7)*(A1:A6>A2:A7))
If you wanted to make a bit more dynamic (assuming there are no gaps in the data) you could try
=SUMPRODUCT((A1:INDEX(A:A,COUNT(A:A)-1)-A2:INDEX(A:A,COUNT(A:A)))*(A1:INDEX(A:A,COUNT(A:A)-1)>A2:INDEX(A:A,COUNT(A:A))))
If there are blanks between numbers, this won't work and you would probably need to go back to a simpler pull-down formula
I'm trying to get the average of four data points.
The problem is that one or more data points could be missing.
The average should be the average of the last four mondays or four last tuesdays etc.
Each data point is about 1000 rows apart so my idea was to "list" the dates needed and use vlookup and average.
Generic formula
// I only add two dates, but the same formula is repeated for four dates
=AVERAGE(VLOOKUP(DATE_1;Table;25;FALSE);VLOOKUP(DATE_2;Table;25;FALSE))
The DATE_1 and DATE_2 is dynamic calculations of the previous two, lets say mondays.
This works if all dates are there, but if one monday is missing VLOOKUP returns an error and the error can't be calculated as an average.
I figured I could wrap VLOOKUP with IFERROR, but I can't get that working either
// for simplicity I removed the average and only show one.
IFERROR(VLOOKUP(DATE_1;Table;25;FALSE);"") // returns empty string, can't calculate
IFERROR(VLOOKUP(DATE_1;Table;25;FALSE);0) // Works, but it skews the result with a zero.
I know AVERAGE skips empty cells, but how can I "emulate" a empty cell. "" is empty string and that is not the same.
Is there formula that can handle errors and still give me the average, or a formula that returns "empty cell"?
This is the whole point of the AGGREGATE function.
Instead of AVERAGE(SomeRange), use AGGREGATE(1, 6, SomeRange). Instead of AVERAGE(Value1, Value2), use AGGREGATE(1, 6, Value1, Value2)
The 1 tells AGGREGATE to calculate the AVERAGE, and the 6 tells it "Ignore error values". A full list of the values is at the bottom of this post
=AGGREGATE(1,6,VLOOKUP(DATE_1;Table;25;FALSE);VLOOKUP(DATE_2;Table;25;FALSE))
(As people have pointed out, this doesn't quite work properly without interim calculation cells - when you use a Formula in the function, Excel refuses to accept it in Reference Form)
Reference form: AGGREGATE(function_num, options, ref1, [ref2], …)
Array form: AGGREGATE(function_num, options, array, [k])
Function_num | Function
1 | AVERAGE
2 | COUNT
3 | COUNTA
4 | MAX
5 | MIN
6 | PRODUCT
7 | STDEV.S
8 | STDEV.P
9 | SUM
10 | VAR.S
11 | VAR.P
12 | MEDIAN
13 | MODE.SNGL
14 | LARGE
15 | SMALL
16 | PERCENTILE.INC
17 | QUARTILE.INC
18 | PERCENTILE.EXC
19 | QUARTILE.EXC
Option | Behaviour
0 | Ignore nested SUBTOTAL and AGGREGATE functions
1 | Ignore hidden rows, nested SUBTOTAL and AGGREGATE functions
2 | Ignore error values, nested SUBTOTAL and AGGREGATE functions
3 | Ignore hidden rows, error values, nested SUBTOTAL and AGGREGATE functions
4 | Ignore nothing
5 | Ignore hidden rows
6 | Ignore error values
7 | Ignore hidden rows and error values
Just giving you a different approach even though it is not exactly the same way as your question is going, I just thought to share how i've solved a similar issue.
No lookup table in this one, I personnally try to avoid these in these situations, as you always have to update them given some conditions.
{=AVERAGE(IF((WEEKDAY(A1:A276,2)=1)*((L1:L276)>0)*((A1:A276)>((TODAY())-29)),L1:L276,""))}
array formula, so ctrl+shift+enter
(WEEKDAY(A1:A276,2)=1) tests if it's a monday
(L1:L276)>0) is where I have values and therefore want to ignore zeros
((A1:A276)>((TODAY())-29)) added this one for you to check if it's less than 4 weeks old
if these conditions are fulfilled the respective value in L:L is take for the average (A:A being the date in this example)
Here's one more solution for you to try (array formula - Ctrl+Shift+Enter):
=AVERAGE(IF(ISNUMBER(MATCH($A$1:$A$10,CHOOSE({1,2,3,4},DATE_1,DATE_2,DATE_3,DATE_4),0)),$B$1:$B$10))
Result:
INDEX & MATCH doesn't produce the same problem, try this:
=AVERAGE(INDEX(YourColumnRange;MATCH(DATE_1;Table));INDEX(YourColumnRange;MATCH(DATE_2;Table)))
EDIT: To match your dataset you can manually calculate an average like this:
=SUM(IFERROR(INDEX(Y:Y,MATCH(Date_1,A:A,0)),0), IFERROR(INDEX(Y:Y,MATCH(Date_2,A:A,0)),0))/
COUNT(INDEX(Y:Y,MATCH(Date_1,A:A,0)), INDEX(Y:Y,MATCH(Date_2,A:A,0)))
This will allow you to skip empty rows. The formula is simplified for a generic case to make it easier to read.
I have an excel spreadsheet with a list of values, column A contains the grading, column B contains the number of occurrences:
A | B
---------------
Grading | Count
1 | 1
2 | 1
3 | 2
4 | 3
5 | 5
I would like to find the average grading based on the count but to do this I need to build a list based on these values, I.E. the above chart should translate into:
=AVERAGE(1,2,3,3,4,4,4,5,5,5,5,5).
I have managed to come to a solution through a very convoluted method of creating a new table, using IF and COUNTIF to print out an array and then AVERAGE the entire range but this is time consuming to repeat and I'm sure there is much simpler way of doing this.
If I'm not mistaken, you can just take the sum of product of columns A and B, then divide by the sum of the Count column:
=SUMPRODUCT(A2:A6, B2:B6) / SUM(B2:B6)
Note that using your hand written expanded formula yielded the same results:
=AVERAGE(1,2,3,3,4,4,4,5,5,5,5,5)
I've got a spreadsheet with two columns that represent the number of processed records, and the date the records were processed. In some cases, the records can be processed in multiple batches, so the document looks something like this:
33 4/1/2009
22 4/1/2009
12 4/2/2009
13 4/4/2009
36 4/4/2009
I'm trying to add a new set of columns that contain a date, and shows the total number of records for that date, automagically:
4/1/2009 55
4/2/2009 12
4/3/2009 0
4/4/2009 49
I know how to do this algorithmically, and I could probably manipulate the spreadsheet outside of Excel, but I'm trying to do this in the live spreadsheet, and am a bit bewildered as to how to pull it off.
Any ideas?
Thanks!
IVR Avenger
Will the SUMIF function work for you? SUMIF([range],[criteria],[sum_range]) I think you could set range = the set of cells containing dates in your first listing, criteria would be the cell containing the date in the second listing, and sum_range would be the counts in the first column of your first listing.
I would suggest using a Pivot Table. Put the dates into the row area and 'sum of' records in the data area. Nothing in the columns area.
A pivot table will be more dynamic than a formula solution because it will only show you dates that exist.
Assuming your dates are in column B and the numbers to be accumulated are in A, you could try something like this:
| A | B | C D
1 | 33 | 4/1/2009 | =MIN(B:B) | {=SUM(IF(B1:B5=C1,A1:A5,0))} |
2 | 22 | 4/1/2009 | =C1+1 | {=SUM(IF(B1:B5=C2,A1:A5,0))} |
3 | 12 | 4/2/2009 | =C2+1 | {=SUM(IF(B1:B5=C3,A1:A5,0))} |
4 | 13 | 4/4/2009 | =C3+1 | {=SUM(IF(B1:B5=C4,A1:A5,0))} |
5 | 36 | 4/4/2009 | =C4+1 | {=SUM(IF(B1:B5=C5,A1:A5,0))} |
Note the {} which signifies an array formula (input using Control-Shift-Enter) for any non-trivial amount of data it's heaps faster than SUMIF().
I'd be inclined to define dynamic names for the A1:A5 and B1:B5 parts, something like
=OFFSET(A1,0,0,COUNT(A:A),1)
so that I didn't have to keep fixing up my formulae.
There's still a manual element: adding new rows for extra dates, for example - that might be a good place for a little VBA. Alternatively, if you can get away with showing, for example, the last 90 days' totals, then you could fix the number of rows used.