Constructing the name of a pdf export from multi-line cell entries causing problems - google-apps

I'm pretty new to scripting and have been learning by doing stuff (or more precisely finding generous people to do the stuff for me) so don't really know a lot. Apologies if the code is wrong, dumb or formatted incorrectly.
I have this code which should export a sheet in PDF format and name the export based on the strings in particular cells. This works well until you drop a multi-line cell entry into the mix. The code causing the trouble is below and the bit that is causing trouble is engine[0]:
function Generate_Form() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName('JobRequestForm'));
var tpjlr = ss.getRange("H8:I8").getValue();
if (tpjlr.length > 0) {
var email = "x#jaguarlandrover.com"
var email1 = ss.getRange("H5:I5").getValue() + ("#jaguarlandrover.com");
var email2 = ss.getRange("H6:I6").getValue() + ("#jaguarlandrover.com");
}
var subject = "Job request from " +ss.getRangeByName("D5:E5").getValue()+ "_" +ss.getRangeByName("D13:E13").getValue()+ "_" +ss.getRangeByName("D14:E14").getValue()+ "_TPJLR_" +ss.getRangeByName("H8:I8").getValue()+ "_" +ss.getRangeByName("D7:E7").getValue();
var body = "Objective of the request:- " + ss.getRange("D18:I18").getValue();
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ss.getId());
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true&source=labnol' // fit to page width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='+ss.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
var engine = ss.getRange("D15:E15").getValue().split("\n");
var name = ss.getRange("D13:E13").getValue() + "_" + ss.getRange("D14:E14").getValue() + "_" + engine[0] + "_" + engine[1] + "_" + "TPJLR_" + ss.getRange("H8:I8").getValue() + "_" + ss.getRange("D7:E7").getValue() + ".pdf";
var response = UrlFetchApp.fetch(url + url_ext, {
headers: {
'Authorization': 'Bearer ' + token
}
}).getBlob().setName(name);
// var blob = response.getBlob().setName(name);
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments:[response]
});

So I replaced
var engine = ss.getRange("D15:E15").getValue().split("\n");
var name = ss.getRange("D13:E13").getValue() + "_" + ss.getRange("D14:E14").getValue() + "_" + engine[0] + "_" + engine[1] + "_" + "TPJLR_" + ss.getRange("H8:I8").getValue() + "_" + ss.getRange("D7:E7").getValue() + ".pdf";
with
var input = ss.getRange("D15:E15").getValue();
var engine = input.replace(/(?:\r\n|\r|\n)/g, '_');
var name = ss.getRange("D13:E13").getValue() + "_" + ss.getRange("D14:E14").getValue()+ "_" + engine + "_" + "TPJLR_" + ss.getRange("H8:I8").getValue() + "_" + ss.getRange("D7:E7").getValue() + ".pdf";
Works now

Related

How to fix "Invalid email undefined" error in closing MailApp.sendemail step

