Updating different tab with a script from a pivot table???? - google-apps-script

I am new to coding scripts in google and come into a problem I can not work through and my script "mentor" is still not that experienced and can't figure it out either.
I am trying to update a different tab on my sheet from a pivot table when I use my script to send out bulked emails.
So the link below will bring you to the dummy sheet built off my real sheet. The 'PM' tab column L is what I am trying to update. It starts at 1 on all jobs. The emails are sent out by the Blue button on the next tab 'Follow up email' (this is just a pivot table so I can always adjust who is getting the emails easily). But I cant figure out how to have it update the 'PM' tab with the button at the same time as the emails go out.
Link to the open shared spreadsheet. Feel free to play around if you can help.
https://docs.google.com/spreadsheets/d/1_hipIj4suI2xMGUrZhMTBDvkQv9Y9O3JRNNQUpSeAP0/edit?usp=sharing
(only got the emails to send properly so far)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var rows = sheet.getLastRow()
var dataRange = sheet.getRange(2, 1, rows-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = 'Hello, we have submitted this job ' + row[2] + ' days Ago. ' + row[4] + ' \n\n' + ' -' + row[5];
var subject = row[0]; // First column
MailApp.sendEmail(emailAddress, subject, message);
}
}
I need the button to send out emails on the 'Follow up email' tab and at the same time "email counter" (column L) would get 1 added to it on the 'PM' Tab. This way I can keep track of how many times that job was emailed from the sheet.

Try this code:
function sendEmails() {
var pmSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PM");
var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Follow up email");
var startRow = 2; // First row of data to process
var rows = emailSheet.getLastRow()
var dataRange = emailSheet.getRange(2, 1, rows-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = 'Hello, we have submitted this job ' + row[2] + ' days Ago. ' + row[4] + ' \n\n' + ' -' + row[5];
var subject = row[0]; // First column
MailApp.sendEmail(emailAddress, subject, message);
updatePM(pmSheet, emailAddress);
}
}
function updatePM(sheet, email){
var value;
var emails = sheet.getRange("G3:G" + sheet.getLastRow()).getValues();
for (var i = 0; i < emails.length; i++)
if (emails[i][0] == email){
value = sheet.getRange("K" + (i+3)).getValue() + 1
sheet.getRange("K" + (i+3)).setValue(value);
}
}
I changed the way you got the sheets just to be safe, then I just wrote a small function that gets called after the email is sent, which checks the list of emails in the PM sheet and then updates the value in the sent email column.

Related

MailApp sendEmail in google sheets

been using MailApp script to automatically send emails from within a google sheet for several years. developed my script from an example i found online and reverse engineered it until i could make it work (i am not a coder!). worked brilliantly for months/years...
but recently it is no longer functioning. i get a daily email summary of errors which states that EMAIL_SENT is not defined, but when running the script in debug mode it times out after the logger.log(user) - so does appear to hang on the EMAIL_SENT variable.
As i say, this has been running brilliantly for many months, but appears to have stopped around july 22nd.
i have included the script below in case it is something simple:
function autoemailES() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ESautoemail");
//var lastRow = sheet.getLastRow();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow() -1; // Number of rows to process
var EMAIL_SENT = 'EMAIL_SENT';
// Fetch the range of cells A2:G
var dataRange = sheet.getRange(startRow, 1, numRows, 30);
// 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 emailSent = row[7]; // 8th column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var superMail = row[2]; // 3rd column
var responseNo = row[3]; // 4th column
var user = row[0]; // 1st column
var firstName = row[1]; // 2nd column
var pdfLink = row[5]; // 6th column
var pdfID = row[6]; // 7th column
Logger.log(responseNo) //these logger lines just display the values for each of the variables in debugging
Logger.log(superMail)
Logger.log(user)
Logger.log(pdfLink)
Logger.log(pdfID)
var file = DriveApp.getFileById(pdfID);
var subject = 'IBTPHEM MSF results for ' + user;
var message = 'Dear Educational Supervisor,' + "\n" +
'This is an automated notification that your trainee, ' + firstName + ', has now received a quorate number of MSF responses.'+"\n"+
'The anonymised summary of responses is attached in PDF format, or can be downloaded from the link below.'+"\n" + pdfLink +"\n"+
'Further submissions will be added automatically (the trainee is notified for each), but the pdf will need downloading again'+"\n"+
'Please feel free to share this with your trainee however you see fit - we are now releasing the results via the ES in case there is any feedback that may require debriefing or handling more delicately.'+"\n"+
'Please do let me know of any problems or concerns?'+"\n"+
'Kind Regards,' + "\n" +
'IBTPHEM MSF'
MailApp.sendEmail(superMail,subject, message,{
name: 'IBTPHEM MSF',
replyTo: 'dr_nick#doctors.org.uk',
attachments: [file.getAs(MimeType.PDF)]});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
I would be really grateful for any help to identify my problem.
thanks!
dr_nick
(i cannot easily share the sheet in its entirity as it contains a fair bit of senstive/confidential information - though I suppose I could make an anonymised version if this is necessary/helpful?)
This is the same script with a try catch block. It will only log things if you have an error.
function autoemailES() {
const ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("ESautoemail");
var startRow = 2;
var EMAIL_SENT = 'EMAIL_SENT';
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow() - startRow + 1, 30);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
try{
var row = data[i];
var emailSent = row[7];
if (emailSent !== EMAIL_SENT) {
var superMail = row[2];
var responseNo = row[3];
var user = row[0];
var firstName = row[1];
var pdfLink = row[5];
var pdfID = row[6];
var file = DriveApp.getFileById(pdfID);
var subject = 'IBTPHEM MSF results for ' + user;
var message = 'Dear Educational Supervisor,' + "\n" +
'This is an automated notification that your trainee, ' + firstName + ', has now received a quorate number of MSF responses.' + "\n" +
'The anonymised summary of responses is attached in PDF format, or can be downloaded from the link below.' + "\n" + pdfLink + "\n" +
'Further submissions will be added automatically (the trainee is notified for each), but the pdf will need downloading again' + "\n" +
'Please feel free to share this with your trainee however you see fit - we are now releasing the results via the ES in case there is any feedback that may require debriefing or handling more delicately.' + "\n" +
'Please do let me know of any problems or concerns?' + "\n" +
'Kind Regards,' + "\n" +
'IBTPHEM MSF'
MailApp.sendEmail(superMail, subject, message, {
name: 'IBTPHEM MSF',
replyTo: 'dr_nick#doctors.org.uk',
attachments: [file.getAs(MimeType.PDF)]
});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
catch(e){
Logger.log('responseNo: %s\nsuperMail: %s\nuser: %s\npdfLink:%s\npdfID: %s',responseNo,superMail,user,pdfLink,pdfID);
Logger.log(e);
}
}
}
Try setting up another spreadsheet and adjust the data so that it doesn't send data to your clients and see if it will generate any errors. Also if you could share a copy of the new spreadsheet as a markdown table that would enable us to test it a little. But be careful about sharing private information

