"Needs a positive frequency of recurrence" google apps clock trigger - triggers

I am having trouble with a clock based trigger I am trying to create. This is for google apps script. This script is supposed to call a function that will email information at 5 am from a spreadsheet. I know the function works because I had used it with the 5 am to 6 am built in trigger, but they want it at exactly 5 am and not anytime in that hour range. Here is my code:
var SOD_Briefing_Trigger = ScriptApp.newTrigger("sendBriefingByEmail")
.timeBased().
atHour(5)
.create();
Everytime I try to run or debug it I get an error message of:
Needs a positive frequency of recurrence
Sorry if this seems like a newb question. I spent a few days searching here and google generally for a similar issue. I could not find anything.

That error message is a bit cryptic. If you just say "atHour", the system knows the "time" but not the "frequency".
This following should work.
var SOD_Briefing_Trigger = ScriptApp.newTrigger("sendBriefingByEmail")
.timeBased()
.atHour(5)
.everyDays(1)
.create();
Note the "everyDays" call. That means run it every X day(s) -every day in this call. You can change it to other frequencies based on the calls documented here. Some other examples - "atDate" (if you just want it run today or tomrorow) and "onWeekDay" (if you want it run every Monday for eg.).

I was able to get it to work once by using a simple function that just sent me an email with a short message. I have since not been able to get it to work to send me the longer email based off the spreadsheet.
Here is the entire code I was trying to run, that did not send me anything at 0500 today.
function createTimeTrigger3() {
try{
var SOD_Briefing_TriggerMonday = ScriptApp.newTrigger("sendBriefingByEmail2")
.timeBased()
.atHour(5)
.nearMinute(15)
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.create();
var SOD_Briefing_TriggerTuesday = ScriptApp.newTrigger("sendBriefingByEmail2")
.timeBased()
.atHour(5)
.nearMinute(15)
.onWeekDay(ScriptApp.WeekDay.TUESDAY)
.create();
var SOD_Briefing_TriggerWednesday = ScriptApp.newTrigger("sendBriefingByEmail2")
.timeBased()
.atHour(5)
.nearMinute(15)
.onWeekDay(ScriptApp.WeekDay.WEDNESDAY)
.create();
var SOD_Briefing_TriggerThursday = ScriptApp.newTrigger("sendBriefingByEmail2")
.timeBased()
.atHour(5)
.nearMinute(15)
.onWeekDay(ScriptApp.WeekDay.THURSDAY)
.create();
var SOD_Briefing_TriggerFriday = ScriptApp.newTrigger("sendBriefingByEmail2")
.timeBased()
.atHour(5)
.nearMinute(15)
.onWeekDay(ScriptApp.WeekDay.FRIDAY)
.create();
}
catch(err)
{
MailApp.sendEmail("************.gov", "there was a problem with the SOD trigger", err.message);
}
Logger.log("Unique ID of SOD_Briefing_TriggerMonday: " + SOD_Briefing_TriggerMonday.getUniqueId());
Logger.log("Unique ID of SOD_Briefing_TriggerTuesday: " + SOD_Briefing_TriggerTuesday.getUniqueId());
Logger.log("Unique ID of SOD_Briefing_TriggerWednesday: " + SOD_Briefing_TriggerWednesday.getUniqueId());
Logger.log("Unique ID of SOD_Briefing_TriggerThursday: " + SOD_Briefing_TriggerThursday.getUniqueId());
Logger.log("Unique ID of SOD_Briefing_TriggerFriday: " + SOD_Briefing_TriggerFriday.getUniqueId());
Logger.log("Unique ID of SOD_Briefing_TriggerToday: " + SOD_Briefing_TriggerToday.getUniqueId());
}
function sendBriefingByEmail2() {
var email = SpreadsheetApp.openById("***********").getSheetByName("Email Roster").getRange(4, 3).getValue()
+SpreadsheetApp.openById("***************").getSheetByName("Email Roster").getRange(5, 3).getValue()
+SpreadsheetApp.openById("***************").getSheetByName("Email Roster").getRange(6, 3).getValue()
+SpreadsheetApp.openById("***************").getSheetByName("Email Roster").getRange(7, 3).getValue()
+SpreadsheetApp.openById("*************").getSheetByName("Email Roster").getRange(8, 3).getValue()
+SpreadsheetApp.openById("*********************").getSheetByName("Email Roster").getRange(9, 3).getValue()
+SpreadsheetApp.openById("**********************").getSheetByName("Email Roster").getRange(10, 3).getValue()
+SpreadsheetApp.openById("**************").getSheetByName("Email Roster").getRange(11, 3).getValue()
+SpreadsheetApp.openById("**********************").getSheetByName("Email Roster").getRange(12, 3).getValue();
if (SpreadsheetApp.openById("**********************").getSheetByName("Previous_24_Hours").getRange(2, 1).isBlank()){
try {
MailApp.sendEmail(email, "No SOD Daily Briefing to Report Today", "There were no daily briefing entries submitted for SOD in the previous 24 hours.");
}
catch(err){
MailApp.sendEmail("*************.gov", "there was a problem sending the SOD BLANK briefing in the AM", err.message);
}
}
else {
try {
var subject = "Special Operations Bureau Daily Briefing";
var row = 2;
var email24sheet = SpreadsheetApp.openById("*********************").getSheetByName("Previous_24_Hours");
var LastRow = SpreadsheetApp.openById("******************").getSheetByName("Previous_24_Hours").getLastRow();
var msgHtml = ""
do {
msgHtml = msgHtml + "<br><hr><br>"
+"<p>"+"<b>"+"Unit: "+"</b>"+email24sheet.getRange(row, 11).getValue()+"</p>"
+"<p>"+"<b>"+"Incident: "+"</b>"+email24sheet.getRange(row, 1).getValue()+"</p>"
+"<p>"+"<b>"+"Date / Time: "+"</b>"+email24sheet.getRange(row, 2).getValue()+ " # " + email24sheet.getRange(row, 3).getValue()+ " hours"+"</p>"
+"<p>"+"<b>"+"Location: " + "</b>" +email24sheet.getRange(row, 4).getValue()+"</p>"
+"<p>"+"<b>"+"Trooper: "+"</b>"+email24sheet.getRange(row, 5).getValue()+"</p>"
+"<p>"+"<b>"+"Assisting Trooper(s): "+"</b>"+email24sheet.getRange(row, 6).getValue()+"</p>"
+"<p>"+"<b>"+"Suspect: "+"</b>"+email24sheet.getRange(row, 7).getValue()+"</p>"
+"<p>"+"<b>"+"Charges: "+"</b>"+email24sheet.getRange(row, 8).getValue()+"</p>"
+"<p>"+"<b>"+"Yield: "+"</b>"+email24sheet.getRange(row, 9).getValue()+"</p>"
+"<p>"+"<b>"+"Synopsis: "+"</b>"+email24sheet.getRange(row, 10).getValue()+"</p>";
row = row + 1;
} while(row < LastRow+1);
var msgHeader = "<p>"+"<H1>"+"<P ALIGN=Center>"+"Special Operations Bureau Daily Briefing"+"</H1>"+"</p>"
+"<p>"+"<H2>"+"<P ALIGN=Center>"+"Created: " + new Date().toLocaleDateString()+"</H2>"+"</p>";
var msgFooter = "<p>"+"<i>"+"<P ALIGN=Center>"+"This message was automatically generated using data submitted electronically from the Spec Ops Bureau website and / or form. For errors or suggestions for improvements, email **************.gov "+"</i>"+"</p>";
var msgPlain = msgHtml.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
MailApp.sendEmail(email, subject, msgPlain, { htmlBody: msgHeader + msgHtml + msgFooter });
SpreadsheetApp.openById("*************").getSheetByName("Previous_24_Hours").getRange("Previous_24_Data").clearContent(); //clears the incidents that were just sent
}
catch(err){
MailApp.sendEmail("**************.gov", "there was a problem sending the SOD briefing in the AM", err.message);
}
}
}
I was getting nothing at 0500. I then tried to make more triggers just to test the trigger builder and try different things to see what I could make work.
I used the command I found from the google script site (https://developers.google.com/apps-script/managing_triggers_programmatically) to delete the triggers:
// Delete a trigger with the given unique ID
function deleteTrigger(triggerId) {
// Locate a trigger by unique ID
var allTriggers = ScriptApp.getScriptTriggers();
// Loop over all triggers
for(var i=0; i < allTriggers.length; i++) {
if (allTriggers[i].getUniqueId() == triggerId) {
// Found the trigger and now delete it
ScriptApp.deleteTrigger(allTriggers[i]);
break;
}
}
}
But now I am getting:
This script has too many triggers. Triggers must be deleted from the
script before more can be added.
and
Already setting up a recurring clock trigger.
as error messages emailed to me when I try to run anything.
Should I instead do a different function for each day of the week's trigger?

Related

Cannot read property 'getRange' of null error. I am positive the sheet exists and is named correctly in the script

My fellow teachers and I like to send students little google drawings to let them know they've been doing well lately. We have a spreadsheet that we use and I am trying to automate the process of sending them an email when their drawing is ready to be viewed. I keep getting the 'Cannot read property 'getRange' of null error' even though I am 100% sure that a sheet exists with the name PR and that it is spelled right. I am new to Google Script so I lack the skills to troubleshoot any more than the googling I've done already, which basically just says to make sure you've named the sheet correctly. Any help would be very appreciated!
var studentFirstNameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("A2:A");
var studentFirstname = studentFirstNameRange.getValues();
var studentEmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("D2:D");
var studentEmail = studentEmailRange.getValues();
var emailSendRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("L2:L");
var emailSend = emailSendRange.getValues();
if (emailSend){
// Send Alert Email.
var message = 'Hi ' + studentFirstname + '! Your teachers noticed you have been doing a great job this year, so we made this for you! Keep up the great work!' ; // Second column
var subject = 'Positive Recognition';
MailApp.sendEmail(studentEmail, subject, message);
}
}```
According to the title and the error you related, I did'nt get any error.
However, I don't understand your condiiton if (emailSend) neither the way you send emails. If you send emails to all the population at once, you can try
function myFunction() {
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getLastRow()
var studentFirstNameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("A2:A"+lastRow);
var studentFirstname = studentFirstNameRange.getValues();
var studentEmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("D2:D"+lastRow);
var studentEmail = studentEmailRange.getValues();
var emailSendRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("L2:L"+lastRow);
var emailSend = emailSendRange.getValues();
if (emailSend){
// Send Alert Email.
var message = 'Hi ' + studentFirstname + '! Your teachers noticed you have been doing a great job this year, so we made this for you! Keep up the great work!' ; // Second column
var subject = 'Positive Recognition';
Logger.log(studentEmail.join())
MailApp.sendEmail(studentEmail.join(), subject, message);
}
console.log('there is no errors!')
}
if you want to send individually
function myFunction() {
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getLastRow()
var studentFirstNameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("A2:A" + lastRow);
var studentFirstname = studentFirstNameRange.getValues();
var studentEmailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("D2:D" + lastRow);
var studentEmail = studentEmailRange.getValues();
var emailSendRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('PR').getRange("L2:L" + lastRow);
var emailSend = emailSendRange.getValues();
for (var i = 0; i < studentFirstname.length; i++) {
if (emailSend[i][0]) {
// Send Alert Email.
var message = 'Hi ' + studentFirstname[i][0] + '! Your teachers noticed you have been doing a great job this year, so we made this for you! Keep up the great work!'; // Second column
var subject = 'Positive Recognition';
MailApp.sendEmail(studentEmail[i][0], subject, message);
}
}
}

MailApp.sendEmail function runs without errors but no emails are sent

The below script runs without any visible error, but no emails are sent. Any ideas as to why?
function sendEmailLoop() {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
sheets.forEach(function(sheet) {
var range = sheet.getDataRange();
if (sheet.getName() == "Summary") //Disregard tab named 'Summary'
{
}
else {
var range = sheet.getDataRange(); //to set the range as array
var values = range.getDisplayValues(); //to get the value in the array
var lastRow = range.getLastRow();
var ss = SpreadsheetApp.getActiveSpreadsheet(); //declare the spreadsheet
var sheet = ss.getSheetByName("Sheet1");
var Title = values[0][0]; //[Title] cell A1
var URL = values[0][1]; //[URL] cell B1
var i;
var logContent = '';
for (i = 3; i < lastRow; i++) {
var Name = values[i][0]; //[Name] cell A++
var Email = values[i][1]; // [Email] cell B++
Logger.log('to: ' + Email);
Logger.log('subject: ' + Name + Title + 'Test');
Logger.log('message: ' + 'This is a test message for the training that can be found at ' + URL);
/*
MailApp.sendEmail({
to: Email,
subject: Name + Title + 'Test',
message: 'This is a test message for the training that can be found at ' + URL});
*/
}; //end for loop - email tab data
}; // end 'else'
}); // end function(sheet)
} // end SendEmailLoop()
Here is the Stackdriver log of a successful execution (success meaning no errors, but still no emails are sent):
The structure of the spreadsheet associated with the script:
Note - an earlier version of this script didn't include the sheets.forEach() method call (ie, to loop through each tab of the spreadsheet) and the emails were sent fine.
Could the lack of emails being sent or received be related to the fact that I have many sheets and this function is looping through them?
function sendEmailLoop() {
var exclA=['Summary'];
var ss=SpreadsheetApp.getActive();
var sheets=ss.getSheets();
sheets.forEach(function(sheet) {
if (exclA.indexOf(sheet.getName())==-1) {
var range=sheet.getDataRange();
var values=range.getDisplayValues();
var lastRow=range.getLastRow();
var Title=values[0][0];
var URL=values[0][1];
var logContent='';
for (var i=3; i <values.length; i++) {
var Name=values[i][0];
var Email=values[i][1];
Logger.log('to: %s\nsubject: %s %s Test\nmessage: %s This is a test message for the training that can be found at %s',Email,Name,Title,URL);
/*
MailApp.sendEmail({
to: Email,
subject: Name + Title + 'Test',
message: 'This is a test message for the training that can be found at ' + URL});
*/
}
}
});
}
Answer:
You need to uncomment your MailApp code.
Code changes:
I tested your code and it seems to run without issue for me, including the receipt of the emails, only that the code comments around your MailApp call need to be removed (the /* and the */).
I would also suggest adding a conditional line before you send the email in the event .getDataRange() obtains seemingly empty rows:
if (Email == "") {
continue;
};
MailApp.sendEmail({
to: Email,
subject: Name + Title + 'Test',
message: 'This is a test message for the training that can be found at ' + URL});
References:
JavaScript Comments

E-mail notification based on cell value. Unable to apply script function for all rows

I am using Google sheets and the Google script editor to create a script to automatically send myself an e-mail every time a product quantity goes below the minimum inventory level. Since I have multiple products with different minimum inventory levels I expect to get a series of e-mails, one for each row.
I use one sheet for the actual Inventory data and another sheet that contains information for the script to refer to, such as my email and what message to include in the e-mail.
I succeeded having an e-mail sent collecting data from the first row of the Inventory sheet but I am not being able to apply that for all the following rows.
I tried changing the .getRange("F2") to .getRange("F2:F"), then whenever one of the products goes under the minimum inventory level I get one single e-mail containing the information about all products, regardless of whether their quantity is under the minimum level or not.
The ideal solution would be ONE single e-mail containing all the information about all products that are under the minimum quantity .
Here is a link to my spreadsheet: https://docs.google.com/spreadsheets/d/1ZHmBvi8ZeaDRYq6Qigaw08NUiOwZumPrLnvnka_mgmA/edit?usp=sharing
Current script:
function CheckInventory() {
// Fetch inventory quantity
var InventoryRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory").getRange("F2");
var Inventory = InventoryRange.getValue();
// Fetch minimum quantity
var MinimumQuantityRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory").getRange("D2");
var MinimumQuantity = MinimumQuantityRange.getValue();
// Check Inventory
if (Inventory < MinimumQuantity){
// Fetch email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("E2");
var emailAddress = emailRange.getValues();
// Fetch email message details.
var detailsRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("G2");
var details = detailsRange.getValues();
var subjectdetailsRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Notification Rules").getRange("H2");
var subjectdetails = subjectdetailsRange.getValues();
// Send Alert Email.
var message = details;
var subject = subjectdetails;
MailApp.sendEmail(emailAddress, subject, message);
}
}
Update:
As you said in a comment, you want the email to be sent when you edit an inventory cell, and only if this edited inventory quantity is below the corresponding minimum. So here I update my answer accordingly.
First, I guess you have done this already, but because the function uses sendEmail, you will have to grant authorization for it to work. I created a trigger for that. Run this once:
function createEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger("CheckInventory")
.forSpreadsheet(ss)
.onEdit()
.create();
}
Then, this is the function that will run every time the spreadsheet is edited. To avoid the email to be sent every time the file is edited, we need a condition that checks whether the edited cell is an inventory and that this inventory is below the minimum:
function CheckInventory(e) {
var ss = e.source;
var inventorySheet = ss.getSheetByName("Inventory");
var rowIndex = e.range.getRow();
var columnIndex = e.range.getColumn();
var numCols = 6;
var row = inventorySheet.getRange(rowIndex, 1, 1, numCols).getValues()[0];
var editedInventory = row[5];
var editedMinimum = row[3];
var sheetName = ss.getActiveSheet().getName();
// Checking that: (1) edited cell is an inventory quantity, and (2) Inventory is below minimum
if(editedInventory <= editedMinimum && sheetName == "Inventory" && columnIndex == 6 && rowIndex > 1) {
var inventoryValues = inventorySheet.getDataRange().getValues();
var emailBody = "";
for(var i = 1; i < inventoryValues.length; i++) {
var inventory = inventoryValues[i][5];
var minimum = inventoryValues[i][3];
if(inventory <= minimum) {
var productName = inventoryValues[i][0] + " " + inventoryValues[i][1];
var productUnits = minimum + " " + inventoryValues[i][4];
var messagePart1 = "Inventory for " + productName + " has gone under " + productUnits + ". ";
var messagePart2 = "Organise purchase order. Inventory as of today is: " + inventory + " " + inventoryValues[i][4];
var message = messagePart1.concat(messagePart2);
var newItem = "<p>".concat(message, "</p>");
emailBody += newItem;
}
}
var emailSubject = "Low inventory alert";
var emailAddress = "your-email#your-domain.com";
// Send Alert Email
if(emailBody != "") {
MailApp.sendEmail({
to: emailAddress,
subject: emailSubject,
htmlBody: emailBody
});
}
}
}
As I said in a comment, if you just want to send an email, it doesn't make sense to have many email subjects, so I hardcoded the subject.
Regarding the emails, I assumed you just want an email address to receive the email, so I hardcoded it too. If you want all the different email addresses found in Notifications tab to receive emails regarding all products, a small fix would be needed to this code. Tell me if that's needed for you.
Also, I didn't use your notifications tab at all, I created the message directly using the script. I'm not sure it is that useful to have the sheet "Notification Rules". Much of its info is the same as the one in inventory, and the rest of data (email address, basically) could be easily included there. But whatever suits you.
I hope this is of any help.

Google Apps Script Defined Time-frame for time-driven Triggers Not Working

I am using the functions from the code that I saw here:
http://mashe.hawksey.info/2012/09/google-app-script-scheduling-timed-triggers/
with my added sub-function, as instructed.
function scheduledCollection2(){
var schedule = [];
// dates/times in mm/dd/yyyy hh:mm - timezone matches settings in File > Project properties
schedule.push({start:"10/25/2014 09:00", end:"12/25/2014 10:00"});
checkCollect2(schedule);
}
function checkCollect2(schedule){
var now = new Date();
for (i in schedule){
var start = new Date(schedule[i].start);
var end = new Date(schedule[i].end);
if (now > start && now < end){
function sendEmails() {
var emailAddress = "abc#gmail.com";
var message = "Hello, this is a test email.";
var subject = "Sending Recurring Emails";
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
}
The sendEmails function alone works very well. However, when I add it to the rest of the code for some reason it stops working. My aim is to have it work with a time-driven trigger.
Any advice on why it's not working, and how I can get it to work?
simply build your script slightly differently : (instead of defining a function just execute the code)
function checkCollect2(schedule){
var now = new Date();
for (i in schedule){
var start = new Date(schedule[i].start);
var end = new Date(schedule[i].end);
if (now > start && now < end){
var emailAddress = "abc#gmail.com";
var message = "Hello, this is a test email.";
var subject = "Sending Recurring Emails";
MailApp.sendEmail(emailAddress, subject, message);
}
}
}

Google Apps Script: How to pull values from column A based on values in column E and send all values in one email?

I'm trying to create a script for a student attendance spreadsheet that will look in Column E for the string "X". For each instance of "X", the string from column A (the student name) will be added to the body of an email. I'm pretty new to JavaScript, although I have been studying the basics. I've done a lot of research and found some scripts I was able to modify to send an individual email for each instance of X in E. However, I have not been able to figure out how to combine that information into a single email.
Here's what I have so far:
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
EMAIL_SENT = "EMAIL_SENT",
statusArray = sheet.getDataRange().getValues();
var class = statusArray[0][8],
status = "X",
email = "XXXX"
for (i=7;i < statusArray.length;i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
var body = "This is a No-Show Report for " +student+ " from " + class;
var subject = "No-Show Report for " + student+ " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
sheet.getRange(i+1, 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
I realize I'll probably need to move the sendEmail function to be outside the IF statement. I tried to create an array with the names and join those into a string and add it to the body of the email, but I've had no luck. It just ended up sending the last name instead of all of them.
If anyone has any suggestions for me I would be deeply grateful.
First set up variables to keep track of which student did not show up:
var students = [];
var student_rows = [];
Then, add student to these arrays when X is found:
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
students.push(student);
student_rows.push(i+1);
}
Then send the email with all student names combined (outside of the for loop like you said)
var body = "This is a No-Show Report for " + students.join(', ') + " from " + class;
var subject = "No-Show Report for " + students.join(', ') + " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
Finally update the spreadsheet indicating which names were in that email:
for (var i=0; i<student_rows.length; i++) {
sheet.getRange(student_rows[i], 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
Here's the complete script:
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
EMAIL_SENT = "EMAIL_SENT",
statusArray = sheet.getDataRange().getValues();
var class = statusArray[0][8],
status = "X",
email = "francis#bposolutions.com";
var students = [];
var student_rows = [];
for (i=7;i < statusArray.length;i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != EMAIL_SENT) {
var student = statusArray[i][0];
students.push(student);
student_rows.push(i+1);
}
}
var body = "This is a No-Show Report for " + students.join(', ') + " from " + class;
var subject = "No-Show Report for " + students.join(', ') + " from " + class;
MailApp.sendEmail(email,subject,body,{NoReply : true});
for (var i=0; i<student_rows.length; i++) {
sheet.getRange(student_rows[i], 85).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
There are probably many ways to implement a new version of your code, the other answer probably works but I think it can be improved (a bit).
First of all, you can get rid of the flush method that does nothing else than slowing down the function (it was originally used in the Google example to check the sent status row by row, it is useless when we send only one mail with all the data in it)
Secondly, it might be a good idea to use html format to get a better looking result.
And lastly, it is good practice to write back to the sheet using one setValues instead of multiple setValue() in a loop.
Here is a possible replacement code, you'll have to "tune" it to your needs to eventually improve the message format but the main structure is there and working.
function Email_ReminderNS() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("July_August"),
statusArray = sheet.getDataRange().getValues();
var email = Session.getActiveUser().getEmail(); //replace with the email you want, this value will send mails to you I used it for test.
var class = statusArray[0][8],
status = "X",
students = [];
for (var i=7;i < statusArray.length; i++){
var emailSent = statusArray[i][84];
if (status == statusArray[i][4] & emailSent != "EMAIL_SENT") {
students.push(statusArray[i][0]);
statusArray[i][84]="EMAIL_SENT";
}
}
var subject = "No-Show Report for " + students.length + " from " + class;
var textBody = "This is a No-Show Report for " +students.length+ " from " + class+"\n";
var HTMLBody = "<b>This is a No-Show Report for " +students.length+ " from " + class+"</b><br><br>"
+'<table style="background-color:lightblue;border-collapse:collapse;" border = 1 cellpadding = 5><th>Sent Mails</th><tr>';
for(var n in students){
HTMLBody += '<tr><td>'+n+'</td><td>'+statusArray[n][0]+'</td></tr>';
textBody += '\n'+n+' - '+statusArray[n][0];
}
HTMLBody+='</table><BR> kind regards.' ;
textBody+='\n\nKind regards';
Logger.log(HTMLBody);
Logger.log(textBody);
MailApp.sendEmail(email,subject,textBody,{'NoReply' : true, 'htmlBody' : HTMLBody});
sheet.getRange(1,1,statusArray.length,statusArray[0].length).setValues(statusArray);
}