Multiple OR conditions in time difference - date

I want to make a script that send me mail whith the content of what I've enterd in a form some days after the form is submitted. As a help for students to study. In the form enter what to study, then 1 day, 7 days and 28 days later get that in a mail.
I've made a form that collect time, recipient adress, subject and body for the mail. These are saved in a Google spreadsheet.
The code kind of work. But it send all of the mail from my test input in the sheet. I've added one 6 days ago, one yesterday and one today.
Today I should only get one mail and tomorrow two. But I get all of them today.
I think it's this line:
if (diffDays == 1 || diffDays == 7 || diffDays == 28) continue;
I've trided to change it, searched other ways of writing it, as array for example.
Here's the full code:
function createTimeDrivenTriggers() {
ScriptApp.newTrigger('reminder')
.timeBased()
.everyDays(1)
.atHour(16) // Change time of day here
.inTimezone("Europe/Stockholm")
.create();
}
function reminder() {
var today = new Date(); // Today
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
var headerRows = 1;
for (i=0; i<data.length; i++){
if (i < headerRows) continue;
var row = data[i];
var time = row[0];
// Get time difference
var timeDiff = Math.abs(today.getTime() - time.getTime());
var diffDays = Math.ceil((timeDiff) / (1000 * 3600 * 24)-1);
if (diffDays == 1 || diffDays == 7 || diffDays == 28) continue;
var recipient = row[1];
var subject = row[2];
var body = row[3];
// Send mail
GmailApp.sendEmail(recipient, subject, body)
}
}
Thanks

Make sure to execute the code only when your if statement is true.
Include all code after if statement in the statement itself, only executing it when diffDays = 1, 2 or 28.
function reminder() {
var today = new Date(); // Today
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
var headerRows = 1;
for (i=0; i<data.length; i++){
if (i < headerRows) continue;
var row = data[i];
var time = row[0];
// Get time difference
var timeDiff = Math.abs(today.getTime() - time.getTime());
var diffDays = Math.ceil((timeDiff) / (1000 * 3600 * 24)-1);
if (diffDays == 1 || diffDays == 7 || diffDays == 28) {
var recipient = row[1];
var subject = row[2];
var body = row[3];
// Send mail
GmailApp.sendEmail(recipient, subject, body)
}
}
}

Note that continue means "stop processing this iteration of whatever loop is getting executed, and begin the next iteration." So your script sends reminders on every day except the days you want to remind them.
Changing your test to an "AND NOT", moving the code for reminding inside the existing check, or using a more expressive syntax like switch will satisfy your intent.
switch (diffDays) {
case 1:
case 7:
case 28:
sendReminder(your, Args, Here);
break;
case 0:
sendWelcome(some, other, Args);
break;
...
default:
break;
}
...
function sendReminder(your, Args, Here) {
/* Code that uses function arguments to build and send an email */
}
"And not" meaning if (diffDay != 1 && diffDay != ...), i.e. "if it's not this, and not that, and not this other thing, and not..."

Related

Script to send email based on value in a column - problem with script

