How to use index match formula that automatically expands in Google Sheets - google-sheets

In Google Sheets I am using a filter function to pull in Names into column A and a Timestamp into column B. Every time a second occurrence of the name shows up into columns A & B of the list I want column C next to the prior occurrence to reference the new timestamp. In column D I will then calculate the difference from the names timestamp and the next occurrence of that same name.
Currently I am using the following formula:
=IFERROR(INDEX(B3:B,MATCH(A2,A3:A,0)))
If I drag this formula down it does what I need it to do, but due to how many rows are being added to the first two columns, rows are being added to the bottom of the sheet due to the filter and the formulas keep needing to be dragged down. The durations in column D are being calculated with the following formula, that automatically arrays the results and automatically expands with the filter results:
=IFERROR(ARRAYFORMULA(IF(C2:C="","",C2:C-B2:B)))
I would like my index match formula to do the same, but it seems I cannot use the index formula with an arrayformula.
I attempted to achieve this by using a vlookup combined with an offset for the range. The first row is giving me the result I want, but all the subsequent rows are not referencing the offset range, probably because the offset isn't changing with each new array result here is that attempt:
=IFERROR(ARRAYFORMULA(VLOOKUP(A2:A,OFFSET(A2:B,1,0),2,FALSE)))
Any ideas how this could be accomplished by placing a formula in one cell, or would this have to be accomplished with a script?
I have added an example spreadsheet of the current method HERE
Thanks in advance for any help.

Formula
Instead of
INDEX, MATCH and OFFSET
try the following formula
=ArrayFormula(IFERROR(VLOOKUP(
TRANSPOSE(VALUE(REGEXEXTRACT(QUERY(TRANSPOSE(
IF(FILTER(ROW(A2:A),LEN(A2:A))<TRANSPOSE(FILTER(ROW(A2:A),LEN(A2:A))),
IF(FILTER(A2:A,LEN(A2:A))=TRANSPOSE(FILTER(A2:A,LEN(A2:A))),
TRANSPOSE(FILTER(ROW(A2:A),LEN(A2:A))),
),)
),,2000000),"(\d+)"))),
FILTER({ROW(A2:A),B2:B},LEN(A2:A)),2,0)))
Formula description
This part creates a square matrix showing the row number of the value that matches if it's below of the current row:
IF(FILTER(ROW(A2:A),LEN(A2:A))<TRANSPOSE(FILTER(ROW(A2:A),LEN(A2:A))),
IF(FILTER(A2:A,LEN(A2:A))=TRANSPOSE(FILTER(A2:A,LEN(A2:A))),
TRANSPOSE(FILTER(ROW(A2:A),LEN(A2:A))),
),)
This part takes the smallest row that matches the current row (the next occurrence of the row value)
TRANSPOSE(VALUE(REGEXEXTRACT(QUERY(TRANSPOSE( ),,2000000),"(\d+)")))
This part returns the related value, if any, otherwise a blank:
IFERROR(VLOOKUP( ,FILTER({ROW(A2:A),B2:B},LEN(A2:A)),2,0)))

Related

Is there any solution to left the cell empty

