Need array formula to auto increment column A when date is set and amount is not equal to 0
sheet link
Use scan(), like this:
=arrayformula(
if(
len(B2:B) * (to_text(C2:C) <> "0");
scan(
""; isdate_strict(B2:B) * (to_text(C2:C) <> "0");
lambda(
result; increment;
result + increment
)
);
iferror(1/0)
)
)
Here's one way you could do that:
=ArrayFormula(IF(B2:B*(C2:C&""<>"0");SCAN(;ROW(B2:C)-1;LAMBDA(a;c;a+IF(INDEX(B2:B;c)*INDEX(C2:C&""<>"0";c);1)));))
another approach:
=LAMBDA(y,MAP(INDEX(y,,1),INDEX(y,,2),LAMBDA(r,c,IF(r=0,,c))))(LAMBDA(z,{z,SCAN(,z,LAMBDA(ac,cv,ac+cv))})(INDEX(ISDATE_STRICT(B2:B)*(C2:C&""<>"0"))))
Related
In this spreadsheet
Cols G and H give the total of each Account Type, from the data (A1:D)
If sum Dr - sum Cr > 0, then only this is shown in col G.
=if(sumifs(C:C,A:A,F2)-sumifs(D:D,A:A,F2)>0, sumifs(C:C,A:A,F2)-sumifs(D:D,A:A,F2),"")
If sum Cr - sum Dr > 0, then only this is shown in col H
=if(sumifs(D:D,A:A,F2)-sumifs(C:C,A:A,F2)>0, sumifs(D:D,A:A,F2)-sumifs(C:C,A:A,F2),"")
I am looking for an array formula which replaces these summifs formula, so that if either new Account Types (e.g. Type E, Type F etc) are added or new rows of data are added, then the formula would automatically calculate the sum Dr or sum Cr, instead of having to copy the formula down
try this in cell G2:
=BYROW(F2:F,LAMBDA(fx,IF(fx="",,LAMBDA(cx,dx,{IF(cx-dx>0,cx-dx,),IF(dx-cx>0,dx-cx,)})(SUMIF(A:A,fx,C:C),SUMIF(A:A,fx,D:D)))))
-
Use query(), like this:
=arrayformula(
lambda(
aggregated,
lambda(
account, balance,
{
"Account Type", "Dr", "Cr";
account,
if( balance >= 0, balance, iferror(1/0) ),
if( balance < 0, -balance, iferror(1/0) )
}
)(
query(aggregated, "select Col1", 0),
query(aggregated, "select Col2", 0)
)
)(
query(
A3:D,
"select A, sum(C) - sum(D)
where A is not null
group by A
label sum(C) - sum(D) '' ",
0
)
)
)
You can set a QUERY that finds both entire columns like this:
=QUERY(A2:D,"SELECT A,SUM(C)-SUM(D),SUM(D)-SUM(C) where A is not null group by A",1)
And check with LAMBDA if there are negative values and change them to null:
=LAMBDA(a,INDEX(IF(a<0,,a)))(QUERY(A2:D,"SELECT A,SUM(C)-SUM(D),SUM(D)-SUM(C) WHERE A is not null group by A",1))
If the values in your result table are just for display, you can use the QUERY format clause to hide negative values, such that the whole thing can be generated within a single QUERY:
=QUERY(A2:D,"select A,sum(C)-sum(D),sum(D)-sum(C) where A is not null group by A label sum(C)-sum(D) 'Dr',sum(D)-sum(C) 'Cr' format sum(C)-sum(D) '0;',sum(D)-sum(C) '0;'",1)
I'm trying to count longest and current streak from null or 1 values in google sheets.
It's going to be used in Data Studio, but I have to make calculation in Sheets.
I've tried a sultion from below post, but it's nor working for me and also I have null values not 0, and it has to stay this way (rows in sheet are being appended from google forms form, where I check whether I did a habit or not).
Google Sheets - How to count streaks of non-zero numbers on one column
Please help if you can, thanks before
Here is the spreadsheet with some example data
https://docs.google.com/spreadsheets/d/1GaaEJ24ERulPftYAILOuokY929HInkh-SjAJUEvrW5M/edit?usp=sharing
values to visualize in streaks
Use this to get the longest streak in data:
=arrayformula(
if(
len(join(""; Data!A1:A));
max( len( split(
concatenate( left(isblank(Data!A1:A)) );
"T"
) ) );
"no streak"
)
)
And this to get the last streak in the data:
=+sort(
if(
len(join(""; Data!A1:A));
len( transpose( split(
concatenate( left(isblank(Data!A1:A)) );
"T"
) ) );
"no streak"
);
sequence( rows(
transpose( split(
concatenate( left(isblank(Data!A1:A)) );
"T"
) )
) );
false
)
See your sample spreadsheet.
longest:
=INDEX(COLUMNS(SPLIT(FLATTEN(SPLIT(TRIM(QUERY(IF(A1:A=""; 0; "×");;9^9)); " 0 "; )); " ")))
all:
=INDEX(QUERY(LEN(SUBSTITUTE(FLATTEN(TRIM(SPLIT(QUERY(
IF(A1:A=""; "×"; "¤");;9^9); "×"; ))); " "; ));
"where Col1 <> 0"))
last:
=INDEX(QUERY(SORT(LEN(SUBSTITUTE(FLATTEN(TRIM(SPLIT(QUERY(
IF(A1:A=""; "×"; "¤");;9^9); "×"; ))); " "; ));
SEQUENCE(ROWS(A1:A)-COUNTA(A1:A)); 0); "where Col1 <> 0 limit 1"; ))
={ QUERY(B2:D41, "SELECT B,C,D WHERE D <> ''", 0); QUERY(B42:B54, "SELECT B WHERE B <> ''",0)}
"In ARRAY_LITERAL, An Array Literal was missing values for one or more rows"
As I mentioned both quires work, and when I alter the first the be
=QUERY(B2:D41, "SELECT B,C,D WHERE C <> ''", 0)
where is doesn't have a value to output I get #VALUE! then the 2nd query output.
Thank you for any help.
When you combine two arrays vertically using an { array expression }, both arrays must be the same width.
Similarly, when you combine two arrays horizontally using an { array expression }, both arrays must be the same height.
To avoid the issue, use this pattern:
=arrayformula(
{
query(B2:D41, "where D <> '' ", 0);
query( { B42:B54, iferror(C42:D54 / 0) }, "where Col1 <> '' ", 0)
}
)
the first query has 3 columns and the second query has 1 column - that's the reason why you getting that array error because you are trying to stack 3-columned array on top of 1-columned array
if your intention was to put it next to each other formula should be:
={QUERY(B2:D41, "SELECT B,C,D WHERE D <> ''", 0),
QUERY(B42:B81, "SELECT B WHERE B <> ''", 0)}
if your intention was to put it under each other formula should be:
={QUERY(B2:D41, "SELECT B,C,D WHERE D <> ''", 0);
QUERY(B42:B54, "SELECT B,' ',' ' WHERE B <> '' label ' ''', ' '''", 0)}
I need to formulaic solution to copy a column range stacking on top of itself a given number of times. I found one ugly solution by incorporating a sequence function (to get 1,2,3...n) into an arrayformula for a text operation (Left). The Left operation does nothing but return the original value, but gives me the opportunity to include the sequence array.
There must be a better way to do this.
Problem: Write a formula that creates a column where a named column range is stacked on top of each other an arbitrary number of times. Must be a single formula as other users will need this to self adjust to a new length automatically.
=flatten( transpose( arrayformula( left( Column_Range,len( Column_Range ) + 0 *
sign( sequence( 1,Number_of_Times_To_Repeat ) ) ) ) ) )
could be written as:
=ARRAYFORMULA(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*SIGN(SEQUENCE(1, C1))))))
or:
=INDEX(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*SIGN(SEQUENCE(1, C1))))))
or:
=INDEX(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*TRANSPOSE(ROW(INDIRECT("A1:A"&C1))^0)))))
or:
=INDEX(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*TRANSPOSE(SIGN(ROW(INDIRECT("A1:A"&C1))))))))
or:
=INDEX(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*SPLIT(REPT(1&"♀", C1), "♀")))))
or:
=INDEX(FLATTEN(TRANSPOSE(LEFT(A1:A5, LEN(A1:A5)*COLUMN(INDIRECT("A1:"&ADDRESS(1, C1)))^0))))
or:
=QUERY(FLATTEN(SPLIT(REPT("♀"&JOIN("♀", A1:A5), C1), "♀",,)), "offset 1")
or:
=FLATTEN(SPLIT(REPT(QUERY(A1:A5,,9^9)&" ", C1), " ",,))
Solution 1
Here is a way without FLATTEN:
=ARRAYFORMULA(
VLOOKUP(
1 + MOD(
SEQUENCE(C1 * MAX(ROW(A:A) * (A:A <> ""))) - 1,
MAX(ROW(A:A) * (A:A <> ""))
),
{ROW(A:A), A:A},
2,
0
)
)
MAX(ROW(A:A) * (A:A <> "") inside ARRAYFORMULA just gives you the row number of the last non-empty cell. The rest is quite straightforward.
Solution 2
And here is a FLATTEN solution without LEFT:
=FLATTEN(
ARRAYFORMULA(
ARRAY_CONSTRAIN(
TRANSPOSE(A:A),
1,
MAX(ROW(A:A) * (A:A <> ""))
) & IF(SEQUENCE(C1), "")
)
)
I made a bash script to display numbers in range and I wonder if it's possible to do the same in Sheets without scripting.
I got in a column (let's say A) a list of numbers, for example :
001
002
004
012
013
014
...
and I have a variable prefix in a cell (let's say B1="PREFIX")
Is there a way to display the result as below :
PREFIX001-PREFIX002
PREFIX004
PREFIX012-PREFIX014
...
Thank you by advance for your help !
Could be done. For example A3:A range has the numbers, B1 will be the prefix and B3:B will have the resulting rows.
The formula is only (as it is an array formula) in B3:
=ARRAYFORMULA(
TRANSPOSE(SPLIT(
REGEXREPLACE(
REGEXREPLACE(
TEXTJOIN(
",",
True,
IF(
NOT(ISNUMBER(A3:A)),
"",
IF(
NOT(ISNUMBER({""; OFFSET(A3:A, 0, 0, ROWS(A3:A) - 1)}))
+ NOT(ISNUMBER({A4:A; ""}))
+ ( ISNUMBER({""; OFFSET(A3:A, 0, 0, ROWS(A3:A) - 1)})
* (A3:A <> {""; OFFSET(A3:A, 0, 0, ROWS(A3:A) - 1)} + 1))
+ ( ISNUMBER({A4:A; ""})
* (A3:A <> {A4:A; ""} - 1)),
TEXT(A3:A, "00#"),
""
)
)
& IF(
ISNUMBER({A4:A; ""})
* (A3:A = {A4:A; ""} - 1),
"-",
""
)
),
"(?:-,)+",
"-"
),
"\d+",
B1 & "$0"
),
","
))
)
Here is a sample sheet with step by step description of the solution: link.
#kishkin
Thank you so much for taking the time to do that ! I made a copy to check it, that's very kind of you !
I made mine with multiple columns but in the nasty way (I'm quite new with Sheets but I love it so far) :
to group consecutive numbers :
=IF(CNUM(V2)=CNUM(V1)+1,IF(REGEXMATCH(W1,"-"),LEFT(W1,CHERCHE("-",W1)-1)&"-"&V2,V1&"-"&V2),V2)
to replace lonelies that are part of a range :
=IF(LEFT(W3,2)=LEFT(W2,2),0,W2)
Split the range to calculate range value later :
=SPLIT(X2,"-")
To calculate the range except for 0 values :
=IF(Z2-Y2+1<0,1,Z2-Y2+1)
To remove all the 0 so only the ranges remain :
=filter(X2:X,X2:X>0)
To align the totals with the ranges (useful for group reservations for a project)
=filter(AA2:AA,X2:X>0)
After that, it's just adding the prefix and add some text (sorry for the french).
As I told you it's not as sexy as your solution ^^