How do you set up automatic email alerts triggered by date - google-apps-script

I am struggling to write an apps script to trigger automatic emails based on a date. I have reviewed other questions/answers but can't get it right. My Google Sheet is below:
Google Sheet
My alert data is in the sheet called H&S Reviews.
My email message is in cell A1 of the Email Alerts Sheet.
The trigger date to send an email is column J of the H&S Reviews sheet and I thought that the code could be written against this and cell J1 which is today's date.
Column J = date email to be sent
Column I = first name of email recipient
Column H = email address
Column B = task per message
Column C = description per message
My code is called functionsendEmails`. You will see that it needs your expertise.
Also, I am hoping that the alert could be written to the email recipients Google Calendar but not sure if this is possible.

Here is the code from your script modified to send the email when date on J column match the date in J1. I recommend you change your code to use getValues() [1] and loop the resulting array instead of using getValue() every time, is much more optimized and will prevent you from hitting the Google quotas[2].
function sendEmails() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName("H&S Reviews").activate();
var lastRow = sheet.getLastRow();
var message = spreadsheet.getSheetByName("Email Alerts").getRange(1,1).getValue();
for (var i = 3;i<=lastRow;i++){
var emailAddress = sheet.getRange(i, 8).getValue();
var firstName = sheet.getRange(i, 9).getValue();
var todaysDate = sheet.getRange(1, 10).getValue();
var date = sheet.getRange(i, 6).getValue();
date = Utilities.formatDate(date,'GMT+0200','dd MMMM yyyy');
var task = sheet.getRange(i, 2).getValue();
var description = sheet.getRange(i, 3).getValue();
var messageBody = message.replace("{name}",firstName).replace("{Task}",task).replace("{Description}",description).replace("{Date}",date);
var subject = "Health & Safety Review Task";
var sendDate = sheet.getRange(i, 10).getValue();
var sheetDate = new Date(sendDate);
Sdate=Utilities.formatDate(todaysDate,'GMT+0200','yyyy:MM:dd')
SsheetDate=Utilities.formatDate(sheetDate,'GMT+0200', 'yyyy:MM:dd')
Logger.log(Sdate+' =? '+SsheetDate)
if (Sdate == SsheetDate){
var subject = "Health & Safety Review Task";
MailApp.sendEmail(emailAddress, subject, messageBody);
Logger.log('SENT :'+emailAddress+' '+subject+' '+messageBody)
}
}
}
[1] https://developers.google.com/apps-script/reference/spreadsheet/range#getValues()
[2] https://developers.google.com/apps-script/guides/services/quotas

Related

How to reference a value in a different sheet?

This is prob simple but I'm new to this. I'm trying to map out my variables at the beginning of a Google Form>Spreadsheet>Template Doc workflow. The form fills out the following 4 columns (timestamp through campaign_start_date) but the other 2 columns (insertion_order_number and month) are values that are coming from a different sheet in the SAME google spreadsheet/workbook. How do I reference these values?
//e.values is an array of form values
var timestamp = e.values[0];
var client = e.values[1];
var advertiser = e.values[2];
var total_spend_amount = e.values[3];
var campaign_start_date = e.values[4];
var insertion_order_number =
var month =
As mentioned in the above comment.
You want to open a spreadsheet by it's ID.
Once you have that spreadsheet you want to the range where "Campiagn Start Date" and Insertion Order Month" are in.
Once you have that range, you want to get the value(s) inside that range.
Then you can assign the value of those two variables to be the value that you got above.
The below code is an example of what you could do.
I would highly advise using getValues() over getValue.
But for the purpose of this sample code, will keep it nice and simple:
function onSubmit(e) {
//Get Spreadsheet by ID and get sheet by name
var ss = SpreadsheetApp.openById("YOUR ID HERE");
var sheet = ss.getSheetByName("YOUR SHEET NAME HERE");
var campiagnStartDate = sheet.getRange(2, 2, 1, 1).getValue(); //Gets the value in B2
var insertionOrderMonth = sheet.getRange(2, 3, 1, 1).getValue(); //Gets the value in B3
var timestamp = e.values[0];
var client = e.values[1];
var advertiser = e.values[2];
var total_spend_amount = e.values[3];
var campaign_start_date = e.values[4];
var insertion_order_number = campiagnStartDate
var month = insertionOrderMonth
}

Function to clear a cell based on clicking on a URL in a Google Spreadsheet to reopen a form?

Is it possible to create a function that will clear a cell when a URL on the active row is clicked? I need to clear the cell on the active row in column AG, or [32], whenever the response link on that cell is activated to be opened to go back to the form.
I have the code that creates the date value in the column I need cleared. The code is to disburse emails automatically (on a trigger) when an email is submitted. However, when a response needs to be added to the form, the 'Response Link' needs to be activated so the user can be taken back to the form to fill in response data. I want the emails to go out again when the form is updated. But because I added a date there to stop emails from going out over and over, updated emails cannot send. Once the form is resubmitted, it will put a date back into the cell.
function disburseEmails(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Form Responses 1');
var allRange = sheet.getDataRange();
var allData = allRange.getValues();
allData.shift();
allData.forEach(function(row,i) {
if(row[32] === '') {
// get data
var dateSubmitted = row[0];
var dateEdited = row[1];
var studentID = row[2];
var studentName = row[3];
var responseLink= row[4];
var submitRespond = row[5];
var senderName = row[6];
var senderEmail = row[7];
var senderPhone = row[8];
var senderExt = row[9];
var senderRole = row[10];
var senderReason = row[11];
var senderAdditional = row[12];
var householdName = row[13];
var householdAddress = row[14];
var householdPhone = row[15]
var studentGrade = row[16];
var studentSchool = row[17];
var anySiblings = row[18];
var sibling1Name = row[19];
var sibling1Grade = row[20];
var sibling1School = row[21];
var sibling2Name = row[22];
var sibling2Grade = row[23];
var sibling2School = row[24];
var additionalSiblings= row[25];
var numberHomeVisit = row[26];
var responseContactName = row[27];
var responseContactRelationship = row[28];
var responseOutcome= row[29];
var responseAdditional = row[30];
var email = row[31];
var confirmSenderEmail = row[32];
// send an email to the sender for each row
sendEmail(dateSubmitted, email, dateEdited, studentID, studentName, responseLink, submitRespond, senderName, senderEmail, senderPhone, senderExt, senderRole, senderReason, senderAdditional, householdName, householdAddress, householdPhone, studentGrade, studentSchool, anySiblings, sibling1Name, sibling1Grade, sibling1School, sibling2Name, sibling2Grade, sibling2School, additionalSiblings, numberHomeVisit, responseContactName, responseContactRelationship, responseOutcome, responseAdditional);
// add date to confirm the sender email went out
var d = new Date();
sheet.getRange(i + 2, 33).setValue(d);
}
});
}
Let's asssume you have the links the needed in the F column:
function onSelectionChange(e) {
var range = e.range;
var sheet = e.range.getSheet();
if(range.getColumn() == 6) {
sheet.getRange("RANGE_OF_THE_CLEARED_CELL").clear();
}
}
The above snippet uses an onSelectionChange(e) trigger which will trigger whenever a cell is selected. In order to check that a cell from the F row is selected, a condition is set and based on that, the cell wanted is cleared.
The code makes use the e event object which contains information about which cell has been selected.
Note
This works for all the cells in the F column, so if you want to make it specific to a particular cell, you can just add another condition and/or a loop to reflect the data you want accordingly.
Reference
Apps Script Triggers;
Apps Script Event Objects ;
Apps Script Class Sheet - getRange

Sending out emails based on date in Google Sheets Scripts

I'm trying to create a Script that will send an email for every cell that contains today's date. Here's what I have so far:
function email() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var rowCounter = 1;
var limit = sheet.getLastRow();
// Fetch the estimated dates & Today's date
var estimatedReturnDateRange = sheet.getRange("F:F");
var estimatedReturnDate = estimatedReturnDateRange.getCell(rowCounter, 1);
var todayDateRange = sheet.getRange("S1");
var todayDate = todayDateRange.getValue();
// Check totals sales
for(i=1; i<=limit; i++){
if (estimatedReturnDate = todayDate){
// Fetch the email address
var emailAddress = "maxbkimmel#gmail.com";
// Send Alert Email.
var message = estimatedReturnDate; // Second column
var subject = 'Your Google Spreadsheet Alert';
MailApp.sendEmail(emailAddress, subject, message);
}
rowCounter++;
estimatedReturnDate = estimatedReturnDateRange.getCell(rowCounter, 1);
}
rowCounter =1;
}
This is how I envision the logic of the script working:
estimatedReturnDate initially grabs the first cell in column F, which is a list of dates.
todayDate grabs cell S1, which contains today's date.
a for loop then loops through all rows of the sheet, and checks if estimatedReturnDate = todayDate.
If it does, an email is sent that contains the Row Number that matched today's date.
Then, rowCounter is incremented, estimatedReturnDate is set to the next cell in the row, and the loop runs again.
The problem I'm having is that when I run this script, an email is sent out for each row in the sheet, regardless of whether estimatedReturnDate matches todayDate or not.
Does anyone know what would be causing this?
function email() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getSheets()[0];//This is always the left most sheet but not necessarily the same sheet depending how users move the sheets around.
var vA=sheet.getRange(1,5,sheet.getLastRow(),1).getValues()
var dt=new Date();
var toda=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();//midnight yesterday
var tmro=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()+1).valueOf();//midnight today
for(var i=0;i<vA.length;i++){
var dt=new Date(vA[i][0]).valueOf();//date from column5 of spreadsheet
//dt is between midnight yesterday and midnight today
if(dt>=toda && dt<=tmro){
var emailAddress = "maxbkimmel#gmail.com";
var message = Utilities.formatDate(dt, Session.getScriptTimeZone(), "E MMM dd, yyyy");
var subject = 'Your Google Spreadsheet Alert';
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
Utilities.formatDate
Date Class

Log the user that modified a row in a Google Spreadsheet?

I have the following code which writes the last edit date and time in the last cell of the row:
function onEdit(event)
{
var sheet = event.source.getActiveSheet();
// Note: actRng = return the last cell of the row modified
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
var cindex = actRng.getColumnIndex();
// Note: date = return date + time
// Note: user = return the user email
var dateCol = sheet.getLastColumn();
var lastCell = sheet.getRange(index,dateCol);
var date = Utilities.formatDate(new Date(), "GMT-0300", "dd-MM-yy HH:mm");
//var user = event.user; // Note: event.user will not give you collaborator's Id
var user = Session.getEffectiveUser();
// Note: setcomment = Inset a comment with the user email
// Note: setValue = Insert in the cell the date + time when this row was modified
lastCell.setValue("'" + date).setComment(user);
}
This also comments the modifier email on the last cell. However, this is only commenting the owner's email ID and not the email ID of the person with whom the shared is shared and who has made the change.
How can I log the email id of the person who last edited a row?

Email notification based on date and name

hoping someone can steer me in the right direction.
I have a schedule sheet and a contact sheet.
The schedule sheet looks something like this
4/11/16 John Front Desk
4/11/16 Chris Back Room
4/11/16 John Stage
4/11/16 Sarah Front Desk
4/12/16 Joe Back Room
4/12/16 Alex
The contact sheet looks something like this
John john#gmail.com
Chris chris#gmail.com
Alex
Sarah sarah#gmail.com
Joe
So basically the script, will go through the sheet, and if date in the date column is 3 days away from today, it will email a reminder to the person who is assigned a task that day. It will compare the name on the schedule sheet to the name in the contact sheet to find the email address and add it to the emailadd variable.
It works, but due to my limited knowledge in scripting, I feel I am doing this extremely ineffectively. Additionally, when for example John has three duties on the same day, he'll get three separate emails instead of one.
Also, some folks don't have email address, so the script will still attempt to email the message, fail and move on to the next one. Though that's totally fine for me since it's no more than 10-12 emails per night, I feel that there is a more effective way to do this. Any assistance would be really appreciated!
Here is the code
function checkReminder() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName('Notification'));
var schedulesheet = spreadsheet.getActiveSheet();
var lastRow = schedulesheet.getLastRow();
var contactspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(contactspreadsheet.getSheetByName('Contacts'));
var contactsheet = contactspreadsheet.getActiveSheet();
var conlastRow = contactsheet.getLastRow();
var startRow = 2;
//Grab column of scheduled dates and number of rows in the schedule sheet
var schedulerange = schedulesheet.getRange(2,2,lastRow-startRow+1,1 );
var numRows = schedulerange.getNumRows();
var scheduledassigneddate = schedulerange.getValues();
var scheduledformatteddate = Utilities.formatDate(new Date(scheduledassigneddate), "GMT-4:00", "MM/dd/YYYY");
//Grab column of scheduled names in the schedule sheet
var schedulenamerange = schedulesheet.getRange(2, 3, lastRow-startRow+1, 1);
var schedulednames = schedulenamerange.getValues();
//Grab column of assignments
var scheduleassignmentrange = schedulesheet.getRange(2, 4, lastRow-startRow+1, 1);
var assignmentrange = scheduleassignmentrange.getValues();
//Grab column of names and number of rows in the contact sheet
var contactrange = contactsheet.getRange(2,2,conlastRow-startRow+1,1 );
var contactname = contactrange.getValues();
var numRows2 = contactrange.getNumRows();
//Grab column of email addresses in the contact sheet
var contactemailrange = contactsheet.getRange(2, 3, conlastRow-startRow+1, 1);
var assignedemail = contactemailrange.getValues();
// Format today's date to match lists of dates in schedule sheet
var today = new Date();
today = today.setDate(today.getDate()+3);
var threedaysaway = Utilities.formatDate(new Date(today), "GMT-4:00", "MM/dd/YYYY");
var emailadd ="";
// Loop over the column of date values in the schedule sheet
for (var i = 0; i <= numRows - 1; i++) {
var scheduleddate = scheduledassigneddate[i][0];
var scheduledformatteddate = Utilities.formatDate(new Date(scheduleddate), "GMT-4:00", "MM/dd/YYYY");
//if the scheduled date is three days away, start associating names to email.
if(scheduledformatteddate == threedaysaway)
{
var notify_name = schedulednames[i][0];
for (var j = 0; j <= numRows2 - 1; j++) {
// Set email variables to null
var email_value = 0;
var msg = "";
//compare names falling under date that is 3 days away from today
var comparenames = contactname[j][0];
var assignment = assignmentrange[i];
if(notify_name == comparenames)
//if the name in the schedule sheet matches the name in the contact sheet,
//grab the email address in the next colum "assignedemail" and add it to var emailadd.
emailadd = emailadd + assignedemail[j] +",";
assignment = assignmentrange[i];
}
msg = msg + "Hello "+notify_name+", \n\nYou are scheduled to cover " + assignment + " on " +threedaysaway;
email_value++;
Logger.log(emailadd);
Logger.log(msg);
//if email_value is not null, send email. Loop back to stop and start over until loop is finished.
if(email_value) {
MailApp.sendEmail(emailadd,
"Reminder Email", msg);
}
emailadd = "";
assignment = "";
}
}
};
You can modify your approach to this:
Filter data with dates falling under the condition for notification.
Filter Names to remove duplicate.
Prepare sending notification function.
Search for the tasks under one person and concatenate it to the email body. To search for a specific value of a row here is an SO ticket that will guide you.
Here is a sample code:
function findCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == "User") {
row = values[i][j+1];
Logger.log(row);
Logger.log(i); // This is your row number
}
}
}
}
Send Notification with the prepared email body.
NOTE:
DATE NAME TASK
4/11/16 John Front Desk
That is the sample format for the task sheet.