Combine Text in ArrayFormula - google-sheets

I have a table using Google Sheets. It has three columns that will always have a null value or a specific value for that column. Each line will have one, two, or three values; it will never have three null values on one line. In the fourth column, I want an ArrayFormula that will combine those values and separate the values with a comma if there is more than one.
Here is a photo of what I am trying to accomplish.
I've tried several ideas so far and this formula is the closest I've gotten so far but it's still not quite working correctly; I think it is treating each column as an array before joining rather than doing the function line by line. I'm using the LEN function rather than A2="" or ISBLANK(A2) because columns A-C are ArrayFormulas as well. I realize this probably isn't the most efficient formula to use but I think it covers every possibility. I'm definitely open to other ideas as well.
={"Focus";
ArayFormula(
IFS(
$A$2:$A="", "",
(LEN(A2:A)>0 & LEN(B2:B)>0 & LEN(C2:C)>0), TEXTJOIN(", ", TRUE, A2:A, B2:B, C2:C),
(LEN(A2:A)>0 & LEN(B2:B)>0 & LEN(C2:C)=0), TEXTJOIN(", ", TRUE, A2:A, B2:B),
(LEN(A2:A)>0 & LEN(B2:B)=0 & LEN(C2:C)>0), TEXTJOIN(", ", TRUE, A2:A, C2:C),
(LEN(A2:A)=0 & LEN(B2:B)>0 & LEN(C2:C)>0), TEXTJOIN(", ", TRUE, B2:B, C2:C),
(LEN(A2:A)>0 & LEN(B2:B)=0 & LEN(C2:C)=0), A2:A,
(LEN(A2:A)=0 & LEN(B2:B)>0 & LEN(C2:C)=0), B2:B,
(LEN(A2:A)=0 & LEN(B2:B)=0 & LEN(C2:C)>0), C2:C
)
)
}
Is it possible to achieve this with Google Sheets?

Sample File
Please try:
=ARRAYFORMULA(SUBSTITUTE(TRIM(TRANSPOSE(QUERY(TRANSPOSE(FILTER(A2:C,ROW(A2:C)<=MAX(IF(LEN(A2:C),ROW(A2:C)*COLUMN(A2:C)^0,0)))),,2^99)))," ",", "))
Notes:
The formula will work incorrectly if some names have space inside: like "Aston Martin"
So if you have spaces, please try this:
=ARRAYFORMULA(SUBSTITUTE(
SUBSTITUTE(TRIM(TRANSPOSE(QUERY(TRANSPOSE(FILTER(SUBSTITUTE(A2:C," ",char(9)),ROW(A2:C)<=MAX(IF(LEN(A2:C),ROW(A2:C)*COLUMN(A2:C)^0,0)))),,2^99)))," ",", "),
CHAR(9)," "))
EDIT
Noticed the shorter variant (without *COLUMN(A2:C)^0) will work:
=ARRAYFORMULA(SUBSTITUTE(
SUBSTITUTE(TRIM(TRANSPOSE(QUERY(TRANSPOSE(FILTER(SUBSTITUTE(A2:C," ",char(9)),ROW(A2:C)<=MAX(IF(LEN(A2:C),ROW(A2:C),0)))),,2^99)))," ",", "),
CHAR(9)," "))
Notes:
I used an old trick to join strings with an array-formula. See sample file
Explanations
If you like to understand any tiered formula, the best way is to split it by parts:
Part 1. Filter the data
FILTER(any_columns,ROW(A2:C)<=MAX(IF(LEN(A2:C),ROW(A2:C)*COLUMN(A2:C)^0,0))). this is my way to limit the data range.
The range is open, means it starts from the second row (A2) and
ends in any row.
I want to get the limited array in this step to reduce work that the formula should do. This is done with a condition, if.
ROW(A2:C) must be less or equal to the max row of data.
MAX(IF(LEN(A2:C), some_rows) gives the max row.
If(len.. part checks if a cell has some text inside it.
Note some_rows part:
MAX(IF(LEN(A2:C),ROW(A2:C)*COLUMN(A2:C)^0,0)))),,2^99))).
ROW(A2:C) must be multiplied by columns, because filter formula
takes only one row into its condition. That is why I multiply by
COLUMN(A2:C)^0 which is columns with 1s. Edit. Now noticed,
that the formula works fine without *COLUMN(A2:C)^0, so it's an
overkill.
Part 2. Join the text
query formula has 3 arguments: data, query_text, and a number_of_header_rows.
data is made with a filter.
query_text is empty, which gives us equivalent to select all
("select *").
And the number of rows of a header is some big number (2^99).
This is a trick: when a query has more headers then one row,
it will join them with space.
After a union is made, transpose function will convert the result back to the column.
Part 3. Substitute and trim
The function trim deletes extra spaces.
Then we replace spaces with the delimiter: ", ". That is why the
formula needs to be modified if spaces are in strings. Correct
result: "Ford, Aston Martin". Incorrect: "Ford, Aston, Martin". But
if we previously replace spaces with some char (char(9) is Tab),
then we do not replace it in this step.

