Prevent onEdit to run on some tabs - javascript

im using this script to auto date Col 1, when I edit Col 6
function onEdit(e) {
var colToWatch = 6, colToStamp = 1;
var timezone = "GMT-6";
var timestamp_format = "MM-dd-yyyy"; // Timestamp Format.
if (e.range.columnStart !== colToWatch) return;
if (e.source
.getActiveSheet()
.getRange(e.range.rowStart, colToStamp)
.getValue()) {
return;
}
var date = Utilities.formatDate(new Date(), timezone, timestamp_format);
e.source.getActiveSheet()
.getRange(e.range.rowStart, colToStamp)
.setValue(date);
}
is working perfect
What I have to do to prevent this onEdit to don't run on some tabs ?
Thanks !

You can define an array of tabs to exclude then check if current sheet is one among the excludes. Add this code after line 4.
var name = e.source.getActiveSheet().getName();
// enter names of the sheets to exclude, ['Sheet1', 'Sheet2'] etc
var excludes = [];
if (excludes.indexOf(name) != -1) return;

Related

Exclude First Row from Edit Script

I am very new to coding so I appreciate the community keeping this in mind. This script is limited to worksheet 1 and worksheet 2. When a line is edited the user email is recorded in the edited row column 41. I would also like to put a timestamp in column 42.
Bottom Line: I need for this to include a timestamp in column 42 AND exclude edits on the first (header) row.
function onEdit (e)
{
var ss = SpreadsheetApp.getActive()
var sheets = ["Worksheet","Worksheet2"]
var ws = e.range.getSheet()
if (sheets.indexOf(ws.getName()) != -1)
{
var row = e.range.getRow()
var rng = ws.getRange(row,41)
rng.setValue(e.user.getEmail())
function onEdit (e)
{
var ss = SpreadsheetApp.getActive()
var sheets = ["Worksheet","Worksheet2"]
var ws = e.range.getSheet()
if (sheets.indexOf(ws.getName()) != -1)
{
var row = e.range.getRow()
var rng = ws.getRange(row,41)
rng.setValue(e.user.getEmail())
var timezone = "GMT-4";
var timestamp_format = "yyyy-MM-dd HH:mm:ss";
var dateCol = headers[0].indexOf('Date');// create a column if its not exits
// note: actRng = the cell being updated
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
if (dateCol > -1 && index > 1) { // only timestamp if 'Date' header exists, but not in the header row itself!
var cell = sheet.getRange(index, dateCol + 1);
var date = Utilities.formatDate(new Date(), timezone, timestamp_format);
cell.setValue(date);
}
var sheetFrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Worksheet");
var sheetTo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Worksheet2");
var valuesToCopy = sheetFrom.getRange(0, 41, sheetFrom.getLastRow(), 1).getValues();
//Paste to another sheet from first cell onwards
sheetTo.getRange(1,sheetTo.getLastColumn()-1,valuesToCopy.length,1).setValues(valuesToCopy);
}
}
This will add current time to column 42 and copy column 41 from worksheet one to worksheet2
I was able to figure it out, thank you for the help it pointed me in the right direction. The following works:
function onEdit (e)//get the range of the edited cell
{
var ss = SpreadsheetApp.getActive()
var sheets = ["Worksheet","Copy of Worksheet"]
var ws = e.range.getSheet()
if (sheets.indexOf(ws.getName()) != -1)
// Check if the edit was made in an applicable sheet
{
var row = e.range.getRow()
if(row != 1){
//Get the row of the edited cell
var rng = ws.getRange(row,41)
//Range = Row of edited cells and Column 41
rng.setValue(e.user.getEmail())
var rng = ws.getRange(row,42)
//Range = Row of edited cells and Column 42
rng.setValue(Utilities.formatDate(new Date(),"America/New_York","yyyy-MM-dd HH:mm"))
}}}

Auto Move Yesterday's Data from Google Form Response Sheet

I have Google form which is linked to Form Response Sheet. I want to Move data from "Discrepancy Report - Outlet" to "Vaishali Nagar - DTR" Sheet on each day. The date is to be used from "Discrepancy Report - Outlet" sheet from Colum J.
The condition is that if I run the script today it should move data of Previous Day. For Ex. If I run script Today i.e. 31/10/2020 then It should only pick data of 30/10/2020. This process goes on each day. For running this script I will use Time Trigger.
I am using script which is mentioned below the Question. The problem I am facing it runs on the basis of today's date.
Link of Spreadsheet is:
https://docs.google.com/spreadsheets/d/1MhCdwFscPqskeeM2Hza-t2VXoVkI6sq3XRCNybMm4NM/edit?usp=sharing
function copyrange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Discrepancy Report - Outlet'); //source sheet
var testrange = sheet.getRange('J:J');
var testvalue = (testrange.setNumberFormat("#").getValues());
Logger.log(testvalue);
var ds = ss.getSheetByName('Vaishali Nagar - DTR'); //destination sheet
var data = [];
var j =[];
var today = new Date();
var yesterday = new Date(today); yesterday.setDate(yesterday.getDate()-1);
var today = Utilities.formatDate(new Date(), 'GMT-0', 'dd/MM/yyyy')
//Condition to check in J:J, if true, copy the same row to data array
for (i=0;i<testvalue.length;i++) {
if (testvalue[i] == today) {
data.push.apply(data,sheet.getRange(i+1,1,1,9).getValues());
//Copy matched ROW numbers to B
j.push(i);
}
}
//Copy data array to destination sheet
var start_row=ds.getRange('B7:B').getValues().filter(String).length +6; //calculate max row
ds.getRange(start_row+1,1,data.length,data[0].length).setValues(data);
}
Explanation:
The main issue is that your current code compares the dates with the date of today instead of yesterday.
However, your code can be further optimized. Instead of using a for loop to check if an element matches the date of today, you can use filter to get the data only for yesterday and then remove the lst column because you don't need it to be in the destination sheet:
yest_data = data.filter(r=>r[9]==yesterday).map(v=>v.slice(0,-1));
It is a good practice to check if the data has a length higher than 0, otherwise the script will drop an error when setting the values.
Solution:
function copyrange() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Discrepancy Report - Outlet'); //source sheet
const ds = ss.getSheetByName('Vaishali Nagar - DTR'); //destination sheet
const data = sheet.getRange('A2:J'+ sheet.getLastRow()).getDisplayValues();
var yesterday = new Date();
yesterday.setDate(yesterday.getDate()-1);
var yesterday = Utilities.formatDate(yesterday, ss.getSpreadsheetTimeZone(), 'dd/MM/yyyy');
yest_data = data.filter(r=>r[9]==yesterday).map(v=>v.slice(0,-1));
const start_row=ds.getRange('B7:B').getValues().filter(String).length +6; //calculate max row
if (yest_data.length>0){
ds.getRange(start_row+1,1,yest_data.length,yest_data[0].length).setValues(yest_data);
};
}
When checking date equality, you should use the date value or epoch time. Try this instead, which allows you to pass a specific date as your today value.
function test() {
var now = new Date('October 28, 2020');
var today = new Date(now.setHours(0, 0, 0, 0));
copyYesterday(today);
}
/**
* Copy yesterday's responses from Sheet1 to Sheet2.
* #param {Date} [today] - Optionally include a value to use as "today".
*/
function copyYesterday(today) {
if (today == null) { today = new Date(new Date().setHours(0, 0, 0, 0)); }
var yesterday = (new Date(today)).setDate(today.getDate() - 1);
var ss = SpreadsheetApp.getActive();
var sourceSheet = ss.getSheetByName('Sheet1');
var sourceData = sourceSheet.getDataRange().getValues();
var responses = [];
for (var rowIndex = 0; rowIndex < sourceData.length; rowIndex++) {
var row = sourceData[rowIndex];
var responseDate = row[0];
if (responseDate.valueOf() == yesterday) {
responses.push(row);
}
}
if (responses.length > 0) {
var destination = ss.getSheetByName('Sheet2');
destination.getRange(destination.getLastRow()+1, 1, responses.length, responses[0].length).setValues(responses);
}
}
function copyrange() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Discrepancy Report - Outlet'); //source sheet
var rg=sh.getRange(1,10,sh.getLastRow(),1);
var vA= rg.setNumberFormat("#").getValues();
var ds = ss.getSheetByName('Vaishali Nagar - DTR'); //destination sheet
var data=[];
var j=[];
var today = new Date().valueOf();
var yesterday = new Date(today.getFullYear(),today.getMonth(),today.getDate()-1).valueOf();
for (var i=0;i<vA.length;i++) {
var dt=new Date(vA[i][0]);
var dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
if (dtv==today) {
data.push(sheet.getRange(i+1,1,1,9).getValues());
}
}
ds.getRange(getColumnHeight(ds,2,ss)+1,1,data.length,data[0].length).setValues(data);
}
function getColumnHeight(col,sh,ss){
var ss=ss||SpreadsheetApp.getActive();
var sh=sh||ss.getActiveSheet();
var col=col||sh.getActiveCell().getColumn();
const rcA=sh.getRange(1,col,sh.getLastRow(),1).getValues().reverse()
let s=0;
for(let i=0;i<rcA.length;i++) {
if(rcA[i][0].toString().length==0) {
s++;
}else{
break;
}
}
return rcA.length-s;
}