New to GAS. I have a Google Form feeding into a spreadsheet. After watching tutorial videos and reading other posts, I attempted to create a script that will send an email to an address in column 2, and send a different email based on either a yes or no in another column (column 25). It also includes another column (26) that I want to have the date populated into when the email is sent, ensuring that every time I run this script, there are no duplicates sent. I have debugged and nothing comes up as an error, but it's not working - I have not received an email. Help would be greatly appreciated! Here is an example spreadsheet: https://docs.google.com/spreadsheets/d/1AKaSOk1ZbnfKeadgB_mugnqplKzJJ3bDQ_KsRY0sMvQ/edit?usp=sharing
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responses = ss.getSheetByName("Field Trip Requests");
var data = responses.getRange(2,1,responses.getLastRow()-1,25).getValues();
data.forEach(function(row,i) {
// variables
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
if(emailSent == ' ') {
if(approval == "Y") {
var body = "Your field trip request for " +
destination +
" has been approved! If you requested transportation, Najma will make arrangements and contact you if she requires more information." +
"<br><br>" +
"Cheers," +
"<br><br>" +
"Boaty McBoatface";
}
else if(approval == "N") {
var body = "Your field trip request for " +
destination +
" has not been approved. Please come and see me and we can chat!" +
"<br><br>" +
"Cheers," +
"<br><br>" +
"Boaty McBoatface";
}
var subject = "Your Field Trip Request";
MailApp.sendEmail(recipient, subject, body)
var d = new Date();
responses.getRange(i + 1, 25).setValue(d);
}
})
}
One problem of the script is that you it's using 1 based indexes when it should be using 0 based in
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
The above is because JavaScript uses 0 based indexes for Array elements (as well as for other things), so intestead of the above use
var recipient = row[0];
var destination = row[5];
var approval = row[23];
var emailSent = row[24];
Another problem is the following condition:
emailSent == ' ' /* is emailSent equal to a blank space? */
it should be
emailSent == '' /* is emailSent equal to an empty string? */
the above because getValues() returns an empty string for empty cells
If this var data = responses.getRange(2,1,responses.getLastRow()-1,25).getValues(); is correct then there is no row[25] as shown below:
data.forEach(function(row,i) {
// variables
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
row starts at zero and ends at 24
row is an array
Perhaps this is what you wish:
function sendEmail() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("Field Trip Requests");
var data=sh.getRange(2,1,responses.getLastRow()-1,25).getValues();
data.forEach(function(row,i) {
var recipient=row[0];
var destination=row[5];
var approval=row[23];
var emailSent=row[24];
if(emailSent=='' && approval=='Y') {
var body=Utilities.formatString('Your field trip request for %s has been approved! If you requested transportation, Najma will make arrangements and contact you if she requires more information. <br><br>Cheers<br><br>Boaty McBoatface',destination);
}else if(emailSent=='' && approval == "N") {
var body=Utilities.formatString('Your field trip request for %shas not been approved. Please come and see me and we can chat!<br><br>Cheers,<br><br>Boaty McBoatface',destination);
}
var subject="Your Field Trip Request";
MailApp.sendEmail(recipient, subject, body);
sh.getRange(i+1,25).setValue(Utilities.formatDate(new Date, Session.getScriptTimeZone(), "MM/dd/yyyy"));
})
}

How to pull date from cell and compare it to today's date

I am using a spreadsheet to manage certification expiration dates. I want to send an email to an employee when their certification is expiring within 90 days. I only want to send one email. I am struggling getting the date from the cell and comparing it to today's date.
I want to send an email if Todays Date + 90 days in MS is > certification expiration date in MS.
I started using a template to prevent sending duplicate emails. I got it working with if && with words in two cells. I am struggling getting the dates to work. I have tried using getTime() to get the dates in MS but getValues().getTime returns an error.
var EMAIL_SENT = 'EMAIL_SENT';
var NintyDayInMs = 90*24*60*60*100;
var Today = new Date().getTime();
var expired = Today+NintyDayInMs;
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 4);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var emailSent = row[2]; // Third column
var exp = row[3]; // Fourth column
var expDate = exp.getTime();
if (emailSent != EMAIL_SENT && expDate < expired) { // Prevents
sending duplicates
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is
interrupted
SpreadsheetApp.flush();
}
}
}
My current code results in
TypeError: Cannot find function getTime in object (Date in cell).
(line 26, file "Code")
Read Adding Days to a Date - Google Script for a better understanding of date arithmetic in scripts.
The flaw is in trying to chain the expiry date. Instead of:
var exp = row[3]; // Fourth column
var expDate = exp.getTime();
use just:
var expDate = new Date(row[3]); // make the sheet value a date object
Then the rest goes naturally...
var expDate = new Date(row[3]); // make the sheet value a date object
Logger.log("expiry = "+expDate);
var today = new Date();
Logger.log("today = "+today);
var today90 = new Date(today.getTime()+90*3600000*24);// 90 days from today
Logger.log("today90 = "+today90);
if ((today90 > expDate) && (emailSent!=EMAIL_SENT)){
Logger.log("send the email");
}
else
{
Logger.log("don't send the email");
}