Related

how to concat/merge two columns with different length?

I'm new to google sheet. I have a column(E) with the date and another with a session(F), I want to merge them into one column with each date & different session just like the first few rows in column C.
I've tried "=ArrayFormula(concat(D2:D,concat(" ",F2:F5)))" in column C but only got the first date.
use:
=INDEX(QUERY(FLATTEN(FILTER(E2:E, E2:E<>"")&" "&
TRANSPOSE(FILTER(F2:F, F2:F<>""))), "where not Col1 starts with ' '", ))
see: https://stackoverflow.com/a/68775825/5632629
In your cell C1, try this formula:
=ArrayFormula(E1:E&" "&F1:F)
Well you can simply do concatenate cells like this:
CONCATENATE(E1, " ", F1)
to get what you want I think.
What you're looking for is a cartesian product. I don't have a single formula that does the entire thing for you, but I can suggest a two-step approach.
Get the cartesian product with this formula:
=ARRAYFORMULA(SPLIT(FLATTEN(E2:E9 & "|" & TRANSPOSE(F2:F5)), "|"))
This gives a pair of each date against each time in two result columns. You can then concatenate each row of them in a final result column.

mapping vlookup for each element of splitted list in google sheets

This question is also answered here:
Get a vlookup of a cell after split in Google sheet
but not marked as corrected answer, and cannot make it work.
Goal : I want to apply a vlookup function to a split function, so that I can search for corresponding values (found by the vlookup) for each token obtained from a string.
Consider this sheets:
// Sheet 'veggies'
A
apple, pine, tree
pine
// Sheet 'themes':
A
B
C
apple
8
theme1,theme2
tree
3
theme2
pine
1
theme1,theme3
I want to:
split cells of column A of 'veggies' by commas, so to have tokens
vlookup for the C column in 'themes' sheet, by using the index of tokens, for all of them
As approach I tried to first retrieve the frequences of tokens in column B, sheet 'themes', and cannot understand what my formula is doing:
=ARRAYFORMULA( VLOOKUP( split(A2;",");'themes'!A$2:D;2;FALSE))
This formula only get the frequency from column be for the first token, while for others will only report N/A saying could not find a value, but it is clearly there.
Any help?
Am I on the right track ?
P.s. if one would like to offer use of query , like in the other SO answer, please help me to break down what it does.
ARRAYFORMULA( VLOOKUP( split(A2;",");'themes'!A$2:D;2;FALSE))
Your formula works. But when splitting by comma , there's a extra space left over in all the elements from the second element. So, when
apple, pine, tree is splitted, it becomes apple, pine, tree(note the extra space prefix). To fix, you can simply add a space to the split as well:
=ARRAYFORMULA( VLOOKUP( split(A2;", ");'themes'!A$2:D;2;FALSE))
this should work if you want the results in one cell.
=ARRAYFORMULA(TEXTJOIN(", ";TRUE;IFERROR(VLOOKUP(SPLIT(A2;", ";0);themes!A:C,2,0))))
Use this formual
=ArrayFormula(LAMBDA(v,
IF(v="",,{v,SPLIT(VLOOKUP(v,themes!A2:C,3,0), ", ",1)}))
(FLATTEN(IF(A2:A="",,SPLIT(A2:A, ", ", 1)))))

