I currently have this script for a Google Sheets file I'm working on:
function myAlerts() { // this runs based on daily trigger
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Reminders");
var range = sheet.getDataRange(); var values = range.getDisplayValues();
var lastRow = range.getLastRow();
var curDate = values[1][5]
var anyMatches = false;
var message = ""; var sheetUrl = ss.getUrl();
var email = Session.getActiveUser().getEmail();
var optionalEmail = values[2][1];
if (optionalEmail != "") { email = email + "," + optionalEmail; }
for (var i = 5; i < lastRow; i++) {
// if today matches the alert date, send an alert
if (values[i][3].toString() == curDate.toString()) {
// add a message for this row if date matches
message = message + values[i][0] + " will expire on " + values[i][1] + "<br />\n";
// if there is a match, set anyMatches to true so and email gets sent
anyMatches = true;
}
} // ends for loop
// footer for message
message = message + "<br />\nThis is an auto-generated email to remind you of your document expiration. <br />\n"
if (anyMatches) { // send an email
MailApp.sendEmail({
to: email,
subject: 'Document Expiration Notice!',
htmlBody: message});
}
}
In my sheet, the script sends an email to me (owner of the sheet) and an additional person if I enter an email address in B3. The script looks at F2, and checks column D to see if any dates match. If they do it sends an email with information from the other columns, in that same row.
How can I edit this script so that it will not only send the email to me, and the email address in B3, but ALSO the email address in that same row, which has a matching date??
Just remove your { email = email + "," + optionalEmail;} from the first if statement, and move it after the second, adding the email value just like you did for the optionalEmail variable.
if (values[i][3].toString() == curDate.toString()) {
email = email + "," + optionalEmail + "," + values[i][2];
UPDATE for comment:
Valid point that I didn't catch when I made the change suggestion. That requires a little more work. You need to move the whole MailApp.sendEmail chunk into the second if statement. Then you need to 'clear' your variables each iteration so that they don't carry over into the next iteration. To do this effectively, you will need to create a new variable to hold the email recipients (recip). The code will throw an error if you clear the email variable, because of the logic you are using to populate it.
Here is the updated code:
function myAlerts() { // this runs based on daily trigger
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Reminders");
var range = sheet.getDataRange(); var values = range.getDisplayValues();
var lastRow = range.getLastRow();
var curDate = values[1][5]
var message = ""; var sheetUrl = ss.getUrl();
var email = Session.getActiveUser().getEmail(); var optionalEmail = values[2][1];
for (var i = 5; i < lastRow; i++) { // if today matches the alert date, send an alert
if (values[i][3].toString() == curDate.toString()) {
var recip = email + "," + optionalEmail + "," + values[i][2];
//changed variable to allow for clearing.
// add a message for this row if date matches
message = message + values[i][0] + " will expire on " + values[i][1] + "<br />\n";
MailApp.sendEmail({
to: recip,
subject: 'Document Expiration Notice!',
htmlBody: message});
recip = ""; // clears email recipients for next iteration.
message = ""; // clears message for next iteration.
}
} // ends for loop
}
// footer for message message = message + "<br />\nThis is an auto-generated email to remind you of your document expiration. <br />\n"
I also removed the anyMatches variable, and the first if statement, because they aren't really needed for this to work.
Let me know if it still doesn't do what you need.
Related
New to GAS. I have a Google Form feeding into a spreadsheet. After watching tutorial videos and reading other posts, I attempted to create a script that will send an email to an address in column 2, and send a different email based on either a yes or no in another column (column 25). It also includes another column (26) that I want to have the date populated into when the email is sent, ensuring that every time I run this script, there are no duplicates sent. I have debugged and nothing comes up as an error, but it's not working - I have not received an email. Help would be greatly appreciated! Here is an example spreadsheet: https://docs.google.com/spreadsheets/d/1AKaSOk1ZbnfKeadgB_mugnqplKzJJ3bDQ_KsRY0sMvQ/edit?usp=sharing
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responses = ss.getSheetByName("Field Trip Requests");
var data = responses.getRange(2,1,responses.getLastRow()-1,25).getValues();
data.forEach(function(row,i) {
// variables
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
if(emailSent == ' ') {
if(approval == "Y") {
var body = "Your field trip request for " +
destination +
" has been approved! If you requested transportation, Najma will make arrangements and contact you if she requires more information." +
"<br><br>" +
"Cheers," +
"<br><br>" +
"Boaty McBoatface";
}
else if(approval == "N") {
var body = "Your field trip request for " +
destination +
" has not been approved. Please come and see me and we can chat!" +
"<br><br>" +
"Cheers," +
"<br><br>" +
"Boaty McBoatface";
}
var subject = "Your Field Trip Request";
MailApp.sendEmail(recipient, subject, body)
var d = new Date();
responses.getRange(i + 1, 25).setValue(d);
}
})
}
One problem of the script is that you it's using 1 based indexes when it should be using 0 based in
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
The above is because JavaScript uses 0 based indexes for Array elements (as well as for other things), so intestead of the above use
var recipient = row[0];
var destination = row[5];
var approval = row[23];
var emailSent = row[24];
Another problem is the following condition:
emailSent == ' ' /* is emailSent equal to a blank space? */
it should be
emailSent == '' /* is emailSent equal to an empty string? */
the above because getValues() returns an empty string for empty cells
If this var data = responses.getRange(2,1,responses.getLastRow()-1,25).getValues(); is correct then there is no row[25] as shown below:
data.forEach(function(row,i) {
// variables
var recipient = row[1];
var destination = row[6];
var approval = row[24];
var emailSent = row[25];
row starts at zero and ends at 24
row is an array
Perhaps this is what you wish:
function sendEmail() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("Field Trip Requests");
var data=sh.getRange(2,1,responses.getLastRow()-1,25).getValues();
data.forEach(function(row,i) {
var recipient=row[0];
var destination=row[5];
var approval=row[23];
var emailSent=row[24];
if(emailSent=='' && approval=='Y') {
var body=Utilities.formatString('Your field trip request for %s has been approved! If you requested transportation, Najma will make arrangements and contact you if she requires more information. <br><br>Cheers<br><br>Boaty McBoatface',destination);
}else if(emailSent=='' && approval == "N") {
var body=Utilities.formatString('Your field trip request for %shas not been approved. Please come and see me and we can chat!<br><br>Cheers,<br><br>Boaty McBoatface',destination);
}
var subject="Your Field Trip Request";
MailApp.sendEmail(recipient, subject, body);
sh.getRange(i+1,25).setValue(Utilities.formatDate(new Date, Session.getScriptTimeZone(), "MM/dd/yyyy"));
})
}
I want the script to send an email to those mail addresses where unchecked boxes are in the row - This works fine. But I want the value of the checkbox to be set “True” after the mails were sent.
My Problem is that I need the last for-loop to stop after all checkboxes are checked. In other words: The last loop has to stop when an empty cell appears.
First of all I manually trigger the script - later I will start it with the help of a button in the menu (function onOpen...)
Appreciate any help – thanks a lot!
Check out the sheet and the code below:
function sendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
var response = ui.alert("mail was send to ", ui.ButtonSet.OK);
}
for (k=1; k < 20; k++) { //loop which has to stop
s.getRange(k, 3).setValue("True");
}
}
A couple of major changes in your script.
The condition for the loop is wrong. Change to:
for(var i=v.length-1;i>0;i--)
The UI response is missing the recipient name. Change to:
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
var UserData = range.getValues(); is declared twice: delete one row
Immediately after the UI alert (and still within the IF loop), add a line to update the checkbox: UserData[i][2] = true;
Simplify the updating of checkboxes.
Delete the existing lines:
for (k=1; k < 20; k++) {
s.getRange(k, 3).setValue("True");
}
Substitute:
range.setValues(UserData)
Revised Script
function sosendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
// MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
Logger.log("mail sent")
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
UserData[i][2] = true;
}
range.setValues(UserData)
}
Alternative Script
The following script is offered as an alternative. It avoids multiple getRange()/getValue statements and uses a more conventional top-down loop.
function sosendmail01() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
// get the number of rows (Alast)
var Avals = ss.getRange("A2:A").getValues();
var AlastRow = Avals.filter(String).length;
// Logger.log("DEBUG: number of rows = "+AlastRow)
// get the data range
var r = s.getRange(2, 1, AlastRow, 3);// get all the data
// Logger.log("DEBUG: the data range = "+r.getA1Notation())
var v = r.getValues(); // get the data
// loop through the rows of data
for (var i = 0;i<AlastRow;i++){
if (v[i][2] != false) {
// the checkbox is ticked Don't sent an email
// Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" - the checkbox is ticked");
} else{
// the checkbox IS NOT ticked - send an email
//Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" checkbox = "+v[i][2]+" - the checkbox is NOT ticked");
var name = v[i][0];
var email = v[i][1];
//MailApp.sendEmail(email, "Test", "Hello " + name + ", This is an email");
Logger.log("DEBUG: mail sent to "+name+" at "+email)
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
v[i][2] = true;
}
}
r.setValues(v);
}
I need to sent an e-mail to a group of people. Therefor I have a list of e-mailadresses set up in Spreadsheet, the Sheetname = Contacts.
The Weeknr-sheet is used to generate the required weeknumber in the subject.
I want to send this e-mail to everyone using the BCC, but I don't want to place all the e-mailadresses in the code itself (almost every solution gives that option), but extract them from the sheet.
My current code:
function sendEmail() {
var originalSpreadsheet = SpreadsheetApp.getActive();
var Weeknr = originalSpreadsheet.getSheetByName("Weeknr");
var period = Weeknr.getRange("C2").getValues();
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var emailTo = contacts.getRange("A2:A500").getValues();
{
var subject = " SUBJECT " + period;
var message = " MESSAGE ";
MailApp.sendEmail(emailTo, subject, message);
}
}
The below code should do the trick.However, note there is a limit (100per day for general user) on how many email you can send using mailApp each day.
function sendEmail() {
var originalSpreadsheet = SpreadsheetApp.getActive();
var Weeknr = originalSpreadsheet.getSheetByName("Weeknr");
var period = Weeknr.getRange("C2").getValues();
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var emailTo = contacts.getRange("A2:A500").getValues();
var emailsubject = " SUBJECT " + period ;
var message = " MESSAGE ";
MailApp.sendEmail({to: "youremailId#example.com",
bcc: emailTo.join(","),// joins the emailto array to form a comma separated string of addresses
subject: emailsubject,
body: "message",
});
}
I'm having a problem sending an html body message from a Google sheet from another email address that is an alias.
I can send it using the mailApp, but when I switch to the GmailApp I can't seem to get it to work.
The script I am using is below:
function sendNotification(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var emailAdd = "email#yourdomain.com";
if(event.range.getA1Notation().indexOf("G") > -1 && sheet.getRange("G" + row).getDisplayValue() > 999 && emailAdd.length > 1)
{
var rowVals = getActiveRowValues(sheet);
var aliases = GmailApp.getAliases();
Logger.log(aliases);
GmailApp.sendEmail(
"email#yourdomain.com",
"Allocation Request - " + rowVals.quantity + " cases on " + rowVals.date,
{htmlBody: "There has been a new allocation request from " + rowVals.name + " in the " + rowVals.team + " team.<br \> <br \> "
+ "<table border = \"1\" cellpadding=\"10\" cellspacing=\"0\"><tr><th>Issuing Depot</th><th>Delivery Date</th><th>Case Quantity</th></tr><tr><td>"+rowVals.depot+"</td><td>"+rowVals.date+"</td><td>"+rowVals.quantity+"</td></tr></table>"
+ "<br \>To view the full details of the request, use the link below.<br \> <br \>" +
"Allocation Requests"
+"<br \> <br \><i>This is an automated email. Please do not reply to it.<\i>"},
{from: aliases[0]}
);
}
}
function getActiveRowValues(sheet){
var cellRow = sheet.getActiveRange().getRow();
// get depot value
var depotCell = sheet.getRange("E" + cellRow);
var depot = depotCell.getDisplayValue();
// get date value
var dateCell = sheet.getRange("F" + cellRow);
var date = dateCell.getDisplayValue();
// get quantity value
var quantCell = sheet.getRange("G" + cellRow);
var quant = quantCell.getDisplayValue();
// return an object with your values
var nameCell = sheet.getRange("B" + cellRow);
var name = nameCell.getDisplayValue();
var teamCell = sheet.getRange("C" + cellRow);
var team = teamCell.getDisplayValue();
return {
depot: depot,
date: date,
quantity: quant,
name: name,
team: team
} }
I've managed to get the email to send from my alias, but it just sends and message containing [object], whereas not sending it from an alias works fine.
Could someone take a look and see what I'm doing wrong? I've not been able to find an answer on here yet. Thanks.
Create an object then add elements to the object:
var bodyHTML,o,sendTO,subject;//Declare variables without assigning a value
o = {};//Create an empty object
bodyHTML = "There has been a new allocation request from " + rowVals.name;
o.htmlBody = bodyHTML;//Add the HTML to the object with a property name of htmlBody
o.from = aliases[0]; //Add the from option to the object
sendTO = "email#yourdomain.com";
subject = "Allocation Request - " + rowVals.quantity + " cases on " + rowVals.date;
GmailApp.sendEmail(sendTO,subject,"",o);//Leave the third parameter as an empty string because the htmlBody advanced parameter is set in the object.
I'm new to using the google doc script editor so please be kind. Here's what I have so far:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Define variables from sheet by column
//Column count starts at 0, not 1.
var timestamp = e.values[cellrow,14];
var yourName = e.values[cellrow, 0];
var email = e.values[cellrow, 1];
var plot2013 = e.values[cellrow, 5];
var plotrequest = e.values[cellrow, 6];
var sharing = e.values[cellrow, 7];
var totalprice = e.values[cellrow, 8];
var paid = e.values[cellrow, 13];
var subject = "TSF Payment Confirmation"
//email body
var emailBody = "Thank you for your payment submitted on " + timestamp +
"\n\nThe details you entered were as follows: " +
"\nYour name: " + yourName +
"\nYour plot #: " + plot2013 +
"\nNumber plots requested: " + plotrequest +
"\nSharing plot with: " + sharing +
"\nTotal payment: " + totalprice;
//html version of email body
var htmlBody = "Thank you for your payment submitted on <i>" + timestamp +
"</i><br/> <br/>The details you entered were as follows: " +
"<br/><font color=\"red\">Your Name:</font> " + yourName +
"<br/>Your Email: " + plot2013;
"<br/>Plots requested: " + plotrequest;
"<br/>Sharing plot with: " + sharing +
"<br/>Total payment: " + totalprice;
//sends email if cell contents are 'yes'
if (e.values[13,cellrow] == "yes") {
//Sends email
MailApp.sendEmail(email, subject, emailBody);
}
}
And what I'm hoping is that once a user clicks in column 13 (assuming its counting from 0 on the left, and not variable numbers) and types 'yes' it will email the information from that users row as specified.
I'm getting an error message, saying:
var timestamp undefined
I got that from this example here: http://alamoxie.com/blog/tech-tips/sending-confirmation-emails-google-docs-form/
You're trying to reference the cells in a way that doesn't make sense (or work). Try this tested/working code instead:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
// Ensure the event was triggered by typing "yes" in the appropriate column
if(e.range.getColumn() == 14 && e.value.toUpperCase() == "YES"){
// Get the corresponding row
var row = sheet.getRange(e.range.getRow(), 1, 1, sheet.getLastColumn()).getValues()[0];
// Define variable from row by column
var timestamp = row[14];
var yourName = row[0];
var email = row[1];
var plot2013 = row[5];
var plotrequest = row[6];
var sharing = row[7];
var totalprice = row[8];
var paid = row[13];
var subject = "TSF Payment Confirmation"
// Construct the email body
var emailBody = "Thank you for your payment submitted on " + timestamp +
"\n\nThe details you entered were as follows: " +
"\nYour name: " + yourName +
"\nYour plot #: " + plot2013 +
"\nNumber plots requested: " + plotrequest +
"\nSharing plot with: " + sharing +
"\nTotal payment: " + totalprice;
// Construct an HTML version of the email body
var htmlBody = "Thank you for your payment submitted on <i>" + timestamp +
"</i><br/> <br/>The details you entered were as follows: " +
"<br/><font color=\"red\">Your Name:</font> " + yourName +
"<br/>Your Email: " + plot2013;
"<br/>Plots requested: " + plotrequest;
"<br/>Sharing plot with: " + sharing +
"<br/>Total payment: " + totalprice;
// Send email
MailApp.sendEmail(email, subject, emailBody);
}
}
Notice I put everything in a conditional statement; there's no sense in trying to parse all that data if a cell in column N wasn't changed to "yes". Immediately after, I retrieve all the values from the edited row and fill all your variables with the result. The rest is pretty much the same as you wrote it.
Good luck!