Excel Array Function to Sum a number of COUNTIF statements - excel

I'm having difficulty phrasing this intelligently, but I'll try the long way -- I need a function that assigns a 1 or 0 depending on whether the row has an "x" in one of four previous columns and then sums all those assigned values.
In other words, imagine the following formula is in E2 and autofills down for any given number of rows.
=IF(COUNTIF(A2:D2, "x")>=1, 1, 0))
I want to write an array function in F2 that would do the equivalent of summing all the values in column E (but don't reference column E).
Sum of ...
=IF(COUNTIF(A2:D2, "x")>=1, 1, 0))
=IF(COUNTIF(A3:D3, "x")>=1, 1, 0))
=IF(COUNTIF(A4:D4, "x")>=1, 1, 0))
=IF(COUNTIF(A5:D5, "x")>=1, 1, 0))
...for all of column A through D
Sample Data:
A B C D
20-Sep 20-Sep 21-Sep 21-Sep
x x
x x
x
x
x
x
x
x x
x
The formula should return the value 9. There are 9 rows that have an "x" between the columns A and D.

Try this out:
=SUM(--(MMULT(--(A2:D5="x"),{1;1;1;1})>0))
Commit normally (array entry will neither help nor hurt). If your production range is wider than 4 columns expand the {1;1;1;1} array.
Also works:
=SUM(N(MMULT(N(A2:D5="x"),{1;1;1;1})>0))

Related

Return Multiple Unique Matches in Excel without Array Formula

Given an Excel table of shape
Col. A Col B Col. C Col. D Col. E
x 2 x 2 3
x 3 y 7
y 7 z -5
x 2
z -5
I want to return the first unique hit in Column B for argument "x" in Column D,
the second unique hit in Column B for argument "x" in Column E and so forth.
The formula I'm currently using in cell D1 for this is
{=IFERROR(INDEX($B$1:$B$5,MATCH(0,COUNTIF($C1:C1,$B$1:$B$5)+($A$1:$A$5<>$C1),0)),"")}
which is working.
The problem I'm having is that since this is an array formula and since I'm analyzing a decent amount of data computation time for my sheet is too high.
Is there an alternative for this functionality avoiding an array formula?
Thanks!
Haven't got time to test this properly, but if you have Excel 365 you can use a single formula per row and it may be faster:
=TRANSPOSE(UNIQUE(FILTER(B1:B10,A1:A10=C1)))
in D1.
EDIT
To pull the formula down, you need static references as OP has pointed out. Probably should check for empty cells in column C as well, so formula becomes:
=IF(C1="","",TRANSPOSE(UNIQUE(FILTER(B$1:B$10,A$1:A$10=C1))))

Return an array of True/False based on two columns meeting a criteria

I would like to adjust the following CSE formula to return an array of Booleans for each row should the criteria in columns A and B be met. The statement below is acting as an OR function currently.
= (A:A="Y")+(B:B="Y")
E.g.if I have two columns as follows I'd like a third column C with the formula to return as follows:
A B C
Y N {False,False,True}
N Y {False,False,True}
Y Y {False,False,True}
The formula above currently returns:
A B C
Y N {True,True,True}
N Y {True,True,True}
Y Y {True,True,True}
Use the TRANSPOSE() function: =TRANSPOSE(((A:A="Y")+(B:B="Y"))=2)
The CSE formula =(A:A="Y")+(B:B="Y") will return a tall array: {FALSE;FALSE;TRUE}. {FALSE,FALSE,TRUE} is a long array. TRANSPOSE will convert tall to long and vice-versa.

EXCEL counting empty rows

A B C D E F G H
1 Y Y Y X
2 X X
3 Y Y
4 X X
5 Y Y Y X
Count the number of empty rows (from Columns A to E) and put result here. Answer should be 2 from example above.
Hi Folks,
I'm struggling to find the correct Excel formula to count the number of rows with no data from columns A through E, and putting that answer in a cell. These 'empty rows' may have data in later columns (like F, G, H), but I just want to count the rows with no data from columns A to E.
Any help would be appreciated.
Since array formulas tend to confuse people, here's a non-Array formula approach:
Place =IF(COUNTA(A1:E1)=0,1,0) into row 1 of (for example) column I and drag down to row 5. Then place a sum formula below that to get the answer, for example: =SUM(I1:I5)
Try this array formula,
=SUM(IF(ROW(1:5), IF(A1:A5&B1:B5&C1:C5&D1:D5&E1:E5="", 1)))
Remember to finalize with ctrl+shift+enter, not just enter.
You could also use a variation on the standard formula for getting row sums of a 2d array
=SUM(N(MMULT(N(A1:E5=""),TRANSPOSE(COLUMN(A1:E5)^0))=COLUMNS(A1:E5)))
or
=SUM(N(MMULT(N(A1:E5="Y"),TRANSPOSE(COLUMN(A1:E5)^0))=0))
Again they are array formulas and have to be entered with CtrlShiftEnter

Average based on criteria then output

