Send reminder emails based on date - email

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

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

How to count no of rows in Google Spreadsheet and check if it contains a emailId value in the required column

Cant work out how to count the number of rows that have an email address in them, to populate the number of rows to process. I have a spreadsheet with a list of emails, the number of emailable rows changes regularly, so I'd like to count emailable rows, and instead of manually typing "28" or whatever, I'd like it to automatically find that number :)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 28; // Number of rows to process
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
// 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 = "membership number"
MailApp.sendEmail(emailAddress, subject, message);
}
}
Returns the current number of rows in the sheet, regardless of content.
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var noOfRows = sheet.getMaxRows();
var dataRange = sheet.getRange(startRow, 1, noOfRows , 4)
var data = dataRange.getValues();
data.foreach((row)=>{
if(emailRegex.test(row[0])){
var emailAddress = row[0];
var message = row[1];
var subject = "membership number"
MailApp.sendEmail(emailAddress, subject, message);
}
});
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getLastRow%28%29
for counting email addresses in a range you can use simply:
=COUNTIF(A:C, "*#*")
or the proper way:
=ARRAYFORMULA(COUNTIF(ISEMAIL(A:C), TRUE))

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

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