Spread array or range to arguments of SWITCH - google-sheets

How can I switch using an array or a range of values in google sheets? In other words, how can I use the range of values in B2:B to work as the "Switch" Parameters in the formula below?
The 1st formula used in the table below generates the desired result in column C
1. arrayformula(if(A2:A<>"",SWITCH(trim(A2:A),"A","B","C","D"),""))
But the 2nd formula I use evaluates as #N/A
2. arrayformula(if(A2:A<>"",SWITCH(trim(A2:A),JOIN(",",FILTER(B2:B,B2:B<>""))),""))
A
B
C
1
Values
Replacement
Desired (using formula 1)
2
A
"A","B"
B
3
C
"C","D"
D
What I tried - replacing using switch
Both textjoin(",",TRUE,B2:B) and JOIN(",",FILTER(B2:B,B2:B<>"")) result in "A","B","C","D" so I figured that replacing those values in formula 1 above as in the 2nd formula would work buy it didn't instead evaluating to #N/A
Can I use SWITCH with a range that is generated or is there some other way to achieve using the joining the values in column B to be used to replace values in column C?

try:
=INDEX(TRIM(REGEXREPLACE(B2:B3, "\b"&A2:A3&"\b", )))
or:
=INDEX(IFNA(IFNA(VLOOKUP(A2:A6, SPLIT(B2, "|"), 2, ),
VLOOKUP(A2:A6, SPLIT(B3, "|"), 2, )), A2:A6))

No. Currently, It's not possible to unpack/unzip/spread a array/range to arguments of a function.
Workaround in this specific case would be to use regex:
=ARRAYFORMULA(REGEXREPLACE(B2:INDEX(B2:B,COUNTA(B2:B)),"["&A2:INDEX(A2:A,COUNTA(A2:A))&",""]",))
This creates a regex like [A",], where
[] is a character class
A", is literal A," and ,
If it matches, it gets replaced with nothing.

Related

Sum column until first empty cell

i have the following table:
A1 - 25
A2 - 26
A3 - 27
A4 - BLANK
A5 - 30
A6 - 23
A7 - BLANK
A8 - 24
In B1, i want the following - Starting from A1, sum up the entries until the first blank cell is encountered. In this case, it would be 25+26+27 = 78.
I have looked at multiple answers for hours and tried tweaking them, but nothing is working. Any help is appreciated (Also many things do not make sense, the function isblank(a1:a10) is going to return true or false, then how does arrayformula(isblank(a1:a10)) suddenly convert it to an array, since isblank is just returning a boolean?)
Here's another way you can do it:
=sum(indirect("A1:A"&filter(row(A:A),A:A="")))
try:
=FLATTEN(INDEX(QUERY(; "select "&SUBSTITUTE(JOIN("+";
IF(INDIRECT("A1:A"&MAX(ROW(A1:A)*(A1:A<>"")))="";
","; A1:A)); "+,+"; ",")); 2))
Here's a couple of methods for it and a spreadsheet showing them both.
https://docs.google.com/spreadsheets/d/1rkLarQC6NQ4HdGa38X3-rPoAW0A2-USvImFimlelhZM/edit#gid=0
Method 1: use MATCH to find the row of the first blank row, then construct a reference with INDIRECT to pass to SUM:
=sum(indirect("a1:a" & match("~~", arrayformula("~" & A1:A10 & "~"), 0) - 1))
Reformatted:
=sum(
indirect(
"a1:a" &
match(
"~~",
arrayformula("~" & A1:A10 & "~"),
0
) - 1
)
)
The only tricky thing here is that MATCH returns an error if you just pass it "" to look for, so I use ARRAYFORMULA to wrap the A1:A10 range in a delimiter (~ in this case, but that was arbitrary) and then look for ~~ in the array. That returns me row 4, and so I use indirect to construct a reference to A1:A3 and pass that to sum.
similar to ztiaa's method, but inferior. He filters the ROW() results directly, and uses A:A as the filter argument. Both are superior to my use of ISBLANK etc passed to FILTER
Second, the same idea (find the number of the first empty row and construct a reference to pass to INDIRECT):
=sum(indirect("a1:a" & filter(ARRAYFORMULA(isblank(A2:A11)*row(A2:A11)), ARRAYFORMULA(isblank(A2:A11)*row(A2:A11))<>0)-1))
Reformatted for easier reading:
=sum(
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
) - 1,
)
)
So I use ISBLANK(A1:A10) to get an array of booleans indicating which rows are empty, then multiply that by ROW(A1:A10) which will return an array containing all the row numbers for the range, all inside of ARRAYFORMULA.
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))
Using boolean values in the multiplication converts them to zeroes, so this will generate an array of either 0 (for non-blank rows) or a row number (for any blank rows). Then I take the same formula and use FILTER on it to remove all of the zeroes
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)
leaving an array containing the row numbers of each blank row. Since they are in order and Sheets lacks dynamic array handling, the return value will just be the first value instead of the array, and so we can pass that to INDIRECT to generate a reference to a range using that row number - 1 (since I want to have the range run from A1 to the row immediately preceding the first blank row):
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)-1
)
and then as a final step wrap the whole thing in SUM to sum the values in the range you just used INDIRECT to create a reference to.
=sum(
indirect(
"a1:a" &
filter(
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10)),
ARRAYFORMULA(isblank(A1:A10)*row(A1:A10))<>0
)-1
)
)
[![enter image description here][1]][1]
Let me know if that works for you. I imagine there is a better way to do it. I'll keep thinking about it.
Few alternative
=SUM(QUERY(A:A,"select A limit " & MIN(FILTER(ROW(A:A),A:A=""))-1))
With INDEX() function
=SUM(INDEX(A:A,1):INDEX(A:A,min(filter(row(A:A),A:A=""))-1))

