Apps Scirpt and regex. How? - regex

I am using .indexOf() to parse an array in a separate sheet via url and find a string in a header to return a numerical value or -1. Issue is I need to find the string match that is non case sensitive. ie var targetEmail = targetHeader.indexOf("Email"); would need to match "email", "user email", User email", etc. Normally I would use a regex but can't find a way to do this in Apps Script. Please any help would be very much appreciated.
sample code below:
var userHeader = USER.getRange(1, 1, 1, USER.getLastColumn()).getValues()[0];
var targetHeader = importSheet.getRange(1, 1, 1, importSheet.getLastColumn()).getValues()[0];
var ui = SpreadsheetApp.getUi();
var targetEmail = targetHeader.indexOf("Email");
if(targetEmail == -1)
ui.alert("Can not find Email column. Please rename column in source sheet.");

Using Javascript RegExp, you can use the following
let targetEmail = targetHeader.findIndex(h => /email/gi.test(h));
if(targetEmail == -1)
ui.alert("Can not find Email column. Please rename column in source sheet.");
Note: findIndex, let and the function shorthand will only work if your script is using the new V8 runtime.
I personally prefer to name the column I want using Google Sheets named ranges, and then use getNamedRanges(), so I'll be able to find the column number by its range name, regardless of the column heading text. If columns are inserted or deleted, the named range still points to the column you're looking for.

You could solve for this by
(1) joining the array into a string
targetHeader.join()
(2) and then changing the string to lowercase
toLowerCase()
and then looking for "email" (lower case).
var targetHeader = importSheet.getRange(1, 1, 1, importSheet.getLastColumn()).getValues()[0];
targetHeader = targetHeader.join().toLowerCase();
var targetEmail = targetHeader.indexOf('email');
Edit:
To find the column number with the word 'email' in it:
var importSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet101');
var targetHeader = importSheet.getRange(1, 1, 1, importSheet.getLastColumn()).getValues()[0];
var flag = false;
for (var c = 0; c < targetHeader.length; c++) {
var cellValue = targetHeader[c].toLowerCase();
if (cellValue.indexOf('email') > -1) {
flag = true;
break;
}
}
if (!flag) {
// ui alert that email not found
} else {
var columnWithEmalInHeader = c + 1;
// column with value 'email' found. Column number is c+1
// first time match of 'email' will pop-up here. All subsequent amounts will be ignored.
}

Related

deleting sheets with a date older than the past two days