Struggle to pull email with reminder message on date count down

I have tried over and over to get this 'simple' script to work. I would like to scan over a column of dates and if a pre set 'days due' is today, it will then pull the email from the same row with a reminder message stating the task is due. For whatever reason, when I do this I cannot get multiple emails to fire to different owners and my loop keeps stacking the tasks due on the same day. I can SHARE SHEET HERE. any help is appreciated!!
function checkReminder() {
// get the spreadsheet object
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// set the first sheet as active
SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
// fetch this sheet
var sheet = spreadsheet.getActiveSheet();
// figure out what the last row is
var lastRow = sheet.getLastRow();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 2;
// grab column 5 (the 'days left' column)
var range = sheet.getRange(2,5,lastRow-startRow+1,1 );
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Now, grab the reminder name column
range = sheet.getRange(2, 1, lastRow-startRow+1, 1);
var reminder_info_values = range.getValues();
//Range A2:End of rows and columns
data = sheet.getRange(2, 6, lastRow-startRow+1,1);
//Now, grab the emails
var email_values = data.getValues();
//Logger.log(email_values)
//Logger.log(reminder_info_values)
//=======================Above this line works
fine====================================
for (k in email_values){
var row = email_values[k];}
//var emailAddress =row[5]
var warning_count = 0;
var msg = "";
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if(days_left == 7) {
// if it's exactly 7, do something with the data.
var reminder_name = reminder_info_values[i][0];
var emailAddress = row[6]
msg = msg + "Reminder: "+reminder_name+" is due in "+days_left+"
days.\n";
}
}
warning_count++;
if(warning_count) {
//MailApp.sendEmail(emailAddress,
//"Reminder Spreadsheet Message", msg);
Logger.log(emailAddress);
Logger.log(msg);
}
}

Send reminder emails based on date

I'm using the following script to send email reminders from a Google Sheet, but would like to modify it so that it send the email out on a date specified in cell F of each row.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 999; // Number of rows to process
// Fetch the range of cells A2:B999
var dataRange = sheet.getRange(startRow, 1, numRows, 999)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var subject = row[1]; // Second column
var message = row[2]; // Third column
var emailSent = row[3];
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 4).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
That's what I have and any attempts to add a date in there have failed pretty badly.
I came across this earlier question: Google Apps Script - Send Email based on date in cell but was unable to combine it with my script.
The solution Serge provided in that previous answer sets the stage for you to have a very flexible script, able to use any portion of the date / time as a criteria for sending.
Here's a simpler and less flexible approach. Assumptions:
The date is in the spreadsheet as a date, not a string.
We only care that the date matches; hours, minutes and seconds are inconsequential.
The script and the reminder dates in the spreadsheet are based on the same timezone.
The magic here is all about comparing dates. A JavaScript Date object is a numeric representation of time elapsed from the start of 1970, Universal time. Comparing equality of dates then, is difficult. However, thanks to the assumption above, we only care about the date, which is helpful. To get around timezone concerns and eliminate the effect of hours, minutes, etc., we just use the same Date method to generate date strings from the date objects we want to compare. The toLocaleDateString() method adjusts for time zones for us.
Resulting script:
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails3() {
var today = new Date().toLocaleDateString(); // Today's date, without time
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 999; // Number of rows to process
// Fetch the range of cells A2:B999
var dataRange = sheet.getRange(startRow, 1, numRows, 999)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var subject = row[1]; // Second column
var message = row[2]; // Third column
var emailSent = row[3];
var reminderDate = row[5].toLocaleDateString(); // date specified in cell F
if (reminderDate != today) // Skip this reminder if not for today
continue;
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 4).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