For a new course project, I'm coming back to a google script for SendEmail from Google Sheets that worked perfectly a couple of years ago. (Original code from https://medium.com/#sebfung/custom-emails-from-a-spreadsheet-b11ff050bc5f ). Now I get three errors and can't figure out how to fix the third.
The full code is below. I've got limited code experience, but I figure I can work around the first two errors I get because they're cosmetic and my students can deal with it. (First, I can take out code to live without the "split" that used to let me drop off the second half of email addresses in the SendToName salutation. Second, I can take out the "replace" code that switches newline to paragraph breaks.)
But I can't figure out how to get around the third error. Something in the last command (MailApp.SendEmail) gives me a "Invalid email: undefined (line 66, file "Code")" error.
I don't see that any of these could be a spreadsheet-related error, since I went back to the earlier spreadsheets that worked a couple years ago and the debug now brings up the same three errors.
I'd be happy for suggestions on the first two, but I really most need and value help with that third error. I can't even run or test anything unless I fix it. Thanks!
function sendEmail(to, score, questions, answer1, answer2, answer3, answer4, answer5) {
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getActiveRange();
var numRows = range.getNumRows();
var values = range.getValues();
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
var to = row[1];
var score = row[2];
var questions = row[3]
var answer1 = row[4];
var answer2 = row[5];
var answer3 = row[6];
var answer4 = row[7];
var answer5 = row[8];
var sendToName = to.split('#')[0];
// email content
var emailSubject = "Quiz 1 Response";
// plain text body - just in case receiver can't parse html formatted email
var plainTxtBody = "Hello " + sendToName + ",\n" +
"You scored:\n" + score + "\n" +
"The questions were:\n" + questions + "\n" +
"Your answer:\n" + answer1 + "\n" +
"Your answer:\n" + answer2 + "\n" +
"Your answer:\n" + answer3 + "\n" +
"Your answer:\n" + answer4 + "\n" +
"Your answer:\n" + answer5;
// html formatting isn't necessary, but nice for reading :)
var htmlBody = '<html><body>';
var htmlFooter = '</body></html>';
// replacing newline characters with paragraph breaks to make it more readable
var scoreHTML = score.replace(/\n/g, "</p><p>");
var questionsHTML = questions.replace(/\n/g, "</p><p>");
var answer1HTML = answer1.replace(/\n/g, "</p><p>");
var answer2HTML = answer2.replace(/\n/g, "</p><p>");
var answer3HTML = answer3.replace(/\n/g, "</p><p>");
var answer4HTML = answer4.replace(/\n/g, "</p><p>");
var answer5HTML = answer5.replace(/\n/g, "</p><p>");
var emailMessage = "<p>Hello " + sendToName + ",</p>" +
"<p><strong>You scored:</strong><p>" +
"<p>" + scoreHTML + "</p>" +
"<hr>" +
"<p><strong>Here are the questions--see the answer key on the Quiz 1 page on the wiki:</strong></p>" +
"<p>" + questionsHTML + "</p>" +
"<hr>" +
"<p><strong>Here are your answers:</strong></p>" +
"<p>" + answer1HTML + "</p>" +
"<p>" + answer2HTML + "</p>" +
"<p>" + answer3HTML + "</p>" +
"<p>" + answer4HTML + "</p>" +
"<p>" + answer5HTML + "</p>";
htmlBody += emailMessage + htmlFooter;
// GmailApp must have default recipient, subject, body attributes followed by jsobject options {}
// Differs from MailApp syntax but has more options -- see documentation on GmailApp
MailApp.sendEmail(to, emailSubject, plainTxtBody, {
htmlBody: htmlBody,
});
}
}
The script does work. Var "to" probably doesn't contain a valid email adres. Make sure you have selected an active range in your spreadsheet. Please also note the first item in an array has index 0. Which reflects to the first column in your selection.
You can set a break point and use the debugger or use Logger.log(to); View -> Logs will show the outcome of var to.

Condition to skip data is not working as intended

Hi everyone I copied this from a previous post and matched it up to my needs. I'm having trouble preventing it from sending the entire list when the word Sent is in column 10. I've messed with the coding more than I would like to at this point and feel it's getting messy.
Can someone take a look at it and see what is missing?
It will send the email and do everything I need, but so far it just sends all the lines of data regardless if Sent is in the column or not.
function sendEmails2() {
//setup function
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var StartRow = 2;
var RowRange = ActiveSheet.getLastRow() - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,11);
var AllValues = WholeRange.getValues();
var message = "";
//iterate loop
for (i in AllValues) {
//set current row
var CurrentRow = AllValues[i];
//define column to check if sent
var EmailSent = CurrentRow[10];
//if row has been sent, then continue to next iteration
if (EmailSent == "sent")
continue;
//set HTML template for information
message +=
"<p><b>Sales Rep: </b>" + CurrentRow[0] + "</p>" +
"<p><b>Case ID: </b>" + CurrentRow[1] + "</p>" +
"<p><b>Name: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Signing Date: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Draft Date: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Sign to Draft: </b>" + CurrentRow[5] + "</p>" +
"<p><b>Enrolled Debt: </b>" + CurrentRow[6] + "</p><br><br>";
//set the row to look at
var setRow = parseInt(i) + StartRow;
//mark row as "sent"
ActiveSheet.getRange(setRow, 10).setValue("sent");
}
//define who to send email to
var SendTo = "my email address" + "," + "";
//set subject line
var Subject = "NEW DEAL CLOSED";
//send the actual email
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
}
mistake is there in var EmailSent = CurrentRow[10] where the column being considered actually in 11. When taking the whole data range from sheet, the column index starts from 0 and so the actual index to be taken should be 9 for 10th column
//define column to check if sent
var EmailSent = CurrentRow[9];

