Hi I am doing some codes in google script but the output that I am expecting did not happen.
Here is the code that i came up with hope you can help me solve this problem,
function sendEmail() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = activeSheet.getLastRow();
var dRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("March Cycle").getRange("I6")
var rData = dRange.getValue();
var templateTxt = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1,1).getValue();
for (var i = 6;i<=lr;i++) {
if(rData = "Touch Course Completed") {
var frstname = activeSheet.getRange(i,4).getValue();
var lstname = activeSheet.getRange(i,3).getValue();
var gradelvl = activeSheet.getRange(i,5).getValue();
var msgbody = templateTxt.replace("{name of student}",(frstname + " " + lstname)).replace("{Gr Lvl}",gradelvl);
MailApp.sendEmail("email add","Test Email",templateTxt);
}
Logger.log(msgbody);
}
}'
below is the data of picture that i wanted to automate.
enter image description here
Thank you
There are a couple of mistakes you have on your code. Let me show you in my comments on this working code.
Code:
function sendEmail() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var templateTxt = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1, 1).getValue();
var lr = activeSheet.getLastRow();
// Compile list of students with "Touch Course Completed" in array before sending
var msgbody = [];
// You need to get the range of all data on column I for it to be optimized
var dRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("March Cycle").getRange("I6:I"+lr);
var rData = dRange.getValues();
// rData is equal to [[Touch Course Completed],[Touch Course Completed],[Not completed]]
// Loop all column I data
rData.forEach(function (data, i){
// Since rData is 2D array, the cell should be accessed by data[0]
if (data[0] == "Touch Course Completed") {
// i is the index of the rData array per loop, so 0 is equivalent to row 6
// We need to offset it to get the correct row
var frstname = activeSheet.getRange(i + 6, 4).getValue();
var lstname = activeSheet.getRange(i + 6, 3).getValue();
var gradelvl = activeSheet.getRange(i + 6, 5).getValue();
// My idea here is optional, but I prefer sending it on 1 email instead of separate per student
// That way, we do it faster and more efficient (note that there are quota/limits on sending mail thus doing this is better)
// But if you need it separate, then do what you did in your script
// I push all message first, then send as bulk outside the loop with join
msgbody.push(templateTxt.replace("{name of student}", (frstname + " " + lstname)).replace("{Gr Lvl}", gradelvl));
}
});
// Send an email only IF there is a "Touch Course Complete" student
if(msgbody)
MailApp.sendEmail("email", "Test Email", msgbody.join("\n"));
}
March Cycle:
Template:
Email:
Note:
Note that the earlier tests did send the email separately. If you need them separate then send it every loop (no need for arrays). But if not, then the code above should be better.
EDIT:
To only send the last row, there can be 2 approach that comes to mind:
Add a column for the identification of the data if it was already sent
You will need to add a column.
If new data doesn't contain "Touch Course Completed", it will not send anything.
If you added multiple rows that contains "Touch Course Completed", all of them will be sent.
Get the last row of msgbody
You will not need to add a column.
If new data doesn't contain "Touch Course Completed", it will send the last row with "Touch Course Completed" that was already sent before.
This will not send multiple rows if ever you added more than 1 "Touch Course Completed"
First approach:
function sendEmail() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var templateTxt = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1, 1).getValue();
var lr = activeSheet.getLastRow();
var msgbody = [];
// Get all headers, check if there is "Already Sent" header
var lc = activeSheet.getLastColumn();
var headers = activeSheet.getRange(1, 1, 1, lc).getValues();
var sentColumn;
if(!headers[0].includes("Already Sent")){
// If not found, add header "Already Sent" right to the last column
sentColumn = lc + 1;
activeSheet.getRange(1, sentColumn).setValue("Already Sent");
}
else {
// If found, get column number of existing "Already Sent" header
sentColumn = headers[0].indexOf("Already Sent") + 1;
}
var dRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("March Cycle").getRange("I6:I"+lr);
var rData = dRange.getValues();
rData.forEach(function (data, i){
if (data[0] == "Touch Course Completed") {
var frstname = activeSheet.getRange(i + 6, 4).getValue();
var lstname = activeSheet.getRange(i + 6, 3).getValue();
var gradelvl = activeSheet.getRange(i + 6, 5).getValue();
// Check if column is already populated with "Y"
var isSent = activeSheet.getRange(i + 6, sentColumn).getValue();
if(isSent != "Y"){
// If column value is not "Y", then add row to the email to be sent, also put "Y" on the column after
msgbody.push(templateTxt.replace("{name of student}", (frstname + " " + lstname)).replace("{Gr Lvl}", gradelvl));
activeSheet.getRange(i + 6, sentColumn).setValue("Y");
}
}
});
// Modified condition for checking array
if(msgbody.length > 0)
MailApp.sendEmail("email", "Test Email", msgbody.join("\n"));
}
Sample data:
Output:
Email:
Note:
The script will automatically add/locate the header, so no need to adjust your sheet manually.
But you can still initialize a column to become "Already Sent" by writing the header name on the first row of the column and write "Y" to those rows you don't want to be sent anymore.
Related
function findTextsendupdate(){
var sheet = SpreadsheetApp.getActiveSheet()
var startRow = 3// First row of data to process
var numRows = 50 // Number of rows to process
// if a yes is entered in column M
var sendUpdateRange = sheet.getRange(startRow, 1, numRows, 14);
// Fetch values for each row in the Range.
var yes = "yes"
var no = "no"
var send = sendUpdateRange.createTextFinder(yes);
send.matchCase(false); //{Boolean} -> match target text's case or not;
send.matchEntireCell(true); //{Boolean} -> check the whole Range or within;
send.ignoreDiacritics(true); //{Boolean} -> ignore diacretic signs during match;
send.matchFormulaText(true); //{Boolean} -> search in formulas (if any) or values;
var dontSend = sendUpdateRange.createTextFinder(no)
dontSend.matchCase(false); //{Boolean} -> match target text's case or not;
dontSend.matchEntireCell(true); //{Boolean} -> check the whole Range or within;
dontSend.ignoreDiacritics(true); //{Boolean} -> ignore diacretic signs during match;
dontSend.matchFormulaText(true); //{Boolean} -> search in formulas (if any) or values;
//invoke search;
var res = send.findNext();
var tes = dontSend.findNext();
{ //do something with result;
if (tes) {
var emailNotSent = "Email Not Sent"
sheet.getRange(startRow, 14, numRows, 1).setValue(emailNotSent)}
if(res) {
var sendEmail = sendUpdateRange.getValues();
var emailSent = "Email Sent";
for (var i = 0; i < sendEmail.length; i++) {
var row = sendEmail[i];
var Name = row[1]
var job = row[2]
var model = row[4]
var info = "Job number: " + job + "\n"
var emailAddress = row[0];
var isEmailSent = row[14]
if (isEmailSent != emailSent && no) {
var message = "Dear " + Name + "\n" + "
var body = info + "\n" + message
var subject = "email";
MailApp.sendEmail(emailAddress, subject, body);
sheet.getRange(startRow, 14, numRows, 1).setValue(emailSent);
} }}}}
I have dedicated column M for the edit trigger. But, every time I enter a yes or a no in the first row, it sends the emails for all the other rows. If I put no on the first row, and yes on the send, it changed from not sending to sending all emails whereas if I put yes on the first row and no on the second, it flips between sending and not sending all emails.
I want to make the script look at column M and decide on a row by row basis on whether to send or not to send an email. This is the part I'm having trouble with and I've exhausted my search options.
Assuming everything you had in there works then this might be close.
function findTextsendupdate(e){
const sh=e.range.getSheet();
if(sh.getName()=="My Email Sheet" && e.range.columnStart==13 && e.value=="TRUE") {
const row=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var Name = row[1];
var job = row[2];
var model = row[4];
var info = "Job number: " + job + "\n";
var emailAddress = row[0];
var isEmailSent = row[14];
if (isEmailSent != "EmailSent" && MailApp.getRemainingDailyQuota()>0) {
var message = "Dear " + Name + "\n";
var body = info + "\n" + message;
var subject = "email";
MailApp.sendEmail(emailAddress, subject, body);
sh.getRange(e.range.rowStart,14).setValue('EmailSent');
}
}
}
I am having problems with a script that I wrote. It isn't throwing any errors however I am not receiving the emails. The goal of this script is to send an email if column G has value Y.
Column A = Organization Name
Column C= Days Aging
Column F= Email (where the email should be sent)
Column G= Status (where the Y will be)
function CheckPastDueAccounting() {
//Fetch Accounting Spreadsheet with past due accounts
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
for(var i=2;i<=lrow;i++);
var Status =ss.getRange(i,7);
var value = Status.getValue();
if (value == 'Y') {
var DaysAgingColumn = ss.getRange(i,3);
var DaysAging = DaysAgingColumn.getValue();
// Fetch Organization Name
var Organizations = ss.getRange(i,1);
var org = Organizations.getValue();
// Fetch the email address
var emailRange = ss.getRange(i,6);
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = 'Hi. Your account is past due ' + DaysAging + ' days.'; // Second column
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message);
}
}
Issue:
You should be enclosing the statements you want to run in loop between { }. Otherwise, the for loop is just incrementing the variable i and not running any of your desired code.
Moreover, after the for loop ends, the variable i is higher than the last row with content (lrow) which means that all calls to .getRange(i, columnIndex) refer to empty cells. Because of this, no email is sent, and no error is shown.
Solution:
function CheckPastDueAccounting() {
// Code before for loop starts
for(var i=2; i<=lrow; i++) {
// Code to run in loop (iterate through all rows with content)
}
// Code to run after for loop ends
}
Improving code:
Calling getRange(row, column) for individual cells, for each row in a for loop, is not the best way to iterate through rows with data.
It's much better to first (1) get all the values in the desired range, with getRange(row, column, numRows, numColumns) and getValues(), and then (2) iterate through the resulting 2D array, like this:
function CheckPastDueAccounting() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
var firstRow = 2;
var values = ss.getRange(firstRow, 1, lrow - firstRow + 1, 7).getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
var value = row[6];
if (value == 'Y') {
var DaysAging = row[2];
var org = row[0]; // Fetch Organization Name
var emailAddress = row[5]; // Fetch the email address
var message = 'Hi. Your account is past due ' + DaysAging + ' days.';
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message); // Send Alert Email.
}
}
}
Reference:
for loop
getRange(row, column, numRows, numColumns)
I have a google apps script to send emails to every row of data that meets a certain criteria. It will also modify some of the data in the sheet as it passes through the script. However, my script repeats for the correct number of times, but it sends all the emails out to the email address in the first line of data.
I have tried changing where i store the variable as i believe it is the reason why the var emailAddress is not updating as the for loop runs. However, i cannot seem to figure out exactly why the var does not update to the next row of data.
var header = "**Please show this email during collection.\n\n"
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 500;
var dataRange = sheet.getRange(startRow, 1, numRows, 500); // (startRow, 'first row of column to process', numRows, 'number of columns to process')
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var invoiceNum = row[2];
var orderNum = row[3];
var emailAddress = row[5];
var orderStatus = row[9];
var dispatchMode = row[11];
var message = "Dear Customer, \n\nYour order is ready for collection.\n\n";
var emailSent = row[19];
var date = new Date;
var title = "Order Ready";
var header = "**Please show this email during collection.\n\n";
var footer = "This is a System Generated email. Please do not reply to this email."
if (emailSent == '' && orderStatus == 'Stock' && dispatchMode == 'Collection' && orderNum != ''){
var subject = 'Prints Ready (Invoice No. ' + invoiceNum + '/Order No. E' + orderNum + ')';
sheet.getRange(startRow + i, 10).setValue('Office');
sheet.getRange(startRow + i, 20).setValue(EMAIL_STATUS);
sheet.getRange(startRow + i, 21).setValue(date);
this.sendgrid();
SpreadsheetApp.flush();
}
else if (emailSent == '' && orderStatus == 'Stock' && dispatchMode == 'Collection' && orderNum == ''){
var subject = 'Prints Ready- (Invoice No. ' + invoiceNum + ')';
sheet.getRange(startRow + i, 10).setValue('Office');
sheet.getRange(startRow + i, 20).setValue(EMAIL_STATUS);
sheet.getRange(startRow + i, 21).setValue(date);
this.sendgrid();
SpreadsheetApp.flush();
}
}
}
function sendgrid() {
var SENDGRID_KEY ='*****';
var headers = {
"Authorization" : "Bearer "+SENDGRID_KEY,
"Content-Type": "application/json"
}
var body =
{
"personalizations": [
{
"to": [
{
"email": emailAddress
}
],
"subject": title
}
],
"from": {
"email": "noreply#*****.com"
},
"content": [
{
"type": "text",
"value": header + message + footer
}
]
}
var options = {
'method':'post',
'headers':headers,
'payload':JSON.stringify(body)
}
var response = UrlFetchApp.fetch("https://api.sendgrid.com/v3/mail/send",options);
Logger.log(response);
}
All the emails for the entire loop ends up being sent to the email address in the first row of data instead of its respective rows.
The problem is the way how you use this.
It will be much easier if you don't use this at all, but
Define constant variables like message, date, title, header and footer one single time outside the function, rather than redefining them in every loop
Define sendgrid as function sendgrid(emailAddress) {...} and call it within the for loop with the email retrieved during each iteration sendgrid(emailAddress); instead of this.sendgrid();
Other small issues with your code:
You define header twice
Instead of using this.sendgrid(); SpreadsheetApp.flush(); two times - both in if and else statements - you can use it a single time after those statements
I am building a badge sending program using Google sheets and everything is going great so far. There is a control page that once marked yes and the script runs, sends an email to the email listed and inserts information from that page, including the recipients name. I want to be able to find the name of the person I'm sending a badge email to, use that name to activate a sheet, and then date stamp a certain cell on that sheet. I'm having trouble finding the name value.
The email and date stamp is working on the control page, but I'm having trouble figuring out the logic to determine the name value to open each person's individual page. The Logger just shows all the names in the range and I only want the names to show that are receiving emails/badges.
function sendEmails3() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Badge Issuing Central")
var startRow = 2; // First row of data to process
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow()-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
data.forEach(function(row,i) {
var name = row[0]; // First column
var badge = row[1]; // Second column
var recomendations = row[2]//third column
var awarded = row [3] // fourth column
var email = row [4] // fifth column
var dateEmailed = row [5] // 6th column
var emailSent = row[6]; // Seventh column
if (emailSent != EMAIL_SENT && awarded == 'Yes') { // Prevents sending duplicates
var body = 'Hi ' + name + '<br><br>' +
'Congratulations! You have recieved a badge!<br><br>' +
'Your teammates think you are doing great lately.<br><br>' +
'You were nominated at least twice by those around you, and you are being awarded:<br><br>' +
"<em>" + badge + '<br><br>' +
"Make sure you check out your Badge Pathway to see how you're doing!<br><br>" +
'Thanks, <br>' +
"Jordan, Mark, and Jarrod";
var subject = 'Congratulations! You have earned a badge!';
GmailApp.sendEmail(email, subject, "", { htmlBody: body } );
sheet.getRange(startRow + i, 7).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 6).setValue(d);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
if (emailSent != EMAIL_SENT && awarded == 'Yes') {
var nameTab = sheet.getRange(2,1,sheet.getLastRow()-1,1).getValues();
Logger.log(nameTab);}
});}
Try this:
function sendEmails3() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("Badge Issuing Central")
var data=sh.getRange(2, 1, sh.getLastRow()-1, 7).getValues();
for(var i=0;i<data.length;i++) {
var name=data[i][0]; // First column
var badge=data[i][1]; // Second column
var recomendations=data[i][2]//third column
var awarded=data[i][3] // fourth column
var email=data[i][4] // fifth column
var dateEmailed=data[i][5] // 6th column
var emailSent = data[i][6]; // Seventh column
if(emailSent != "EMAIL_SENT" && awarded=='Yes') {
var body=Utilities.formatString('Hi %s <br><br>Congratulations! You have recieved a badge!<br><br>Your teammates think you are doing great lately.<br><br>You were nominated at least twice by those around you, and you are being awarded:<br><br><em> %s<br><br>Make sure you check out your Badge Pathway to see how you\'re doing!<br><br>Thanks, <br>Jordan, Mark, and Jarrod', name,badge);
var subject = 'Congratulations! You have earned a badge!';
GmailApp.sendEmail(email, subject, "", { htmlBody: body } );
sh.getRange(i + 2, 7).setValue("EMAIL_SENT");
sh.getRange(i + 2, 6).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MMddyyyy HH:mm:ss"));
}
}
}
I am still learning the ropes here. Based on code suggested by other contributors, I put together a script to send reminder emails to consultants who record their time entries using a Google Form. The spreadsheet first imports calendar entries with all the Job information for each consultant. After the calendar entries are imported, if the consultant has not yet recorded their time entry, the following script will send them an email with a reminder to do so:
function sendReminder() {
var rmndrFrom = "XYZ, Inc.";
var myemail = "support#xyz.com";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
var numRows = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var dataRange = sheet.getRange(2, 1, numRows, lastCol); // row 1 is the header row
var sheetData = dataRange.getValues();
for (var i = 0; i < sheetData.length; ++i) {
var row = sheetData[i];
if (row[0]){
var jobNumb = row[0]; // Job Number
var conName = row[2]; // Consultant Name
var conMail = row[3]; // Consultant Email
var jobDate = row[4]; // Date
// format email string
var subject = "Time Entry Reminder: " + conName + " / Job " + jobNumb;
try {
var conMsgH = 'This is a reminder for you to record your time entry for Job #<strong>' + jobNum + '/' + jobDate + '</strong>';
// strip HTML for plain text message
var conMsgP = conMsgH.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
// send reminder to consultants
MailApp.sendEmail(conMail, subject, conMsgP, { htmlBody:conMsgH, name:rmndrFrom });
} catch (e) { // error handler
MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
}
}
}
}
So basically, this script parses the Pending sheet, if column A has a Job Number, it will send a reminder email to the consultant with that Job Number. However, a single consultant may have several job numbers to their name. I would like the script to send a single email to each consultant with a list of the Job Numbers for which they have to record their time entries.
Thanks in advance for your kind help. Any suggestions on how to optimize the code will also be very much appreciated.
There are a number of ways that you can approach this. One way is to keep a sheet with the consultants emails, names and a list of their job numbers. Load this data into your script, a list of all job ids and the job info. Then filter the job ids based on the consultants list and build your email, or you could just send that list of numbers for a very short script.
Another way is to do all of that sorting per consultant in the code and send out the emails that way. This is the approach I've taken, and I've also made use of the iterative JS functions map, filter and reduce more details at MDN.
The code is posted below, but if you would like to take a look at it attached to a spreadsheet and commented (as well as the functions to build that extra sheet with just the consultants info on it) take a look here.
Below is my iteration of your function. I hope it is helpful for your situation:
var rmndrFrom = "XYZ, Inc.";
var myemail = "me#emailisawesome.com";
var subject = "Time Entry Reminder";
function sendReminder() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
var numRows = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var sheetData = sheet.getRange(2, 1, numRows-1, lastCol).getValues();
var cons = sheet.getRange(2,3,numRows-1,1).getValues().reduce(flatten_).filter(getUniqueConsultants_);
cons.forEach(sendEmail_, sheetData);
}
function sendEmail_(consultant) {
var consultantsJobs = this.filter(getJobsForConsultant_, consultant);
var jobList = consultantsJobs.map(buildJobLine_).join("<br>");
try {
var conMsgH = "Hi " + consultant + ",<br>";
conMsgH += "This is a reminder for you to record your time entry for the following jobs:<br><br>";
conMsgH += jobList;
conMsgH += "<br><br>Thank you for your cooperation.";
var conMsgP = conMsgH.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
MailApp.sendEmail(consultantsJobs[0][3], subject, conMsgP, {htmlBody:conMsgH, name:rmndrFrom});
} catch (e) {
MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
}
}
function buildJobLine_(job) {
return "Job #" + job[0] + " on " + Utilities.formatDate(job[4], Session.getTimeZone(), "MMM dd yyyy");
}
function getJobsForConsultant_(row) {
return row[2] == this;
}
function getUniqueConsultants_(v,i,a) {
return a.indexOf(v) == i;
}
function flatten_(a,b) {
return a.concat(b);
}
I must say that fooby's answer is far beyond my JS skills, I'm sure it will work nicely but I still feel like proposing something different (and simpler from my pov), just for the fun of it ;-)
The main difference with your original script is the sorting of the array that allowed me to detect duplicate names and threat it accordingly. The html composition could be far better for sure but that was not your main request.
Here is the code
function sendReminder() {
var rmndrFrom = "XYZ, Inc.";
var myemail = "support#xyz.com";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pending");
var initial = "Hi conName,<BR>This is a reminder for you to record your time entry for the following jobs : <BR><BR><table border = 1 cellpadding = 3 bgcolor='#FFFFBB'><TR><TD>";
var sheetData = sheet.getDataRange().getValues();// simplified code to get the data array
sheetData.shift();//skips the headers
sheetData.sort(function(x,y){
var xp = x[2];// sort on column 3 but you can change here...
var yp = y[2];// sort on column 3 but you can change here...
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort ascending, eventually change here...
});
// Logger.log(sheetData);// sorted
var last = sheetData.length
var i = 1;//index 0 is handled outside the loop
var row = sheetData[0];
var subject = "Time Entry Reminder: " + row[2] + " / Job "
var conMsgH = initial
var msgComponent = makeline_(row)
subject += msgComponent[0]
conMsgH += msgComponent[1]
while (i<last){
if(sheetData[i][2]!=sheetData[i-1][2]||i==last-1){
sendData_(sheetData[i-1][3],sheetData[i-1][2],subject,conMsgH)
var subject = "Time Entry Reminder: " + sheetData[i][2] + " / Job "
var conMsgH = initial;
}
msgComponent = makeline_(sheetData[i])
subject += msgComponent[0]
conMsgH += msgComponent[1]
++i
}
}
function sendData_(conMail,conName,subject,conMsgH){
conMsgH = conMsgH.substr(0,conMsgH.length-8)+'</TABLE>'
conMsgH = conMsgH.replace('conName',conName)
var conMsgP = conMsgH.replace(/<\/tr>/ig, '\n').replace(/<br>/ig, '\n').replace(/(<([^>]+)>)/ig, "")
subject = subject.substr(0,subject.length-2);// remove the last '+ '
// Logger.log(subject)
// Logger.log(conMsgH)
Logger.log(conMsgP)
// Logger.log(conMail)
try{
// send reminder to consultants
MailApp.sendEmail(conMail, subject, conMsgP, { htmlBody:conMsgH, name:rmndrFrom });
} catch (e) { // error handler
// MailApp.sendEmail(myemail, "Error in sending reminder email.", e.message);
}
}
function makeline_(row){
var jobNumb = row[0]; // Job Number
var conName = row[2]; // Consultant Name
var conMail = row[3]; // Consultant Email
var descr = row[1]; // description
var FUS1=new Date(row[4]).toString().substr(25,6)+':00';// get timezone of this event, taking care of daylight savings
var jobDate = Utilities.formatDate(row[4], FUS1, "MMM dd yyyy # hh:mm aaa"); // Date
var subject = jobNumb+' + ';
var conMsgH = 'Job #'+jobNumb + '</TD><TD>' + jobDate + '</TD><TD>' + descr + '</TD></TR><TR><TD>';
return [subject,conMsgH];
}
EDIT : made some improvement in the mail format, used a table to show jobs & dates + removed some bugs ;-) (to be honest, I made this also for my personal use as I am having almost the same use case )