I have an Excel table with the first six columns having a value of 1 or 2. The next six columns are associated with the first six columns and have values that will need to be averaged - two averages will be computed based on whether there is a 1 or 2 value in the first six columns. Then depending on the two averages, the last six columns will need to be assigned a value equal to H (high average) or L (low average). This is difficult to explain, so here is an example:
A B C D E F G H I J K L M N O P Q R
1 2 2 1 2 2 1 8 8 9 8 6 8 L L H L L H
Columns C and F have values equal to 1, so columns I and L need to be averaged. Then because columns A, B, D and E have values equal to 2, columns G, H, J and K need to be averaged. The average of the columns associated with a value of 1 (I and L) is 8.5, and the average of the columns associated with a value of 2 (G, H, J and K) is 7.5. Columns M-R now must be labeled with an H or L depending on whether the corresponding values from columns G-L were part of the high (H) or low (L) average. In this case, since columns I and L had the larger average, then columns O and R need to be assigned an H. The other columns (M, N, P and Q) will be assigned an L because their associated columns (G, H, J, K) had the lower average.
Please consider the following formula placed on the first row of Column M and then copied across to Column R:
=IF(AVERAGEIF($A$1:$F$1,A1,$G$1:$L$1)=MAX(AVERAGEIF($A$1:$F$1,1,$G$1:$L$1),AVERAGEIF($A$1:$F$1,2,$G$1:$L$1)),"H","L")
Logic is if the average of the values that correspond to either the 1 or 2 on A1 is equal to the MAX of calculations between both, then this corresponds to the High number. If not it corresponds to the Low value. Note that this does not consider for when the averages are equal in which case all entries are noted as High. You can extend this by adding to the formula to check if the value is equal to the MIN of the same. Hope this helps. Regards,
If you don't want to use Visual Basic, you could use this method, but it might require more columns.
xx A B C D E F G H I J K L
1 2 2 1 2 2 1 8 8 9 8 6 8
For cell M1 type in: =if(A1=1, G1, "")
Note that this is two regular quotes (")s in a row after the G1 term.
Copy this over to cells M1-R1.
Now cells M1-R1 should only contain data for columns marked with a 1.
Next for cell S1 type in: =average(M1:R1)
This shouldn't factor in blank cells, So you should just have the average of "1" cells.
Now copy the process for the "2" cells:
For cell T1 type in: =if(A1=2, G1, "")
Copy this to cells T1-Y1.
For cell Z1 type in: =average(T1:Y1)
Now for cell AA1 type in: =if(S1 > Z1, 1, 2)
Now AA1 will have the number that has the higher average. So if the "1" cells had a higher average, cell AA1 will be a 1, otherwise it will be a 2.
Now for cell AB1 type in =if(A1=$AA1, "H", "L")
Copy AB1 to cells AB1 through AG1 and you're done.
Cells AB1-AG1 will have your H's and L's. Note that there is one drawback to this method, apart from it being a little complex, that is that if the averages are equal, it will still print "2"s as having the higher average.
Anyways hopefully you can find a simpler method, but this one should work if you can't.

Return value of last populated cell in variable range

Into column D, I'd like to copy the value from the last cell with data in columns E up until the column with the header "DETAIL". There might be anywhere from 2 to 15 columns from E until the column with that header, so that's where I'm stuck. So to be clear, an example:
A B C D E F G H DETAIL
1 x x x a b c d x
2 x x x x
3 x x x c b a x
3 x x x d c x
Should fill column D like so:
A B C D E F G H DETAIL
1 x x x d a b c d x
2 x x x x
3 x x x a c b a x
3 x x x c d c x
I don't mind handling this with a formula (which I couldn't come up with) or programmatically.
Create a dynamic named range by pressing CtrlF3 to bring up the Name Manager, click New, name the range something (I chose MyRange) and then use this formula to define it (Note you may need to change the Sheet name):
=Sheet1!E2:INDEX(Sheet1!2:2,MATCH("Detail",Sheet1!$1:$1,0)-1)
Then, in cell D2 and copied down, use this formula (I did not use IFERROR so that it would be backwards compatible):
=IF(COUNTA(MyRange),INDEX(MyRange,MATCH(REPT("z",255),MyRange)),"")
Here are the results (highlighted) using your provided sample data:
Please try:
=IFERROR(INDEX(F2:T2,,MATCH("zzzzzz",F2:T2)),"")
in D2 and copied down to suit.
Try using LOOKUP:
=IFERROR(LOOKUP(9^99,SEARCH("*",E1:H1),E1:H1),"")
SEARCH("*",E1:H1) returns a number when it matches any character and an error when the cell is blank. LOOKUP then returns the contents of the cells of the last number smaller than 9^99 in the array generated by SEARCH.
For example, in the first row, SEARCH("*",E1:H1) returns {1,1,1,1} so that LOOKUP returns the last 1, being d.
In the third row, SEARCH("*",E3:H3) returns {1, 1, 1, #VALUE!} and LOOKUP returns the last 1, which is a here.
This formula will work with numbers and text alike. The downside is that it is considered slower than INDEX/MATCH. On the other hand, you can modify the INDEX/MATCH to work with numbers, or modify it to work for both but becomes an array formula:
=IFERROR(INDEX(E1:H1,,MATCH(1,SEARCH("*",E1:H1))),"")
[Works with Ctrl+Shift+Enter, otherwise returns an empty cell with Enter alone]

Resources