Google Scripts - Dates/Spreadsheets/Automatic Emails - google-apps-script

Apologies in advance - I am not a programmer. Just trying to piece together something for my business. Currently, I have a script that references a spreadsheet and sends out an automated email to my receptionist. This script provides all of the information I'd like it to but problem is that it sends out a separate email for every entry. Ideally, I would like to send a single email to my receptionist that contains a list of all of the appointments for the upcoming day.
Issues I'm having include:
I need to consolidate multiple emails into a single email containing a list of the upcoming appointments for the next day.
I don't know how to select the rows I need because they are date values (DD/MM/YYYY). So I'm Looking for a way to read the date, recognize that it is one day before the appointment, and add these entries to a single list.
If anyone can help me out with this it would be greatly appreciated!
Here's what I have so far:
function receptionist() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 8)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[2];
var timeslot = sheet.getRange(i+2,7,1,1).getValues();
var name = sheet.getRange(i+2,2,1,1).getValues();
var date = Utilities.formatDate(new Date(sheet.getRange(i+2,6,1,1).getValue()),"EST", "E MMM dd, yyyy");
var receptionist= name+" scheduled on "+date+" at "+timeslot;
var subject = "Appt. List";
var emailAddress = "receptionist#example.com";
MailApp.sendEmail({emailAddress, subject, receptionist});
Thanks in Advance!

I've tested this code, and it works:
function receptionist() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 8)
var data = dataRange.getValues();
var receptionist = "Today's Appointments \r\r";
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[2];
var timeslot = sheet.getRange(i+2,7,1,1).getValue();
var name = sheet.getRange(i+2,2,1,1).getValue();
var dateData = sheet.getRange(i+2,6,1,1).getValue();
var dayOfAppointment = dateData.getFullYear() + dateData.getMonth() + dateData.getDate();
var todaysDate = new Date();
var todaysDayNumber = todaysDate.getFullYear() + todaysDate.getMonth() + todaysDate.getDate();
if (todaysDayNumber === dayOfAppointment) {
var date = Utilities.formatDate(new Date(),"EST", "E MMM dd, yyyy");
var thisAppointment = name+" scheduled on "+date+" at "+timeslot + "\r";
receptionist+=thisAppointment;
};
};
var subject = "Appt. List";
var emailAddress = "receptionist#example.com";
MailApp.sendEmail(emailAddress, subject, receptionist);
};
You do need a for loop. I removed the curly braces from the .sendEmail() parameters. Note the "\r" values to wrap each line to a new line. This Line:
receptionist+=thisAppointment;
makes the receptionist variable longer by one appointment line on each iteration. I didn't go through every line of code to determine whether the code is optimal or not. The basics of what you need are there. It may work "as is".

Related

Send the reminder email as per reminder date in google sheet

Given
Column G is having the expected return date(i.e. reminder date).
Column J is having email address stored
Column L is having return status
Need
Need to send the reminder email(email address Col J) on the reminder date(COl G) if the Column L (Return_Status) is blank.
I already have a code written, can't figure out the exact issue why it is not working.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails() {
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)
//var dataRange= sheet.getRange("Form Responses 1!A1:L");
var dataRange= sheet.getRange(startRow,numRows)
// 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 = "dummy#gmail.com";
var subject = "RC Reminder # "+row[3];
var message = "Reminder for "+row[4]+" RC of vehicle"+row[3]+" handed over to "+row[5]+" against "+row[2]+" on "+row[0];
var emailSent = row[10];
var reminderDate = new Date(row[6]).toLocaleDateString();
if (reminderDate != today) // Skip this reminder if not for today
continue;
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
MailApp.sendEmail(emailAddress, subject, message,{name:'Sam'});
sheet.getRange(startRow + i, 11).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
In this line of code you're just getting the value of one cell
var dataRange= sheet.getRange(startRow,numRows)
getRange(row, column)
You should change it to:
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow()-1,sheet.getLastColumn())
getRange(row, column, numRows, numColumns)
This way you will only iterate through the values that are in your sheet and you will not work through empty data. If you have several sheets in your spreadsheet try consider to work with the one you have the data, accesing to the right one like this:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('NAME OF YOUR SHEET');
getSheetByName(name)

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.

How can I import the last row ONLY of a spreadsheet to my calendar using Google Apps Script?

