This question already has answers here:
How to use SUM function with (new) dynamic arrays in Excel
(4 answers)
Closed 1 year ago.
I have a 2D dynamic array of 0s and 1s (e.g. B1#). I want to calculate the number of 1s in each row. This can be done using SUM of each row or COUNTIFS on each row.
My goal is to have a single dynamic array formula which would sum/countifs each row and hence spill automatically according to the number of rows in the 2D dynamic array.
How do I do this?
What I tried:
I added a support column in A1# as Sequence(Rows(B1#))
I tried SUM(INDEX(B1#,A1#,0)) but obviously this doesn't work because SUM is bound to return a single value while I am expecting a spill of totals across ROWS(B1#)
I tried COUNTIFS(INDEX(B1#,A1#,0),1) but this also results in a single value that too #VALUE!
MMULT() with SEQUENCE() may work for you. Give a try on below formula.
=MMULT(B1:E14,SEQUENCE(COLUMNS(B1:E14),,,0))
Related
This question already has answers here:
Excel Dynamic Array formula to create a running product of a column
(3 answers)
Closed 5 months ago.
I would like to obtain the cumulated products of an array, also calculated through an array formula.
What that means is, assuming I have an array of numeric values, I want to do a row-wise multiplication of all values up to that row. The following screenshot might clarify the task:
I was trying to do it as follows, where the range of 'rates' in the screenshot above is named 'Rates'. I split the vector of n values into an n-times-n matrix where each column includes one more value than the previous one:
Here using the formula:
=(ROW(Rates)<TRANSPOSE(ROW(Rates))+1)*Rates
And then I would have to take the product of each column (value > 0 condition) through an array formula, but I didn't find a way to that yet.
Notes:
I'm using Office 365 (x64), but BYCOL() and BYROW() are not available to me.
All values of the 'rates' vector are strictly positive.
I'm trying to avoid VBA to keep the file in .xlsx format since it is often removed from emails otherwise.
I want to use the table as a template where the 'rates' vector would come in various sizes in the future, hence a dynamic array solution would be best.
I'd appreciate your input.
With SCAN:
=SCAN(1,Rates,LAMBDA(κ,λ,κ*λ))
Without some of the newer O365 functions, a non-volatile solution might not be straightforward. A volatile option would be:
=SUBTOTAL(6,OFFSET(INDEX(Rates,1),,,SEQUENCE(ROWS(Rates))))
I am trying to make a formula that could count the max sum of any number of consecutive days that I indicate in some cell. Here is the dataset and the formula:
Dataset
The formula that calculates the maximum sum of three consecutive days:
=MAX(IFERROR(INDEX(
INDEX(E2:AI2,0)+
INDEX(F2:AI2,0)+
INDEX(G2:AI2,0),
0),""))
As you can see the number of days here is determined by the number of rows in the formula that start with "Index". The only difference between these rows is the letters (E, F, G). Is there any way I could reference a cell in which I could put a number for those days, instead of adding more rows to this formula?
Another approach avoding use of Offset is to use Scan to generate an array of running totals, then subtract totals which are N elements apart (where N is the number of consecutive cells to be added):
=LET(range,E2:AI2,
length,A1,
runningTotal,SCAN(0,range,LAMBDA(a,b,a+b)),
sequence1,SEQUENCE(1,COLUMNS(range)-length+1,A1),
sequence2,SEQUENCE(1,COLUMNS(range)-length+1,0),
difference,INDEX(runningTotal,sequence1)-IF(sequence2,INDEX(runningTotal,sequence2),0),
MAX(difference))
The answer here was posted by another user on another website, so I will repost it here:
One way to achieve this without relying on a VBA solution would be to use the BYCOL() function (available for Excel for Microsoft 365):
=BYCOL(array, [function])
The array specifies the range to which you want to apply your function, and the function itself is specified in a lambda statement. In the end, you want to get the minimum value of the sum of x consecutive days. Assuming that your data is stored in the range E2:AI2 and the number of consecutive days is stored in cell A1, the function looks like this:
=MIN(BYCOL(E2:AI2,LAMBDA(col,SUM(OFFSET(col,,,,A1)))))
The MIN() part ensures that you get only the smallest sum of the array (all sums of the x consecutive values) returned. The array is simply the range in which your data is stored; it is named in the lambda argument col and consequently used by its name. In your case, you want to apply the sum function for, e.g., x = 4 consecutive days (where 4 is stored in cell A1).
However, with this simple specification, you run into the problem of offsetting beyond cells with values toward the right end of the data. This means that the last sum you get would be 81.8 (value on 31 Jan) + 3 times 0 because the cells are empty. To avoid this, you can combine your function with an IF() statement that replaces the result with an empty cell if the number of empty cells is greater than 0. The adjusted formula looks like this:
=MIN(BYCOL(E2:AI2,
LAMBDA(col,IF(COUNTIF(OFFSET(col,,,,A1),"")>0,"",SUM(OFFSET(col,,,,A1))))))
If you do not have the Microsoft 365 version, there are two approaches that would also work. However, the two approaches are a bit more tedious, especially for cases with multiple days (because the number of days can not really be set automatically; except for potentially constructing the ranges with a combination of ADDRESS() and INDIRECT()), but I would still argue a bit neater than your current specification:
=MIN(INDEX(E2:AF2+F2:AG2+G2:AH2+H2:AI2,0))
=SUMPRODUCT(MIN(E2:AF2+F2:AG2+G2:AH2+H2:AI2))
The idea regarding the ranges is the same in both scenarios, with a shift in the start and end of the range by 1 for each additional day.
Another approach getting to the same result:
=LET(range,E2:AI2,
cons,4,
repeat,COLUMNS(range)-cons+1,
MAX(
BYROW(SEQUENCE(repeat,cons,,1)-INT(SEQUENCE(repeat,cons,0,1/cons))*(cons-1),
LAMBDA(x,SUM(INDEX(range,1,x))))))
This avoids OFFSET (volatile, slowing your file down) and the repeat value, consecutive number and/or the range are easily changeable.
Hope it helps (I answered to the max sum, as stated in the title). Change max to min to get the min sum result.
Edit:
I changed the repeat part in the formula to be dynamic (max number of consecutive columns in range), but you can replace it by a number or a cell reference.
The cons part can also be linked to a cell reference.
Also found a big in my formula which is fixed.
This question already has answers here:
RANDBETWEEN(1,11) but not 6?
(4 answers)
Closed 1 year ago.
Is there a way to use RANDBETWEEN for 2 ranges of numbers?
Perhaps something like:
=RANDBETWEEN(0,9 [and] 18,23)
This, way it can scan both ranges before spitting out a result.
=IF(RANDBETWEEN(0,15)<10,RANDBETWEEN(0,9),RANDBETWEEN(18,23))
The first randbetween gives you a random number for the total digits in each range. Burying it in and if function allows you to split the result on equal probability by setting the cut off at the first possible digit count in the next range. Once the range case has been decided, a randbetween of the appropriate range is performed.
Note this will only work for 2 ranges. If you have 3 or more ranges you would need to perform the first randbtween in its own cell, then in a second cell do the nested IF functions as required.
Your best option is probably the following:
=LET(Value,RANDBETWEEN(0,15),IF(Value<10,Value,Value+8))
I found something that worked for this:
=IF(RANDBETWEEN(1,2)=1,RANDBETWEEN(0,9),RANDBETWEEN(18,23))
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))
This question already has an answer here:
SUMIF excluding hidden rows. SUBTOTAL? SUMPRODUCT?
(1 answer)
Closed 6 years ago.
Updated:
I've excel 2007 spreadsheet which is look like this
I did all header to filter, So in C column there could be lot of fodder type. I want when i filtered only Corn or Nipiar then show all total quantity only for visible rows.
I tried this code but it return all corn or nipiar quantity but i need only visible rows
For Corn:
=SUMIF(C6:C500,"corn",D6:D500)
For Nipiar:
=SUMIF(C6:C500,"nipiar",D6:D500)
I tried also , it did not work cause i need depend on specific text like corn or nipiar or whatever
=SUBTOTAL(9,D6:D500)
You need to deal with the hidden/visible property of the quantities in column D individually. Use SUMPRODUCT for this style of cyclic processing and OFFSET with ROW to break the D6:D500 range into individual values to be preprocessed by the SUBTOTAL function into invalid hidden values and valid visible ones.
Before filtering:
After filtering column G for Sheep:
Since once filtered for Corn I think you want to add all visible, please try:
=SUBTOTAL(109,D:D)