Result of formula changing when encapsulating it in ArrayFormula - google-sheets

I am trying to calculate the elapsed time between a specific date and time and another date and time, excluding weekends and non-office hours.
I have done everything already and all seems to work correctly but for one formula.
Here you can see the formula that gives me problems, while here you can see the same formula without the ArrayFormula encapsulation.
The result should be 08:00:00 like in screenshot 2, i can't understand what's going on with the first screenshot.
I need to have the formulas applied when the value are written in the columns from D to G, not before, that's the reason why i am using ArrayFormula. If there is another way to achieve the same result in another way let me know.
Thanks.
Edit: i have found that the issue is that the formula in column K is referencing a fixed cell in column E in the last bracket, E2:E is always a fixed cell in column E (see this screenshot).
Here you can download a copy, thanks in advance!

MIN is not supported by ARRAYFORMULA
You should instead use if to do the comparison
=ArrayFormula(if(isblank(D2:D),,if(H2:H=0,0,if(Constants!$B$3<Constants!$B$2-E2:E,Constants!$B$3,Constants!$B$2-E2:E))))

Related

How to get only one of two repeating values

The Issue
In simple terms, I am trying to set a formula for an alternating pattern. The issue I keep running into is the fact that there are two alternating values, and Google Sheets doesn't like to repeat only one of those values without the other.
I have created an example sheet to demonstrate my issue. In Column A, a date is input. Column B and Column C then autofill with the day of the week and AM or PM respectively. Every other value in Column C alternates between AM and PM. I am trying to set it up so that the row is blank until a value in input in Column A. The issue comes when there is an odd number of Dates in Column A. Note that the alternating AM/PM pattern will never change.
What I've Tried
As seen in the image above, there are three main methods that I have tried. The data in C2:C8 is the desired result.
Method 1:
E2: =transpose(split({rept(join(";",{"AM";" "})&";",(roundup(counta(A2:A9)/2)))},";"))
F3: =transpose(split({rept(join(";",{"PM";" "})&";",(counta(A2:A9)/2))},";"))
These formulas work separately, and best represent what I am trying to accomplish, but I have not found a way to combine them to work together in one column.
Method 2:
H2: =transpose(split({rept(join(";",{"AM";"PM"})&";",(roundup(counta(A2:A9)/2)))},";"))
This is essentially the same as Method 1, but put into one formula. The issue here is that Google Sheets doesn't like to repeat half a number of times. So if the number of times to repeat (counta(A2:A9)/2) contains a half (i.e. 3.5), it will still round down to the nearest whole number.
Method 3:
J2: =ArrayFormula(TEXT(SEQUENCE(3),"")&{"AM";"PM"})
This one appeared most promising to me because when incrementing by one, it added one row, but I quickly ran into the issue where if I went over a sequence number of 2, it threw the error Array arguments to CONCAT are of different size.
References
I have used various search terms and websites to try to solve this, and have yet to find something that works. I may be missing something very simple, though, and hopefully this is a quick solution.
Example Sheet:
https://docs.google.com/spreadsheets/d/1I3EtptFLfDHpAQ8AR6Lwa01dSpJ3Cy8MTX1_OjHExSc/edit?usp=sharing
All my formulas are derived from the websites below:
REPT Function in Google Sheets
How to Repeat Multiple Columns N Times in Google Sheets
Delete everything in Col C (including the header) and place this formula in C1:
=ArrayFormula({"AM/PM"; IF(A2:A="",,IF(COUNTIFS(A2:A,A2:A,ROW(A2:A),"<="&ROW(A2:A))=1,"AM","PM"))})
The COUNTIFS finds the number of matches for the date "up to this row" for every row. Since that count will (or should) only ever be a 1 or a 2, the IF makes easy work of assigning "AM" or "PM" accordingly.
If I understand correctly it is enough to use ISEVEN function to alternate by rows:
=ArrayFormula(IF(A2:A,CHOOSE(ISEVEN(ROW(A2:A))+1,"PM","AM"),))

IF statement to ArrayFormula