How to send data from spreadsheet by email using google scripts

I'm making an online registration with google forms. Once a person submits, an email will be sent to the email they entered. The data is the things they entered in the form. So this email serves as a data confirmation email. The problem now is, the test i did was successful but, the emails contained aaalll of the data. My question would be, how to email the data from a specific row for a specific email
here's what i did (copied from someone)
function sendEmail() {
//setup function
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var StartRow = 3;
var RowRange = ActiveSheet.getLastRow() - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,11);
var AllValues = WholeRange.getValues();
var message = "";
//iterate loop
for (i in AllValues) {
//set current row
var CurrentRow = AllValues[i];
//define column to check if sent
var EmailSent = CurrentRow[11];
//if row has been sent, then continue to next iteration
if (EmailSent == "sent")
continue;
//set HTML template for information
message +=
"<p><b>Found by: </b>" + CurrentRow[1] + "</p>" +
"<p><b>Title: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Agency: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Summary: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Due: </b>" + CurrentRow[5] + "</p>" +
"<p><b>Posted: </b>" + CurrentRow[6] + "</p>" +
"<p><b>Total Funding: </b>" + CurrentRow[7] + "</p>" +
"<p><b>Announcement Number: </b>" + CurrentRow[8] + "</p>" +
"<p><b>Useful Links: </b>" + CurrentRow[9] + "</p><br><br>";
//set the row to look at
var setRow = parseInt(i) + StartRow;
//mark row as "sent"
ActiveSheet.getRange(setRow, 11).setValue("sent");
}
//define who to send grants to
var SendTo = "emailaddress1#gmail.com" + "," + "emailaddress2#gmail.com";
//set subject line
var Subject = "Grants";
//send the actual email
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
}
I answered a similar question about this recently. It's always easier for me to break down the problem into the parts we need. In this case, we need: All the responses, then we need to match a response
The best way is to first read the form responses as an array:
function formResponsesToArray() {
var app = FormApp.openById(...),
responses = app.getResponses(), stringResponses = []
responses.forEach(function(r) {
var response = []
r.getItemResponses().forEach(function(i) {
response.push(i.getResponse())
})
stringResponses.push(response)
})
Logger.log(stringResponses)
}
If you know the persons email, then we can get their response like this, assuming the email is the first thing they enter in to the form:
var theirEmail = "hello#hello.com"
var theirResponse = stringResponses.filter(function(response) {
return response[0] === theirEmail
})
Then you can use theirResponse to get the information they entered in to the form!
The code you shared basically gathers all the rows data where a email status field has no "sent" value and composes a single message at the end and sends it.
According to your condition, you need to send a different mail for every row where email status field has no "sent" value.
I have added the mailApp syntax inside the loop only to send different mails and done some changes with message variables.
function sendEmail() {
//setup function
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var StartRow = 3;
var RowRange = ActiveSheet.getLastRow() - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,11);
var AllValues = WholeRange.getValues();
//iterate loop
for (i in AllValues) {
//set current row
var CurrentRow = AllValues[i];
//define column to check if sent
var EmailSent = CurrentRow[11];
//if row has been sent, then continue to next iteration
if (EmailSent == "sent")
continue;
//set HTML template for information
//here i have removed the "+" sign to create a new message for its respective row
var message=
"<p><b>Found by: </b>" + CurrentRow[1] + "</p>" +
"<p><b>Title: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Agency: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Summary: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Due: </b>" + CurrentRow[5] + "</p>" +
"<p><b>Posted: </b>" + CurrentRow[6] + "</p>" +
"<p><b>Total Funding: </b>" + CurrentRow[7] + "</p>" +
"<p><b>Announcement Number: </b>" + CurrentRow[8] + "</p>" +
"<p><b>Useful Links: </b>" + CurrentRow[9] + "</p><br><br>";
//here you can add the email address field to whom you want to send emails.
//e.g. var SendTo=CurrentRow[1];
//define who to send grants to
var SendTo = "emailaddress1#gmail.com" + "," + "emailaddress2#gmail.com";
//set subject line
var Subject = "Grants";
//send the actual email
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
//set the row to look at
var setRow = parseInt(i) + StartRow;
//mark row as "sent"
ActiveSheet.getRange(setRow, 11).setValue("sent");
}
}
Hope this helps, Thanks

