I'm having trouble with the "Email _Sent" text. It is supposed to appear next to the recipient who received the email from my spreadsheet. However, when I select certain emails to send the message to, the text "Email _Sent" starts filling out the first empty rows in my spreadsheet. In this way, the text appears beside some recipients who didn't receive the message.
I'll post the script that I'm using:
function sendGeneralEmail() {
var Email = 4;
var Name = 3;
var emailSent = 6;
var subject = "Sample Analysis Service"
var html = HtmlService.createTemplateFromFile("SUM.1");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test");
var data = ws.getRange("A5:G" + ws.getLastRow()).getValues();
data = data.filter(function(r){ return r[5] == true});
var Email_Sent = 'Email_Sent';
var sheet = SpreadsheetApp.getActiveSheet();
var notBlank = sheet.getRange("D5:G5");
var lastRow = notBlank.getLastRow();
data.forEach(function(row){
html.en = row[Name];
var htmlMessage = html.evaluate().getContent();
if(emailSent !=Email_Sent) {
GmailApp.sendEmail(
row[Email],
subject, "Your Email doesn't support HTML", {
name: "MASAR Team",
htmlBody: htmlMessage},
);
sheet.getRange(lastRow, 7, data.length, 1).setValue(Email_Sent);
SpreadsheetApp.flush();
}
});
}
Can someone help me to fix that?
The second issue is that, if I run the script and then stopped and came back and run it again on the same day, the text "Email_sent" stops updating to the spreadsheet. It only appears the first I run the script during the day.
Screenshot
Hope to have a solution to this
I tried to replicate your code and found some issues:
using setValue on range with multiple cells will copy the value to all cells within the range. In your example, all cells in getRange(lastRow, 7, data.length, 1) will have the value "Email_Sent". This causes the unwanted write of "Email_Sent" in your spreadsheet.
if(emailSent !=Email_Sent) will always true because '6' is not always equal to 'Email_Sent'
Based on your example, your goal is to send an email and write "Email_Sent" to the Email Status column of the recipient.
Here, I fixed some part of your code and added features.
Code:
function sendGeneralEmail() {
var subject = "Sample Analysis Service"
// var html = HtmlService.createTemplateFromFile("SUM.1");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test");
var data = ws.getRange("A5:G" + ws.getLastRow()).getValues();
var sheet = SpreadsheetApp.getActiveSheet();
for(var i=0; i<data.length; i++){
var selected = data[i][5];
var emailStatus = data[i][6];
if(selected && emailStatus != "Email_Sent"){
var email = data[i][4];
// html.en = row[Name];
// var htmlMessage = html.evaluate().getContent();
GmailApp.sendEmail(
email,
subject, "Your Email doesn't support HTML", {
name: "MASAR Team",
message: "ABCD",
// htmlBody: htmlMessage},
}
);
sheet.getRange(i+5, 7, 1, 1).setValue("Email_Sent");
}
}
}
Note: I commented the html parsing since I don't have the sample html and replaced the email message with a string.
Before running the script:
After running the script:
Reference:
setValue()
Related
I'm new to g-scripts and facing some issues in coming up with the code for the below. My goal is:
Want to send an automatic email to specific people once the information in any of the rows in the google sheet are edited.(note: the range is the whole sheet)
For each row in the google sheet, there's an email address next to it (under a new column) which specifies the person this automatic email should be sent to.
Can the changes be compiled once per day and sent via 1 email per email address?
Thank you in advance for your help.
Currently, this is my code:
function onEdit(e){
var rows = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1").getRange(30000,30).getValue();
var headerRow = rows.shift();
var editedRow = e.range.getRow();
var template = HtmlService.createTemplateFromFile("Template1.html");
template.headerRow = headerRow;
template.editedRow = editedRow;
template.rows = rangeValues;
var html = template.evaluate().getContent();
function sendEmails(){
var ss=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1").activate();
var ss=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr=ss.getLastRow();
//getting email body:
var sheet2Text = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet2").getRange(1,1).getValue();
// Logger.log(emailText);
var quotaLeft = MailApp.getRemainingDailyQuota();
Logger.log(quotaLeft);
if((lr-1)>quotaleft){
Browser.msgBox("You have"+quotaLeft+"left & you're trying to send"+(lr-1)+"emails. Emails not sent");
} else{
for(var i=2; i<lr; i++){
var currentEmail = ss.getRange(i,26).getValue();
var currentClientName = ss.getRange(i,1).getValue();
var currentTeamName = ss.getRange(i,27).getValue();
var messageBody = sheet2Text.replace("{name}",currentTeamName);
var subjectLine = "notification on" + currentClientName + "process list", html;
MailApp.sendEmail(currentEmail, subjectLine, messageBody);
//26 is the column number that contains the emails in the google sheet
} //closing the for loop
} // closing the else loop
} // closing the function sendEmails
} // closing the onEdit function
new to google script, I have a google script with a button on the sheet which sends out emails from a google sheet, it works fine.
however I want to send emails to those emails that I checkmark manually, I have a column (F) with a checkmark, so I want to checkmark emails then send emails to those emails that have been check-marked only.
I stuck in the completion of the coding for the checkmark part, I appreciate your help.
I have commented out my 2 lines of code for filtering the checkmarks.
the code check for send email quote as well as writes timestamp and email sent note every time email has been sent.
Thanks.
these are columns, one header:
A1: timestamp
B1: email address
C1: Name
D1: Email Sent?
E1: Data emaill sent
F1: check box
function sendEmails(){
var sheet = SpreadsheetApp.openById("mySheetid");
var ss = sheet.getSheetByName("Emails");
var lr = ss.getLastRow();
var EMAIL_SENT = 'Email has been sent';
var messageSubject =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("BodyTextSheet").getRange(2, 1).getValue();
var messageText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubjectSheet").getRange(2, 2).getValue();
var quotaLeft = MailApp.getRemainingDailyQuota();
if ((lr-1) > quotaLeft){
Browser.msgBox("you have " + quotaLeft + "left and you're trying to send " + (lr-1) + "emails. Emails were not sent.");
} else{
for (var i = 2; i<=lr; i++){
var currentEmail = ss.getRange(i, 2).getValue();
var currentName = ss.getRange(i, 3).getValue();
var messageBody = messageText.replace("{name}",currentName);
//var selected = ss.getRange("F2:F" + ss.getLastRow()).getValues();
//data = selected.filter(function(r){ return r[6] == true});
MailApp.sendEmail(currentEmail, messageSubject, messageBody);
var EmailSent = ss.getRange(i, 4).setValue(EMAIL_SENT);
var TimeEmailSent = ss.getRange(i, 5).setValue(new Date());
SpreadsheetApp.flush();
}
}
}
This worked out when i tested it. In your code you have BodyTextSheet with the var: messageSubject and viseversa... This is a bit confusing. So you need to change those ranges in this code.
function sendEmails() {
const ss = SpreadsheetApp.openById("mySheetid");
const emailSheet = ss.getSheetByName("Emails");
const bodyText = ss.getSheetByName("BodyTextSheet").getRange(2, 1).getValue()
const subjectText = ss.getSheetByName("SubjectSheet").getRange(2, 2).getValue()
const emails = emailSheet.getDataRange().getValues();
const filterdRows = [];
for (i = 0; i < emails.length; i++) {
const row = emails[i]
if (row[5] == true) {
row.unshift(i+1)
filterdRows.push(row)
}
}
const quotaLeft = MailApp.getRemainingDailyQuota();
if (filterdRows.length > quotaLeft) {
Browser.msgBox(`you have ${quotaLeft} left and you're trying to send ${filterdRows.length} emails. Emails were not sent.`);
} else {
filterdRows.forEach(email => {
const messageBody = bodyText.replace("{name}", email[3]);
MailApp.sendEmail(email[2], subjectText, messageBody);
emailSheet.getRange(email[0], 4, 1, 2).setValues([['Email has been sent', new Date()]])
})
SpreadsheetApp.flush();
}
}
So i made some modifications:
const emails: Get all the emails at once (much quicker)
Loop over the data and check if column F (arrays are 0 indexed so column 5) is true
If is true then add i+1 (rownumber) to the beginning of the array
Then forEach filtertEmail send the mail and set set text and date in the right row (in one call) That is why i pushed the rownumber in the beginning.
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'
);
}
}
}
I have been looking how to write the script to check and run on multiple tabs. What I have now, I would need to copy/paste and set execution triggers one by one.
Script I have:
function SendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("1");
var value = sheet.getRange("F3").getValue();
var subject = "subject";
var message = "message";
if (value >0){
MailApp.sendEmail("email", subject, message);
}
}
I have this running every 8 hours (trigger run).
I am looking to add more tabs so that for each tab the script can check and send an email if the value of individual tabs is more than 0.
Any ideas on how to do this?
The value in every tab is under F3. Tab names, for example, 1,2,3,4...
Thank you!!!
This should do what you looking for if I understood the issue correctly.
function SendEmail() {
//Get the Spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
//Get all Sheets in the Spreadsheet
var sheets = ss.getSheets();
//Create a variable for the email address, subject and message
var email = "";
var subject = "";
var message = "";
//Can change the starting sheet by changing the value of "i" - 0 will be the first sheet.
for (var i = 0; i < sheets.length; i++){
var sheet = sheets[i];
var value = sheet.getRange("F3").getValue();
switch(sheet.getSheetName) {
case "Sheet1":
email = "email1#domain.com";
break;
case "Sheet2":
email = "email2#domain.com";
break;
default:
value = 1
email = "yourEmailAddress#domain.com";
subject = "Message Failed to Send";
message = "There was an error sending email, please investigate";
}
if (value >0){
MailApp.sendEmail(email, subject, message);
}//END OF IF STATEMENT
}//END OF FOR LOOP
}//END OF FUNCTION
I have a long standing form/spreadsheet/script - that send emails triggered on spreadsheet edit. The trigger is working but the email is not sending. I have dropped the script and recreated - which authorized again.
function sendNotification() {
//Get Active spreadsheet and worksheet
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var sheet = spreadsheet.getSheetByName("Change Requests");
var sheet2 = spreadsheet.getSheetByName("Email Addresses");
//Set row for which to send notification
//get values
var lastRow = sheet.getRange(row, 1, 1, sheet.getLastColumn());
var values = lastRow.getValues();
//Other Variables
var body = "<HTML><BODY>";
var stuNumber = values[0][2];
var stuName = values[0][3].toString();
var stuHouse = values[0][5].toString();
var gradeLevel = values[0][6].toString();
var oldCourse = values[0][7].toString();
var newCourse = values[0][8].toString();
var subject = "New course change request submitted for " + stuName;
var academicAdviser;
var cc_recipients = sheet2.getRange(4, 2).getValue();
//Send notification email
try {
MailApp.sendEmail(academicAdviser, subject, body, {htmlBody: body, noReply: "True", cc: cc_recipients})
}
catch (f) {
Browser.msgBox(f.message);
}
}
In this line:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
spreadsheet is set to the activeSheet which is not a spreadsheet
In this line:
var lastRow = sheet.getRange(row, 1, 1, sheet.getLastColumn());
row is undefined.
In this Line:
MailApp.sendEmail(academicAdviser, subject, body, {htmlBody: body, noReply: "True", cc: cc_recipients})
academicAdviser is undefined and htmlBody is set to <HTML><BODY> which will produced no output for htmlBody parameter.
Instead of Using this:
Browser.msgBox(f.message);
You might consider using SpreadsheetApp.getUi().prompt() or alert()
And I think it's a good idea to add MailApp.getRemainingDailyQuota() somewhere to keep yourself from running over your quota.
After looking at your code I'd guess that it might be a good idea for you to read this section.