Regexreplace with ignore - google-sheets

I want to regexreplace the number 2 in some rows with "double", but I want to ignore if the numbers are 12, 22, 32 etc.
EDIT:
What if I add letters to the numbers? Like this:

There are a few ways to tackle this, but using ^2$ will only match 2
=ARRAYFORMULA(
IF(ISBLANK(A1:A),,
IF(
REGEXMATCH(
TO_TEXT(A1:A),
"^2$"),
"double",
A1:A)))
Using REGEXMATCH instead of REGEXREPLACE allows us to return the values in A1:A as actual numerical values instead of the text value the formula requires.
Working with a2 etc, this will allow for optional letters before the 2
=ARRAYFORMULA(
IF(ISBLANK(A1:A),,
IF(
REGEXMATCH(
TO_TEXT(A1:A),
"^(?i)[A-Z]+?2$"),
"double",
A1:A)))

Related

How do you conditionally format arbitrary text in google sheets?

How do you conditionally color a column where the column contains Alphanumeric text, such that all like strings are colored the same? Aware how to do this if you know the value of possible strings, but in this case combinations are not known ahead.
Thought about converting string=>hex=>binary=>decimal, then do a color scale format rule. Then realized these functions are readily available without custom functions.
Color scale formatting can only format numbers. Assuming that the text strings are in column A2:A, you can convert duplicates among them into fairly unique numbers with this formula in row 2 of a free column:
=arrayformula(
lambda(
data, modulo,
map(
to_text(data),
lambda(
text,
if(
countif(data, text) < 2,
iferror(1/0),
iferror(
mod(
sum(
mod(
1.1 ^ sequence(len(text))
*
code( mid(text, sequence(len(text)), 1) ),
modulo
)
),
modulo
)
)
)
)
)
)( A2:A, 8 )
)
Then format the new column as a color scale and use the values there as a guide to locate duplicate text strings in column A2:A.
You can try using the following formula:
=IF(REGEXMATCH(A1, "[^A-Za-z0-9]+"), FALSE, TRUE)
This is an example of how it works:
Once you have the formula you can use conditional formatting in Google Sheets to change the cell color to the one you prefer.
References:
Regular expressions
REGEXMATCH
Conditional formatting

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 ) ) ), " ", ", " ) )

How to use SUMIF with the criteria as text within a string

I have column A that has dates in the "8-Oct-2021" format, I have column B that has numbers I want summed.
=SUMIF(A2:A, "*Oct*", B2:B)
I currently have the formula above, with the criteria as "*Oct*" because there's text before and after the 'Oct'. I have other months so I want each month added up.
=SUMIFS(B2:B, A2:A, ">="&DATE(2021,10,1), A2:A, "<="&DATE(2021,10,30))
Above does the trick, but I'd like to keep it simple with the first formula. Suggestions?
At the moment you have numbers in range A2:A, not text, because the dates in GS are numbers, so your formula SUMIF() will return 0.
You can shorten your SUMIFS() formula to =ARRAYFORMULA(SUMIF(month(A2:A), 10, B2:B)) or to =ARRAYFORMULA(SUMIF(text(A2:A, "mmm"), "Oct", B2:B))

Array formula for a rolling AVERAGEIF formula?

I have a working formula that I need to drag to autofill down a column and want to make it into an array formula:
=AVERAGEIF(INDIRECT("A2:A"&ROW()), ">=0",INDIRECT("A2:A"&ROW()))
So if you put this formula in column B it will take the values in column A and continually average them going down, skipping any values that are less than 0. Here is an example screenshot: https://i.imgur.com/nRq8hAH.png
How can I make an array formula for this?
This formula comes close but I couldn't figure out how to add the ">=0" conditional:
=ArrayFormula(IF(LEN(A2:A),SUMIF(ROW(A2:A),"<="&ROW(A2:A),A2:A)/COUNTIF(ROW(A2:A),"<="&ROW(A2:A)),))
Lambda Update
There is no longer any need to use ArrayFormula for this.
=MAP(SEQUENCE(COUNTA(A2:A)),
LAMBDA(rowOff,
AVERAGEIF(OFFSET(A2,0,0,rowOff),">=0"))
)
How?
For each element rowOff in 1..# items in column:
Use AverageIf to get the average of everything starting at the top taking rowOff rows, excluding everything >=0
Old solution
Here's a single formula that can go into B2 (no need to drag), but it's fairly complicated:
=ArrayFormula(IFERROR(IF(LEN(A2:A),MMULT(TRANSPOSE((SEQUENCE(COUNTA(A2:A),1,2)<=TRANSPOSE(SEQUENCE(COUNTA(A2:A),1,2)))*FILTER(A2:A,LEN(A2:A))),--(FILTER(A2:A,LEN(A2:A))>0))/COUNTIFS(SEQUENCE(COUNTA(A2:A)),"<="&SEQUENCE(COUNTA(A2:A)),FILTER(A2:A,LEN(A2:A)),">=0"),"")))
Readable:
=ArrayFormula(IFERROR(
IF(
LEN(A2:A),
MMULT(
TRANSPOSE(
(SEQUENCE(COUNTA(A2:A),1,2)<=
TRANSPOSE(SEQUENCE(COUNTA(A2:A),1,2))
)*FILTER(A2:A,LEN(A2:A))
),
--(FILTER(A2:A,LEN(A2:A))>0)
)/
COUNTIFS(
SEQUENCE(COUNTA(A2:A)),
"<="&SEQUENCE(COUNTA(A2:A)),
FILTER(A2:A,LEN(A2:A)),
">=0"
),
""
)
))
How?
We can achieve a running sum using MMULT on a Lower Triangular Matrix of size COUNTA(A2:A) of all 1's and all non blanks of A2:A, which we filter out if the number is negative. In this case, it produces {2;2;6;6;6;6}.
The COUNTIFS() produces an array of the number of elements we want to divide by. Here, it's {1;1;2;2;3;4}
Then ignore any blanks at the with IF.
Blank out any errors with IFERROR. (#DIV/0! errors can happen if the leading numbers are negative.)
Perhaps, this formula can help:
=ARRAYFORMULA(AVERAGE(IF($A$2:A2>=0,$A$2:A2,"")))

Combine Text in ArrayFormula

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.

Resources