SUMIF for first 5 cells meeting criteria - excel

Simple Excel Table such as
A B
1 John 5
2 John 7
3 John 9
4 Jill 25
5 John 21
6 John 22
7 Jill 50
8 John 100
9 John 2000
10 Jack 4
Using SUMIF, we can return the total assigned to John.
=SUMIF(A:A,"John",B:B)
Is there a way to return only the first 5 values that match the criteria? Or is there a way to return the 5 smallest values for John? Either would work.

Oh well. I'll go ahead and presume that you have Excel 2010 or later.
With e.g. "John" in D1, enter this formula in E1:
=SUMIFS($B$1:$B$10,$A$1:$A$10,D1,$B$1:$B$10,"<="&AGGREGATE(15,6,$B$1:$B$10/($A$1:$A$10=D1),5))
Copy down to give similar results for names in D2, D3, etc.
Regards

Formula:
=IF(COUNTIF($A$1:A1,A1)<=5,SUMIF($A$1:A1,A1,$B$1:B1),"")
The last value shown for each person will be the sum of the first (up to)5 values for that person. Just copy and paste values then sort.

Your sample data would show the same result for either the first 5 or lowest 5 as John's numbers are in ascending order. If that is not always the case or if you need to provide compatibility to versions of Excel earlier than 2010 I would offer the following. Note that in my sample image, I've resorted the numerical values in descending order to illustrate the difference.
For John's first 5 values (E2 in the sample image):
=SUM(INDEX(($B$2:$B$11)*($A$2:$A$11=D2)*(ROW($1:$10)<=SMALL(INDEX(ROW($1:$10)+($A$2:$A$11<>D2)*1E+99,,), 5)),,))
For John's lowest 5 values (F2 in the sample image):
=SUMPRODUCT(SMALL(INDEX(($B$2:$B$11)+($A$2:$A$11<>D2)*1E+99,,),ROW($1:$5)))
These are standard formulas. Any array processing is supplied by INDEX and/or SUMPRODUCT. Ctrl+Shift+Enter is not required. Some form of error control may be necessary when there are less than 5 matching values; a simple IF(COUNTIF(), <formula>) would suffice. When transcribing these type of formulas it is important to note that ROW(1:10) is the position within B2:B11 or A2:A11, not the actual row on the worksheet.
 
                  

In C1 enter:
=IF(A1="John",1,0)
In C2 enter:
=IF(A2="John",1+MAX($C$1:C1),0)
and copy down. Then use:
=SUMPRODUCT((A:A="John")*(B:B)*(C:C<6))
.

Assuming John in D1 you can get the sum of the 5 smallest values for John with this array formula
=SUM(SMALL(IF(A$1:A$100=D1,B$1:B$100),{1,2,3,4,5}))
confirm with CTRL+SHIFT+ENTER and copy down for to work for all names in the list

Related

Get multiple values in a single cell with array formula

I'm trying to get an array formula to get the multiple results in a single cell. Is that possible?
For example below, I'd like to show in D2 all the names in column B corresponding to rows for values less than 4 in column A.
My current attempt below:
A C
2 Jane
3 John
6 Thomas
1 Michael
2 Mary
7 Jason
3 Gloria
1 Andrea
=CONCAT(INDEX($B$2:$B$9,IF($A$2:$A$9<4,$B$2:$B$9)))
My desired result would be:
Jane, Michael, Mary, Andrea
You need FILTER() then TEXTJOIN().
=TEXTJOIN(", ",TRUE,FILTER(B2:B9,A2:A9<4))

Distributing students across classes based on marks