i have a sheet along with this question,the formula used in column E2 is : if(and(d2>=0,d2<=2),5. So when the column is blank it gives the value 5 My query is can we left the "E" column blank when there is no value in "D". ??? 5 must displayed only if there score between 0 & 2.
https://docs.google.com/spreadsheets/d/1XpdXcWDReB8TGvZ6ocALAilVPLDKzZXvd90YhNos0Io/edit?usp=sharing
Iker. I've added a sheet with two approaches.
If you want to drag the formula, just set an initial IF that rules out blanks like this:
=if(D2="","",if(and(D2>=0,D2<=2),5,if(and(D2>=3,D2<=4),0)))
I placed this into my sheet, E2, and dragged down as you were doing.
However, this is a great example of where array formulas are handy. An array formula can "run" your whole column from just one cell. I placed the following array formula into cell I1 of my sheet:
=ArrayFormula({"POINT";IF(H2:H="","",IF((H2:H>=0)*(H2:H<=2),5,IF((H2:H>=3)*(H2:H<=4),0,"")))})
First, keep in mind that array formulas must have unused space below them in order to fill in results. If you type anything manually below an array formula, inside the range it is trying to work on, you'll get an error. If you do want to put other data below an array formula, just limit the range in the array formula (e.g., change every H2:H to H2:H6 or whatever the end of that data range might be).
ArrayFormula() tells Google Sheets to apply this formula to the entire range in the formula. Since the range in the formula is H2:H, every cell in I2:I will be "reserved" by this array formula.
The curly brackets {} allow us to build another custom array inside the first array.
Since I want a header in I1, I put that header name first in the curly brackets. The semicolon tells the array to put the next part underneath.
The next part may look strange, but it's basically the same as your original formula, except that AND(), OR(), etc., don't work inside arrays. So the logical operators inside arrays are different. In this case, an asterisk * means AND.
The same conditions from your original formula are used here. And if it meets none of those criteria (for instance, if someone entered -1 or 7 or M somewhere in Column H, the last part of the last IF would just assign a blank.
You can use an added IF to your formula
=IF(D2="","", if(and(D2>=0,D2<=2),5,if(and(D2>=3,D2<=4),0)))

How to use ARRAYFORMULA with OFFSET to previous row without getting circular reference error

Example sheet: https://docs.google.com/spreadsheets/d/14ma-y3esh1S_EkzHpFBvLb0GzDZZiDsSVXFktH3Rr_E/edit?usp=sharing
In column B of ItemData sheet, I have achieved the result I want by copying the formula into every cell in the column, but I want to solve this using ArrayFormula instead.
In column C I have achieved the same result using ArrayFormula. However, for addition, column C is referring to cells in column B, while column B is referring to cells in column B. I.e. every cell in column B is adding 1 to the cell on the row above.
If I select the C3 formula text and paste it into the cell edit field for cell B3 (to not screw up cell references during copy - I know I could make them static references, but this is not my problem), the cell gets an error value of
#REF!
Error
Circular dependency detected. To resolve with iterative calculation, see File > Spreadsheet Settings.
Do note that the additions that need to be done are the same in both cases: Add 1 to the value of the cell on the previous row, so there is no circular reference involved. There is a starting value provided in B2, and cells in B3 and downwards should use the data from the B cell in the previous row.
Also, note that I did try File->Spreadsheet settings and enabling circular reference computation with max 25 items, but this only fills in the first two cells (B3 and B4).
How can I solve this problem? I would prefer having something like ArrayFormula, where the formula only exists in a single cell. But copy-pasting would be acceptable as long as any new rows, inserted in between or added at the bottom, would get the same formula added in column B.
Will matching items always be consecutive? It seems that way since you're comparing each Item cell to the cell above it right in your formula logic. That breaks an [unwritten?] rule of spreadsheet normalization; values' addresses themselves generally should not be treated as data.
IF you're committed to it though, have you considered explicitly using location as a data source? Example:
=ARRAYFORMULA(IFS(
NOT(LEN(A3:A40)),,
ROW(A3:A40)-3-MATCH(A3:A40,A$3:A$40,0)<=VLOOKUP(VLOOKUP(A3:A40,Items!$A$2:$D,2,false),DataPerColor!$A$2:$B,2,false),ROW(A3:A40)-3-MATCH(A3:A40,A$3:A$40,0),
true,
))
Just like your formulas, all that does in English is:
for each row,
if there's no Item, don't output any ItemData,
if the number that belongs in this cell¹ is less than or equal to the lookup, print it,
otherwise, don't output any ItemData
But then what is ¹ "the number that belongs in this cell" and how can we calculate it without using column B? I abuse locations of things to get it. Looking down your row B, each number that appears is just:
this row's number,  minus  
the row where items start [always 3],  minus  
the row number [in just the Item rows] of the first row containing this row's Item
Using the second-to-last ItemC as an example: the first ItemC is the 16th item listing, and the one we're looking up… the "second-to-last ItemC" is in row 21 of the sheet. 21-3-16 = 2 …the number you wanted.
If you can stomach that, it's a single formula and does work according to your specifications.

Specify Column Range Except Second-to-last Row

I am currently using SUM on an entire column with the following formula:
=SUM(A2:A)
Unfortunately this total is displayed on the last row of this column, so it creates a circular reference, #REF, there that I need to get rid of. How can I make it so that it selects the column starting from the second row until the second-to-last?
I could change the formula manually every time I enter a new row, but that's not ideal at all.
Pseudocode
=SUM(A2:A[last row - 1])
See if this works
=sum(indirect("A2:A"&row()-1))

How to apply a formula to cells in a given range?

I have a sheet that is the result of a query and can return an arbitrary number of result rows (the number of columns is fixed).
I am calculating the range that corresponds to the result set. This is working well. I use it to copy the result set into my sheet.
Now that I have the results copied to my sheet I want to add a column with a formula that works against the cells in the row. How to do this? The issue is that the number of rows is not fixed, how to have the formula apply to the rows that happen to be there.
Here is a sample sheet:
Result Set is the output of the query
Report is the sheet I made with a copy of the result set
Link to Sheet
Column C is what I am trying to populate, the number of rows for Columns A and B will update each time I open the sheet.
Another way:
=arrayformula(if(A13:A<>"",A13:A&"="&B13:B,""))

Working with hierarchical data in Google Sheets

If I have hierarchical data in a Google Sheet as in columns A and B in the example below, how can I write a formula that will fill the corresponding cells in column C with the product of the "parent" value in A1, and the "child" values in column B. That is, The formula in C8 for example, will search upward in column A until it finds the value 5 in A6, then multiplies it by 8, the value in B8.
Obviously I'm trying to avoid having to put the "parent" value in every row in column A.
After a fiddling around and jogging my memory on ArrayFormulas I figured out how to get the result I wanted. Here's the formula I'm using:
=ArrayFormula(index($B$2:$B2,MAX(IF(ISNUMBER($B$2:$B2),ROW($B$2:$B2)))-1,1))
(Note: Row 1 contains headings)
Edit: Explanation of how I arrived at this solution:
Ordinarily, IF(ISNUMBER(cell)), and ROW(cell) would return TRUE/FALSE, or a row number respectively. When used in an array formula and a range of cells as input instead, what you get is a list of TRUE/FALSE values, and row numbers evaluated for each cell in the input range. Wrap MAX around that and it will return the position in those two lists where IF(ISNUMBER()) is TRUE and the row number returned by ROW() is the highest, effectively searching from the bottom of the range.
The absolute reference for the first element in the range to be searched (in this case $B$2) keeps the range anchored to the same starting location when dragging the formula into other cells, while the lower bound of the range (in this case $B2) to be searched grows vertically.
Finally, the INDEX takes the input range, row number returned by the above (-1 row because of the header) and column position (1, since there is only one column) in order to return the desired value.
One way you could do this would be to associate each value in column B with a category or key that can be used to lookup the value for A in a separate table. This abstracts it somewhat, so you can change the values for the A column without having to have them in every row, but there's no empty cells.
i.e.
and lookup table:
In column C
= VLOOKUP($A1, <range for category lookup table>, 2, 0) * $B1
(And then this formula can be filled down)
More on VLOOKUP in Google Sheets here
Alternatively I suppose you could use a formula to find the last non-empty row in column A, or something along those lines, but this is more of a hack than a proper way to structure your data. Tables aren't really designed to be used in a hierarchical fashion like what you've shown. But they can easily represent hierarchical data using techniques like what I've suggested.

Resources