Sending Email populated by google sheets

Our Engineering Department has a request form on Google that our company uses to notify us of projects and other issues that need attending. The requests are assigned a project lead in our weekly meeting. I'm trying to write a script that will populate an email using data from the spreadsheet the form is driving to notify both the requester and the project lead so that they can contact each other directly instead of email everyone in the Engineering Group for updates. I tried splicing two different codes to achieve this as I was unable to find code I could easily adapt to fit our goal. I have listed the links below to the codes I used to write what I have.
https://developers.google.com/apps-script/articles/sending_emails
https://www.youtube.com/watch?v=_ToKh2JLQYs
The code tells me "Invalid email:" and highlights MailApp.sendEmail, even with real email addresses. Can anyone help? I haven't written any code since high school web design. We are considering using this form of notification in a few of our other departments as well. Assuming I get this version to work.
function SendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; //First row of data to process
var numRows = 2; //Number of rows to process
// Fetch the range of cells A2:L3
var dataRange = sheet.getRange(startRow, 1, numRows, 12)
// Fetch values for each row in the Range.
var Data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var requestername = row[1]; // Second column
var emailAddr = row[2]; // Third column
var requestspecifics = row[5]; // Sixth column
var projectlead = row[6]; // Seventh column
var projectleademail = ""; // Tenth Column
else if (projectlead == "Tom Smith") {projectleademail = "tom#fakeemail.com";}
else if (projectlead == "Dick Smith") {projectleademail = "dick#fakeemail.com";}
else if (projectlead == "Harry Smith") {projectleademail = "harry#fakeemail.com";}
else if (projectlead == "none") {projectleademail = null;}
var emailSent = row[12]; // Last column
if (emailSent !=EMAIL_SENT) { // Prevents sending duplicates
var myheader = "Minor Engineering Projects Requests";
MailApp.sendEmail({
to:emailAddr,
subject:myheader
body:requestername + ", \n\n + requestspecifics + " \n\nThe request you
submitted, listed above, has been assigned to " + projectlead + ". \nPlease
contact this person with any concerns. \n\nThank You, \n\nEngineering",
cc:projectlead]);
sheet.getRange(startRow + i,12).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I don't know if the code above was an exact copy/paste of your actual script but if it was it has a lot of syntax errors that I (hopefully) corrected, please give it a try, it should work if the structure of your spreadsheet is right...
function SendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; //First row of data to process
var numRows = 2; //Number of rows to process
// Fetch the range of cells A2:L3
var dataRange = sheet.getRange(startRow, 1, numRows, 12)
// Fetch values for each row in the Range.
var Data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var requestername = row[1]; // Second column
var emailAddr = row[2]; // Third column
var requestspecifics = row[5]; // Sixth column
var projectlead = row[6]; // Seventh column
var projectleademail = ""; // Tenth Column
if (projectlead == "Tom Smith") {projectleademail = "tom#fakeemail.com";}
else if (projectlead == "Dick Smith") {projectleademail = "dick#fakeemail.com";}
else if (projectlead == "Harry Smith") {projectleademail = "harry#fakeemail.com";}
else if (projectlead == "none") {projectleademail = null;}
var emailSent = row[12]; // Last column
if (emailSent !="EMAIL_SENT") { // Prevents sending duplicates
var myheader = "Minor Engineering Projects Requests";
MailApp.sendEmail({
to:emailAddr,
subject:myheader,
body:requestername + ", \n\n" + requestspecifics + " \n\nThe request you"+
"submitted, listed above, has been assigned to " + projectlead +
". \nPlease contact this person with any concerns. \n\nThank You, \n\nEngineering",
cc:projectlead});
sheet.getRange(startRow + i,12).setValue("EMAIL_SENT");
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}