App Script - Send Email based on days left to date - Can't make script send it X days left to date

I am using this spreadsheet Here
I am trying to send an email to a specific recipient "email#myemail.com" when there are 3 days left for a specific date.
Each row represents a person and I want the email sent to send me an email for each person whose date of offboarding - date of today is exactly 3 days.
This is my output: Email received
This is the script i am using:
function Offboarding_Reminder() {
// 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
var startRow = 2;
// grab column 11 (the 'days left' column)
var range = sheet.getRange(2,12,lastRow-startRow+1,1 );
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Now, grab the user name column
range = sheet.getRange(2, 1, lastRow-startRow+1, 1);
var reminder_name = range.getValues();
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 == 3) {
// if it's exactly 3, do something with the data.
var user_name = reminder_name[0][i];
msg ="Reminder:"+reminder_name+" offboarding is due in "+days_left+" days.\n";
warning_count++;
}
}
if(warning_count) {
MailApp.sendEmail("email#myemail.com","Reminder Offboarding",msg)
}
};
Two things I don't understand:
Why is my sent email giving me all the user emails instead of just the ones that have days_left == 3?
To automate this script, once it works, I should just add a trigger to the appscript?
Thanks for the help!
I actually revised your code since it wasn't optimized. It had a lot of redundant and unnecessary lines.
Here are the changes:
fetched the range from user column to days_left column once, not separately
created array to store users matching the condition
formatted the email to look better.
Code:
function offboardingReminder() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// set active sheet to first sheet
spreadsheet.setActiveSheet(spreadsheet.getSheets()[0]);
var sheet = spreadsheet.getActiveSheet();
// figure out what the last row is
var lastRow = sheet.getLastRow();
var startRow = 2;
// grab all data from user to days left
var range = sheet.getRange(startRow, 1, lastRow - startRow + 1, 12);
var values = range.getValues();
var users = [];
// loop all data per row
values.forEach(function(row) {
// if days left is 3
if(row[11] == 3) {
// add user if 3 days left
users.push(row[0]);
}
});
// if users has elements
if(users) {
// Formatted the message as html to look nicer
var message = "<html><body><h1>Reminder!!!</h1><p>The following user/s offboarding is due in 3 days:</p>";
// created bulleted list for list of users
var emails = "<ul>";
users.forEach(function(user){
emails = emails + "<li>" + user + "</li>";
});
emails += "</ul>";
message = message + emails + "</body></html>";
MailApp.sendEmail("email#myemail.com", "Reminder Offboarding", "", {htmlBody: message, noReply: true});
}
}
Sample data:
Sample output:
Note:
You can calculate the days left in script instead, but if it is already needed in sheets, then reusing it would be fine.
I populated the days left column via formula =DAYS(C2,TODAY()) for row 2 (dragged for other rows)

Auto Email google sheet response

