I have a complex year-long schedule for 25 people in google sheets and I need to quantify how often each individual has to work multiple nights in a row over the course of the entire year. I need to bin these into 2 nights in a row, 3 in a row, etc. Here is a simplified view of 1 week, in which I need to count consecutive occurrences of "Back Up IV Call". I have found some similar tasks using query function and vlookup but am having trouble adapting this to my data. Is anyone able to give me a hand with this?
schedule week 1
Use this formula
=IFNA(TEXTJOIN(", ", 1,
FILTER(BYROW(SPLIT(FLATTEN(SPLIT(REGEXREPLACE (TEXTJOIN(",",1,IF(B3:3="",, REGEXMATCH(B3:3, "Back Up IV Call" ))),"FALSE,","0"),"0",)),","), LAMBDA(vv, COUNTA(vv))),
BYROW(SPLIT(FLATTEN(SPLIT(REGEXREPLACE (TEXTJOIN(",",1,IF(B3:3="",, REGEXMATCH(B3:3, "Back Up IV Call" ))),"FALSE,","0"),"0",)),","), LAMBDA(vv, COUNTA(vv)))>1)),"No streak")
Get the result in a table
Rename your input sheet to Sheet1
And In another sheet, paste this formula.
=ArrayFormula(IF(Sheet1!B3:B="",, { Sheet1!B3:B,SPLIT(Sheet1!A3:A, ", ", 0)}))
Explanation
01 - REGEXMATCH(B3:3, "Back Up IV Call" )
To get array of TRUE / FALSE
02 - IF(B3:3="",,
IF B3:3 cells is empty "" then do nothing ,, IF not excute the REGEXMATCH formula.
03 - TEXTJOIN(",",1,IF(B3:3="",, REGEXMATCH(B3:3, "Back Up IV Call" )))
To TEXTJOIN the TRUE / FALSE array with ",".
04 - REGEXREPLACE(TEXTJOIN(...)
To Replace "FALSE," with a 0.
05 - SPLIT(REGEXREPLACE(TEXTJOIN(...)
To Split the jointed arrar "cell" with 0 set as a delimiter.
06 - FLATTEN(...)
To Flatten the streaks in one column for example TRUE | TRUE,TRUE in one column
TRUE
+-----------+
TRUE,TRUE
07 - BYROW(SPLIT(FLATTEN(...), LAMBDA(vv, COUNTA(vv))
To COUNTA BYROW the splited cells of the Array from this:
TRUE
+-----------+
TRUE,TRUE
To this
TRUE
+-----------+
TRUE | TRUE
08 - FILTER(BYROW(...), BYROW(...)>1)
To Flatten the streaks in one column for example TRUE | TRUE,TRUE in one column
To filter the counted list and accept only values > 1 Greater than 1.
09 - TEXTJOIN(", ", 1, FILTER(...)
To join the array in one cell with ", " as a delimiter.
I hope you find this helpful.
Related
I need column J to look at multiple different scenarios and return 1,0 if any are true.
In J1 (and continuing down column J)
if B1 is a number and
B2 and B3 are blank and
the sum of G1:G3 is 2 or more
or
if B1 is a number and B2 is a number or if B2 is "-" and B3 is a number
then return 1
However, if in the range of H1:H3 there is a FALSE,
then an additional row must be added to the sum of G1:G3.
If B1 is "-" then J1 is empty
EXAMPLES:
B1 is a number, B3 is also a number, so J1 should read 1
B11 Is a number. B12:B13 are "-". So then we look to the sum of G11:G13. That equals 2, so J11 should read 1.
B23 is a number, and B24:B25 are "-". So then we look to the sum of G23:G25. However H25 is False, so now we look to the sum of G23:G26. If H24 is false too, then we would look to the sum of G23:G27.
One goal is to always add three applicable values from G, looking at H to determine applicable values.
I could split up these formulas into multiple columns if needed.
SAMPLE SHEET
I worked out this formula
=if(B1="-","",if(or(IF(AND(ISNUMBER(B1),SUM(G1:G3)>=2,B2="-",B3="-"),1),if(and(isnumber(B1),or(isnumber(B2),isnumber(B3))),1)),1))
But have no idea how to add the stipulation for column H when a FALSE is present.
We have two tables in Google Sheets.
First:
Date
Amount
Currency
Worth
01.01.2021
100
USD
373
02.01.2021
100
EUR
451
03.01.2021
100
PLN
100
04.01.2021
100
USD
373
05.01.2021
100
USD
372
Second:
Date
PLN
EUR
USD
01.01.2021
1
4,50
3,73
02.01.2021
1
4,51
3,75
03.01.2021
1
4,50
3,74
04.01.2021
1
4,48
3,73
05.01.2021
1
4,49
3,72
I tried find array formula for first table, column Worth. Formula should take proper value from second table (based on two columns from table one - Date and Currency) and multiply that values by worth in column Amount. I really want to use array formula. Is it possible?
Use VLOOKUP to find the correct date row and MATCH to find which column the value is in:
=ARRAYFORMULA(IFERROR(VLOOKUP(A2:A,I2:L,MATCH(C2:C,I1:L1,0))*B2:B))
Option 01: Getting the result with one cell one formula.
Paste this in B3 "Amount" column in the first table, take a look at this Sheet.
=ArrayFormula(IF(ArrayFormula(IF(A3:A="",,VLOOKUP(A3:A,G3:J,ArrayFormula(IF(D3:D="",,MATCH(D3:D,$H$2:$J$2,0)+1)),0)))="",,ArrayFormula(IF(A3:A="",,VLOOKUP(A3:A,G3:J,ArrayFormula(IF(D3:D="",,MATCH(D3:D,$H$2:$J$2,0)+1)),0)))*E3:E))
Explanation ...
1 - MATCH(D3:D,$H$2:$J$2,0) To get the index you want to VLOOKUP the "Currency" column from the second table with, we need that in the next step.
2 - VLOOKUP the "date" found in First table A3:A from Range in the second table G3:J, with Index set to MATCH(D3:D,$H$2:$J$2,0), and [is_sorted] set to 0
3 - till now we have the value of the exchange rate if we can call it that for each Currency chosen in the first Table, we need to multiply it by Worth to get Amount
ArrayFormula(IF(A3:A="",,VLOOKUP(A3:A,G3:J,ArrayFormula(IF(D3:D="",,MATCH(D3:D,$H$2:$J$2,0)+1)),0)))*E3:E is structured like this Exchange rate * Amount note that E3:E is the Amount, and this IF(A3:A="",, to calculate only when A3:A range is not blank.
4 - ArrayFormula and a IF is needed to be wrapped around like this ArrayFormula(IF(Range=Empty,Do nothing,formula)
Range:
ArrayFormula(IF(A3:A="",,VLOOKUP(A3:A,G3:J,ArrayFormula(IF(D3:D="",,MATCH(D3:D,$H$2:$J$2,0)+1)),0)))
Empty
""
Do nothing :
,,
Formula:
ArrayFormula(IF(A3:A="",,VLOOKUP(A3:A,G3:J,ArrayFormula(IF(D3:D="",,MATCH(D3:D,$H$2:$J$2,0)+1)),0)))*E3:E
Option 02: Getting the result with intermediate steps.
Same as option 01 but in seprate columns take a look at this Sheet.
I'm still new to Google Sheets and still learning, so in my GS I tried using AND and OR formula to produce the results like: -
A | B
-----
1 | 1 TRUE
1 | 2 TRUE
2 | 1 TRUE
2 | 2 FALSE
3 | 1 FALSE
3 | 2 FALSE
But this is the closest I get. What is the best formula that will help me produce result like I shown above.
Your rule is not entirely clear. For instance, could there be zero values? Negative values? But since you have not included such examples in your sample set, the following formula will produce the desired result according to the only data you've included.
Assuming you have headers in A1 and B1 and that your numeric data runs A2:B, delete everything from Col C (including any header) and place the following formula in C1:
=ArrayFormula({"Header";IF(A2:A="",,A2:A+B2:B<=3)})
This one formula will produce all results for all rows (again, judging by the very small data set and implied rule for such in our post).
You can change Header to any header text you like.
The rest reads this way: "If any cell in A2:A is empty, return null in the corresponding cell of that row in Col C. Otherwise, assess whether the combined total of the numbers in Col A and Col B is less than or equal to 3 and return TRUE or FALSE accordingly."
i have the following table:
A1 - 25
A2 - 26
A3 - 27
A4 - BLANK
A5 - 30
A6 - 23
A7 - BLANK
A8 - 24
In B1, i want the following - Starting from A1, sum up the entries until the first blank cell is encountered. In this case, it would be 25+26+27 = 78.
I have looked at multiple answers for hours and tried tweaking them, but nothing is working. Any help is appreciated (Also many things do not make sense, the function isblank(a1:a10) is going to return true or false, then how does arrayformula(isblank(a1:a10)) suddenly convert it to an array, since isblank is just returning a boolean?)
Here's another way you can do it:
=sum(indirect("A1:A"&filter(row(A:A),A:A="")))
try:
=FLATTEN(INDEX(QUERY(; "select "&SUBSTITUTE(JOIN("+";
IF(INDIRECT("A1:A"&MAX(ROW(A1:A)*(A1:A<>"")))="";
","; A1:A)); "+,+"; ",")); 2))
Here's a couple of methods for it and a spreadsheet showing them both.
https://docs.google.com/spreadsheets/d/1rkLarQC6NQ4HdGa38X3-rPoAW0A2-USvImFimlelhZM/edit#gid=0
Method 1: use MATCH to find the row of the first blank row, then construct a reference with INDIRECT to pass to SUM:
=sum(indirect("a1:a" & match("~~", arrayformula("~" & A1:A10 & "~"), 0) - 1))
Reformatted:
=sum(
indirect(
"a1:a" &
match(
"~~",
arrayformula("~" & A1:A10 & "~"),
0
) - 1
)
)
The only tricky thing here is that MATCH returns an error if you just pass it "" to look for, so I use ARRAYFORMULA to wrap the A1:A10 range in a delimiter (~ in this case, but that was arbitrary) and then look for ~~ in the array. That returns me row 4, and so I use indirect to construct a reference to A1:A3 and pass that to sum.
similar to ztiaa's method, but inferior. He filters the ROW() results directly, and uses A:A as the filter argument. Both are superior to my use of ISBLANK etc passed to FILTER
Second, the same idea (find the number of the first empty row and construct a reference to pass to INDIRECT):
=sum(indirect("a1:a" & filter(ARRAYFORMULA(isblank(A2:A11)*row(A2:A11)), ARRAYFORMULA(isblank(A2:A11)*row(A2:A11))<>0)-1))
Reformatted for easier reading:
=sum(
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
) - 1,
)
)
So I use ISBLANK(A1:A10) to get an array of booleans indicating which rows are empty, then multiply that by ROW(A1:A10) which will return an array containing all the row numbers for the range, all inside of ARRAYFORMULA.
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))
Using boolean values in the multiplication converts them to zeroes, so this will generate an array of either 0 (for non-blank rows) or a row number (for any blank rows). Then I take the same formula and use FILTER on it to remove all of the zeroes
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)
leaving an array containing the row numbers of each blank row. Since they are in order and Sheets lacks dynamic array handling, the return value will just be the first value instead of the array, and so we can pass that to INDIRECT to generate a reference to a range using that row number - 1 (since I want to have the range run from A1 to the row immediately preceding the first blank row):
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)-1
)
and then as a final step wrap the whole thing in SUM to sum the values in the range you just used INDIRECT to create a reference to.
=sum(
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)-1
)
)
[![enter image description here][1]][1]
Let me know if that works for you. I imagine there is a better way to do it. I'll keep thinking about it.
Few alternative
=SUM(QUERY(A:A,"select A limit " & MIN(FILTER(ROW(A:A),A:A=""))-1))
With INDEX() function
=SUM(INDEX(A:A,1):INDEX(A:A,min(filter(row(A:A),A:A=""))-1))
This is my google script:
https://docs.google.com/spreadsheets/d/1A0zEN4zczP7aYn2aHdFjDxYgDJBi7R3S6NY_MTcM7YA/edit?usp=sharing
How it works:
In my sheet there is plan of production. Column E is only for help to calculate the date from the index used in column C (3M 000 00 0000 is equal to 3M [job_no] [month] [year]). At the top in cell E2 the is MAX fuction which is used to generate next job index with is generated by the script after pressing (+) button.
What I want to get:
Cells in E column calculate data from column C or show value "123456789" if index (3m xxx xx xxxx) in column C is duplicated. I want to get info in cell C2 that "Index 3M xxx xx xxxx is duplicated. Please remove duplicates".
What's the problem:
I use countif function to check for duplicates:
=countif(E5:E;"=123456789")
When I write this function in bar it shows good value (2) but if I click enter it keeps showing 0 in the cell (i8).
The same problem is with vlookup fuction to search the index and name of duplicated values from C column.
I guess the problem is that in E5:E cell have if formulas inside.
Please help me deal with it.
To detect duplicates in column C, use this formula
=if(arrayformula(sum(--(if(C8:C="";;countif(left(C8:C;14);left(C8:C;14)))>1)))>0;"Index 3M xxx xx xxxx is duplicated. Please remove duplicates";)
and with details ...
=if(arrayformula(sum(--(if(C8:C="";;countif(left(C8:C;14);left(C8:C;14)))>1)))>0;"Index """
&textjoin(", ";;unique(query({C8:C\arrayformula(countif(left(C8:C;14);left(C8:C;14)))};"select Col1 where Col1 is not null and Col2>1";0)))&
""" is/are duplicated. Please remove duplicates";)
with only the code (14 characters)
=if(arrayformula(sum(--(if(C8:C="";;countif(left(C8:C;14);left(C8:C;14)))>1)))>0;"Index """
&textjoin(", ";;unique(query({arrayformula(left(C8:C;14))\arrayformula(countif(left(C8:C;14);left(C8:C;14)))};"select Col1 where Col1 is not null and Col2>1";0)))&
""" is/are duplicated. Please remove duplicates";)