I am using a google form to send out emails to parents and coaches if students are missing work. The problem I am running into is that the sometimes the coach email is not listed because the student is not in a sport, so it has a blank cell and then the script will stop running. I just want it to skip over and continue moving down the sheet. Also is there a way that I can get a cell to confirm that it sent? like having the cell next to the email say "sent" or "error" if it fails? I'm not really concerned with this part it just would be nice. I'm really new to this. Thanks!
function SendCoachEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Homework Hour 4.0").activate();//take off 4.0 when done with texting
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DO NOT DELETE! Parent Email Template").getRange(1, 1).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++){ // i is the current row so in this i is row 2
var currentEmail = ss.getRange(i,12).getValue(); // 15 is the email column
var currentStudent = ss.getRange(i, 4).getValue(); // 4 is student name column
var currentMessage = ss.getRange(i, 2).getValue(); // 2 is the message column
var currentMissingAssingment = ss.getRange(i, 9).getValue(); // 9 is the missing assingment column
var massageBody = templateText.replace("<<Student Name>>",currentStudent).replace("<<Message>>",currentMessage).replace("<<Missing Assingment>>",currentMissingAssingment);
var subjectLine = currentStudent +" Has Homework Hour"; // change whats in the "" to what you need the subject on the email to be
MailApp.sendEmail(currentEmail, currentStudent, massageBody); // to change subject on email change "Has Homework Hour" Part//
}
}
}
You can use a simple condition statement, i.e. check if there is an email before you send
if (currentEmail.trim() !== '')// check if email is not blank
MailApp.sendEmail(currentEmail, currentStudent, massageBody); // to change subject on email change "Has Homework Hour" Part//
}
Related
I have "to" in column A & "message/body" in column "B". I have a code which sends an email. However in my message I have a word hyperlinked to another sheet, while sending the email, the hyperlink is not considered. Please find the screenshot below.
However when the email is sent, the hyperlink is not visible. Please the image below
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 1;
var dataRange = sheet.getRange(startRow, 1, numRows, 2);
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
}
}
Use Templated HTML
var htmlBody = HtmlService.createTemplate('Email with <a href=<?=link?>> Some link </a>');
htmlBody.link = row[1];
MailApp.sendEmail({
to: row[0],
subject: 'Sending emails from a Spreadsheet',
htmlBody: htmlBody.evaluate().getContent()
});
If you have embedded cell links, you can extract them using Advanced Sheets services, as describe here, for example
var values = Sheets.Spreadsheets.get(SpreadsheetApp.getActive().getId(), {ranges: "Sheet1!B1:B10", fields: "sheets/data/rowData/values/hyperlink"})
var links = values.sheets[0].data[0].rowData.map(v => v.values[0].hyperlink);
them use them in templated HTML example I provided.
I am having trouble setting up a script to iterate through a Google spreadsheet and email to the employees the lines that contain the reports about them.
In my tests The email address and subject lines are being emailed but depending on what I try the email is either blank or says "[object Object]".
I am viewing emails from the Gmail site in Chrome.
The HTML code does not have any variables yet. I am still working on getting it to email correctly and then I will try working in scriplets to build a table for the report.
Code.gs
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail(employees[i][1], employees[i][0] + ' Scorecards Test', {htmlbody: html.getContent()});
Logger.log(html.getContent());
}
}
Index.html
<body>
<p1>Test 5062</p1>
<table>
<tr>
<td>Test Cell 1</td>
<td>Test Cell 2</td>
<td>Test Cell 3</td>
</tr>
</table>
</body>
When I view the log, it shows the HTML file.
What I am doing wrong?
How about a following modification?
From :
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail(employees[i][1], employees[i][0] + ' Scorecards Test', {htmlbody: html.getContent()});
Logger.log(html.getContent());
}
}
To :
function changeName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shA = ss.getSheets()[0]; // Report download
var shB = ss.getSheets()[1]; // Names & email address
var alRow = shA.getLastRow();
var blRow = shB.getLastRow();
var data = shA.getRange(1, 1, alRow, 14).getValues(); // Array of all employees reports
var employees = shB.getRange(1, 1, 2, 2).getValues(); // List of employees [i][0] and email address [i][1] in Scorecard data
for(i=0;i<employees.length;i++){
var html = HtmlService.createTemplateFromFile('Index').evaluate();
MailApp.sendEmail({
to: employees[i][1],
subject: employees[i][0] + ' Scorecards Test',
htmlBody: html.getContent()
});
Logger.log(html.getContent());
}
}
If this didn't work, I'm sorry.
I find it a lot easier to build the html right in the file like this:
var s='<table>';
s+='Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',data[i][0],data[i][1],data[i][2]);
s+='</table>'`;
MailApp.sendMail({to:emailAddress, subject: subj, htmlBody: s});
And keep in mind your html doesn't have to be complete.
Often I actually build the email this way and disable the sendEmail while I'm building it and just do this to view my results.
var ui=HtmlService.createHtmlOutput(s);
SpreadsheetApp.getUi().showModeLessDialog(ui,title);
And that way I can see what I'm doing while I built it without having to send emails. Some people use the logger but I like doing it this way.
And often people end up wanting to put some conditions on sending the email.
Email Address is not empty
Body is not empty
The email hasn't already been sent
You haven't exceeded your remaining daily quota
But hey everyone is different and you can choose to do it whatever way that makes you happy.
I have been trying to lookup username using activeuser. Only the first part works and the last part doesnt. My goal is to unhide the sheet based on the username of the active user (sheetname is based on username). Below is the code I am using.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Test getActiveUser/getEmail", functionName: "onTest"});
ss.addMenu("Rep Drowndown", menuEntries);
testGetEmail("onOpen");
}
function onTest() {
testGetEmail("menu function");
};
function testGetEmail(callerId) {
var userEmail = "";
var activeUser = Session.getActiveUser();
if (activeUser == null)
Browser.msgBox("Session.getActiveUser() returned null", "called by " + callerId, Browser.Buttons.OK);
else
userEmail = activeUser.getEmail();
if (userEmail == "")
Browser.msgBox("Your Email returned an empty string", "called by " + callerId, Browser.Buttons.OK);
else
var ss = SpreadsheetApp.getActiveSpreadsheet();
var lookup = Session.getActiveUser().getEmail();
var range = ss.getRange('$A$3:$B$8').getValues();
var lookupRange = [];
for (var i = 0; i < range.length; i++)
lookupRange.push(range[i][0]);
var index = lookupRange.indexOf(lookup);
if (index == -1) {
// implicit no-op
}
else {
var link = range[index][2]
var sheet = ss.getSheetByName(link);
sheet.showSheet();
};
}
You need to set up an installable trigger. This allows the script to run with authorization, whereas normally "onOpen()" is run as a Simple Trigger. Since Simple Triggers can't authorize as users, you'll never get an email address.
The simplest solution is to set testGetEmail() to be run on open. Do this within the Script Editor by choosing Resources > Current Project's Triggers in the menu. Then click "No triggers set up. Click here to add one now." Finally, set up your trigger:
Choose your function's name (testGetEmail) from the first dropdown under "Run."
Choose "From spreadsheet" in the second dropdown under "Events."
Choose "On Open" in the third dropdown.
Then test to be sure I didn't commit a typo :-)
A mail merge script that we use for 5 of our google docs stopped working last week - a similar thing happened a few weeks ago when DocsList became obsolete and I was able to fix it, but now it has stopped working again.
var docTemplate = "15kvC3M8b0Me3Vi3GwErQvG60BlTC0qAHMXrlc3Ocky8";
var docName = "RefundByCheck"
function onFormSubmit(e) {
var first_name = e.values[1];
var last_name = e.values[2];
var customer_email = e.values[3];
var brand = e.values[4];
var amount = e.values[5];
var purchase_date = e.values[6];
var customer_address = e.values[7];
var rep_name = e.values[8];
var order_number = e.values[9];
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName+'_'+order_number)
.getId();
var copyDoc = DocumentApp.openById(copyId);
var copyBody = copyDoc.getActiveSection();
copyBody.replaceText('keyFirst', first_name);
copyBody.replaceText('keyLast', last_name);
copyBody.replaceText('keyBrand', brand);
copyBody.replaceText('keyAmount', amount);
copyBody.replaceText('keyPurchaseDate', purchase_date);
copyBody.replaceText('keyAddress', customer_address);
copyBody.replaceText('keyRep', rep_name);
copyBody.replaceText('keyOrder', order_number);
var todaysDate = Utilities.formatDate(new Date(), "GMT", "MM/dd/yyyy");
copyBody.replaceText('keyTodaysDate', todaysDate);
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId);
var theblob = pdf.getBlob().getAs('application/pdf');
var folder = DriveApp.getFolderById('0B3nrCN8N5OBcRnlWaUlHZUxZNE0');
var movefile = folder.createFile(theblob);
DriveApp.removeFile(movefile);
var subject = "Text goes here" + order_number
var body = "Hello " + first_name + " " + last_name + "," + "<br /><br />"
+ "Text goes here" + "<br /><br />"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
+ "Text goes here"
var cc = "test#test.com";
MailApp.sendEmail(customer_email, subject, body, {htmlBody: body, attachments: pdf, cc: cc});
DriveApp.getFileById(copyId).setTrashed(true);
}
I have a feeling that Google updated something else and I need to change my code, but I'm not sure - I am pretty sure that it is something broken in this section due to the summary of failures notification I received: 5/25/15 8:59 AM onFormSubmit We're sorry, no servers are currently available. Please wait a bit and try again. (line 41, file "RefundByCheckCode")
var movefile = folder.createFile(theblob);
Any thoughts or suggestions?
This appears to be Issue 3206, "Sending mail with attachment of Drawing (as PDF) consistently fails". Visit that defect and star it for updates. There doesn't appear to be a new scenario in your script, but if you have any additional info that might help the Googler who is responsible for fixing this problem, you could add a comment to the issue tracker.
Since the problem seems to arise some time after a script has been running successfully, and is then persistent, I suggest duplicating your script, and decommissioning the original.
Edit: OP was able to get around the problem by deploying a replacement of their template file.
I made some modifications to a Google Script I found online, but not knowing how to script so well, I'm sure I'm missing something here.
My goal is to have all the information submitted through a Google Form to then be emailed to me or a group I'll create.
This script here does email me the info, but it's all added as a single line without even mentioning the questions.
I'm a total newb, but I'm sure this could be solved with some kind of command or event that I'm unaware of.
Take a look:
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First column of data to process
var numRow = 1; // Number of columns to process
var dataRange = sheet.getRange(startRow, 1, numRow, 10)
// 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 message1 = row[1,2,3,4,5];
var message2 = row[2];
var message3 = row[3];
var message4 = row[4];
var message5 = row[5];
var message6 = row[6];
var message7 = row[7];
var message8 = row[8];// Second column
var emailSent = row[10]
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "New Hire On The Way!";
MailApp.sendEmail("itgroup#mycompany.com",subject,message1+message2+message3+message4+message5+message6);
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
}
}
}
That whole "EMAIL_SENT" was my attempt at having the script not resend info that was already entered.
If there is a better way of doing this, I'd love to hear it.
Thank you so much!
You can set this function as a trigger for onFormSubmit in the response sheet.
Source: Get Google Forms data in an Email Messages
function SendGoogleForm(e) {
var email = Session.getActiveUser().getEmail();
var subject = "Google Docs Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var columns = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for ( var keys in columns )
message += columns[keys] + ' :: '+ e.namedValues[columns[keys]] + "\n\n";
MailApp.sendEmail(email, subject, message);
}
if your just wanting the email to have a little more structure you can just add html to the individual messages. Depending how crazy your want to get is up to you. Here is a simple change that you can try it should have a little more structure. Replace this with your if statement
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "New Hire On The Way!";
MailApp.sendEmail("itgroup#mycompany.com",subject,message1+"<br />"+"<br />"+"<br />"+message2+"<br />"+"<br />"+"<br />"+message3+"<br />"+"<br />"+"<br />"+message4+"<br />"+"<br />"+"<br />"+message5+"<br />"+"<br />"+"<br />"+message6+"<br />"+"<br />"+"<br />");
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
}
All I did here is add breaks between your messages. This should create some spaces. You can always go crazy with inline css and html. www.w3schools.com is always a great place to start for beginners. Good Luck and happy coding!