Google Sheets 'Text' function & Conditional Formatting - google-apps-script

Is there any way to use the 'TEXT' function in the Google sheets Conditional Formatting sidebar?
For example, if ten rows need to be formatted as currency, based on a text description value in column A -- can a custom formula be used to execute the 'consequence' of an IF/THEN... if a TRUE condition exists?
Desired Format Rules/ Custom Formula (since 'number formatting' is not a viable 'Conditional Formatting option):
Apply to range 1:1
=IF(a1="REVENUE", TEXT(a3,"$#,##0.00"))
(the flag in a1 will dictate the row formatting)
Trying to AVOID having to iterate through all rows using code (such as the sample below) and instead check for the 'flag' column and apply the required formatting in the UI.
var ss = SpreadSheetApp.getActiveSpreadsheet().getSheetByName('sheet1');
var values = ss.getRange('a1:a10').getValues();
values.forEach(row=>{if (Range=="REVENUE") {ss.getRange(r,1).setNumberFormat("$#,##0.00")}}....

Related

Format a Google Sheets cell in numerical formatting 000 via Apps Script

I'm looking to set a column to format 000, which will display the zeros at begenning.
So, if a cell displays "3", I want that the script will set it to display "003".
This column is located in BDD tab, 13th column starting from the second row.
function FormattingGpeTrait() {
const sheet = SpreadsheetApp.getActiveSheet().getSheetByName("BDD").getRange(2,13)
sheet.setNumberFormat('000')
Modification points:
The method of "getSheetByName" is for Class Spreadsheet. In your showing script, you try to use it to Class Sheet. By this, an error occurs. This has already been mentioned in the comment. Ref
From 13th column starting from the second row., I thought that you might have wanted to set the number format of 000 to "M2:M". In your showing script, the number format is set to only a cell "M2".
If you want to set the number format to the cells "M2:M" of the sheet name of "BDD", how about the following modification?
Modified script:
function FormattingGpeTrait() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("BDD");
sheet.getRange("M2:M" + sheet.getLastRow()).setNumberFormat('000');
}
When you run this script, the number format of "000" is set to the cells "M2:M" of "BDD" sheet.
If you want to set the number format to the "M2:M", please modify getRange("M2:M" + sheet.getLastRow()) to getRange("M2:M").
References:
getActiveSpreadsheet()
getSheetByName(name)
The easiest way to get a range on a named sheet is to include the sheet name in the range reference, like this:
function formattingGpeTrait() {
SpreadsheetApp.getActive().getRange('BDD!M3:M').setNumberFormat('000');
}
I think that you can't use the standard number formats as they all will only evaluate your value to a real number value where '003' in reality is equal to '3' from a numeric sense.
You have two real options which is to either store the value in a Text column as "003" or prepend the value with an apostrophe "'003" which is basically the same as storing it as Text but the column can remain numeric.
You can create a custom number format for a cell/column to also do this but I am not certain how to accomplish this programatically. Basically, this is still going to end up like the Text variations I mention above, only you have a named format you can call. The data will still be stored as Text.

Highlight Google Sheet cell (red) when two different cell's text do not match

basically what I am trying to achieve is to highlight or set background of the cell that has a 'typo' so does not match to another one.
I have a tracker used by my team, they enter the code version in column D. Column C contains the environment name, e.g. QA, PROD.
When QA testing activities are completed, they simply copy the code version to a row below, but what happens sometimes, they manually enter the version accidentally making a mistake (typo) - therefore the code that is implement to prod will be incorrect and can cause system malfunction.
Column A will be a primary key let's call it this way (module)
I am trying to validate the text they enter in the cell so I either want to use conditional formatting or a script. Conditional formatting in my opinion will not work properly as the function is quite advance, so it will be easier to implement a script. Is the below script correct?
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getSheetByName("2022").getRange(1,1);
var cellRange = range.getValues();
for(i = 0; i<cellRange.length-1; i++){
if(cellRange[i][0] == "PROD")
elseif(cellRange[i][0] == "QA")
{
ss.getSheetByName("2022").getRange(i+2,6).setBackground("red");
}
}
}
In case I use conditional formatting it would have to be: if environment equals to PROD and QA, and if QA & PROD module is the same, CODE version should match... if does not match, highlight a prod code cell with red color....
I assume that the structure of your code is as follows:
and that your objective is to modify the background color of the C column (in this example) if the values in the A and B columns do not match.
As you said, this can either be accomplished with conditional formatting or with a script attached to the spreadsheet.
If you wish to do it via conditional formatting (which is what I would recommend) you need to select the C2 cell, open Format -> Conditional Formatting, and inside the Format Rules change Format cells if... to Custom formula is. Then enter the following formula:
=A2<>B2
which will trigger the C2 cell coloring whenever the values in A2 and B2 are not equal. You can now scroll down this formatting to apply to as many rows you want. You can read more about conditional formatting here.
If you wish to implement a script, this will do the job:
function myFunction() {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadSheet.getSheetByName("Sheet1");
var range = sheet.getRange(2,1,sheet.getLastRow()-1, 2);
//SHOULD ADAPT THE VALUES IN THE getRange TO FIT YOUR SPREADSHEET
var values = range.getValues();
for (var row = 0; row < values.length; row++){
if(values[row][0] != values[row][1]){
sheet.getRange(row+2,3).setBackground('red');
}
else{
sheet.getRange(row+2,3).setBackground('white');
}
}
}
where you will need to adjust your ranges to fit your spreadsheet (this works for the example spreadsheet above).
#Oriol Castander, it is pretty much as you described above:
As you can see, there is a discrepancy in values between TAGS (column E) which should not happen. So basically I want to prevent such thing of happening, by highlighting mismatched values with red color.

How to use custom function ExtractAllRegex() as an array formula? [Google Sheets]

I'm using #Wiktor Stribiżew 's custom function ExtractAllRegex(). The script extracts all occurrences of a Regex pattern. In the example, I extract all words in column A starting with "v_"
Here is a Google Sheet showing what I'm trying to do.
The original strings are stored in column A. The custom function/the matches are in column B.
Wictors function works great for single cells. It also works great when I manually drag the formula down the column.
Here's Wictor's original code:
function ExtractAllRegex(input, pattern,groupId,separator) {return Array.from(input.matchAll(new RegExp(pattern,'g')), x=>x[groupId]).join(separator);}
Description:
input - current cell value
pattern - regex pattern
groupId - Capturing group ID you want to extract
separator - text used to join the matched results.
The question is, how do I turn column B into a working array formula? Or, perhaps better, how do I modify Wictor's script so it accepts a range instead and auto-fills down column B?
I updated your script to:
function ExtractAllRegex(input, pattern,groupId,separator) {
return input.map ? input.map( inp => ExtractAllRegex(inp, pattern, groupId, separator)) :
Array.from(input.matchAll(new RegExp(pattern,'g')), x=>x[groupId]).join(separator);
}
and changed the formula in B2 to
=ExtractAllRegex(A2:A13,"(v_.+?\b)",0," ")
See if that works for you?

How to create INDIRECT array string of multiple sheet references in Google Sheets?

I am attempting to use a query to display data off multiple Google Sheets. I make a new sheet every week that has a specific sheet name, e.g. Week of 01/13, Week of 01/06 and so forth.
The following is where my idea spawned from for reference:
I have a summary sheet that is using COUNTA(INDIRECT("'" & A5 &
"'!E4:E",true)
A5 being a cell that concatenates a date and words to replicate the
sheet names.
The row on the summary sheet does not populate until B5<=today()
So I am able to set it an forget it and the sheet will continue to
give me my weekly data as the days progress and keeps the sheets clean
until the week is upon us.
Long story short, I have a query that I use that gives me all the data I need with a specific parameter but I have to manually update the data syntax array with the new sheet names each week.
=QUERY({'Week of 01/13'!A:P;'Week of 01/06'!A:P;'Week of 12/30'!A:P;'Week of 12/23'!A:P;'WEEK OF 12/16'!A:P;'WEEK OF 12/09'!A:P;'WEEK OF 12/02'!A:P;'WEEK OF 11/25'!A:P;'WEEK OF 11/18'!A:P;'WEEK OF 11/11'!A:P;'WEEK OF 11/04'!A:P;'WEEK OF 10/28'!A:P;'WEEK OF 10/21'!A:P;'WEEK OF 10/14'!A:P;'WEEK OF 10/07'!A:P;'WEEK OF 09/30'!A:P;'WEEK OF 09/23'!A:P;'WEEK OF 09/16'!A:P;'WEEK OF 09/09'!A:P;'WEEK OF 09/02'!A:P},
"Select * where Col11 = 'RD' order by Col2 desc",0)
I would like to build a reference to an array that will auto-populate a concatenation based on the day.
Using the following code I can have the concatenate give me the array I need,
=if(H4<=today(),CONCATENATE("'",H$1,text(H4,"mm/dd"),"'!A:P;",),"")
but when I try to input it into the query function it just returns the concatenated text:
=QUERY(I1,"Select *")
'Week of 01/06'!A:P;'Week of 01/13'!A:P
I have tried with and without the curly brackets with no success.
I would like the sheet to be able to refresh and see that it is the correct day, the new sheet name is populated and the query gets updated.
I need help with making I1 work.
Link to Test Query Sheet
dudes who copy-pasted INDIRECT function into Google Sheets completely failed to understand the potential of it and therefore they made zero effort to improve upon it and cover the obvious logic which is crucial in this age of arrays.
in other words, INDIRECT can't intake more than one array:
=INDIRECT("Sheet1!A:B"; "Sheet2!A:B")
nor convert an arrayed string into active reference, which means that any attempt of concatenation is also futile:
=INDIRECT(MasterSheet!A1:A10)
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{Sheet1!A:B; Sheet2!A:B}")
————————————————————————————————————————————————————————————————————————————————————
={INDIRECT("Sheet1!A:B"; "Sheet2!A:B")}
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}")
the only possible way is to use INDIRECT for each end every range like:
={INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}
which means that the best you can do is to pre-program your array like this if only part of the sheets/tabs is existant (let's have a scenario where only 2 sheets are created from a total of 4):
=QUERY(
{IFERROR(INDIRECT("Sheet1!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet2!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet3!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet4!A1:B5"), {"",""})},
"where Col1 is not null", 0)
so, even if sheet names are predictable (which not always are) to pre-program 100+ sheets like this would be painful (even if there are various sneaky ways how to write such formula under 30 seconds)
an alternative would be to use a script to convert string and inject it as the formula
A1 would be formula that treates a string that looks like real formula:
=ARRAYFORMULA("=QUERY({"&TEXTJOIN("; ", 1,
IF(A3:A<>"", "'Week of "&LEFT(A3:A, 5)&"'!A1:D5", ))&
"}, ""where Col1 is not null"", 1)")
further populating of A6:A will expand the string automatically
then this script will take the string from A1 cell and it will paste it as valid formula into C5 cell:
function onEdit() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Master Sheet');
var src = sheet.getRange("A1");
var str = src.getValue();
var cell = sheet.getRange("C5");
cell.setFormula(str);
}
of course, the script can be changed to onOpen trigger or with custom name triggered from the custom menu or via button (however it's not possible to use the custom function as formula directly)
If you're trying to update the data your query is looking at and you're feeding it a string, you need to put that string within the indirect() function. That will interpret your string as a data reference and point your query() in the right direction.
So for this you'd probably have
=QUERY(INDIRECT(I1),"Select *")

Google docs query when contains value in a range

In google sheets, I want to return a row when a cell in column C contains any value in a range on a different sheet.
The query below does not work. What am I missing?
=QUERY(
'Form Responses 1'!$1:$1000,
" select A:G where C contains 'Sheet2'!$A1:$A26"
)
If you are trying to match a string value in a range on a different sheet:
=query('Form Responses 1'!$1:$1000, "SELECT A,B,C,D,E,F,G WHERE A MATCHES '"&JOIN("|",'Sheet2'!$A1:$A26)&"'",1)
Hopefully syntax highlighting in the image below makes the above string concatenation operators a little clearer:
GoogleSheets: Select partial row if target column in data set contains value within range declared in another sheet
I suggest flagging the rows of interest in Form Responses 1, say with in H1:
=ArrayFormula(countif(Sheet2!A:A,C1:C))
and then selection based on the flags, say with:
=QUERY('Form Responses 1'!$1:$1000,"select * where H=1")
or if you don't want the flags to appear:
=QUERY('Form Responses 1'!$1:$1000,"select A,B,C,D,E,F,G where H=1")