Can anyone help with a google app script to trigger an auto email to applicants that failed the quiz - scoring lower than 130 on column A on google sheets?
Thanks in advance for the help!
Quiz Results Response
Do you want the mail to go automatically as soon as the form is filled? In that case, you can use the onFormSubmit trigger to send the mail to him automatically.
If you are processing the answers and then creating the result sheet, you can send the mail from the result sheet by processing each row in the sheet. You can easily find many examples how to send a mail from a sheet based on value in a column.
I am enclosing a similar code which sends the response to a user automatically as soon as he submits a form. I am storing his email ID (based on employee number) and sending him some data (based on his employee number) as soon as requests it. It works as a "employee self help portal".
function onFormSumbit(e) {
var emp = e.source.getActiveSheet().getRange(e.range.rowStart,2).getValue();
var lvss = SpreadsheetApp.openById("xxxx"); // blanks https://docs.google.com/spreadsheets/d/1kjOjhH0dvz4j3FsB_1UR5astpy8-ZxszNI4BZo4XJP0/edit#gid=0
SpreadsheetApp.setActiveSpreadsheet(lvss);
var lvsht = lvss.getSheetByName("Blanks");
var lvlr = lvsht.getLastRow();
var vA =lvsht.getRange("A:L").getValues();
var html="<style>th,td{border:1px solid black;}</style><table>";
html+='<tr>';
for(var i=0;i< 4 ;i++) {//make title
html+=Utilities.formatString('<th>%s</th>',vA[0][i]);
}
html+='</tr>';
for (i=1;i<lvlr;i++){
if (vA[i][0]==emp){
html+='<tr>';
for (j=0;j<4;j++) {
if ( j==2 ){
vA[i][j]=Utilities.formatDate(vA[i][j],"GMT+05:30", "dd-MM-yy");
}//if date
html+=Utilities.formatString('<td>%s</td>',vA[i][j]);
}//for emp
html+='</tr>';
}//if
}//for
html+='</table><br>';
var empss = SpreadsheetApp.openById("xxxx"); // emp master
SpreadsheetApp.setActiveSpreadsheet(empss);
var empsht = empss.getSheetByName("Emp");
var emplr = empsht.getLastRow();
var empvals =empsht.getRange("A:H").getValues();
for (i=1;i<emplr;i++){
if (empvals[i][0]==emp){
var em1=empvals[i][7];
var name=empvals[i][1]
break;
}//if
}//for
var subject="Your punch blanks "+name;
if (em1=="") {} else {
//MailApp.sendEmail(em1, subject, html);}
MailApp.sendEmail({
to: em1,
subject: subject,
htmlBody: html
});
}
}
//
//
Hope it helps !!
This function processes the full spreadsheet data from first row to last row and sends failure notification emails where the score is less than 130 ...
function notifyFailedCandidates ()
{
//Get the active sheet from the current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get all the rows from the spreadsheet
var rangeData = sheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = sheet.getRange(2,1, lastRow-1, lastColumn);
var rows = searchRange.getValues();
//loop through each of the rows
for (var rowNumber in rows)
{
//Get each of the values from the row
var quizScore = rows[rowNumber][0];
var firstName = rows[rowNumber][1];
var lastName = rows[rowNumber][2];
var email = rows[rowNumber][3];
//Send a failure notification if the score is less than 130
if (parseInt (quizScore) < 130)
{
MailApp.sendEmail
(
email, //candidate email address
'Notification of test failure', //Subject of failure notification email
//Contents of failure notification email
'Hi ' + firstName + "\n\n" +
'This email is to let you know that unfortunately you failed the test, with a score of ' + quizScore + ' / 170' + "\n\n" +
'Better luck next time'
);
}
}
}

How do I find a cell value based on if 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"));
}
}
}

How to fetch the row number of a Google Spread Sheet via Google Apps Script?

I have a google script I am using and I was wanting to insert the current row I am working with into a value which will be re added into a formula I set back in the spreadsheet. I want to do this in case someone resubmits the same data, so they are emailed the changes. At the moment this script is just a proof of concept for me, so I can then go on and code the entire process.
The problem I am having with the script is with the value currentRow. It seems to get the value of the first pass and then does not change it, which is problematic when you have more than one entry to process.
I use the value currentRow in the variable RESEND_EMAIL, so it can generate a formula which looks to see if the two columns are alike (I am going to use the date time stamp and copy it in just the first time to column D (also known as var resend[4]).
This way I can set the script to run automatically and check if this column is set as "Yes", in which case it will send and email again and then change the a value (shown here as email address - but I will use the timestamp instead) so that the formula RESEND_EMAIL changes resend back to "No".
How do I always ger the correct row Number in the value currentRow?
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
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, 6)
// 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 resend = row[4];
var extension = row [5];
var currentRow = sheet.getActiveRange().getRow();
var RESEND_EMAIL = "=IF(A"+ currentRow +"=D" + currentRow +",\"No\",\"Yes\")";
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 5).setFormula(RESEND_EMAIL);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
if (resend == "Yes") { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
message = message + " " + extension;
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 4).setValue(emailAddress);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
As shown in your code i variable value becomes the current row.
...
var currentRow = startRow + i;
...