Why my ArrayFormula is giving error? How do I correct it? (I'm not looking for another Arrayformula as solutions!)

I wanted a ArrayFormula at C1 which gives the required result as shown.
Entry sheet:
(Column C is my required column)
Date Entered is the date when the Name is Assigned a group i.e. a, b, c, d, e, f
Criteria:
The value of count is purely on basis of Date Entered (if john is assigned a on lowest date(10-Jun) then count value is 1, if rose is assigned a on 2nd lowest date(17-Jun) then count value is 2).
The value of count does not change even when the data is sorted in any manner because Date Entered column values is always permanent & does not change.
New entry date could be any date not necessarily highest date (If a new entry with name Rydu is assigned a on 9-Jun then the it's count value will become 1, then john's (10-Jun) will become 2 and so on)
Example:
After I sort the data in any random order say like this:
Random ordered sheet:
(Count value remains permanent)
And when I do New entries in between (Row 4th & 14th) and after last row (Row 17th):
Random Ordered sheet:
(Doesn't matter where I do)
I already got a ArrayFormula which gives the required result:
={"AF Formula1"; ArrayFormula(IF(B2:B="", "", COUNTIFS(B$2:B, "="&B2:B, D$2:D, <"&D2:D)+1))}
I'm not looking for another Arrayformula as solutions. What I want is to know what is wrong in my ArrayFormula? and how do I correct it?
I tried to figure my own ArrayFormula but it's not working:
I got Formula for each cell:
=RANK($D2,FILTER($D$2:$D, $B$2:$B=$B2),1)
I figured out Filter doesn't work with ArrayFormula so I had to take a different approach.
I took help from my previous question answer (Arrayformula at H3) which was similar since in both cases each cell FILTER formula returns more than 1 value. (It was actually answered by player0)
Using the same technique I came up with this Formula which works absolutely fine :
=RANK($D2, ARRAYFORMULA(TRANSPOSE(SPLIT(VLOOKUP($B2, SUBSTITUTE(TRIM(SPLIT(FLATTEN(QUERY(QUERY({$B:$B&"×", $D:$D}, "SELECT MAX(Col2) WHERE Col2 IS NOT NULL GROUP BY Col2 PIVOT Col1", 1),, 9^9)), "×")), " ", ","), 2, 0), ","))), 1)
Now when I tried converting it to ArrayFormula:
($D2 to $D2:$D & $B2 to $B2:$B)
=ARRAYFORMULA(RANK($D2:$D,TRANSPOSE(SPLIT(VLOOKUP($B2:$B, SUBSTITUTE(TRIM(SPLIT(FLATTEN(QUERY(QUERY({$B:$B&"×", $D:$D}, "SELECT MAX(Col2) WHERE Col2 IS NOT NULL GROUP BY Col2 PIVOT Col1", 1),, 9^9)), "×")), " ", ","), 2, 0), ",")), 1))
It gives me an error "Did not find value '' in VLOOKUP evaluation", I figured out that the problem is only in VLOOKUP when I change $B2 to $B2:$B.
I'm sure VLOOKUP works with ArrayFormula, I fail to understand where my formula is going wrong! Please help me correct my ArrayFormula.
Here is the editable sheet link
if I understand correctly, you are trying to "rank" B column based on D column dates in such way that dates are in theoretical ascending order so if you randomize your dataset, the "rank" of each entry would stay same and not change based on the randomness you introduce.
therefore the correct formula would be:
={"fx"; INDEX(IFNA(VLOOKUP(B2:B&D2:D,
{INDEX(SORT({B2:B&D2:D, D2:D}, 2, 1),,1),
IFERROR(1/(1/COUNTIFS(
INDEX(SORT(B2:D, 3, 1),,1),
INDEX(SORT(B2:D, 3, 1),,1), ROW(B2:B), "<="&ROW(B2:B))))}, 2, 0)))}
{"fx"; ...} array of 2 tables (header & actual table) under each other eg. ;
outer shorter INDEX or longer ARRAYFORMULA (doesnt matter which one) is needed coz we are processing an array
IFNA for removing possible #N/A errors from VLOOKUP function when VLOOKUP fails to find a match
we VLOOKUP joint B and D column B2:B&D2:D in our virtual table {} and returning second 2 column if there is an exact match 0
our virtual table {INDEX(SORT({B2:B&D2:D, D2:D}, 2, 1),,1), ...} we VLOOKUP from is constructed with 2 columns next to each other eg. ,
we are getting the first column by creating an array of 2 columns {B2:B&D2:D, D2:D} next to each other where we SORT this array by date/2nd column 2, in ascending order 1 but all we need after sorting is the 1st column so we use INDEX where we bring all rows ,, and the first column 1
now lets take a look on how we getting the 2nd column of our virtual table by using COUNTIFS which will mimic the "rank"
IFERROR(1/(1/ is used to remove all zero values from the output (all empty rows would have 0 in it as the "rank")
under COUNTIFS we put 2 pairs of arguments: "if column is qual to column" and "if row is larger or equal to next row increment it by 1" ROW(B2:B), "<="&ROW(B2:B))
for "if column is qual to column" we do this twice and use range B2:D and sort it by date/3rd column 3 in ascending order 1 and of this we again need only the 1st column so we INDEX it and return all rows ,, and first column 1
with this formula you can add, remove or randomize your dataset and you will always get the right value for each of your rows
as for why your formula doesnt work... to not get #N/A error for vlookup you would need to define the end row of the range but still, the result wont be as you would expect coz formula is not the right one for this job.
as mentioned there are functions that are not supported under AF like SUM,AND,OR and then there are also functions which work but in a different way like IFS or with some limitations like SPLIT,GOOGLEFINANCE,etc.
I have answered you on the tab in your shared sheet called My Practice thusly:
You cannot split a two column array as you have attempted to do in cell CI2. That is why your formula does not work. You can only split a ONE column array.
I understand you are trying to learn, but attempting to use complicated formulas like that is going to make it harder I'm afraid.

Using multiple SUBSTITUTE functions dynamically

Let's say I have a list of strings and I want to remove specific words from them. I can easily use multiple SUBSTITUTE functions, for example, this will remove the strings in B2, B3 and B4 from the string in A2:
=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A2,$B$2,""),$B$3,""),$B$4,"")
How can I make this dynamic so that when I add more terms to remove in the B column they'll be removed automatically from A2. I tried the following methods but they didn't work:
1 - add the B cells as an array
=SUBSTITUTE(A2,{$B$2:$B$4},"") or =SUBSTITUTE(A2,{$B$2,$B$3,$B$4},"")
2 - Make a single condition
cat|donkey|mouse
3 - Using Indirect and concatenate - I built the correct function as a string (using REPT and CONCATENATE) and tried to activate it with INDIRECT) but this also failed.
Here's the spreadsheet (Col A are the strings to clea, B are the words to remove, D is the manual method that works, F, H and K are the failed 3 attempts).
https://docs.google.com/spreadsheets/d/15u8qZ0xQkjvTRrJca6AInoQ4aPkijccouAETE4Gyr9I/edit#gid=0
In the 'Copy' of the tab I entered
=ArrayFormula(IF(LEN(A2:A), REGEXREPLACE(A2:A, TEXTJOIN("|", 1, B2:B),),))
See if that works for you?
EXPLANTION
LEN(A2:A) basically limits the output to the rows that a value in column A
REGEXREPLACE uses a regular expression to replace parts of the string. That regular expression is constructed by the TEXTJOIN function.
TEXTJOIN combines the text from the range B2:B, with a specifiable delimiter separating the different texts. Here the pipe character (which means 'or' in regex) is used. The second paramater of this function is set to TRUE (or 1) so that empty cells selected in the text arguments won't be included in the result.
REFERENCES
TEXTJOIN
REGEXREPLACE
You can also try-
=TEXTJOIN(" ",TRUE,FILTER(SPLIT(A2," "),ISERROR(MATCH(SPLIT(A2," "),$B$2:$B$7,0))))

Using AND with multiple conditions for formatting google sheets/excel

I'm trying to highlight a cell if 3 different conditions are met in 3 other different cells.
A B C D
Highlight A: if B is greater than 5, C is empty, and D doesn't have a duplicate
When I use these formulas individually, they work:
=AND(b:b,>5)
=AND(isblank(c:c))
=AND(countif(A:A,A1)<2)
But when I combine them this way, they don't work:
=AND(b:b,>5),(isblank(c:c)),(countif(A:A,A1)<2)
What am I doing wrong?
Also, if a value occurs multiple times, is there a formula to highlight all but the first occurrence?
Highlight A: if B is greater than 5, C is empty, and D doesn't have a duplicate
apply to range A1:A:
=(B1>5)*(C1="")*(COUNTIF(D:D, D1)<2)
Also, if a value occurs multiple times, is there a formula to highlight all but the first occurrence?
use shorter:
=COUNTIF(A$1:A1, A1)>1
or:
=ARRAYFORMULA(COUNTIFS(A$1:A, A1, ROW(A$1:A), "<="&ROW(A1))>1)
The AND function requires additional brackets:
=AND((b:b>5),(isblank(c:c)),(countif(A:A,A1)<2))

Using Google Spreadsheets QUERY to Filter

I have the following google sheet where:
Col a= quantities
Col b= product codes, which i´ve split between C and H.
I want to know the quantity according to different "filters"... this filters are the fields between C11 and H11, and they are optional. There are 6 possible filters.
It works using =QUERY formula located in H12 and it returns the sum of quantity values where the filters match...
BUT there´s the possibility of leaving a filter empty to get "all"...
the query is as follows:
=QUERY(A1:H7, "select sum(A) where C contains '"&C11&"' and lower(D) contains lower('"&D11&"') and E contains '"&E11&"' and lower(F) contains lower('"&F11&"') and lower(G) contains lower('"&G11&"') and lower(H) contains lower('"&H11&"') ",-1)
My problem is with the match type: where C contains '"&C11&"' and...
instead of using "contains" it should compare using "matches". this way it would count like it should, but then it won´t accept empty filters.
How can I get it to count only if the field is filled??
What´s wrong with the filter right now? It´s counting "4" matches because model matches "1" happens when model is 1 or 21, also with column D where i´m looking for value X and is also counting value XN as it contains "X". if formula is changed to "matches" instead of "contains", it won´t allow me to leave it blank.
Thank you!
Karl_S formula is great, but it does not sum the quantities in column A. Adapting his approach to SUMIFS seems to do it:
=SUMIFS(A2:A7,C2:C7, IF(ISBLANK(C11), "<>" ,C11),D2:D7, IF(ISBLANK(D11), "<>" ,D11),E2:E7, IF(ISBLANK(E11), "<>" ,E11),F2:F7, IF(ISBLANK(F11), "<>" ,F11),G2:G7, IF(ISBLANK(G11), "<>" ,G11),H2:H7, IF(ISBLANK(H11), "<>" ,H11))
Use this formula instead:
=COUNTIFS(C2:C7, IF(ISBLANK(C11), "<>" ,C11), D2:D7, IF(ISBLANK(D11), "*",D11), E2:E7, IF(ISBLANK(E11), "<>",E11), F2:F7, IF(ISBLANK(F11), "*",F11), G2:G7, IF(ISBLANK(G11), "*",G11), H2:H7, IF(ISBLANK(H11), "*",H11))
If one of the options is blank, it will match all items in that column. Otherwise it should do an exact match.

Resources