Replace comma's with dots on opening google spreadsheet - replace

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);
}

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);
}
});
}

Apps Scirpt and regex. How?

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.
}

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);
}
}

Google Apps Script Copy a range to another sheet based on the value of a cell

I have a table in a sheet in which I have a vlookup to check against another sheet which contains the same data and identify if there are any missing rows (discrepancy).
I want to copy and paste the missing rows identified with the vlookup formula: column I = "#N/A"
I am stuck with the following code, any help is greatly appreciated:
function CopyMissingRows(e) {
if (e.values[8] == '#N/A') {
// do something
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A2:G2').activate();
var currentCell = spreadsheet.getCurrentCell();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Good events'), true);
spreadsheet.getRange('Sales cal').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}
else {
// do something else
}

google-apps-script multiple criteria writing over headers

I have taken a bit of script from Serge which is great (original link here. I have added in a second criteria to exclude certain rows and it works great except, if there is not header in the sheet being copied to, it will not work (error: "The coordinates or dimensions of the range are invalid.") and if I enter a header or some other data, it overwrites it. Can anyone assist please? I have also found that is there is no match to the criteria I get following message "TypeError: Cannot read property "length" from undefined."
Also, what change would I need to make to change the cell 'dataSheetLog[i][12]' to the status variable, i.e. "COPIED" after I have copied it across. I have tried writing a setValue line but it is obviously the wrong instruction for that syntax.
Code is:
{
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetLog = Spreadsheet.getSheetByName("LOG");
var sheetMaint = Spreadsheet.getSheetByName("MAINTENANCE");
var Alast = sheetLog.getLastRow();
var criteria = "08 - Maintenance"
var status = "COPIED"
var dataSheetLog = sheetLog.getRange(2,1,Alast,sheetLog.getLastColumn()).getValues();
var outData = [];
for (var i in dataSheetLog) {
if (dataSheetLog[i][2]==criteria && dataSheetLog[i][12]!=status){
outData.push(dataSheetLog[i]);
}
}
sheetMaint.getRange(sheetMaint.getLastRow(),1,outData.length,outData[0].length).setValues(outData);
}
In:
sheetMaint.getRange(sheetMaint.getLastRow(),1,outData.length,outData[0].length).setValues(outData);
getLastRow() refers to the last occupied row and should be ,getLastRow() + 1,to keep from overwriting your headers and other problems.
Edited:
{
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetLog = Spreadsheet.getSheetByName("LOG");
var sheetMaint = Spreadsheet.getSheetByName("MAINTENANCE");
var Alast = sheetLog.getLastRow(); // Log
var criteria = "08 - Maintenance"
var status = "COPIED"
var dataSheetLog = sheetLog.getRange(2,1,Alast,sheetLog.getLastColumn()).getValues(); //Log
var dataSheetLogStatusRange = sheetLog.getRange(2,13,Alast,1); //Log
var dataSheetLogStatus = dataSheetLogStatusRange.getValues(); //Log
var outData = [];
for (var i =0; i < dataSheetLog.length; i++) {
if (dataSheetLog[i][2]==criteria && dataSheetLog[i][12]!=status){
outData.push(dataSheetLog[i]);
dataSheetLogStatus[i][0] = "COPIED";
}
}
if(outData.length > 0) {
sheetMaint.getRange(sheetMaint.getLastRow() + 1,1,outData.length,outData[0].length).setValues(outData);
dataSheetLogStatusRange.setValues(dataSheetLogStatus);
}
}
}
what change would I need to make to change the cell
'dataSheetLog[i][12]' to the status variable, i.e. "COPIED" after I
have copied it across.
You were trying to update the value in the array that was extracted from the sheet and not the sheet itself. As arrays are zero based and spreadsheets are not, to translate, +1 must be added to array row and column indices. I am assuming status is in column M of your sheet.