Let's say 3 columns (A, B, C) are dynamic arrays and I want to create a fourth/final dynamic array formula that is the sum of these 3 columns for each row in column D. For clarity, I am looking for the row-by-row sum of each row in this final column.
This will work:
=A2#+B2#+C2#
How can the same be accomplished by using the SUM function? The reason I ask is that this is easier to use on larger ranges of data.
The following gives a #REF! error:
=SUM(A2:C2#)
New Edit:
With the addition of BYROW and LAMBDA we can do this a little easier than my original answer below:
=BYROW(A1#:C1#,LAMBDA(x,SUM(x)))
The BYROW passes each row into the LAMBDA which does the SUM iteratively and returns an array:
Original Answer
The problem is that SUM,MAX,MIN all allow arrays and do the whole on the full array. So we need to use something that uses arrays and spills individual results. That is what MMULT was built for.:
=MMULT(A2#:C2#,TRANSPOSE(COLUMN(A2:C2)^0))
Just realized with the dynamic arrays we have SEQUENCE:
=MMULT(A2#:C2#,SEQUENCE(COLUMNS(A2:C2),,1,0))
Try this for sums per column (assuming A1# is the dynamic range with the source data):
=SUBTOTAL(9,OFFSET(A1#,0,SEQUENCE(1,COLUMNS(A1#))-1,ROWS(A1#),1))
Just change the first argument of the SUBTOTAL function to use any of the aggregation functions available (min, max, average, etc.). With some tweaks, this can be made to work for row totals.
When I tried Scott Craner's formula above I received a VALUE# error, possibly related to the fact that I was testing it on data columns of different dynamic lengths.
Even though the expression A2#:C2# returns a matrix of width 3 columns, and height of whichever of the three columns has the most rows (filling in zeros for any blank cells), MMULT didn't seem to like that expression and resulting matrix as the first argument. However I found that I was able to modify it as follows to make it work:
=MMULT((A2#:C2#*1),SEQUENCE(COLUMNS(A2:C2),,,0))
Absolute legend. I've been trying to work this out. Thank you so much. I have never used MMULT before, only SUMPRODUCT for similar problems. My problem was to dynamically sum up the last few columns in a spill table and I was able to adapt your solution.
In terms of the question above, if the three spill columns were one spill table with rows and columns in the one spill range it would be:
=MMULT(A2#,SEQUENCE(ROWS(A2#)),SEQUENCE(COLUMNS(A2#)),,1,0))
Related
I have a sheet that uses the below formula to arrive at a figure:
=SUMPRODUCT(E12:K12,E23:K23)/M10
To my understanding, it's getting the sum of E12:K12(593+622+636+620+595+583+589) and multiplying that together with the sum of E23:K23(5740+5160+5432+4640+4716+7372+6696); then dividing the result by M10(39,756).
I have 2 new cells that contain the results of the two summed ranges but when I try to replicate the formula with a regular sum, the result is different:
=SUM(IntradayPlan2!D346*IntradayPlan2!D347)/P12
The result should be 604 but it's coming out at 4383. P12 contains the same number as M10 and the 2 cells in the SUM are summing the same values as the original SUMPRODUCT formula is.
For clarity, I'm currently replicating the main sheet a second time to generate this result. It's slowing down the workbook and most of the other detail on the replicated sheet isn't needed, so I'm trying to get rid of it.
I'm sure I'm missing something when it comes to SUMPRODUCT but after an hour of Googling around I can't work it out. Is there a way of replicating the same maths procedure with my new totals instead?
After the great explanation by Gowtham I don't think it's possible to recreate the result of a SUMPRODUCT by using total values of the 2 used arrays.
Those cells actually get their values from another sheet, which I need to keep anyway. So I've created a couple of new rows which puts those figures in a line (their otherwise spread out across the sheet) and have referenced those new groups instead.
=SUMPRODUCT(IntradayPlan2!D355:J355,IntradayPlan2!D356:J356)/O12
And I'm getting the expected result :)
I'm trying to re-arrange the columns in a data using xlookup function. But not sure why the formula not working in second case (when I try to do it for the whole table)
I would like to understand why it is not working... Any other solution to achieve column re-ordering using dynamic array formulas is also welcome.
Use INDEX/MATCH/MATCH instead:
=INDEX(D6:G11,MATCH(C17:C22,C6:C11,0),MATCH(D16:G16,D5:G5,0))
As to why it does not work, the first formula is returning a 1 dimensional array to the outer XLOOKUP, while the second is returning a 2 dimensional array which the xlookup does not know how to handle.
Index is made to take two one dimensional arrays, one vertical and one horizonatal and return the intersections.
I have a (large) array of data in Excel of which I need to compute the average value of certain values in one column, based on the values of another column. For example, here's a snippet of my data:
So specifically, I want to take the average of the F635 mean values corresponding with Row values of 1. To take it a step further, I want this to continue to Row values of 2, Row values of 3 etc.
I'm not familiar with how to run code in Excel but have attempted to solve this by using the following:
=IF($C = "1", AVERAGE($D:$D), "")
which (to my understanding) can be interpreted as "if the values (anywhere) in column C are equal to 1, then take the average of the corresponding values in column D."
Of course, as I try this I get a formula error from Excel.
Any guidance would be incredibly appreciated. Thanks in advance.
For more complicated cases, I would use an array-formula. This one is simple enough for the AVERAGEIF formula. For instance =AVERAGEIF(A1:A23;1;B1:B23)
Array-formula allows for more elaborate ifs. To replicate the above, you could do =SUM(IF($A$1:$A$23=1;$B$1:$B$23;0))/COUNT(IF($A$1:$A$23=1;$B$1:$B$23;0)).
Looks like more work but you can create extremely elaborate if-statements. Instead of hitting ENTER, do CTRL-ENTER when entering the formula. Use * between criteria to replicate AND or + for OR. Example: SUM(IF(($A$1:$A$23="apple")*($B$1:$B$23="green");$C$1:$C$23;0)) tallies values for green apples in c1:c23.
Your sample data includes three columns with potential ifs so my guess is that you're going to need array formulas at some point.
Excel already has a builtin function for exactly this use; AVERAGEIF().
=AVERAGEIF(C:C,1,D:D)
I've the following data set from which I need the count of distinct values in a pivot. I've tried few function like FREQUENCY, COUNTIFS etc. but I could not make it.
Input
Input Data
Output
Expected Output
=SUM(IF((B2:D4=C10),1,0))
To get result after using formula hit ctrl+shift+enter
I think it's an awkward case because the data values are in more than one column and because they are text not numbers.
The only way I could come up with would be to repeat a standard method of getting the distinct values and then use COUNTIF to get the counts.
So starting in F2 I have:-
=IFERROR(INDEX($B$2:$B$4,MATCH(0,COUNTIFS($F$1:$F1,$B$2:$B$4),0)),
IFERROR(INDEX($C$2:$C$4,MATCH(0,COUNTIFS($F$1:$F1,$C$2:$C$4),0)),
IFERROR(INDEX($D$2:$D$4,MATCH(0,COUNTIFS($F$1:$F1,$D$2:$D$4),0)),"")))
(It's an array formula and must be entered with CtrlShiftEnter)
And starting in G2:-
=COUNTIF($B$2:$D$4,F2)
To avoid having to specify an exact range (e.g. $B2:$B4), you could use the following in F2 and adjust it to the maximum number of rows you are likely to use:-
=IFERROR(INDEX($B$2:$B$10,MATCH(0,IF(ISTEXT($B$2:$B$10),COUNTIFS($F$1:$F1,$B$2:$B$10),1),0)),
IFERROR(INDEX($C$2:$C$10,MATCH(0,IF(ISTEXT($C$2:$C$10),COUNTIFS($F$1:$F1,$C$2:$C$10),1),0)),
IFERROR(INDEX($D$2:$D$10,MATCH(0,IF(ISTEXT($D$2:$D$10),COUNTIFS($F$1:$F1,$D$2:$D$10),1),0)),"")))
and this in G2:-
=IF(F2="","",COUNTIF($B$2:$D$10,F2))
but of course it's restricted to three columns and anything beyond this I think may point to a VBA solution.
There is a also a general formula for distinct values from a 2d array here but the output includes a zero when blank rows and columns are included so would need some modification.
So here is the modified formula from the reference above with error handling starting in I2:-
=IFERROR(INDEX(tbl_text, MIN(IF( IF(ISTEXT(tbl_text),COUNTIF($I$1:$I1, tbl_text),1)=0, ROW(tbl_text)-MIN(ROW(tbl_text))+1)),
MATCH(0, COUNTIF($I$1:$I1, INDEX(tbl_text, MIN(IF(IF(ISTEXT(tbl_text),COUNTIF($I$1:$I1, tbl_text),1)=0, ROW(tbl_text)-MIN(ROW(tbl_text))+1)), , 1)), 0), 1),"")
With the counts starting in J2:-
=IF(J2="","",COUNTIF(tbl_text,J2))
where tbl_text is a named range defined (when I tested it) as $B$2:$E$10
This I think should meet your additional criterion of it being more generalized because you can set tbl_text to include the maximum number of rows and columns that you are likely to use.
Will need a slight further modification to ignore blanks within the table.
Looking to find the max value in a column based on two sets of criteria
So the logic would be: Find the minimum value in column M, where the value in column A matches column N, and the value in Column Y is less than 318.
I've tried using an array formula like this but it doesn't seem to be working/is to memory heavy to run:
=MIN(IF(AND(N:N=A2,Y:Y<=318),M:M))
is there a simpler way? or perhaps a UDF that could work?
Thank you for your help!
You can't use AND in these type of formulas because it only returns a single value rather than the required array.
Here are three possible working versions:
1.) Use * to simulate AND
=MIN(IF((N:N=A2)*(Y:Y<=318),M:M))
confirmed with CTRL+SHIFT+ENTER
2.) Use multiple nested IFs
=MIN(IF(N:N=A2,IF(Y:Y<=318,M:M)))
confirmed with CTRL+SHIFT+ENTER
3.) Use AGGREGATE function
=AGGREGATE(15,6,M:M/(N:N=A2)/(Y:Y<=318),1)
The advantages of this approach are that you don't need "array entry", and it can ignore any errors in the data
Either way it's best to reduce the ranges sizes if you can because it might be slow with whole columns
Give this a try and adjust ranges to suit. Try not to use whole column references:
=SMALL(INDEX(($N$2:$N$101=A2)*($Y$2:$Y$101<=318)*$M$2:$M$101,),1+ROWS($M$2:$M$101)-COUNTIFS($N$2:$N$101,A2,$Y$2:$Y$101,"<=318"))
If you are using the whole column to pick up new data as it is added, consider using Dynamic Named Ranges instead
When things get this complex, I'll usually break it down and setup smaller/simpler formulas in seperate columns.
In other words, you have data in columns A through Y ?
So let's create a formula in column AA:
1) identify when value in Col A matches col N, and value in col Y < 318
=and(A1=N1,Y1<318)
2) copy AA1 to all the rows of your data.
3) now we have a condition to work off .. since there is a SUMIF and COUNTIF, but no MINIF .. we'll have to build that ourselves. first the IF:
in column AB1:
=if(AA1,M1,"")
copy that down to all your data.
finally, do your min:
=MIN(AB:AB)
Should give you your answer.
You could probably splice the first two together, but again, building a complex formula like this, build it simply, first, ;)