Working in Google Scripts, I'm trying to create a function that will look at the names of all tabs in a Google Sheet, and delete all sheets that meet these conditions: 1) tab name include a date (sheet names that do have a date are prefaced with some other text - the mm/dd/yyyy formatted date is in the string) and 2) the date in that sheet name is older than today's date minus 2 days).
There are two sheet names that include dates: "Leadership Review mm/dd/yyyy" and "Leadership Review w/notes mm/dd/yyyy". I have a script that auto-runs DAILY to create these sheets, so the goal is to automate a one-time clean-up for old sheets and set up a daily trigger to auto-run that function.
So far, I've created an array to capture the names of each sheet name ("tabNameArray") and have a regexp for use in matching for mm/dd/yyyy text that shows up in a sheet name.
My thought on how this would work - not sure how to accomplish 2 and 3:
create that array
parse the array - match each sheetname in the array against the regexp mm/dd/yyyy to identify sheetnames with a date.
A loop through that array... IF that sheetname has a date (create a new array or subarray with just those? doesn't seem necessary, but a thought), AND that date is > 2 days from today(), delete those sheets.
function deleteOldReportSheets() {
var sheetNameArray = new Array();
var sheetWithDatesArray = new Array(); //not sure this is necessary
var dateRegex = new RegExp("[0-3]?[0-9]\/[0-3]?[0-9]\/(?:[0-9]{2})?[0-9]{2}"); //for mm/dd/yyyy match, tested successfully on regex101.com
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i=0 ; i<sheets.length ; i++) sheetNameArray.push( [ sheets[i].getName() ] ) // populates the sheetNameArray with names of each sheet
(do this: for sheets that have a date that is older than 2 days from today, delete...)
I'd appreciate support to code this - even better if there's a more efficient way than what I started thinking through.
Thanks for your assistance.
Description
The following example will compare the named sheets containing the date to today and indicate which sheets should be deleted. I leave the deletion operation to the OP.
Script
function test() {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let sheets = spread.getSheets();
let dateRegex = new RegExp("[0-3]?[0-9]\/[0-3]?[0-9]\/(?:[0-9]{2})?[0-9]{2}"); //for mm/dd/yyyy match, tested successfully on regex101.com
let today = new Date();
console.log("today = "+Utilities.formatDate(today,"GMT","MM/dd/yyyy"));
today = new Date(today.getFullYear(),today.getMonth(),today.getDate()-2);
for( let i=0; i<sheets.length; i++ ) {
let sheet = sheets[i];
let name = sheet.getName();
console.log("Sheet name = "+name);
let match = name.match(dateRegex);
if( match ) {
match = new Date(match[0]);
if( match.valueOf() <= today.valueOf() ) {
console.log("delete");
}
else {
console.log("keep");
}
}
}
}
catch(err) {
console.log(err);
}
}
Console.log
11:45:16 AM Notice Execution started
11:45:17 AM Info today = 05/01/2022
11:45:17 AM Info Sheet name = Sheet1
11:45:17 AM Info Sheet name = Sheet 04/29/2022
11:45:17 AM Info delete
11:45:17 AM Info Sheet name = Sheet 04/30/2022
11:45:17 AM Info keep
11:45:17 AM Info Sheet name = Sheet 05/01/2022
11:45:17 AM Info keep
11:45:16 AM Notice Execution completed
Reference
Date()
String.match()
I think it can be something like this:
function myFunction() {
const reg = new RegExp(/\d{2}\/\d{2}\/\d{4}/);
const ss = SpreadsheetApp.getActiveSpreadsheet();
const if_two_days_ago = date =>
new Date(date).valueOf() < new Date().valueOf() - 3600000 * 48;
ss.getSheets()
.filter(s => reg.test(s.getName()))
.filter(s => if_two_days_ago(s.getName().match(reg)))
.forEach(s => { console.log('bye-bye -->', s.getName()); ss.deleteSheet(s) });
}
Delete Sheets with dates older than two days
function delSheets() {
const ss = SpreadsheetApp.getActive();
const dt = new Date();
const dtv = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate() - 2).valueOf();//date threshold value
ss.getSheets().forEach(sh => {
let m = sh.getName().match(/\d{1,2}\/\d{1,2}\/\d{4}/g);//includes a date
if(m && new Date(m[0]).valueOf() < dtv) {
ss.deleteSheet(sh);
}
});
}

Google Sheets Scripts, IF date of a cell

I ve been getting some issues trying to use IF statement using items on the sheets as answers, mostly i been trying either using as firt statement a string directly or using another cell of the sheets with the statement comparing to the one i ve been trying to detect with out any results. Mostly my objective would be to, with a daly trigger, use an IF statement to detect every day if the date of today is the same as a date marked on a cell, my only current solution is and only thing is to make it detect if a cell is empty or not, so i just been using google Formulas that do the detect of the date, and if True make it empty, and if not make something appear
Here are some of the tests I ve been trying
Test 1:
var Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName");
else if (Sheet.getRange(1, 1).getValue() == "2/2/2020"){}
(cell A1=2/2/2020)
Test 2:
var Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName");
else if (Sheet.getRange(1, 1).getValue() == Sheet.getRange(1, 2).getValue()){}
(cell A1=2/2/2020)
(cell B1=2/2/2020)
Here are two solutions depending on what you are trying to accomplish.
This first one gets the values, formats them to a date format, and then compares them
function myFunction() {
var tz = Session.getScriptTimeZone();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SheetName');
var data = sheet.getDataRange().getValues();
var aVal = Utilities.formatDate(data[0][0],tz,'MM/dd/YYYY');
var bVal = Utilities.formatDate(data[0][1],tz,'MM/dd/YYYY');
Logger.log([aVal,bVal])
if(aVal == bVal) {
//do something
}
}
This second section gets the display values and compares them. The first solution compares the date values while this second solution compares the dates as a string. Good luck!
function myFunction1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('SheetName');
var data = sheet.getDataRange().getDisplayValues();
var aVal = data[0][0]
var bVal = data[0][1]
Logger.log([aVal,bVal])
if(aVal == bVal) {
//do something
}
}

Spreadsheet Script, match with wildcard and different cases

