We work in gemstones and would like to figure out a formula for codifying the prices. This would depend on the client we could adjust the price without them seeing our baseline.
$1710 would show on the tag: 1GA0.
Essentially, the alphabet would be assigned to the numbers, we'd like to keep the first digit but anything after that would be a letter.
Is there a way to do this in google sheets to generate this?
Suppose the following are true:
1.) Your raw price data runs A2:A.
2.) Your raw price data are actual numbers.
Use the following array formula in the second cell of an otherwise empty column:
=ArrayFormula(IF(A2:A="",,REGEXREPLACE(LEFT(A2:A)&TRANSPOSE(QUERY(TRANSPOSE(IF(SPLIT(REGEXREPLACE(MID(A2:A&REPT("~",10),2,10),"(.)","$1~"),"~")&""="0",0,CHAR(64+SPLIT(REGEXREPLACE(MID(A2:A&REPT("~",10),2,10),"(.)","$1~"),"~"))))," ",10)),"\s|#","")))
This will produce all converted results for A2:A.
As this is a unique custom formula that will not be often requested by future site visitors, and since it is rather complex, I'm providing it as-is and without explanation at this time.
Can you try this:
Formula for B1:
=JOIN("", LEFT(A1, 1), ARRAYFORMULA(IFERROR(SUBSTITUTE(ADDRESS(1, MID(A1, ROW($A$2:INDIRECT("A" & LEN(A1))), 1) * 1, 4), "1", ""), "0")))
Output:
Step by step formula behavior:
Step 1: splits the 2nd digit to the last digit into separate cells
Step 2: convert valid numbers (1-9) into letters
Step 3: convert #VALUE to "0"
Step 4: combine the 1st number and the converted value.
Note:
1st number and zeroes are as is, everything else is converted.
If $ is a necessity and is present together with a ,, then adjust your formula into:
Adjusted formula:
=JOIN("", MID(TO_TEXT(A1), "2", "1"), ARRAYFORMULA(IFERROR(SUBSTITUTE(ADDRESS(1, MID(REGEXREPLACE(TO_TEXT(A1), ",", ""), ROW($A$3:INDIRECT("A" & LEN(REGEXREPLACE(TO_TEXT(A1), ",", "")))), 1) * 1, 4), "1", ""), "0")))
Adjustments:
LEFT(A1, 1) -> MID(TO_TEXT(A1), "2", "1")
since we consider the $, we need to get the 2nd character instead of the first 1.
A1 -> REGEXREPLACE(TO_TEXT(A1), ",", "")
since getting the value directly will yield to a number but the length will result into the string's length, we need to compare them equally, thus converting the number into text and then removing the , to return the proper value as string.
$A$2 -> $A$3
we start to convert the third character instead of the 2nd.
Adjusted formula now should yield the following output:
References:
Convert number to letter
Split number into digits
Related
This is a similar problem to Using ARRAYFORMULA with SUMIF for multiple conditions combined with a wildcard to select all values for a given condition, but trying to get the sum of the first column by all months of a given year. I was trying to extrapolate the same solution provided by #player0, but group by doesn't work because I would like to get a result for each month of the year, regardless of the month's data on the source. Here is the sample:
In column G we have different filter conditions and it can include a special token: ALL to include all values for each criterion. For the year we can select the given year for which we want to sum the result by each month of the year.
Column I has the expected result using the similar idea of the referred question, but it cannot be expressed in an ArrayFormula (query result doesn't expand):
=IFNA(QUERY(QUERY(FILTER($A$2:$E,
IF($G$2="All", $B$2:$B<>"×", $B$2:$B=$G$2),
IF($G$4="All", $C$2:$C<>"×", $C$2:$C=$G$4),
IF($G$6="All", $D$2:$D<>"×", $D$2:$D=$G$6),
YEAR($E$2:$E) = $G$8
),
"select sum(Col1) where month(Col5) =" & MONTH($H2) - 1),
"offset 1", 0),"")
On column J the array try doesn't work because we cannot use the virtual range with SUMIF it can be resolved by creating auxiliary columns with the FILTER, but I am looking for a solution that doesn't require that.
=Arrayformula(if(not(ISBLANK(H2:H)), sumif(
Filter(FILTER($A$2:$E, IF($G$3="All", $B$2:$B<>"×",
$B$2:$B=$G$3), IF($G$5="All", $C$2:$C<>"×", $C$2:$C=$G$5),
IF($G$7="All", $D$2:$D<>"×", $D$2:$D=$G$7),
YEAR($E$2:$E) = $G$9),{1,0,0,0,0}), H2:H,
Filter(FILTER($A$2:$E, IF($G$3="All", $B$2:$B<>"×",
$B$2:$B=$G$3), IF($G$5="All", $C$2:$C<>"×", $C$2:$C=$G$5),
IF($G$7="All", $D$2:$D<>"×", $D$2:$D=$G$7),
YEAR($E$2:$E) = $G$9), {0,0,0,0,1})
),))
Here is the sample spreadsheet:
https://docs.google.com/spreadsheets/d/1Lqjim3c_j8KNr_7LVlKjlR4BXi9_1HFoGDuwsuX1XS0/edit?usp=sharing
try:
=INDEX(IFNA(VLOOKUP(MONTH(H2:H13), QUERY(QUERY(FILTER(A2:E,
IF(G3="All", B2:B<>"×", B2:B=G3),
IF(G5="All", C2:C<>"×", C2:C=G5),
IF(G7="All", D2:D<>"×", D2:D=G7)),
"select month(Col5)+1,sum(Col1)
where Col1 is not null "&IF(G9="",,"
and year(Col5)="&G9)&
"group by month(Col5)+1"),
"offset 1", 0), 2, 0)))
This formula is in cell L2 of your sample Sheet1. It is a sumif() that uses a regex and MMULT to create an array of 3's where the conditions are met and &'s it with the month for the 'sumif' criterium.
=ARRAYFORMULA(SUMIF(MMULT(N(REGEXMATCH(B2:D,SUBSTITUTE({G3,G5,G7},"ALL",))),
{1;1;1})&EOMONTH(E2:E,-1)+1,3&H2:H13,A2:A))
Detail Explanation
(The formula, then in the following lines the explanation)
SUBSTITUTE({G3,G5,G7},"ALL",)
Generate a 1x3 array with G3,G5,G7 values, if "ALL" then will be replaced by empty string. In case of ("ALL", ALL", "ALL") returns: (,,). The result of SUBSTITUTE will be the regular expression to be used in REGEXMATCH. In case of ("ALL", ALL", "ALL") REGEXMATCH will return (TRUE, TRUE, TRUE) on each row.
REGEXMATCH(B2:D,SUBSTITUTE({G3,G5,G7},"ALL",))
Return an array of the same size as B2:D (let's say Mx3 array) where the condition are met (TRUE|FALSE) values and the function N()converts it into (0|1) values.
MMULT(N(REGEXMATCH(B2:D,SUBSTITUTE({G3,G5,G7},"ALL",))),
{1;1;1})
Multiplies two matrixes: Mx3 x 3x1 and returns an array Mx1. If all filters conditions are satisfied will return on a given cell the number 3 (we have three conditions), otherwise a number lower than 3.
EOMONTH(E2:E,-1)+1
Calculate the last day of the previous month of the cells E2:E and add one day resulting the first day of the month of E2:E. We need to compare such dates with the dates in H2:Hthat represent the first day of the month.
SUMIF(range, criterion, [sum_range])
range: will contain an array of Mx1 with one of the values: {0,1,2,3} depending on how many conditions are met. It appends &EOMONTH(E2:E,-1)+1. Remember dates are stored as an integer number.
criterium: 3&H2:H13the reference dates prefixed by number 3.
sum_range: The range A2:A we want to sum based on the range and criterium match, so only rows with 3 values of MMULT will be considered.
Here the result in case of filters have the value ALL:
Here the solution when ALL token is not used:
Note: The only difference with expected result and #player0 solution is that it returns 0when there is no match.
Example of values from my Column C:
https://www.betfair.com/exchange/plus/football/market/1.186894151
https://www.betfair.com/exchange/plus/football/market/1.186867498
https://www.betfair.com/exchange/plus/football/market/1.1869852
https://www.betfair.com/exchange/plus/football/market/1.186986585
https://www.betfair.com/exchange/plus/football/market/1.186986773
https://www.betfair.com/exchange/plus/football/market/1.18698631
https://www.betfair.com/exchange/plus/football/market/1.186971962
https://www.betfair.com/exchange/plus/football/market/1.18698667
https://www.betfair.com/exchange/plus/football/market/1.186973002
After the last / will always have the same amount of characters. But for some inexplicable reason the API is delivering the values without the zeros that exist to the right, so for example:
If the correct value is:
1.1011100
The value delivered is:
1.10111
So to adjust this I need to add the zeros to the right, for that I separate the last part of the value with this formula:
=ARRAYFORMULA(IF(C1:C="","",RIGHT(C1:C,LEN(C1:C)-FIND("*",SUBSTITUTE(C1:C,"/","*",LEN(C1:C)-LEN(SUBSTITUTE(C1:C,"/","")))))))
The result is:
1.186894151
1.186867498
1.1869852
1.186986585
1.186986773
1.18698631
1.186971962
1.18698667
1.186973002
And to calculate the maximum number of characters that can be found, I use:
=ARRAYFORMULA(MAX(LEN( FORMULA I PUT A LITTLE ABOVE IN QUESTION )))
The result in this case is 11, so in all values there must be 11 characters after the last slash.
But now I don't know how I can add the zeros numbers that are missing from each value so that the result is:
https://www.betfair.com/exchange/plus/football/market/1.186894151
https://www.betfair.com/exchange/plus/football/market/1.186867498
https://www.betfair.com/exchange/plus/football/market/1.186985200
https://www.betfair.com/exchange/plus/football/market/1.186986585
https://www.betfair.com/exchange/plus/football/market/1.186986773
https://www.betfair.com/exchange/plus/football/market/1.186986310
https://www.betfair.com/exchange/plus/football/market/1.186971962
https://www.betfair.com/exchange/plus/football/market/1.186986670
https://www.betfair.com/exchange/plus/football/market/1.186973002
What should I do to get this result?
Spreadsheet Link:
https://docs.google.com/spreadsheets/d/1PPnwwzFzN60G0rUjTgbBn5D5uIXaO-OTJtuHeKxCilw/edit?usp=sharing
I have provided you 2 methods in the spreadsheet.
LEN:
=ArrayFormula(IF(C1:C="",,C1:C&REPT("0",F1-LEN(E1:E))))
REGEXEXTRACT:
=ArrayFormula(IF(C1:C="",,REGEXEXTRACT(C1:C&REPT("0",F1),".+\/.{"&F1&"}")))
In a Google Sheets spreadsheet, I have the cell A1 with value "people 12-14 ABC". I want to extract the exact match "ABC" into another cell. The contents of cell A1 can change, e.g. to "woman 60+ ABCD". For this input, I would want to extract "ABCD". If A1 was instead "woman 12-20 CAE", I would want "CAE".
There are 5 possible strings that the last part may be: (ABC, ABCD, AB, CAE, C), while the first portions are very numerous (~400 possibilities).
How can I determine which of the 5 strings is in A1?
If the first part "only" has lower case or numbers and the last part "only" UPPER case,
=REGEXREPLACE(D3;"[^A-E]";)
Anchor: Space
=REGEXEXTRACT(A31;"\s([A-E]+)$")
If you can guarantee well-formatted input, this is simply a matter of splitting the contents of A1 into its component parts (e.g. "gender_filter", "age range", and "my 5 categories"), and selecting the appropriate index of the resultant array of strings.
To convert a cell's contents into an array of that content, the SPLIT() function can be used.
B1 = SPLIT(A1, " ")
would put entries into B1, C1, and D1, where D1 has the value you want - provided your gender filter and age ranges.
Since you probably don't want to have those excess junk values, you want to contain the result of split entirely in B1. To do this, we need to pass the array generated by SPLIT to a function that can take a range or array input. As a bonus, we want to sub-select a part of this range (specifically, the last one). For this, we can use the INDEX() function
B1 = INDEX(SPLIT(A1, " "), 1, COUNTA(SPLIT(A1, " ")))
This tells the INDEX function to access the first row and the last column of the range produced by SPLIT, which for the inputs you have provided, is "ABC", "ABCD", and "CAE".
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.
In Google Sheets, I have this formula:
=ARRAYFORMULA( VLOOKUP( SPLIT(F2,", "), A2:B8, 2, FALSE) )
The intent is to take the comma-delimited string in cell F2 and find all values associated with the pieces. This works correctly, except when one of the pieces of the string looks like a number. For example, if F2 has the text a, 1.2, 1.2.3 then VLOOKUP will look for a as a string, and for 1.2.3 as a string, but will look for 1.2 as a number.
How can I coerce the result of SPLIT so that each piece remains a string?
I have a public copy of a test spreadsheet viewable here:
https://docs.google.com/spreadsheets/d/115WmV0vfXfaRgT0fVifJo86od3irZQy5gB3l-g6c7Ts/edit?usp=sharing
As background information, VLOOKUP treats strings and numbers differently. For example, given this table (where the formulae are shown for the first column):
A B
1 ="1.2" STR
2 =1.2 NUM
4 =VLOOKUP("1.2",A1:B2,2,0)
5 =VLOOKUP(1.2,A1:B2,2,0)
...the value shown in A4 will be "STR", and the value shown in A5 will be "NUM".
You can CONCAT a number with an empty string to convert it into its equivalent string representation.
CONCAT(1.2,"") yields "1.2"
To do this for every value, you must wrap the CONCAT() call in ARRAYFORMULA():
=ARRAYFORMULA(CONCAT(SPLIT(F2,", "),""))
The final formula thus becomes:
=TRANSPOSE(ARRAYFORMULA(VLOOKUP(ARRAYFORMULA(CONCAT(SPLIT(F2,", "),"")),A2:B8,2,FALSE)))