On edit function with more than one letter

I created a bit of code, that has the On edit function.
So when others types "x" it gives me a timestamp in another cell.
Some are working on the google sheets app, and it gives you an "X" to start with
Is there anyway to get the On edit function to also work woth the large "X"?
I tried == "x","X", but then it also inserted a timestamp everytime i changed anything in the cell..
function onEdit(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() ==
"Mandagstræning","Tirsdagstræning","Torsdagstræning","Holdkamp") {
var actRng = sheet.getActiveRange();
var editColumn = actRng.getColumn();
var rowIndex = actRng.getRowIndex();
var headers = sheet.getRange(1, editColumn, 1,
sheet.getLastColumn()).getValues();
var dateCol = headers[0].indexOf("Tid") + editColumn;
if (sheet.getRange(rowIndex, orderCol).getValue() === "x") {
sheet.getRange(rowIndex, dateCol).setValue(Utilities.formatDate(new
Date(), "UTC+8", "dd-MM-yyyy HH.mm.ss"));
}
No error message, just no time stamp when hitting "X"
Sounds like you just want this check to be case insensitive. To accomplish this you can simply lowercase the input before checking it against "x", like so:
if (sheet.getRange(rowIndex, orderCol).getValue().toLowerCase() === "x") {
sheet.getRange(rowIndex, dateCol).setValue(Utilities.formatDate(new
Date(), "UTC+8", "dd-MM-yyyy HH.mm.ss"));
}
//++
const keyss = ['x','X'];
function onEdit(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() ==
"Mandagstræning","Tirsdagstræning","Torsdagstræning","Holdkamp") {
var actRng = sheet.getActiveRange();
var editColumn = actRng.getColumn();
var rowIndex = actRng.getRowIndex();
var headers = sheet.getRange(1, editColumn, 1,
sheet.getLastColumn()).getValues();
var dateCol = headers[0].indexOf("Tid") + editColumn;
// edited -->
if ( keyss.includes(sheet.getRange(rowIndex, orderCol).getValue())) {
sheet.getRange(rowIndex, dateCol).setValue(Utilities.formatDate(new
Date(), "UTC+8", "dd-MM-yyyy HH.mm.ss"));
}

Trigger email alert based on last row's condition NOT WORKING

I attempted to build a script but there are some issues. The table format are 2 columns which are date and values. These are the needs:
IDEAL STATE
Grab the last filled row (today's date) in the Google Sheets called "test".
Check in that row if the value in column F is greater than 0.5.
If it greater than 0.5, then trigger an email.
In email body, it should state "Results found on [date]."
This was my starting point but it does not produce what I want. These are the issues:
CURRENT STATE
1.The script grabs every row in which column F was greater than 0.5 in the past. I only want to check for today (which would be the last row). It should not look through everything in the past.
2.The email body states: Result found on [row number]". This makes no sense. I want the date to show, not the row number.
This is the current code. Please help.
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var values = sheet.getRange("F3:F").getValues(); //this has the values
var date = sheet.getRange("D3:D").getValues(); // this has the date
var results = [];
for(var i=0;i<values.length;i++){
if(values[i]>=0.5)
{
results.push("Result found on:" +(i+3));
}
}
MailApp.sendEmail('blabla#gmail.com', 'Alert', results.join("\n"));
};
Last Row in this context is Row 217, not 218, assuming sheet.getLastRow() would ignore #DIV/o! values. See screenshot for this.
LATEST UPDATE
The current Error is related "toDateString". I think it may be related that my Google Sheet is one day behind. So, it today is Jan 10, the last row in my Google Sheet is Jan 9th. I think that is why the error happens. Can you confirm? In that case, how do I change it to today-1 day?
See below.
Here's how you can check the last row:
function readCell() {
var sheet = SpreadsheetApp.getActive().getSheetByName('test');
var lastRow = sheet.getLastRow();
var value = sheet.getRange('F' + lastRow).getValue();
var date = sheet.getRange('D' + lastRow).getValue();
if (value >= 0.5) {
var result = 'Result found on: ' + date;
MailApp.sendEmail('blabla#gmail.com', 'Alert', result);
}
};
After seeing your data, I think the code below would suit you better.
function readCell() {
var sheet = SpreadsheetApp.getActive().getSheetByName('test');
var dates = sheet.getRange('D1:D').getValues();
var date = null;
var dateRow = 0;
var dateCount = dates.length;
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var yesterdayString = yesterday.toDateString();
for (dateRow; dateRow < dateCount; ++dateCount) {
date = dates[dateRow];
if (date instanceof Date) {
date = date.toDateString();
if (date === yesterdayString) {
++dateRow;
// To account for zero-based array
break;
}
}
}
var value = sheet.getRange('F' + dateRow).getValue();
if (value >= 0.5) {
var result = 'Result found on: ' + date;
MailApp.sendEmail('blabla#gmail.com', 'Alert', result);
}
};

Checking if date equal in Google Sheets/Google Scripts

I have 2 sheets that both have dates saved to columns. My current date is saved on both Sheet1 and Sheet2 with the same code:
curDate = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
I want to have one of my scripts compare the dates from Sheet1 to Sheet2
On Sheet1 I used a small script to set the current date and then used the drag function to set the previous and next dates in the column using the same formatting here:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Update Dates')
.addItem('Set Dates', 'setDatesUp')
.addToUi();
}
function setDatesUp(){
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet1");
var curDate = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
sheet1.getRange("A4").setValue(curDate);
}
Once the dates on Sheet1 are set up I use the following script to compare the dates from Sheet1 and Sheet2, this script also sets the date for Sheet2 because when this script is activated it's supposed to mark the current date in the corresponding box.
function onEdit() {
//Loops through all of Column C to determine which values are True and False
//Saves all True Values Row # in SavedValues
//Initialize Variables
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var sheet2 = ss.getSheetByName("Sheet2");
//Sheet 2 S2
var cValuesS2 = sheet2.getRange("C:C").getValues();
var dValuesS2 = sheet2.getRange("D:D").getValues();
var lastRowS2 = sheet2.getLastRow();
//Variables
var curDate;
var curVar;
//Loops through all S2 rows, stops at last row
for (var i = 0; i <= lastRowS2; i++){
//Checks checkboxes in S2C:C for True OR "Complete" and adds dates in corresponding D:D cells
if (cValuesS2[i] == "true" || cValuesS2[i] == "Complete") {
//If D:i is empty
if (dValuesS2[i] == "") {
//Sets current date
curDate = Utilities.formatDate(new Date(), "EST", "MM/dd/yyyy");
//Set current D:i cell (*+1 offset)
curVar = ("D" + (i + 1));
//Sets curVar value to curDate
sheet2.getRange(curVar).setValue(curDate);
}
//Checks checkboxes in S2C:C for False OR "Incomplete" and deletes dates in corresponding D:D cells
} else if (cValuesS2[i] == "false" || cValuesS2[i] == "Incomplete") {
//If D:i is NOT empty
if (dValuesS2[i] != "") {
//Set current D:i cell (*+1 offset)
curVar = ("D" + (i + 1));
//Sets curVar to ""
sheet2.getRange(curVar).setValue("");
}
}
}
updateS1();
}
Then finally I have my script to compare the dates from the 2 Sheets together.
function updateS1() {
//Initialize Variables
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var sheet1 = ss.getSheetByName("Sheet1");
var sheet2 = ss.getSheetByName("Sheet2");
//Sheet 1 S1
var aValuesS1 = sheet1.getRange("A:A").getValues();
var lastRowS1 = sheet1.getLastRow();
//Sheet 2 S2
var dValuesS2 = sheet2.getRange("D:D").getValues();
var lastRowS2 = sheet2.getLastRow();
//Variables
var curVar;
var curVar2;
//Loop through Sheet 1 until the bottom
//For each value in S1 A I use i
for (var i = 0; i <= lastRowS1; i++) {
//Loop through Sheet 2 until the bottom
//For each value in S2 D I use j
for (var j = 0; j <= lastRowS2; j++) {
//TODO: Compare dates from S1 A:i to S2 D:j
//If they are the same date the if statement will execute
}
}
}
I've already tried using the following
if (aValuesS1[i].toString() == dValuesS2[j].toString()) {
}
and
if (aValuesS1[i] == dValuesS2[j]) {
}
but neither option has worked. I've noticed that when I grab the "value" for the date in the Logger I get a lot of information that I don't want or need:
Thu Oct 30 2018 00:00:00 GMT-0400 (EDT)
instead of 8/30/18.
I think that this is the reason that I do not get "matching" values even if both of my boxes show the date formatted the same. I'm honestly stumped at how to solve this, so any help would be greatly appreciated.
So as it turns out, I actually can compare in my if statement with .toString() it just takes quite a while for my loop to execute in the Google Apps Script.

Categories

Resources