Why does my importrange query fail when I "wrap" with arrayformula - google-sheets

I have the following formula which is currently returning the expected results -
=join(",",query(importrange(vlookup(mid(G4,1,find(",",G4)-1),xref,2,false),vlookup(mid(G4,1,find(",",G4)-1),xref,3,false)),"Select Col3,Col6,Col9 where Col1 = '"&mid(G4,find(",",G4)+1,20)&"' "))
However, I naturally want to make this as dynamic and flexible as possible so I would like to "wrap" it in an arrayformula which ends up like this -
=arrayformula(join(",",query(importrange(vlookup(mid(G4:G,1,find(",",G4:G)-1),xref,2,false),vlookup(mid(G4:G,1,find(",",G4:G)-1),xref,3,false)),"Select Col3,Col6,Col9 where Col1 = '"&mid(G4:G,find(",",G4:G)+1,20)&"' ")))
This formula gives me "Unable to parse query string for Function QUERY parameter 2: NO_COLUMNCol3" error.
I tried to include an iferror to try to trap some error but this made no difference.
I tried various angles to debug and basically focussed on the importrange not providing the data to the query once it was wrapped by the arrayformula. I tried to explicitly reference the external sheet key and range in the importange function, instead of using the lookups, and this did give me a result - but only in the first cell. There should also have been a result returned about 4 rows down.
If I copy the formula down the column, I do get the expected result 4 rows down, but this obviously defeats the purpose of the arrayformula.
In my research in the Google forums there were some suggestions that arrayformula and importrange may not play well together, but no hard and fast facts.
I noticed in this forum that the combination of the two functions has been mentioned but no indication that they did not work together, so I am wondering if there is just some little thing I am missing in my syntax that is causing my ideal scenario not to work ?

I don't think this will work for a couple of reasons.
Firstly, not all the functions in Google Sheets can be automated using an arrayformula, and QUERY is one of them. As far as I know this is because the output of QUERY can be an array itself, so it is not possible to iterate an array output across another array (i.e. your results range).
Secondly, JOIN works across a either a single row or column, whereas your query outputs 3 columns. The arrayformula result would therefore consist of an array with multiple rows and columns, which JOIN cannot use.
I think the best solution is to use the IFERROR as you've described, and copy the single-row formula down the entire column - that way the blank records will not show as errors, but you will be able to add new values to column G and they will be picked up automatically.

Related

Unpivoting using QUERY function is not fetching the expected result