Horizontally Concatenate Array of Columns with delimiter and ignore blank columns in google sheets [duplicate]

This question already has an answer here:
Concatenate non empty cells in each row with arrayformula in google sheets
(1 answer)
Closed 6 months ago.
The shared sheet shows multiple column rows which can be individually concatenated horizontally with a comma & space between using TEXTJOIN(", ", TRUE, A2:D2) and blank spaces are ignored. But textjoin cannot be used in Arrayformula as far as I know and I would like ot find a suitable replacement that can also be combined as a string along with other strings of information.
I want to be able to use this as an independent formula string that might be added to other strings of information. For example, "Favorite colors: "& textjoin(", ",1,A2:D2)&"Favorite foods:"&textjoin(", ",1,E2:G2)&"...
Possible solutions
May be a variant of one of the following:
Modifying this so it could be used w/ an array formula JOIN("~", SPLIT(JOIN(CHAR(60000), B3:E3), CHAR(60000)))
Modifying this formula works with join also JOIN(", ",FILTER(H2:H,H2:H<>""))
Using a combination of IF(a2:A<>"" along with a regex replacement at the end (see my answer below) but this could be very long formula compared to textjoin if there are many columns)
An ideal solution would be concise and look closest to something this:
arrayformula(TEXTJOIN(", ", TRUE, A2:A,B2:B,C2:C)
Shared sheet is here
use:
=INDEX(REGEXREPLACE(TRIM(FLATTEN(QUERY(TRANSPOSE(IF(A2:D="",,A2:D&",")),,9^9))), ",$", ))
Using a series of IF statements, adding a delimiter and then removing any trailing delimiters can be accomplished using: Arrayformula(regexreplace(if(A2:A100<>"",A2:A100&", ","")&if(B2:B100<>"",B2:B100&", ","")&if(C2:C100<>"",C2:C100&", ","")&if(D2:D100<>"",D2:D100&", ",""),", $",""))
Use a query smush, like this:
=transpose(query(transpose(A2:D), "", 9^9))
The formula will separate values with spaces. To separate with commas and remove unwanted white space, use trim() and substitute() or regexreplace(), like this:
=arrayformula( substitute( trim( transpose( query( transpose(A2:D), "", 9^9 ) ) ), " ", ", " ) )

Unique values horizontally every *n cell (Gsheets)

I am trying to convert unique values of vertical range to horizontal however I wish to have the output every second cell (see desired output on the image). I have tried offset() and mod() function however it does not seem to work. Could you please give me a clue of how to modify my function?
Function:
=unique(transpose(T2:T10))
try this formula
=transpose(flatten(query(unique(T2:T10),"select Col1, ' ' label ' ''' ") ))
An alternative solution you can go with by using SPLIT, JOIN, CONCATENATE, REPT and ARRAYFORMULA and it gives you easier way to adjust for every n cells by just changing a number of many cells you want skipped.
Formula for 1 cell skipped:
=SPLIT(ARRAYFORMULA(JOIN(CONCATENATE(REPT(", ", 1), ",") ,UNIQUE(A2:A10))),",")
Change 1 inside REPT function to choose how many cells are to be skipped
Behavior:
Repeats the ", " via REPT and pair with a comma at the end using CONCATENATE
Joins the UNIQUE(A2:A10) with the delimiter generated above via JOIN in an ARRAYFORMULA (resulting to 1, ,2, ,3, ,4...)
Lastly, SPLIT by ",", thus having a blank cell in between the numbers (These blank cells are those spaces in between commas we inserted)
Output:
My simple approach is:
=arrayformula(split(join(",,",unique(T4:T10)),",",1,0))
Then JOIN puts them in a line, separated by two commas.
SPLIT pushes them into different columns. The 'remove_empty_text' parameter in SPLIT is set to false 0, following the 'split_by_each' parameter 1. This splits by each comma in the join. Hence, ",,," would be two spaces apart.
If you need to ignore gaps, then wrap a query around the data range:
query({T4:T10},"where Col1 is not null",0)
The query can also sort the results:
query({T4:T10},"where Col1 is not null order by Col1",0)
So the final formula would be:
=arrayformula(split(join(",,",unique(query({T4:T10},"where Col1 is not null order by Col1",0))),",",1,0))

How format a result using VLOOKUP to loop inside a single cell with an arbitrary number of search keys

I have a column called "Notes (Atomic weights)" with an arbitrary (0 to n) number of search keys in it.
and a corresponding Named Range called "NOTES"
How do I do a vlookup/Query or Filter such that I get the combined column called "Note Texts" (see image below)?
If there is only one search key in the Notes column, I can use
IF(LEN(W3)>0, VLOOKUP(W3, NOTES, 2, false) , )
but now I have an arbitrary number of search keys in one column. how do I approach this without splitting and creating even more cells and then stitch them all back (adding more columns is very messy, since many other columns in my table also require the same fix).
Try this formula:
=TRANSPOSE(SPLIT(JOIN(char(10),ArrayFormula(IFERROR(VLOOKUP("["&SPLIT(JOIN("! ",A1:A4),"![",1),D1:E3,2,0),"!"))),char(10)&"!"&char(10),0))
Sample file:
https://docs.google.com/spreadsheets/d/13QFnYri6d8xvL9kXw-xAP87n1kT4wh4HwxYtHftMU9g/edit#gid=2094642927
Max's Solution works great! took me over an hour to analyse and finally understand the formula.
for my needs, I did not combine the rows and perform a single evaluation. Instead, I repeated the formula for every row using the following simplified formula (this fixes the alignment bug when there's empty rows)
= JOIN(char(10), ArrayFormula(
IFERROR(
VLOOKUP("["&SPLIT( A10 ,"[]", TRUE) &"]",NOTES,2,0),
"Error")
)
)
the following is a break down of what each part of Max's formula means.
start debugging from the inside(1) to the outside (7)
//(7) Finally, we TRANSPOSE the Columns into Rows
TRANSPOSE(
//(6) Now, we SPLIT the column up with the delimiter “\n!\n”
// that was added during Step (1)
SPLIT(
//(5) we now JOIN back all the columns, adding a new line “char(10)" before every column
JOIN(
char(10) //prepend with new line
//(4) The Magic !! ARRAYFORMULA enables the display of values returned from an array formula into multiple rows and/or columns
// Result is now displayed across multiple columns
,ArrayFormula(
IFERROR(
//(3) We can now do a VLOOKUP for each of the split search key
// (but only The first result is displayed)
VLOOKUP(
“[“ //reinsert the [ back after the split
//(2) Now, SPLIT up everything using delimiter “!”(new Row) And “[“ (new item)
& SPLIT(
//******** START FROM HERE*********
//(1) - take all the rows of interest, and then
// JOIN them together with a “!<SPACE>”
JOIN(
"! " //delimiter !<SPACE> ?
,A1:A4) //text to join (all the rows of interests)
,"![“
,TRUE) // split by each
,NOTES //Named range of interest
,2 //take second second column
,FALSE)
,”!”) // insert ! If error
) //ArrayFormula
) //JOIN
,char(10)&"!"&char(10) //delimiter "\n!\n” for split
,FALSE // do not split by each
) //SPLIT
) // TRANSPOSE

Resources