I have the following formula in cell D2 in a Google Spreadsheet:
=IF(ISBLANK(B2),"",B2-C2)
How do I apply that formula to the whole column D with ArrayFormula? Because ArrayFormula is the best solution, right?
Thanks
Enclose the formula in the google sheets Arrayformula() function. Then change the reference from B2 to B2:B500 (or leave blank for open ended reference). Same for the second reference.
So =ARRAYFORMULA(IF(B2:B="","",B2:B-C2:C)) should work. Note that I changed ISBLANK to X="" since the arrayformula is bound to find values in the entire array so it won't return blank.
--
Whether this is the best way I don't know. The benefit is that this grows with the dataset and avoids errors when you haven't filled the formula far enough down. However it can sometimes slow sheets down (I've heard but not experienced anything severe myself). If you're experiencing slow sheets I recommend Ben Collin's blog on the topic.
Whithout closed ended references
=mmult( arrayformula(1*(ROW(A2:A)<TRANSPOSE(ROW(A2:A)+1))*(ROW(A2:A)>=TRANSPOSE(ROW(A2:A))) -1*(ROW(A2:A)>TRANSPOSE(ROW(A2:A)))*(ROW(A2:A)<=TRANSPOSE(ROW(A2:A)+1)) ) , A2:A)

How to make Google Sheet arrayformula work with date functions

I have a column of dates with the format "yyyy-mm-dd". And I want to do summary statistics by month -- using native formulas.
When I put arrayformula around month(...)>month(...), I get the error
Result was not expanded automatically, please insert more rows (1).
Why is that? And how do I get around that?
Example sheet. Formula in B4.
=arrayformula(month(B4:B)>month(B3:B))
Note: I don't know the number of rows ahead of time -- it is expected to update from time to time.
Firstly, erase your formula, it is trying to automatically expand the sheet and the sheet already has over 50,000 rows.
Next delete 48,000 rows or so.
Next put this formula in cell B4:
=arrayformula(month(B4:B)>month(arrayconstrain(B3:B,rows(B4:B),1)))
That will prevent the formula from auto-expanding the sheet.
That should work, though I think you're going to realize you don't like what happens when the year changes. I believe this to be an xyProblem.
=arrayformula(if(isblank(B4:B),,month(B5:B)>month(B4:B)))
works.
It seems it is always better to include an isblank() wrap to avoid indefinite expansion of the sheet.

Is there a way to use ARRAYFORMULA to find the most-recent even input of a column?

SOLVED EDIT
Thank you for the help. Solution here.
ORIGINAL POST
I have made a google sheet to describe the issue I am facing linked here (https://docs.google.com/spreadsheets/d/1yK6ZAX8BFnEqiuQO9HIxuY0l62ewDDccj-8EN1r2i2w/edit?usp=sharing).
I will also describe in words, below, the problem I am facing, along with the solutions I have tried.
The data of column A are random single-digit (0-9). I would like column B to show the most recent even number from column A, but only up to a specific row. That specific row is the row corresponding to the row of the cell in column B. In other words, in cell B7, I want to find the most recently entered even number of column A, specifically only on the range A2:A7 (A1 contains a column header).
This is actually a pretty simple formula, and I can get the desired outputs by simply checking if the value in a cell in column A is even and then returning the value of that cell if it is, or the output of the cell above if it isn't. So the formula would look something like: ​=IF(ISEVEN(A7),A7,B6)​
However, my problem is that the length of the data in column A will be growing as more data are entered, and my current solution of using the fill handle to copy the formula to new cells is inelegant and time-consuming. So my desired solution is to use an array formula entered into the first cell of column B (B2), capable of returning the same value as the other formula. The formula I tried to enter to perform this was the following: ​=ARRAYFORMULA(IF(ISEVEN(A2:A),A2:A,INDIRECT(ADDRESS(ROW(A2:A)-1,2))))​
However, as some of my previous work with arrays has taught me, not all formulas iterate as expected down the array. The formula seems to be able to return the correct output on lines which are already even, but it is unable to return the expected most-recently entered even number for all the other lines. It appears that the formula is not able to appropriately interpret the ​value_if_false​ argument of the ​IF​ formula.
I'm a little new to scripting, so I'm still trying to learn, but I also tried to dabble around with custom functions to no avail. I'm still wet behind the ears when it comes to coding, which is why I've been so lenient on the built-in formulas of Google Sheets, but I fear I may have reached the limit of what Sheets formulas can do.
I am open to trying new approaches, but my only real constraint is that I would really like for this to be a one-touch (or even better no-touch) solution, hope that's not too far beyond the scope of this issue. Any assistance would be much appreciated.
EDIT
After rubber-ducking the problem here, I went back and tried to use the OFFSET formula, hoping I could get it to play nicely with the array formula. Alas, I was unable, but I thought I should at least post my progress here for reference.
Attempt with offset
Still working at it!
Doing a vlookup on the row number seems to work for me
=ArrayFormula(if(A2:A="","",vlookup(row(A2:A),{if(iseven(A2:A),row(A2:A)),A2:A},2)))
Note: if there are no even numbers in range for some rows, it will produce #N/A for those rows.

Google Sheets Recursive Array Formula

I'm trying create a list of sequential dates from a set date to the most recent date in another column.
=ARRAYFORMULA(IF(OR(A2:A=MAX(C:C),A2:A=""),"",DATEVALUE(A2:A+1)))
I use MAX() to find the dates most recent date in column C. What I'm trying to get this formula to do is to recursively check the date in the cell above to determine if the max date has been reached. I've made sure A2 already has the set starting date.
The output is in only one cell though and I don't know why.
Thank you for the help.
What appears to be troubling your current array formula is that as defined it goes on forever and is self-referential. There may be a way to make it by setting preferences to be iterative and helping it interpret getting to repeated cells with "" as convergence.
Here is a way to sidestep those issues. You can bulletproof it more (for example, by encasing it in an IFERROR), but basically you can calculate exactly how many entries you need, and then set your range in the Array formula accordingly. In A3 you place the following:
=arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-A2+2)))+A2-2))
which will construct the exact range you want, then calculate each entry with an explicit rather than recursive formula.
EDIT: the above implementation assumes you need at least 2 dates. You can handle that case and other weird ones with the following, less readable formula, =if(max(C:C)>A2,iferror(arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-$A$2+2)))+$A$2-2))),"")

Resources