I am currently working on a dataset that includes several columns, mostly the dates. What I am trying to achieve is - unpivot all the date columns to use for my subsequent calculations. I use the following formula to unpivot: =ARRAYFORMULA(SPLIT(FLATTEN(Data!A2:A&"|"&Data!D1:AG1&"|"&Data!D2:AG),"|"))
Even though this returns the expected result, when I try to nest this within a Query function, it does not work correctly. This is how I applied the formula - QUERY(ARRAYFORMULA(SPLIT(FLATTEN(Data!A2:A&"|"&Data!D1:AG1&"|"&Data!D2:AG),"|")),"Select * WHERE Col3 IS NOT NULL")
PS: When I change the data range to say, A2:A100, it gives me the correct result. However, it does not help since lot of new data would get added and I want the formula to be dynamic.
Here's the link to the sample sheet - https://docs.google.com/spreadsheets/d/1dgFY5mT9nUJtFefjAros-XpWXRMFtxEf8Fqrv82N5Ys/edit#gid=1813140523
Any help/suggestions would be highly appreciated
Not sure where you got your SPLIT(FLATTEN technique,
but you have to include both the 3rd and 4th parameters of the split function as FALSE or 0. so in your case it would be:
=ARRAYFORMULA(SPLIT(FLATTEN(Data!A2:A&"|"&Data!D1:AG1&"|"&Data!D2:AG),"|",0,0))
If you do that you'll find your query works.
Also note that the way you have it it's not really working. If you look all the way down in column 1 you'll find a bunch of dates formatted to look like integers.

Google sheets formula - lookup (alphabetical sort)

I want to create a formula, that gets me the specific value(s) from row in another table. The formula I've created
=LOOKUP(E5;Ingredients!$A$6:$B$49;Ingredients!$F$6:$F$49)
gives me false results. But when I sort the values by alphabet the results are correct.
Is there some way to create a formula that is not dependent on alphabetical sort of source table?
From https://support.google.com/docs/answer/3256570?hl=en-GB
"Notes:
The LOOKUP function will only work properly if data in search_range or search_result_array is sorted. Use VLOOKUP, HLOOKUP or other related functions if data is not sorted."
Personally, I've never really used the lookup functions because of issues like this, so I'm a bit rusty on the specifics of how they all work. My go-to is the INDEX MATCH solution, which might be something like
=index(Ingredients!$F$6:$F49, match(E5, Ingredients!$A$6:A$49))
What I'm also not sure about is how Lookup is supposed to work when you're giving it more than one column as the input, though; you're giving it A and B - I thought that syntax was for an array where the output comes from the last column, and I don't know what happens if you then specify the output column as well, as you've done.

How to use AVERAGEIFS within ARRAYFORMULA

I am trying to use AVERAGEIFS inside ARRAYFORMULA. Looking at other questions, I have come to the conclusion that it is not possible without using QUERY function.
My intention is to average the values of a column whenever they share the same ID.
I think this question comes pretty close to what I need, but I haven't been able to replicate and adapt its solution on my own sheet.
In this sheet I show the result I expect (I got it by dragging the formula). I've also reviewed the Query Language Reference, unsuccessfully.
Thanks a lot for your time and effort.
So the formula should be
=ArrayFormula(iferror(sumif(A2:A,A2:A,B2:B)/countif(A2:A,A2:A)))
Note that if there were any text values in the points column, this would still return a result (because count would be greater than zero) - you could instead use
=ArrayFormula(if(isnumber(B2:B),(sumif(A2:A,A2:A,B2:B)/countif(A2:A,A2:A)),""))
If you had a mixture of rows with text and rows with numbers for any ID, this would return a smaller result than the avg or average formula. This is a limitation of this method. You can't put an extra condition in (that column B has to contain a number) because you would need countifs and countifs isn't array-friendly. It still seems strange that AFAIK countif and sumif are the only functions out of this family that are array-friendly while countifs, sumifs, averageif etc. are not.
you can do:
=ARRAYFORMULA(IFERROR(VLOOKUP(A2:A; QUERY(A2:B; "select A,avg(B) group by A"); 2; )))

Google Sheets, Is it possible to use Arrayformula to expand formulas downward when the formula uses arrays

I've been using Arrayformula to auto-expand formulas (such as "=Left(A2:A,B2:B-1") downward, but I need some help understanding this formula. I've read up on the function itself and browsed many forums about this but I can only find articles explaining how to use this with simple formulas, so I'm going to try to as this as simply as possible here: Is it possible to use Arrayformula to expand formulas downward when the formula uses arrays?
The summary for Arrayformula reads "Enables the display of values returned from an array formula into multiple rows and/or columns and the use of non-array functions with arrays." This was my understanding of how Arrayformula populated a formula into rows automatically. Using this I thought of it as writing a formula that generated an array of formulas, and then splitting them up with Arrayformula. This seems to not work with some formulas such as concatenate, which I will focus my question on. This example is far from my real life problem, but if someone could show me a solution I can apply it elsewhere.
Arrayformula spreadsheet example
Usually when I use Arrayformula with A1:A it would expand the formula through the column, referencing the corresponding rows as it went. With this example I want to have Column C be the concatenated result of columns A and B. Is this possible with Arrayformula? This question is not specific to concatenate, that is just the simplest one that came to mind. Another example would be Countif. Lets say I want to see how many values in the first 5 columns are over 20, and I want that formula to auto populate down, is that possible and if so how would it be done?
Arrayformula second example
P.S. Please don't say copy the formula using the drag handle in the lower right.

ARRAYFORMULA with IMPORTRANGE

In column B are listed IDs of Google Sheets. In column C are listed cells, from which I want to import data.
Screenshot of the table
In column D is shown the result of using IMPORTRANGE() by simply dragging it. e.g. for D1 it looks like:
=IMPORTRANGE(B1;C1)
for D2:
=IMPORTRANGE(B2;C2)
and so on.
In column E I want to display the same result but using ARRAYFORMULA that looks like:
=ARRAYFORMULA(IMPORTRANGE(B2:B4,C2:C4))
but the function displays only the data from the first spreadsheet.
People complain about this permissions issue a lot, but it's not hard to solve. What I do is have a sheet which I name "Splash sheet" into which I paste the URLs of the documents I wish to link. To its right is a column headed "permit to connect" which contains IMPORTRANGE formulas importing a single cell from each sheet -- usually a cell containing a confirmation code, number or document name -- on a sheet also named "Splash Sheet." For example,
=IF(B3="enter URL",,CONCATENATE(IMPORTRANGE(B3,"Splash sheet!A1")," ",IMPORTRANGE(B3,"Splash sheet!B1")))
So, when you first connect a spreadsheet via its URL, you get those messages telling you you need to connect, you click the Permit Access, the confirmation code/number/document name appears in the second column, and voilá, your sheets are connected forevermore! Now all your other IMPORTRANGEs referencing that URL will work, and you can use IMPORTRANGE formulas that reference the URL-containing cells on the "splash sheet."
As for the OP's original question, I came here seeking an answer to the same problem, and after more research have realized that we are attempting the impossible here. No way to do this an ARRAYFORMULA. No way around writing formulas that reference every single cell a document's URL may go into.
Problem is you can't make arrays of arrays in spreadsheets; that would involve multiple dimensions, and the medium is inherently two-dimensional. This is what people use databases for.
ARRAYFORMULA doesn't work when importing data (I think it relates to permissions). You could use something like this, =IFERROR(IMPORTRANGE(B5:B7;C5:C7)) and pre-fill the column first, but still there would be the permissions issue. Each new imported sheet needs it's permissions granted by a user.
TLDR: If I understand your intention correctly when you say you would like to see
=ARRAYFORMULA(IMPORTRANGE(B2:B4,C2:C4)), I believe you can make that
happen using the following.
=ARRAYFORMULA(IMPORTRANGE(
INDIRECT(ADDRESS(ROW(B2:B4), COLUMN(B2:B4)),
INDIRECT(ADDRESS(ROW(C2:C4), COLUMN(C2:C4))
)
Breakdown
Use IMPORTRANGE with INDIRECT to create ranges inside ARRAYFORMULA
Call INDIRECT with the ADDRESS function
Call ADDRESS with the ROW and COLUMN functions since they take ranges via ARRAYFORMULA
using IMPORTRANGE with INDIRECT
IMPORTRANGE's two parameters are the spreadsheet url stored in B2:B4 for this example and the range (e.g. sheet!A1:B2) stored in C2:C4.
Since IMPORTRANGE doesn't take a range reference directly as you mentioned, you'll need to build it for each row with ARRAYFORMULA using the INDIRECT function.
INDIRECT can be used to compose a cell reference using A1 notation, for instance
=IMPORTRANGE(INDIRECT("B" & 2), INDIRECT("C" & 2))
will produce the same result as
=IMPORTRANGE(B2, C2)
Since this produces the same result, we now just have to find a way to make INDIRECT work with ARRAYFORMULA
Use ADDRESS to build the parameters for INDIRECT
Next you want to use ADDRESS to build the A1 reference for INDIRECT. For the current purposes, ADDRESS takes a numerical value for row and column as parameters
=INDIRECT(ADDRESS(2,2))
will produce the same result as
=INDIRECT("B" & 2)
Since these two are interchangeable, now we just need to find a way to get the numerical row and column values out of ARRAYFORMULA.
Call ADDRESS using the ROW and COLUMN functions
From there, you can get the row and column indexes from standard A1 notation using the ROW and COLUMN functions. While this may seem like we're pointlessly going in circles, the difference now is that ROW and COLUMN perform as expected with the ranges provided by ARRAYFORMULA. So given that ADDRESS will return $B$2 using using either method below
=ADDRESS(2,2)
or
=ADDRESS(ROW(B2),COLUMN(B2))
we now know that
=ARRAYFORMULA(ADDRESS(ROW(B2:B4),COLUMN(B2:B4)))
will produce the following array of addresses
{ $B$2; $B$3; $B$4 }
Final Assembly
So when we put this all together, we get
=ARRAYFORMULA(IMPORTRANGE(
INDIRECT(ADDRESS(ROW(B2:B4), COLUMN(B2:B4)),
INDIRECT(ADDRESS(ROW(C2:C4), COLUMN(C2:C4))
)
where INDIRECT(ADDRESS(ROW(B2:B4), COLUMN(B2:B4)) is more or less interchangeable with what you might expect from B2:B4 inside ARRAYFORMULA and represents the url parameter
and INDIRECT(ADDRESS(ROW(C2:C4), COLUMN(C2:C4)) is roughly interchangeable with what you might expect from C2:C4 inside ARRAYFORMULA and represents the range parameter.
Suggestions on organization
I recommend using the indentation (Alt +Enter to create a new line ) above along with your indentation of choice to keep it easier to read. In the end it's just a bit more syntactic sugar and if spaces are used well it shouldn't be much harder to understand and make changes to 6 months later.
RE: Permissions - as mentioned by Atiq Zabinski, just placing a simple
IMPORTRANGE("http:/xxxx", "A1") somewhere on the sheet will provide a
means to know if the sheet is connected or not and the error message
should give you a context menu for connecting the sheet. You'll might
want to stay away from error handling in these scenarios as it will
slow down the process of connecting the sheets.

Resources