InsertRowBefore() + Defined Range question - google-sheets

I have a bit of code that inserts a blank row to the top of a sheet and copies data into it.
I also have a defined range on that sheet.
Every time a row is inserted, the defined range moves down a row.
The defined range is helping power a query on another sheet and therefore is always missing the inserted rows.
If i delete the query and use importrange, it works no issue.
However the query doesn't work with importrange.
The easiest fix I'm assuming would be to 'hard-code' the range, but how would i call that in my query?
Here is the query, followed by the same query using importrange.
=IFERROR(QUERY(STOCK_IN_DATA,"SELECT *" & IF((LEFT(D4,1))="*","WHERE D STARTS WITH '"&RIGHT(D4,LEN(D4)-1)&"' AND C CONTAINS '"&$C4&"' AND E CONTAINS '"&$E4&"' AND F CONTAINS '"&$F4&"' AND G CONTAINS '"&$G4&"' AND H CONTAINS '"&$H4&"'","WHERE C CONTAINS '"&$C4&"' AND D CONTAINS '"&$D4&"' AND E CONTAINS '"&$E4&"' AND F CONTAINS '"&$F4&"' AND G CONTAINS '"&$G4&"' AND H CONTAINS '"&$H4&"'")),)
=IFERROR(QUERY(IMPORTRANGE("SHEETNAME","MASTER_IN!$B$1:M"),"SELECT *" & IF((LEFT(D4,1))="*","WHERE D STARTS WITH '"&RIGHT(D4,LEN(D4)-1)&"' AND C CONTAINS '"&$C4&"' AND E CONTAINS '"&$E4&"' AND F CONTAINS '"&$F4&"' AND G CONTAINS '"&$G4&"' AND H CONTAINS '"&$H4&"'","WHERE C CONTAINS '"&$C4&"' AND D CONTAINS '"&$D4&"' AND E CONTAINS '"&$E4&"' AND F CONTAINS '"&$F4&"' AND G CONTAINS '"&$G4&"' AND H CONTAINS '"&$H4&"'")),)
What the query does is create a nice little search filter in the cells shown on row 4.

QUERY can use A, B, C columns names only when a reference is used as the first argument. When an array is used as the first argument, as in this case IMPORTRANGE, you should use Col1, Col2, Col3 as column names instead of A, B, C respectively.

Related

Google sheets - format a column by comparing values with another

I have a google sheet with 2 columns, one has unique values the other one a list of several values;
I need to know if all the values of my first column are somewhere in the second one
Thank you
Column A
Column B
A
A, B, C
B
D, E, F
D
G,R, Y
I tried with =COUNTIF(FILTER(B:B,A:A=ROW(A:A)),C:C) > 0
But I can't manage to write this formulae correctly
I expected the column A to be green if the value exists in column B
With REGEXMATCH you'll be able to find the value in the next column. Try with:
=REGEXMATCH(B1,A1)*(A1<>"")
OPTION 2
Above was to checking if it appears in the corresponding row. To check the entire column with more than one value per row:
=REGEXMATCH(TEXTJOIN(",",1,B:B),A1)*(A1<>"")

Dynamic query formula nested inside an array

