How to pull date from cell and compare it to today's date - 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");
}

Related

Google script doesn't send messages

I wrote a google script code (to send specific emails) and it'd been working for a while. But then I stopped it for about a month ago, and now I need it again. The problem is that code is executed, but it doesn't send any message. Could you please tell me what's wrong with my code.
function sendEmailL() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Lb'); //Sheet name
var startRow = 2; // First row of data to process
var numRows = 30; // Number of rows to process
// Fetch the range of cells U:V
var dataRange = sheet.getRange(startRow, 1, numRows, 30)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = row[20]; // First column
var message = row[21]; // Second column
var subject = 'Новое поступление от рекламодателя';
MailApp.sendEmail(emailAddress, subject, message);
}
}
If your not getting the right data in the dialog you need to learn how to use developer tools to figure out what's wrong.
function sendEmailL() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Lb'); //Sheet name
var startRow = 2; // First row of data to process
var numRows = 30; // Number of rows to process
// Fetch the range of cells U:V
var dataRange = sheet.getRange(startRow, 1, numRows, 30)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
let html='Test Data:<br />';
for (var i;i<data.length;i++) {
var row = data[i];
var emailAddress = row[20]; // First column
var message = row[21]; // Second column
var subject = 'Новое поступление от рекламодателя';
//MailApp.sendEmail(emailAddress, subject, message);
html+=Utilities.formatString('<br />Row:%s-emal: %s subject: %s message: %s',i+startRow,emailAddress,subject,message)
}
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html),'Testing');
}
And you probably should be checking getRemainingDailyQuota() to make sure you haven't exceeded the daily quota

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

Multiple OR conditions in time difference

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

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

Edit GoogleSheets "SendEmail" script to only send email if criteria are met

I've been searching online all morning, and haven't been able to find what I want to do. I found a similar post on here, but couldn't figure out how to adapt it to my needs.
I'm a teacher, and I was thinking about how I could use Google Sheets to automatically email parents when their child's grade falls below a C in my class. I was able to quickly find the script to have Sheets send an email, and was wondering if it's possible to edit that script to have the email sent ONLY if the value in a specific cell is below 70.
Here's the script I found. I edited the subject line to read "Math Grade" (that was easy to figure out), but I'd like to edit it so that the email only gets sent if the value in cell D2 (or D3, D4, D5, etc) is below 70. (Column A has email, Column B has the message, Column C would have the student's name, and Column D would have their numerical grade.) I feel like it should be obvious, but my scripting knowledge is non-existent. Can anybody help?
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:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = "Math Grade";
MailApp.sendEmail(emailAddress, subject, message);
}
}
The code was only getting 2 columns of data, and it needs to get 4.
getRange(row, column, numRows, numColumns)
I added a line of code that gets how many columns are in the sheet. Then the for loop got an extra line of code to get the grade, and finally, an if conditional check was added.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var numOfColumns = sheet.getLastColumn();
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, numOfColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var grade = "";
var i = 0;
for (i=0;i<data.length;i++) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
grade = row[3];
if (grade < 70) {
var subject = "Math Grade";
MailApp.sendEmail(emailAddress, subject, message);
};
};
};