Problems with email notification

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!

Adding paragraphs to automated email

I have created a script that automatically sends out emails that pulls information from several cells and populates the body of the email with the information alongside a standard body of the text.
However I can't work out a way to script in a paragraph space between the lines. I have done a workaround of creating a variable with the value of a cell that is just a paragraph space but, as other people will be using this spreadsheet, I am worried that the cell will get deleted and the formatting will change.
Is there another way to format paragraphs into the body of the email?
See my code below if that helps! The variable I need to format is "Var Message"
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = 99;
var dataRange = sheet.getRange(startRow, 1, numRows, 16)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var EMAIL_SENT = "Contacted";
var currentdate = Utilities.formatDate(sheet.getRange("n2").getValue(), "GMT" , "dd/MM/yyyy" );
var staffmember = sheet.getRange("o2").getValue();
var paragraph = sheet.getRange("f2").getValue();
var row = data[i];
var emailAddress = row[0];
var name = row[1];
var company = row[2];
var website = row[3];
var role = row[4];
var show = row[9];
var date = Utilities.formatDate(row[15], "GMT" , "dd/MM/yyyy" );
var date2 = Utilities.formatDate(row[15], "GMT" , "dd/MM" );
var time = Utilities.formatDate(row[11], "GMT" , "HH:mm" );
var message = "Hello," + paragraph + "Could you please authorise or decline the following Arts Industry comp request from the Fringe Office? If you could reply within 72 hours, that would be great:" + paragraph + name + " " + company + " " + website + " " + role + paragraph + show + " " + date + " " + time + paragraph + "Many thanks," + paragraph + staffmember ;
var subject = "ARTS INDUSTRY REQUEST";
var emailSent = row[12];
if (emailSent != EMAIL_SENT) {
if (date > currentdate) {
var subject = "ARTS INDUSTRY REQUEST";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 13).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
else if (emailSent != EMAIL_SENT) {
if (date < currentdate) {
var subject2 = "URGENT: ARTS INDUSTRY REQUEST" + " " + date2;
MailApp.sendEmail(emailAddress, subject2, message);
sheet.getRange(startRow + i, 13).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
}
}
For plaintext emails, you can use the "newline" escape sequence \n.
If you have K&R "C - The Programming Language", you'll find a full list of escape sequences in chapter 2. An online reference is available here.
var message = "Hello,\n"
+ "Could you please authorise or decline the following Arts Industry comp request from the Fringe Office? If you could reply within 72 hours, that would be great:\n\n"
+ name + " " + company + " " + website + " " + role
+ '\n' + show + " " + date + " " + time
+ '\n\n'
+ "Many thanks,"
+ '\n\n'
+ staffmember ;
You can use the advanced options of MailApp.sendEmail() function to achieve paragraph and line breaks more efficiently. Here is an example
var content = "Here is some text <br> " +
"that is split over two lines" ;
MailApp.sendEmail(recipient, subject, '',{'htmlBody' : content } );