dynamic range in arrayformula without using indirect? - google-sheets

I have this formula in spreadsheet that works as supposed. The formula is placed in "O:O" (this one is from O10).
(I've translated the formula from danish - hope I did it right)
=IFERROR(IF(I10<>"";sum(INDIRECT("L"&MATCH(LEFT(B10;LEN(B10)-6);B:B;0)):INDIRECT("L"&ROW()-1));"");"Fejl/Mangler reference")
Here's the result
The data is imported from another sheet and the lines can change over time and there can be added/removed rows that should be taken into consideration in each Sub Total.
This is why I want to convert the formula to an arrayformula - or another solution?
What I thought would work was:
=Arrayformula(IF(ROW(R:R)=5;"Balance";IF(ROW(R:R)<7;"";IF(ROW(R:R)=7;"Sub Total";IF($I:$I<>"";sum(INDIRECT("L"&MATCH(LEFT(B:B;LEN(B:B)-6);B:B;0))&":"&INDIRECT("L"&ROW()-1));"")))))
I guess is the Indirect so I've tried also to do it with a vlookup but that I couldn't figure out either.
Any good ideas?
Here's a link for the document: Spreadsheet

cell P8:
=ARRAYFORMULA(IF(J8:J="";; SUMIF(ROW(O8:O); "<="&ROW(O8:O); O8:O)))
cell O8:
=ARRAYFORMULA(IF(I8:I="";;
SUMIF(ROW(B8:B); "<="&ROW(B8:B); L8:L)-SUMIF(ROW(B8:B); "<"&VLOOKUP(
VLOOKUP(ROW(B8:B); IF(B8:B<>""; {ROW(B8:B)\ SUBSTITUTE(B8:B; " i alt"; )}); 2; 1); {
VLOOKUP(ROW(B8:B); IF(B8:B<>""; {ROW(B8:B)\ SUBSTITUTE(B8:B; " i alt"; )}); 2; 1)\
ROW(B8:B)}; 2; 0); L8:L)))

Related

Inconsistent results when using arrayformula within Googlesheets

I have a formula that will calculate the working hours between two dates.
It works perfectly well when referring a few lines and ranges. As the data in this sheet is going to be automatically added to over time I wanted to use arrayformula to automatically calculate the duration for these new rows.
However when used within arrayforumla the values are unpredictably different.
I can't make any sense of why it's different.
Below is an example;
https://docs.google.com/spreadsheets/d/1cWZwpnkp2MPyM-EppjOYHRcMEcblscU70R62uf691Xw/edit#gid=0
Any suggestions as to why the formula is behaving differently would be greatly appreciated!
Edit
For posterity;
Formula that worked when inline (COL C);
=TEXT((NETWORKDAYS.INTL(A2,B2,1,F$7:F$9)-1)*($G$2-$F$2)+IF(NETWORKDAYS.INTL(B2,B2,1,F$7:F$9),MEDIAN(MOD(B2,1),$F$2,$G$2),$G$2)-MEDIAN(NETWORKDAYS.INTL(A2,A2,1,F$7:F$9)*MOD(A2,1),$F$2,$G$2),"[hh]:mm:ss")
Forumla that didn't work in arrayformula (COL D);
=ARRAYFORMULA(
IF(ROW(B:B)=1, "Array Formula Duration",
IF(ISBLANK(B:B),"",
(NETWORKDAYS.INTL(A2:A,B2:B,1,F$7:F$9)-1)*($G$2-$F$2)+IF(NETWORKDAYS.INTL(B2:B,B2:B,1,F$7:F$9),MEDIAN(MOD(B2:B,1),$F$2,$G$2),$G$2)-MEDIAN(NETWORKDAYS.INTL(A2:A,A2:A,1,F$7:F$9)*MOD(A2:A,1),$F$2,$G$2)
)
)
)
Forumla that sorted it (COL E);
={"Array Formula Duration";map(A2:A,B2:B,lambda(a,b,if(b="",,TEXT((NETWORKDAYS.INTL(a,b,1,F7:F9)-1)*(G2-F2)+IF(NETWORKDAYS.INTL(b,b,1,F7:F9),MEDIAN(MOD(b,1),F2,G2),G2)-MEDIAN(NETWORKDAYS.INTL(a,a,1,F7:F9)*MOD(a,1),F2,G2),"[hh]:mm:ss"))))}
You may try:
={"Array Formula Duration";map(A2:A,B2:B,lambda(a,b,if(b="",,TEXT((NETWORKDAYS.INTL(a,b,1,F7:F9)-1)*(G2-F2)+IF(NETWORKDAYS.INTL(b,b,1,F7:F9),MEDIAN(MOD(b,1),F2,G2),G2)-MEDIAN(NETWORKDAYS.INTL(a,a,1,F7:F9)*MOD(a,1),F2,G2),"[hh]:mm:ss"))))}

Google sheets match index arrayformula

I have a count using a formula that needs to be stretched (the formula is in cell F9
) https://docs.google.com/spreadsheets/d/1sZM1aAuqkHNONJWagiu3aTw6_vfw515gbiKwhKuQAD4/edit#gid=1464536028
=IF(ISBLANK(E9);;IF(O9=TRUE;INDEX('Тех Лист'!$F$2:$M$2;MATCH(TRUE;Q9:X9;0));IF(P9=TRUE;INDEX('Тех Лист'!$F$3:$M$3;MATCH(TRUE;Q9:X9;0));"Ошибка!")))
I tried to remake it under Arrayformula, but nothing came of it ... later I got the idea to do it through query, but when I add query to the array, the data I need disappears
=INDEX(split(FLATTEN(TRANSPOSE({'Стадник'!$D9:D&"x"&'Стадник'!$Q8:$X8&"x"&'Стадник'!Q9:X&"x"&'Тех Лист'!$F$2:$M$2&"x"&'Тех Лист'!$F$3:$M$3}));"x"))
Please tell me how I can compare the headers, and if the list is TRUE, take the sum from the table
In G9 I entered
=ArrayFormula(if(len(E9:E); vlookup(trim(transpose(query(transpose(if(Q9:X; Q8:Y8;));;50000)))&""; transpose('Тех Лист'!E1:M3)&""; if(O9:O; 2; if(P9:P; 3;));0)+0;))
Note that this solution requires that only one checkbox can be ticked in the range X9:X.
See if that helps ?

Google Sheet | ArrayFormula - Get next smaller value of COL

Google Sheets. I want to get the next smaller value of the current value in COL A.
I've tried this...
=MAX( FILTER(INDIRECT("A" & ROW()-1 );MAX(A:A)) )
Looks good for the moment if the values in COL A are sorted.
The formula above is needed to pasted in each field.
"but", I want to use ARRAYFORMULA() ... I'm trying a long time (months) with breaks ...
That's one of my last tests.
=ArrayFormula(IF(ROW(G:G)=1;"Trip"; IF(ROW(G:G)<3;"0"; MAX( FILTER(INDIRECT("A" & ROW() );MAX(A:A)) ) ))
I've already tried VLOOKUP, too. But maybe I'm at the wrong way.
Unfortunately I didn't found a solution which match my case.
Does anybody can solve my issue? Or give me a hint to can solve this by my-self?
UPDATE Jan 26, 2021
Here we go... I've created a dummy sheet based on original values but cut not needed cols.
https://docs.google.com/spreadsheets/d/1yI0UEdZ3aKU03ElPchUuAPcmnAoMmCyXWhZBcu2Hv3g/edit#gid=0
Col A - is the "current value"
Col G+H - are some tries with ArrF
Col J - is working but not with ArrF - Shows the diff to the last value. Yes this can also be done without INDIRECT() and Co. But I want to try the basic logic.
Col K - show the last value.
Currently Col A is sorted. But if not the diff isn't working. I have added some values from above (grey marked) to simulate.
The goal should be to get the next smaller value of "current" COL A using ArrayFormula.
Use OFFSET
See the docs: OFFSET
=
{
"Last";
0;
ArrayFormula( OFFSET(A3:A, -1, 0) )
}
=
{
"Diff";
0;
ArrayFormula( A3:A100 - OFFSET(A3:A100, -1, 0) )
}
I changed the structure slightly so that it would be contained within arrays. That way you don't need the IF statements for the headers, for example.
I also did not use the whole column notation A:A partly because the array already has A1 and A2 covered. I tried A3:A but that didn't work for the diff column, because it always says it needs more rows. Probably because it needs to reference a row that is not on the same row, if that makes sense.
Refs
Arrays
OFFSET
UPDATE
Due to international settings you may need to have your functions written in this way:
=
{
"Last";
0;
ArrayFormula( OFFSET(A3:A; -1; 0) )
}
=
{
"Diff";
0;
ArrayFormula( A3:A100 - OFFSET(A3:A100; -1; 0) )
}

Google sheet - Dynamic lookup function for string in an horizontal range, in order to get the matched column index letter reference

Could you please help retrieving the column index letter in which is the result of a dynamic lookup formula ?
Here I fill a country in K10 and look in which cell it is in Data range B2:F2, and then I need the correspondant column letter. In my example, it should be column B instead of E (in cell L2 or L10). I can't see what's wrong with the formula I picked up somewhere in this forum :
=MAJUSCULE(CAR(COLONNE(INDEX(B2:F2;EQUIV(K10;B2:F2)))+96))
Here is the sheet https://docs.google.com/spreadsheets/d/1B5t4QrSX1_cI1J66nSaHghhHBkz7CBHQKyTm-_mPhp8/edit?usp=sharing
Thank you very much.
proper way (works with column range A-ZZZ) would be:
=SUBSTITUTE(ADDRESS(2; MATCH("*"&K10&"*"; A2:F2; 0); 4); 2; )
you can even create jumping link:
=HYPERLINK("#gid=569443896&range="&
ADDRESS(2; MATCH("*"&K10&"*"; A2:2; 0); 4);
SUBSTITUTE(ADDRESS(2; MATCH("*"&K10&"*"; A2:2; 0); 4); 2; ))
spreadsheet demo
or jump straight to B4:
=HYPERLINK("#gid=569443896&range="&
ADDRESS(1+MATCH(M10; A:A; 1); MATCH("*"&K10&"*"; A2:2; 0); 4);
SUBSTITUTE(ADDRESS(2; MATCH("*"&K10&"*"; A2:2; 0); 4); 2; ))
If I understand your question correctly, you want to
convert the column index into the corresponding column letter for FRANCE.
Please use the following formula in cell L2
=CHAR(64+QUERY(ArrayFormula(TRANSPOSE({IFERROR(REGEXEXTRACT(B2:F2;K10));
COLUMN(B2:F2)}));
"select Col2 where Col1<>'' "))
UPDATE
How to simplify your formula and free it from being tied to the specific columns (as it now is).
Taking a closer look at what you are trying to do, I believe you would greatly benefit if you could make 2 simple modifications.
Add an extra row above your countries having the zones' letters
Replace your formula to the following one
(Notice the changed columns.)
=QUERY(ArrayFormula(TRANSPOSE({IFERROR(REGEXEXTRACT(E3:I3;N11));
(E2:I2)}));
"select Col2 where Col1<>'' ")
You can now freely move and place your data wherever you want.
Functions used:
CHAR
QUERY
ArrayFormula
IFERROR
TRANSPOSE
REGEXEXTRACT
COLUMN
Thanks to all of you, I finally adapted the proposed formulas in order to have dynamic sheet-cell reference wrapped in a dynamic hyperlink with pre-named ranges :
=LIEN_HYPERTEXTE("#gid="&RECHERCHEV(S3;Sheets_GID;2)&"range="&ADRESSE(1+EQUIV(Q3; INDIRECT(S3&"_Poids"); 1); EQUIV("*"&M3&"*"; INDIRECT(S3&"_Zones"); 0); 4);SUBSTITUE(ADRESSE(2; EQUIV("*"&M3&"*"; INDIRECT(S3&"_Zones"); 0); 4); 2; ))
I get the sheets GID thanks to Player0's script found here : Is there a custom function or script that returns gid of a specific sheet in Google Sheets?
Here is some code that will give you the row column letter when you give it the cell id (works no matter where in the sheet you place it.)
you can put the cell id inside the column bracket. eg column(B87) or just copy paste it as is anywhere.
=IF(TRUNC((column()-1)/26)<1;CHAR((MOD((column()-1);26))+65);CHAR(TRUNC((column()-1)/26)+65)&CHAR((MOD((column()-1);26))+65))
hope this is usefull. Cheers Mads
But it doesn't work anymore when I insert some columns to the table reference, I have to correct some details..

arrayformula sum in Google spreadsheet

How do you arrayformula() a sum() such as:
=sum(A1:H1)
I need to go down 1000 rows.
Another option:
=ArrayFormula(SUMIF(IF(COLUMN(A1:H1),ROW(A1:A1000)),ROW(A1:A1000),A1:H1000))
Of the two answers that work, Jacob Jan Tuinstra and AdamL, Jacob gives a better answer. Jacob's runs faster and is easier to remember.
However, why use crazy formulas when it is much easier to use Google Sheets to the fullest?
=ARRAYFORMULA(A2:A+B2:B+C2:C+D2:D+E2:E+F2:F+G2:G+H2:H)
In the foregoing formula, you can use named ranges instead of the ranges by reference.
=ARRAYFORMULA(range1+range2+range3+range4+range5+range6+range7+range8)
As well, you can sum across rows that span sheets rather than being stuck working with columns within the same sheet.
To fix the formula to block returning zeros for blank rows, use this:
=arrayFormula(if(isNumber(A2:A),A2:A+B2:B+C2:C+D2:D+E2:E+F2:F,G2:G,H2:H))
See: See Ahab's answer on Google Forums
For a cool sum accumulation formula, see Otávio Alves Ribeiro's answer on Google Forums
This is what you are looking for:
=MMULT(A1:H1000,TRANSPOSE(ARRAYFORMULA(COLUMN(A1:H1000)^0)))
See this answer on Web Application I gave: https://webapps.stackexchange.com/a/53419/29140
Note: tried it on the new Google Spreadsheet, without succes.
with new functions in google sheets (since 20 Sep, 2022) all you need is:
=BYROW(A:H; LAMBDA(x; SUM(x)))
Summing A-H horizontal and running down for 523 lines:
=ARRAYFORMULA(iferror(mmult(A1:H523;TRANSPOSE(column(A1:H1))^0)))
if I look at this formula I really think the following might be simpler. Add this to Tools > Script Editor:
function row_sum(range_to_sum_per_row) {
var result_column = [];
for (var r = 0; r < range_to_sum_per_row.length; r++) {
var row_sum = parseFloat(0);
for (var c = 0; c < range_to_sum_per_row[r].length; c++) {
row_sum += range_to_sum_per_row[r][c] || 0;
}
result_column.push([row_sum]);
}
return result_column;
}
use this like so for performance reasons, where C:H is the range you want to sum up and A:A is a column that does not contain an empty string:
=row_sum(filter(C2:H, len(A2:A)>0))
If you want to be able to add rows and sum to the last row for all values in A1:H, you can use:
=ArrayFormula(SUMIF(IF(COLUMN(A1:H1),ROW(A1:A)),ROW(A1:A),A1:H))
Alternatively, if you want be be able to add rows and columns to the spreadsheet and sum to the last of both this can also be done. Paste the following code into any cell and it will create a column of summed values for all cells in each row below and to the right of pasted cell:
=arrayformula(SUMIF(IF(COLUMN(indirect(concatenate(REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", ""),VALUE(REGEXREPLACE(address(row(),column()),"[^[:digit:]]", "")),":",VALUE(REGEXREPLACE(address(row(),column()),"[^[:digit:]]", ""))))),ROW(indirect(concatenate(REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", ""),VALUE(REGEXREPLACE(address(row(),column()),"[^[:digit:]]", "")),":",REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", ""))))),ROW(indirect(concatenate(REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", ""),VALUE(REGEXREPLACE(address(row(),column()),"[^[:digit:]]", "")),":",REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", "")))),indirect(concatenate(concatenate(REGEXREPLACE(address(row(),column()+1),"[^[:alpha:]]", ""),VALUE(REGEXREPLACE(address(row(),column()),"[^[:digit:]]", "")),":"),address(rows($A:$A),columns($1:$1))))))
Using Query
=INDEX(TRANSPOSE(
QUERY(TRANSPOSE(FILTER(A2:H,A2:A<>"")),
"select sum(Col"&JOIN("), sum(Col",SEQUENCE(COUNTA(A2:A)))&")",0)
),,2)
notes:
generating query string on the fly
Using DSUM:
=ARRAYFORMULA(DSUM(
TRANSPOSE(FILTER({A2:A,A2:H},A2:A<>"")),
SEQUENCE(COUNTA(A2:A)),{IFERROR(1/0);IFERROR(1/0)}))
notes:
{IFERROR(1/0);IFERROR(1/0)} is to make zero creteria for DSUM.
{A2:A,A2:H} -- added fake column for DSUM to mimic header column.
may be able to cahnge the formula into DMAX or DAVERAGE
Answer similar to #adamL suggestion, but removing the internal if.
=ArrayFormula(
sumif(ROW(A1:A10)*COLUMN(A1:H1)^0,ROW(A1:A10),A1:A10)
)
In this case I use ROW(A1:A10) * COLUMN(A1:H1)^0 to generate the row number matriz. To understand how it works, you can test just this part in your Google sheets:
= ArrayFormula(ROW(A1:A10) * COLUMN(A1:H1)^0)
So, with your row matrix, sumif can operate for each line, is the line has the matched row number, it will be summed up.
Let us not complicate this.
Simply put parenthesis in each of the array in the range.
=arrayformula( Sum( (A1:A):(H1:H) )
This spans not only upto 1000 rows but upto infiinity.
If you really want to limit then go
=arrayformula( Sum( (A1:A1000):(H1:H1000) )

Resources