I am having trouble executing the Spreadsheet script below.
I think there are two mistakes but I do not know how to fix.
Could anyone help it to fix it?
1:Wildcard
if(original_date=='....-..-..')
2:if synteax
if(original_date=='....-..-..')
{condition="matched"}
Detail
On the spreadsheet, there are two columns.
The first columns have dates in a format as YYYY-MM-DD such as 2020-04-21.
But sometimes, they have different formats such as 04/21/2020.
The second columns are empty.
Only when the first column cell has the "YYYY-MM-DD" format, I want to copy the cell into the second cell in the second column.
*They have 10 rows.
Here is the script.
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1')
for(let i=1; i<=10; i++)
{
original_date_range = sheet.getRange(i, 1);
original_date = original_date_range.getValue();
cleaned_date_range = sheet.getRange(i, 2);
var condition = "";
if(original_date=='....-..-..')
{condition="matched"}
switch(condition)
{
case "matched":
cleaned_date_range.setValue(original_date);
case "":
cleaned_date_range.setValue("");
break;
}
}
I found the solution by myself.
1.Wildcard
The date "2020-04-25" can be written as /\d{4}.\d{2}.\d{2}/
2.If syntax
(Wildcard).test(string to check) is going to give you true/false output
In summary,
if you want to execute different tasks through the verification of date format such as 2020-04-25,
var sheet1 = SpreadsheetApp.getActive().getSheetByName('Sheet1')
var limit = sheet1.getLastRow()
for(let i=4; i<=10; i++) //You can add more rows if you have
{
var orignal_date_cell = sheet1.getRange(i, 1);
var orignal_date_cell_value = orignal_date_cell.getValue();
var target_date_cell = sheet1.getRange(i,2);
if ((/\d{4}.\d{2}.\d{2}/).test(orignal_date_cell_value))
{
target_date_cell.setValue(orignal_date_cell_value);
}
}

Gmail App search criteria

I have the following search criteria working very well in Gmail:
user#domain from:/mail delivery/ || /postmaster/ ||/Undeliverable/
I am trying to write Goole Apps code to return the same results. Here is the code:
var thread=GmailApp.search("user#domain from:/mail delivery/ || /postmaster/ ||/Undeliverable/ ");
I am getting different results. I am new to both Regex and Google Apps.
Try Amit Agarwal's tutorial on Gmail Search with Google Apps Script which includes Using Regular Expressions to Find Anything in your Gmail Mailbox:
function Search() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = 2;
// Clear existing search results
sheet.getRange(2, 1, sheet.getMaxRows() - 1, 4).clearContent();
// Which Gmail Label should be searched?
var label = sheet.getRange("F3").getValue();
// Get the Regular Expression Search Pattern
var pattern = sheet.getRange("F4").getValue();
// Retrieve all threads of the specified label
var threads = GmailApp.search("in:" + label);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var msg = messages[m].getBody();
// Does the message content match the search pattern?
if (msg.search(pattern) !== -1) {
// Format and print the date of the matching message
sheet.getRange(row,1).setValue(
Utilities.formatDate(messages[m].getDate(),"GMT","yyyy-MM-dd"));
// Print the sender's name and email address
sheet.getRange(row,2).setValue(messages[m].getFrom());
// Print the message subject
sheet.getRange(row,3).setValue(messages[m].getSubject());
// Print the unique URL of the Gmail message
var id = "https://mail.google.com/mail/u/0/#all/"
+ messages[m].getId();
sheet.getRange(row,4).setFormula(
'=hyperlink("' + id + '", "View")');
// Move to the next row
row++;
}
}
}
}

Replace comma's with dots on opening google spreadsheet

I have a questionaire that fills a google spreadsheet.
When I open the spreadsheet I want all commas (,) to be replaced by dots (.).
The name of my spreadsheet is 'GF Answers' and the sheet that it contains is 'responses'.
Any directions/suggestions for appropriate code?
Thanks!
To take Kriggs answer one step further, and simply drop you off at the destination, something like the following should work (you may have to change the 'range' to conform to your spreadsheet if there are any sections you don't want to modify):
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('responses');
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
var data = range.getValues();
for (var row=0; row<data.length; row++) {
for (var item=0; item<data[row].length; item++) {
data[row][item] = data[row][item].replace(/,/g, '.');
}
}
range.setValues(data);
}