I have a query formula in Google sheets that updates based on additional columns of data in my Google Sheet seen here =QUERY('Deals List - URL Split'!A:DZ, "select A, C where C contains 'http'",)
So it may add QUERY('Deals List - URL Split'!A:DZ, "select A, E where E contains 'http'",)and then it will end up becoming the below and so on for each additional.
=QUERY('Deals List - URL Split'!A:DZ, "select A, C where C contains 'http'",);QUERY('Deals List - URL Split'!A:DZ, "select A, E where E contains 'http'",)
What I am trying to do is have the resultant query formula which is in cell 'List'!A1 as QUERY('Deals List - URL Split'!A:DZ, "select A, C where C contains 'http'",);QUERY('Deals List - URL Split'!A:DZ, "select A, E where E contains 'http'",) be used in an array formula as a reference so I don't have to update the formula each time a new query formula is added.
The static query formula is
=SORT(ARRAYFORMULA({QUERY('Deals List - URL Split'!A:DZ, "select A, C where C contains 'http'",);QUERY('Deals List - URL Split'!A:DZ, "select A, E where E contains 'http'",)}),1,TRUE,2,TRUE)
and indeally the one that gets the dynamic formula would be like below but I always get an error and get just the literal static formula above.
=SORT(ARRAYFORMULA({'List'!A1}),1,TRUE,2,TRUE)
I think I have an answer (or two) for you. After looking at your sheet, I have to say that I am sure that a simpler design is possible for your sheets, that would simplify everything. Anyway, I've built one formula, using only your data on sheet '2 URL SPLIT'!, and the desired columns from '4 URL FILTER'!A1:1. See my sample tab, GK-6 ITEMS AND URLS, added to your sheet.
The formula, reduced to its basic form, is:
={
IFERROR({'2 URL SPLIT'!$A$2:$A, INDIRECT(INDEX(
{ARRAYFORMULA(IFERROR("'2 URL SPLIT'!"
& TRANSPOSE('4 URL FILTER'!1:1)
& TRANSPOSE(SPLIT(
{"2:"
& TEXTJOIN("~2:",1,TRANSPOSE('4 URL FILTER'!1:1))},"~",0,0))
& ROWS('2 URL SPLIT'!A:A)))},1,0))},{"",""})
}
The formula is not truly dynamic, but it ignores blank columns. So the cheat I've used is to expand the capacity of the formula to include extra blank columns, and if they get filled with data, the data will be used. I've set it to include 50 columns of data, where you are currently using 39, but you could expand it to handle about 200 columns, before it reaches the 50,000 character limit of a cell.
The formula as shown above handles one column. For the one that handles fifty columns, as in my sample sheet, I simply duplicate the inner formula, everything inside the outer braces "{....}" and increment the number in it. You only need to do this once, or copy mine from my sheet. You do not need to update if/when your data columns expand.
I'm happy to add much more explanation if you decide that this formula works for you. But the basis of the formula is dynamically building the ranges of cells to query. The result of this inner part of the formula is shown below. Note that the 2 in each range is hard-coded, and can be changed if your structure changes, but the limit of the range is calculated from your data.
The rest of the formula uses an index into this "table", incrementing by one to select each successive data range, which adds a new column of data to be queried. These data ranges from '2 URL SPLIT!' include column A and one subsequent data column, as specified in '4 URL FILTER'!A1:A, and are stacked one above the other, by using a ";" separator.
The query is then run against this vertical, two column stack, selecting all rows where column 2 contains "http".
The final result is shown below:

Find and replace by multiple patterns

Suppose I've got a text values column (named Data), generated by =unique() function. Also, there is an array of patterns to find and replace for (Find and Replace columns).
Which formula should I use to scan each cell in Data for multiple patterns in Find and replace it, if match?
Data Find Replace Result
1 a c z a
2 b f y b
3 c e x z
4 d d
5 e x
6 c z
Tried =SUBSTITUTE() and =IF() functions, but it fails, when I set an array of patterns, instead of single one.
If the table you is in range A1:E7, try this formula
=TRANSPOSE(SPLIT(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(ARRAYFORMULA(CONCATENATE($B$2:$B$7&"|")),$C$2,$D$2),$C$3,$D$3),$C$4,$D$4),"|"))
You can read further about this in an older post and google docs forum.
Array solution
This formula takes range to replace, so it can be used for variable number of patterns:
=QUERY(ARRAYFORMULA({REGEXMATCH(A2,$B$2:$B$4),
REGEXREPLACE(A2,$B$2:$B$4,$C$2:$C$4)}),
"select Col2 order by Col1 desc limit 1")
or this one:
=INDEX(ArrayFormula(REGEXREPLACE(A2,$B$2:$B$4,$C$2:$C$4)),IFERROR(MATCH(A2,$B$2:$B$4,0),1))
or this:
=IFERROR(INDEX($C$2:$C$4,MATCH(A2,$B$2:$B$4,0)),A2)
The formula is need to be dragged down.
Single Formula & Array solution
Also this single ArrayFormula will do the trick:
=ArrayFormula(trim(transpose(query({IF(--REGEXMATCH(TRANSPOSE(A2:A7),$B$2:$B$4)=1,
REGEXREPLACE(TRANSPOSE(A2:A7),$B$2:$B$4,$C$2:$C$4),"");
TRANSPOSE(if(--not(REGEXMATCH(A2:A7,JOIN("|",B2:B4))),A2:A7,""))},,COUNTA(A2:A)))))
or this shorter formula:
=ArrayFormula(IFERROR(VLOOKUP(MATCH(A2:A7,B2:B4,0),{ROW(INDIRECT("a1:a"&COUNTA(C2:C4))),C2:C4},2,0),A2:A7))
Please, see explanations in Sample file