Name
Marks
Rank
Class
Eddie
20
6
C
Tom
10
10
A
Jenny
30
4
A
Riva
40
3
C
Andy
50
2
B
Mark
5
11
B
Sally
78
1
A
Jack
15
8
B
Dick
15
8
C
Harry
20
6
A
Dom
30
4
B
The students are expected to be distributed across classes A, B and C, based on their marks in the above picture.
The student with the highest marks goes in A. The one with the next highest goes in B. The next highest goes in C. The next goes again to A and so on.
What should be the formula to be used in Excel 2013 and above for calculating the Class?
Sort the table by either Marks descending or Rank ascending.
D2: =CHOOSE(MOD(ROWS($1:1)-1,3)+1,"A","B","C")
If you are using Excel 365, you can use the SORTBY function to solve the question.
Assume the Name column is in a named range called List_Name, the Marks column is in a named range called List_Marks, your example dataset is in range A1:D12, and you want to return the class code in column D.
In cell D2, enter any one of the following formulas and drag it down:
=CHOOSE(MOD(MATCH(A2,SORTBY(List_Name,List_Marks,-1),0),3)+1,"C","A","B")
Alternatively, you can use the following in cell D2 instead:
=INDEX({"C";"A";"B"},MOD(MATCH(A2,SORTBY(List_Name,List_Marks,-1),0),3)+1)
If you cannot use the SORTBY function, then the answer provided by Ron Rosenfeld should do the job quite well.
Let me know if you have any questions.
Assuming that the chart you provided is in cells A1-D11
Try making a 2x3 chart on the side (I’m using F2-G4 with 1...A 2...B 0...C
and then put the formula in D1 as follows: =vlookup(mod(C2,3),F2:G4, false)
You could even skip out the whole C column if you wanted, writing =vlookup(mod(rank(A2,B:B),3),F2:G4, false)
But then you might have an issue of 2 people going to the same class if they rank the same.

How to SELECT N values ABOVE and BELOW from specific value

If I have a table:
Column A
Column B
Column C
1
Jane
10
2
Stewe
9
3
John
8
4
Mike
7
5
Luke
6
6
Andrew
5
7
Carl
4
8
Sasha
3
9
Ariel
2
10
Carol
1
I would like to SELECT 3 rows above and below WHERE Column B = someValue .
IF query SELECT * WHERE Column B = "Andrew" result should look like:
Column A
Column B
Column C
3
John
8
4
Mike
7
5
Luke
6
6
Andrew
5
7
Carl
4
8
Sasha
3
9
Ariel
2
I know how to select one row, but cant understand how to select such range.
Thanks for ideas!
You can limit and offset inside your QUERY():
=QUERY(A1:C,"limit "&2+MIN(5,MATCH(D1,B:B,0))&" offset "&MAX(0,MATCH(D1,B:B,0)-5))
Well, this was fun...
If 3 above or below are not available then blank... rolling data around is a different proposition.
Below the image is the list of formulae used.
So, per cell not including the data validation that is based on cells B2:B11
A14 and dragged down:
=IFERROR(INDEX($A$2:$A$11,MATCH(B14,$B$2:$B$11,0)),"")
C14 and dragged down:
=IFERROR(INDEX($C$2:$C$11,MATCH(B14,$B$2:$B$11,0)),"")
Cells B14 through B20:
=IFERROR(IF(MATCH(B$17,$B$2:$B$11,0)=3,NA(),INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)-3)),"")
=IFERROR(IF(MATCH(B$17,$B$2:$B$11,0)=2,NA(),INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)-2)),"")
=IFERROR(IF(MATCH(B$17,$B$2:$B$11,0)=1,NA(),INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)-1)),"")
=E2
=IFERROR(INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)+1),"")
=IFERROR(INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)+2),"")
=IFERROR(INDEX($B$2:$B$11,MATCH(B$17,$B$2:$B$11,0)+3),"")
In Excel 365, you could try:
=INDEX(A:C,MAX(2,MATCH(D2,B:B,0)-3),0):INDEX(A:C,MIN(COUNTA(B:B),MATCH(D2,B:B,0)+3),0)
In Google sheets, on the other hand, the formula would be:
=INDEX(A:C,MAX(2,MATCH(D2,B:B,0)-3),0):INDEX(A:C,MIN(COUNTA(B:B),MATCH(D2,B:B,0)+3),0)
(spot the difference).
Excel
Google Sheets
This should produce what you want in all cases:
=IFERROR(FILTER(A2:C,B2:B<>"",ROW(A2:A)>=VLOOKUP("Andrew",{B2:B,ROW(B2:B)},2,FALSE)-3,ROW(A2:A)<=VLOOKUP("Andrew",{B2:B,ROW(B2:B)},2,FALSE)+3))
Of course, you can replace the two instances of "Andrew" with a cell reference (one where you type a changeable name).
This just looks up the row in a curly-bracket array formed from the names and row numbers and uses FILTER to keep results to rows between +/-3 rows of where the target name is found. If you choose the first name (or any other name), you won't get an error; because even if the target name were on Row 1 and the formula goes looking for anything "greater than or equal to 1 minus 3, all rows will be greater than a negative number. Same on the high end. You just won't get a full seven names if there aren't at least three other rows prior to or after the target row.
this not the best solution but it will work , you can use a helper column 'D' that contains the following formula =if(countif(INDIRECT("B"&ROW()+3&":"&"B"&ROW()-3),"Andrew")>0,TRUE,FASLE)
and u can query from here like this SELECT * WHERE Column D = TRUE

