In array formula, find last specific value up till each row - google-sheets

I have a Google Sheets in question. Here is a mocked version that you can copy or comment on: https://docs.google.com/spreadsheets/d/1szcfZt_CtE0Cd_evKJwN4enZE7JcmDFcw9XhoX-_mlw/edit?usp=sharing
The sheets comes with 2 columns, Test number and Test result. I'd like to use array formula to automatically fill column C whenever new tests are entered. The specification is that the number in column C should always refer to the last "Fail" test number up till each row. You can see the expected result in column E.
I can come up with many solutions that require a formula to be applied to each new cell, which I think is iterative approach. One example is in column G. The reason is that "up till the current row" can't be met with array formula. I tried QUERY function with no success. I know App Script can do this too, but that's not auto fill approach as well.
EDIT: Added a brute-force solution, which can only work with limit number of consecutive "Pass" results.

Please see the screenshot for a solution using an array formula.

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"),))

Error "Result was not expanded automatically, please insert more rows": how to add rows automatically?

I use an ImportRange formula to get data from multiple tabs into single one. The formula looks like
=QUERY({IMPORTRANGE("123","B1!A2:D");IMPORTRANGE("123","B2!A2:D")},"where Col1 is not null", 0)
Is it there a way to add rows to table automatically if they are needed? With formula or setting - not by app script.
I had the same problem
Added another "arrayformula" to my original formula:
=INDEX(QUERY(...))
Made some tests and appeared all array-like formulas will add new rows automatically, including query. This means adding a new array function to your original formula will force the engine to recalculate again and add new rows. In general, this case looks like a bug / not expected behavior. The reason may be in the limit of resources the formula has, and it stops the work if calculations are heavy.
Limit test: Sequence
This formula will work:
=SEQUENCE(50500)
This will produce an error:
=SEQUENCE(50501)
After you add a new row manually, the formula works again.
Adding new formulas like INDEX(SEQUENCE(50501)) does not fix the error.
Limit test: array-like functions
I've also tested these functions:
QUERY
{Array}
SEQUENCE
Offset
Sort
Index
ArrayFormula
All of them stopped working after row 50501 including.
Possible Script solution
Possible to get the number of rows from the original formula.
=ROWS(SEQUENCE(50501))
Next, create a trigger to execute every N minutes to add new rows to your sheet.
Source
My Sample file with tests
All tests were made by date and in my environment. Your own tests may vary.
The sheet pulling the data (importrange) from another sheet does not have sufficient rows to display the data. Add more rows to the sheet - this solution worked for me. Ideally, this should have happened automatically, but it did not.
Refer:
https://support.google.com/docs/thread/4985024/error-in-gsheets-result-was-not-expanded-automatically-please-insert-more-rows-4

COUNTIF Formula moves down when row at top added

I have the following COUNTIF Formula in my Google Sheet.
=COUNTIFS('Events/Incidents'!$E$3:$E,X4,'Events/Incidents'!$I$3:$I,"Accident")
This is a sample of the sheet which has the formula in the first row under the "Accidents" header:
It works until a user adds a row 3 to the top of the source sheet (Events/Incidents) then the formula changes to the following so that it captures row 4 down instead of the desired row 3.
=COUNTIFS('Events/Incidents'!$E$4:$E,X4,'Events/Incidents'!$I$4:$I,"Accident")
I used the Query function for "All Events" (the first 3 columns). The Countif formula is under each of the Incidents. In my Countif example, X4 is the Employee, John White which was returned in the QUERY.
The QUERY continues to return/include row 3 but I don't know how to do this for the individual Incidents. I tried adding ArrayFormula to the Countif function but I have the same problem.
Would appreciate some help with this.
I understand that you want to update your QUERY to reflect the correct row without resorting to returning the Branch in every response. If my comprehension is correct, there is a way to reach your goals with little modification.
First, you'll have to create a named range that includes the whole table (from the headers to the last row). You can then use this named range in every formula so new rows can be detected without changing the formula per se.
Finally, you can modify your QUERY to return only the values of Incidents in a Branch with something similar to =QUERY(myNamedRange,"SELECT G WHERE A = 'Auckland'"). That QUERY won't return the Branch, only the Incidents. If you keep having any doubts, please ask me for further help.
I worked it out by combining Countifs with ImportRange:
=COUNTIFS(IMPORTRANGE("1-f6OU8ylDSlpqdpt4P5B7GDcIel3IboVkUbY2huMA6U","Events/Incidents!$E$3:$E"),X4,IMPORTRANGE("1-f6OU8ylDSlpqdpt4P5B7GDcIel3IboVkUbY2huMA6U","Events/Incidents!$I$3:$I"),"Accident")

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.

Return column header for last date in Google Sheets as an array formula

I've got a number of columns used to track some stages of Google Sheets entries with dates. I'd like a column that returns the latest stage for each entry, preferably using an array formula since this is a list that will be constantly added-to and copying the formulae down to new rows is a pain (this is something that will end up in with an end-user so needs to be straightforward).
This is a sample of my desired input/output.
I tried using array formulae combined with this lookup trick, but I think changing the inputs of that formula to multi-row ranges means the result ignores what row the entry is on. For instance wrapping the lookup in ARRAYFORMULA and applying it to the sample returns "Stage4" on every line. Alternatively I think there might be a way to do this using QUERY/FILTER but I'm getting nowhere. Thanks everyone.
EDIT: For clarification, the 'Stages' are not going to be numbered, but will be text fields (potentially dynamic ones, hence my reticence to use an HLOOKUP).
Assuming "Stage1" is in cell A2 and that you can not jump stages. You can use this formula on F3 to auto-populate your output:
=ArrayFormula(transpose(
split(
concatenate(
if((A3:D<>"")*(B3:E=""),A2:D2,"")&
if(column(A2:D2)=column(D2),char(9),"")
)
,char(9),true,false
)
))
You can see that we're determining the stage by checking the not empty that is followed immediately by an empty one. Hence the no jumping stages rule :-)
Also, this requires an extra empty column after the last stage column (in your example, column E must be empty).
ps: added bonus, this formula also works for "no stage" rows ;-)

Resources