Lookup value based on latest matching criteria

Below is an example of a table I have, what I am trying to do is get the value in the value column for a specific criteria based on the last occurrence (not including today's date).
So in the example below I want to find the value for the last occurrence of 'A', which is 12.
I think this can be done using an Index-Match, I just can't get my head around it though.
For example
Todays Date: 15/12/2013
---------------------------------|
|Date | Criteria | Value
|--------------------------------|
|12/11/2013 | A | 3 |
|16/11/2013 | B | 6 |
|27/11/2013 | C | 7 |
|3/12/2013 | A | 12 |
|5/12/2013 | B | 8 |
|15/12/2013 | A | |
----------------------------------
EDIT:
I would also like to add that this formula will be in a different sheet to the table above. The sheet reference in the formula also needs to be dynamic, it will draw the sheet name from another cell.
I would use this formula:
=index(C:C,max(arrayformula(match(filter(A:A,B:B="A",C:C<>""),A:A,0))),1)
This formula assumes that your data is in the columns A,B,C and for every "A" value in the Criteria column, the Date is different. (If that's not the case, then this formula won't work, see below.
Let's look the formula inside from outside:
filter(A:A,B:B="A",C:C<>"") - This will result with the dates where there is an "A" in the Criteria column, and where the Value column is not empty.
arrayformula(match(filter(A:A,B:B="A",C:C<>""),A:A,0)) - In this step we basically find the row number in which those dates are present. The match function will search for the dates (counted in step 1). The arrayformula is needed because there will be more results.
max(arrayformula(match(filter(A:A,B:B="A",C:C<>""),A:A,0))) - This will find the maximum row number (The maximum row number which contains an "A" in the Criteria column)
index(C:C,max(arrayformula(match(filter(A:A,B:B="A",C:C<>""),A:A,0))),1) - Finally, we use the INDEX function to navigate to the value, which has the maximum row number.
Now, if you want this formula to work on another sheet, you should write, instead of for example:
=index(C:C,... => =index(Data!C:C,...
Assuming that your data is in your Data worksheet.
If you want to this sheet to be dynamic, it's a bit tricky. Let's assume, that you're getting the value of the sheet name from the G1 cell. Then you should write:
=index(indirect(concatenate(G1,"!C:C")),...
This is not so pretty as you should do this for every occasion when it occurs in that long formula (described earlier). Instead you can do some pre-work.
Let's write this to your H1 cell: =concatenate(G1,"!C:C") - If in the G1 cell the sheet name is "Data", then the H1 cell should contain: Data!C:C, similarly you can add to the
H2 cell: =concatenate(G1,"!A:A"),
H3 cell: =concatenate(G1,"!B:B")
Now you can write (and that's the final answer for your question I think):
=index(indirect(H1),max(arrayformula(match(filter(indirect(H2),indirect(H3)="A",indirect(H1)<>""),indirect(H2),0))),1) - where H1,H2,H3 will reference to your Data sheet's columns.
I hope it helps.
Use the following formula to accomplish that.
Formula
=QUERY(
B1:D6, // data
"SELECT D // select
WHERE // where clause
C = 'A' AND // first criterium
D IS NOT NULL // second criterium
ORDER BY B DESC // order by
LIMIT 1, // limit
0" // headers
)
for copy/paste
=QUERY(B1:D6, "SELECT D WHERE C = 'A' AND D IS NOT NULL ORDER BY B DESC LIMIT 1", 0)
Explained
The clue to the formula is the usage of the ORDER BY and the LIMIT options within the QUERY formula. The WHERE clauses will prepare the result in the first place. Next, column B (the dates) is ordered descendingly (highest first). The LIMIT option sets the amount of rows to be displayed at 1.
Example
I've created an example file for you: Lookup value based on latest matching Criteria
I appreciate this is a slightly old question, but there is a way that I achieved the goal of filtering an array which I found both more conceptually straightforward, and also more generally applicable than the other answers I have seen, using vlookup's definitional ability to pick the first matching value in an array.
PROBLEM, RESTATED:
Assuming sample data:
A...B...C...D...E, created by a google form
A is the form entry date
B, C and D are entries from a list (let's assume they are e.g. product name, geography, and sales date)
E is the value
If a new value is entered for a particular product, in a geography, on a date, then I want this to be used in preference to the older version of that same data.
SOLUTION:
If, in your form, you create three new columns:
F Unique test
G Test cells combined
H Unique cells
Then in column G, you create a combination of all the cells you want to test on (in this case B, C and E)
cell G2: "=arrayformula(B2:B & char(9) & C2:C & char(9) & D2:D)"
The next column is a restatement of the cells you want to filter based on (in this case the date in A)
cell H2: "=arrayformula(A2:A)"
And then finally in column F we actually undertake the test:
cell F2: "=arrayformula(A2:A=vlookup(G2:G,sort({G2:H},2,false),2,false))"
Breaking that down, the vlookup (vlookup(G2:G,[RANGE],2,false) compares the data in G2, G3...Gn with a [RANGE], which is a virtual array consisting of two columns, G and H, pre-sorted according to cell H in descending order.
i.e. For any unique value of G (the combination of test data) the vlookup will return the largest value of H
The last part is a simple comparison to the original data (A2, A3... An) to return TRUE or FALSE based on whether it is the latest version of the unique value.
A final step if needed would be to create a new sheet with "=filter('Form Responses 1'!A:E,'Form Responses 1'F:F=TRUE) to recreate the data without the older versions.
Hope this helps.

Change Query Source depending on Cell Value

I use cell values on a sheet to change what values a query will be looking for. Is there a way to change what sheet the query is using as a source depending on the value of a cell?
This is the query I currently use. For example, if I type something in the cell C4, the query will only return values that contain whatever I typed in C4.
=Query(Input!A:AD,"select * where C contains """&C4&""" AND D contains """&D4&""" AND E contains """&E4&""" AND F contains """&F4&""" AND G contains """&G4&""" AND H contains """&H4&""" ORDER BY A desc",2)
I now want to have this same concept, but change Input!A:AD to whatever I type in cell A4. A4 could contain "Input", but if I change A4 to "Archive", I would like it to "read"
=Query(Archive!A:AD,"select * where C contains """&C4&""" AND D contains """&D4&""" AND E contains """&E4&""" AND F contains """&F4&""" AND G contains """&G4&""" AND H contains """&H4&""" ORDER BY A desc",2)
I've tried similar wildcards like &A4& and """&A4&""" in place of the sheet name, but this returns errors. What am I missing?
You can try with the following formula, adapting it to their needs:
=QUERY(INDIRECT(C2); "SELECT *")
Here's an example:

Resources