I have been able to create a script to import a spreadsheet (delivery schedule) to a calendar. It works great, but I am constantly adding new deliveries to the schedule. When I import it to the calendar, it imports everything every time. Is there a way to have ONLY the last row imported and not the whole spreadsheet?
This is the script that I am using...
var DELIVERY_IMPORTED = "DELIVERY_IMPORTED";
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var menuEntries = [{name: "Import Events in Calendar", functionName: "importCalendar"}];
ss.addMenu("Calendar", menuEntries);
}
function importCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 5; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 5)
// 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 title = row[1]; // Name
var location = row[2];
var startDate = row[3]; // Start Date
var description = row[4];
var cal = CalendarApp.getCalendarsByName('Calendar Name')[0];
var advancedArgs = {description: description, location: location};
cal.createAllDayEvent(title, new Date(startDate), advancedArgs);
SpreadsheetApp.flush();
}
}
Any help would be greatly appreciated!
If you only have one new lime each time, you can use Sheet.getLastRow() to get the index of the last row with content.
Else you might use Properties service to store the last imported row, and start from there.

Trying to add an IF statement to an array of objects in Google Apps Script for Sheets

Trying to send an email to a list in a Google Sheet, but only if column N gets marked "Yes." Acceptable data in column N is "Yes" or "No" so I want to test that and send emails only to the rowData that contain "yes" there. Then write the date in the adjacent column on the same row. I can't seem to figure out how to iterate through the array of objects and couldn't find any good resources to explain this. Help greatly appreciated. My best effort was emailing all the rows and then also filling in the date no matter what was in column N (Yes/No/Blank).
function sendEmails() {
validateMySpreadsheet() //a function that checks for "Yes" in column N
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getActiveSheet();
var dataRange = dataSheet.getRange(2, 1, dataSheet.getMaxRows() - 1, 16);
var d = new Date();
var dd = d.getDate();
var mm = d.getMonth() + 1; //Months are zero based
var yyyy = d.getFullYear();
var date = mm + "/" + dd + "/" + yyyy;
var needsaYes = "Yes";
//Gets the email template
var templateSheet = ss.getSheetByName("Template");
var emailTemplate = templateSheet.getRange("A1").getValue();
// Create one JavaScript object per row of data.
objects = getRowsData(dataSheet, dataRange);
//This is where I am stuck - how to check if column N contains a "Yes" before allowing the MailApp.SendEmail command to run.
for (var i = 0; i < objects.length; ++i) {
// Get a row object
var rowData = objects[i];
var values = dataRange.getValues();
for (var j = 0; j < values.length; ++j) {
var row = values[j];
var checkFirst = row[13]; //row J, Column N?
if (checkFirst = needsaYes) { //does column N contain "Yes"?
var emailText = fillInTemplateFromObject(emailTemplate, rowData);
var emailSubject = "mySubject";
MailApp.sendEmail(rowData.email, emailSubject, emailText);
dataSheet.getRange(2 + i, 15).setValue(date); //then write the date
SpreadsheetApp.flush();
}
}
}
}
I didn't check whole code but
if (checkFirst = needsaYes)
It may be the problem, you need to use ==
I figured it out I needed to just use the .getValues() method for my data range rather than the whole sheet and also remove the unnecessary second for loop:
var rowData = objects[i]; var checkData = ss.getActiveSheet().getDataRange().getValues();
var row = checkData[i]
var colN = row[13] if (colN == needsaYes) { //etc.

Create a Contact Group via Google Spreadsheet

I am trying to create an email distribution list from a Google form. I then want to place the individuals in a particular contact group. Here is the code I've compiled thus far. Please help. Thank you in advance.
function addContact() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 3;
var numRows = 10; // I want the rows to be infinite
var dataRange = sheet.getRange(startRow, 2, numRows, 10)
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var firstName = row[1];
var lastName = row[2];
var emailAdd = row[3];
}
// The code below creates a new contact and adds it to the "Work Friends" contact group
var contact = ContactsApp.createContact(firstName, lastName, emailAdd);
var group = ContactsApp.getContactGroup('Work Friends');
group.addContact(contact);
}
You were close, just needed some tweaking. See comments in-line, explaining the changes.
function addContact() {
var sheet = SpreadsheetApp.getActiveSheet();
// var startRow = 3; // This implies you have two header rows...
var headerRows = 2; // Number of header rows to skip
// var numRows = 10; // I want the rows to be infinite (so use getDataRange)
var dataRange = sheet.getDataRange(); // Range containing all non-blank rows & cols
var data = dataRange.getValues(); // Read all data
data.splice(0,headerRows); // Remove header rows
for (i =0; i<data.length; i++) { // Avoid using for..in with arrays
var row = data[i];
var firstName = row[1];
var lastName = row[2];
var emailAdd = row[3];
// Do this IN the loop vvv
// The code below creates a new contact and adds it to the "Work Friends" contact group
var contact = ContactsApp.createContact(firstName, lastName, emailAdd);
var group = ContactsApp.getContactGroup('Work Friends');
debugger; // Pause if running in debugger, to examine state
group.addContact(contact);
}
}