Sumproduct matching values in excel

I have two excel tables:
A B C D E
1 John 10 Mark 2
2 Tommy 20 Tommy 3
3 Jane 15 John 4
4 Kate 2
5 Jane 1
Is there a function to sumproduct values in colum B with those values in column E which match by name, i.e. 10*4 + 20*3 + 15*1 ?
You can use sumif for this and just sum up the results when you are done:
=B1 * sumif(D:D, A1, E:E)
Copy that down your sheet, and then add up the totals.
If you don't want a ton of formulas hanging out on your sheet, you could convert this to a CSE/Array formula:
=SUM($B$1:$B$3*SUMIF(D:D, $A$1:$A$3,E:E ))
Just enter that in and hit Ctrl+Shift+Enter to enter it. It will get curly braces around it, which means it's an Array formula.
Since you asked about sumproduct, we could use SUMPRODUCT
=SUMPRODUCT(($A$1:$A$5=A1)*$B$1:$B$5)*SUMPRODUCT(($D$1:$D$5=A1)*$E$1:$E$5)
Now that is assuming there are no repeats (all names are unique). In the event that names are not unique you will have those numbers added together then multiplied.
After you apply that to a column and copied down appropriately, lets say F1 to F3, in F5 you could get your final answer using:
=SUM(F1:F3)

Return value of last match

I need a formula to return the value of Data for the last match of "Text". Row number is also acceptable. Macro is NOT acceptable. Name column is unsorted and cannot be sorted!
Only column "Name" is used as lookup value. I would rather use a/multiple helper column(s) instead of an array formula.
Row Name Data
1 Joe 10
2 Tom 20
3 Eva 30
4 Adam 40
5 Tom 21
LARGE only works with numbers, and VLOOKUP only returns the first match. LOOKUP only works sometimes, so its out too.
So if I wanted the last match for "Tom" then it should return "21".
Array formulas could be avoided with a helper column.
Suppose to have in F1 the name to match (i.e. Tom)
In the helper column row C2 enter
=IF(A2<>$F$1,0,row())
Then copy the formulas along your data.
Now the column C contains 0 for the unmatched names and the row number for the matched ones. Maxing the column yield the row of the solution.
Now the result is simple a matter of using the correct offset with the function offset:
=OFFSET(B1,max(C:C)-1,0)
PS: my copy of excel is in italian, so I can't test this english translaction of the formulas.
I think it's the easiest way to make it.
=LOOKUP("Tom";A2:B7)
Create a column with an array formula (enter it with Ctrl+Shift+Enter):
=VLOOKUP(MAX(IF($B$2:$B$6=B2, $A$2:A$6, 0)), $A$2:$C$6, 3, FALSE)
To make sure you did it right, click on the cell, and the formula should be shown encased in curly brackets ({}).
Note: This assumes that "Row" is in A1.
I have come up with a solution, but it requires that numbers in Data are concurrent, like so
Name Data
Joe 1
Tom 1
Eva 1
Adam 1
Tom 2
Tom 3
Eva 2
But thats okay, since that my data looks like that anyway. So if Name is used before then it must be the old highest +1 aka concurrent.
Name is A1 and Data is B1, and this formula goes into C2:
FLOOR(SQRT(2*SUMIF(A2:A7,A2,B2:B7)),1)

Resources