experts!
I'm faced with a question that has no answer, so I'm reaching out for help. Thanks in advance to anybody that can make sense of this.
I made a script (triggered weekly) that converts a Google sheet into a pdf, then attaches it to an email and sends it off. It's been working fine for months, now suddenly won't save or run. I'm getting the error "Invalid argument: fileName (line 80, file "Code")" (The "GmailApp.sendEmail" line is line 80.) As expected, the web didn't shed much light on why this is happening, or how to fix it.
Any ideas to throw my way?
Here is the relevant code. (GAS is flagging the "GmailApp.sendEmail" line as an error.)
// Sets the recipient(s) of the email message
var emailAddress1 = srcSheet1.getRange('J299').getValue();
// Sets the subject of the email message
var emailSubject1 = srcSheet1.getRange('C12').getValue();
// Sets the 'body message' of the email message
var emailBodyMessage1 = srcSheet1.getRange('C54').getValue();
// This section converts the new sheet into a pdf blob
// Make the pdf
var blob1 = DriveApp.getFileById(srcSpreadsheet1.getId()).getAs("application/pdf");
// Set the title of the pdf
var PDFsubject1 = srcSheet1.getRange('C54').getValue() + ".pdf";
blob1.setName(PDFsubject1);
// This section assembles and sends the email
GmailApp.sendEmail(emailAddress1,emailSubject1,emailBodyMessage1, {
htmlBody: emailBodyMessage1,
attachments:[blob1]
});
var emailBodyMessage1 = srcSheet1.getRange('C54').getValue();
var PDFsubject1 = srcSheet1.getRange('C54').getValue() + ".pdf";
There is something wrong with the cell 'C54'. You're getting a body of the message and a file name from this cell. And at some point the content of the cells was changed into something that can't be a file name. Perhaps the cell now contains line breaks or tab symbols and the like.
This is an example that works perfectly
function myFunction() {
var myEmail = 'xxxxxx#gmail.com'
var blob1 = DriveApp.getFileById('1IsP2bETUE-d2RZakxbkuASSCZYdSaUCk3uAFstFdIWM').getAs("application/pdf")
blob1.setName('test pdf file');
GmailApp.sendEmail(myEmail, 'test pdf', 'test', {
htmlBody: '<b>test</b>',
attachments: [blob1]
});
}
I recommand to check any individual term in your script :
Logger.log(srcSpreadsheet1.getId())
Logger.log(emailAddress1)
Logger.log(emailSubject1)
Logger.log(emailBodyMessage1)
Related
I have quite a long email template I want to automatically send to welcome new users.
The script copies the body of a Google Doc and uses that as the body of the email using MailApp.sendEmail.
The issue is that the email that arrives is very narrow and doesn't copy exactly what is in the template. Is there any way of formatting this to make it the same as the Google Doc template?
Any help much appreciated
var doc = DocumentApp.openByUrl("https://docs.google.com/document/d/"doc id"/edit");
var body = doc.getBody().getText();
var message = body;
var subject = "subject line";
MailApp.sendEmail (user.primaryEmail, subject, message)
I learned something new with this:
When you send an email as a plain text email it won't let you control where the line breaks are
It actually adds line breaks when you call the .getText() method, as well as part of the .sendEmail method when you are sending it just as plain text.
The easiest solution is to send it as an HTML message. I experimented with this and have what I believe the easiest solution for it below:
//this will replace the line breaks with html line breaks
var htmlBody = doc.getBody().getText().replace(/\n/g,'<br/>');
var message =
{
to: user.primaryEmail,
subject: 'subject line',
htmlBody: htmlBody
}
MailApp.sendEmail ({message})
I've tested this and this should fix your problem.
I use the following Google Script Code to generate a pdf of a google sheet and send it through email. The code works fine except that the generated pdf includes too many blank pages. How can I limit the generated pdf to only the sheet rows that contain data?
function emailReport() {
readyForExport();
var spreadsheet = SpreadsheetApp.getActive();
var subject = spreadsheet.getRange("U1:U1").getValues();
var emailTo = spreadsheet.getRange("V1:V1").getValues();
var message = spreadsheet.getRange("W1:W1").getValues();
var fileName = spreadsheet.getRange("X1:X1").getValues();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName("Students"));
var pdf = DriveApp.getFileById(spreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:fileName[0][0],content:pdf, mimeType:'application/pdf'};
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
};
Thanks in advance.
I finally managed to write a code that can successfully remove the empty pages of my pdf attachment by first removing the empty rows from the sheet. :)
I intentionally wrote the code in a way to leave just a single empty row at the end to make it clear to the user that no other data exists in the succeeding rows.
I had to solve a number of bugs because the code ran into errors depending on the number of empty rows that already existed on the page. Finally I managed to deal with all the bugs and come up with a code than runs sleekly and considers all the exceptional cases. :)))
Here is the code:
var firstDelRow = spreadsheet.getSheetByName('Students').getLastRow()+2;
var lastDelRow = spreadsheet.getSheetByName('Students').getMaxRows();
var rowDif = lastDelRow-firstDelRow+1;
if (rowDif == -1) {
spreadsheet.getSheetByName('Students').insertRowAfter(firstDelRow-2);
};
if (rowDif >= 1) {
spreadsheet.getSheetByName('Students').deleteRows(firstDelRow, rowDif);
};
The following code isn't working, giving the following error:
TypeError: Cannot find function getFileByID in object Drive.
I'm trying to first test by directly providing ID in the script:
var atta = DriveApp.getFileByID('1XD...c'); //ID is Folder and Google Doc ID I want to attach
MailApp.sendEmail(emailto, subject, message, {
cc: emailcc,
attachments:[atta]
});
Ultimately, I want to read in the link from a Google Spreadsheet:
var range = active_actions.getRange(i+1,16) //active_actions is the spreadsheet and i+1,16 is the cell with the link
var link = range.getFormula();
var atta = DriveApp.getFileByID(link);
MailApp.sendEmail(emailto, subject, message, {
cc: emailcc,
attachments:[atta]
});
This isn't too difficult. Google Docs/Spreadsheets/etc. CANNOT be placed as an attachment in an E-mail. This is because it isn't actually a 'physical document'. It only exists on the cloud. Instead, put the URL in the email, and it will give the receiver a little box at the bottom with the Doc looking like an attachment.
It's not perfect, but it is good enough. For more details, you can see this issue request or Google's App Script Issue page:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=585&q=attachment%20types&sort=-stars&colspec=Stars%20Opened%20ID%20Type%20Status%20Summary%20Component%20Owner
EDIT (To explain data fetching in SS):
To get data out of a range object, (text, number, etc.), you should use this format.
var range = getRange();
var rangeData;
var cellValue;
while (range.hasNext()) {
rangeData = range.next();
cellValue = rangeData.getValue();
}
If you an accumulator variable, you can get every bit of data in one list/string/etc.
Now that you have your data, you can E-mail it, or do anything else with it.
I have looked at other similar posts and got some help with setting up trigger correctly but still have an error.
I have tried to automate sending a pdf doc to be emailed in response to a form submission in google apps. I used a script shared on web to get started and have fixed some deprecated terms.
I created a document template with keyItems embedded as placeholders and I created a form to capture data. The spreadsheet associated with the form is capturing data as planned. I edited the script associated with the spreadsheet to hopefully do the work required on submission of the form. The trigger looks correctly set up to run on form submit from the spreadsheet. My question is about the error I get repeatedly regarding the e.values being undefined. I assumed that I would be labelling these as e.values[0] and onwards when I declared the variables - i.e. they would be based on their order in the array drawn from the spreadsheet fields. Sorry to be long winded. If i place dummy content in the variables it works and sends the pdf so the actual mechanism works ok but my e.values are not working.
Here is my script
// Certificate of Completion
// Get template from Google Docs and name it
var docTemplate = "1V_PqCBZ9vWmmIELp47X12iNtdwRCqHyOyey6VPL0o0Q";
var docName = "CertificateOfCompletion";
//When form submitted get info from form and set as variables
function onFormSubmit(e) {
var name = e.values[2];
var email = e.values[3];
var date = e.values[4];
//make temporary working copy of template doc for the submitter
var copyId = DriveApp.getFileById(docTemplate).makeCopy(docName+' for '+name).getId();
//open the temporary doc
var copyDoc = DocumentApp.openById(copyId);
// tell script to go into the doc
var copyBody = copyDoc.getBody();
//replace placeholders in the doc with data from a submitted form
copyBody.replaceText('keyFullName', name);
copyBody.replaceText('keyDate', date);
copyDoc.saveAndClose();
//create PDf
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
//send email to recipient
var subject = "Certificate";
var body = "Congratulations!" + name + " Here is your certificate of completion " ;
MailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: pdf});
//delete temporary document
DriveApp.getFileById(copyId).setTrashed(true); }
Have you tried using named values instead.
Heres an example
var handling = Number(e.namedValues["Call Handling"]);
var security = Number(e.namedValues["Security"]);
var agentName = String(e.namedValues["Agent Name"]);
These are questions in a form I have. The bit after the e.namedValues["text here"]); , replace text here with whatever your column is called in form responses, this will be the question name.
I'm not sure why e.values[0] onwards isn't working for you as it works for me.
My script is in the spreadsheet, with an onFormSubmit trigger installed via the menu.
Also bear in mind, to test your script, you must sumbit a form, hitting the play button won't work as there is no event to pass to your function.
I'm trying to make a google form of mine send me the contents of the form via email each time someone fills out the form. I'm using the instructions below, and I've followed them exactly. For some reason, however, when I fill out a form, I get an error saying "TypeError: Cannot call method "getRange" of null. (line 7, file "Code")"
I look at the line of code right above it, in which "s" is defined and I'm thinking that the problem is that getActiveSpreadsheet is not working for some reason. I think that maybe the script can't find the active sheet. Below is the code snippet which is causing the problem, according to the error email I get from google.
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
Whole piece of code I'm using;
function sendFormByEmail(e)
{
// Remember to replace this email address with your own email address
var email = "support#itjones.com";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
var subject = "Jones IT - New User Form";
// The variable e holds all the form values in an array.
// Loop through the array and append values to the body.
for(var i in headers)
message += headers[i] + ': '+ e.namedValues[headers[i]].toString() + "\n\n";
// Insert variables from the spreadsheet into the subject.
// In this case, I wanted the new hire's name and start date as part of the
// email subject. These are the 3rd and 16th columns in my form.
// This creates an email subject like "New Hire: Jane Doe - starts 4/23/2013"
subject += e.namedValues[headers[1]].toString() + " - starts " + e.namedValues[headers[2]].toString();
// Send the email
MailApp.sendEmail(email, subject, message);
}
Ok, thank you, that makes sense but when I changed my code to use that code snippet I get this error.
2/12/15 4:56 PM sendFormByEmail TypeError: Cannot call method "getRange" of
null. (line 9, file "Code") formSubmit 2/12/15 4:56 PM
Line 9 is the line with the function call for sheet.getRange().
var s = SpreadsheetApp.openById('1WYhDQct8vF-3rlca9dP6lYC2Z23vLLofwJt_DpQU--c');
var sheet = s.getSheetByName('Jones IT - New User Form (Responses)');
var headers = sheet.getRange(1,1,1,s.getLastColumn()).getValues()[0];
Is there any way you recommend me changing my code to get the desired result. I don't really care what I have to change, I just want it to email me the contents of the forms when submitted.
The reason you are getting the error, is because the code is being run from a script project bound to the form, and not a spreadsheet. The script bound to the form has no connection to the spreadsheet. It can't find the active sheet. There is no active sheet associated with the form. The form is associated with the spreadsheet as far as where to submit the data, but not in terms of the code. You can set a trigger in the spreadsheet to run when the form is submitted, but you might want to get the spreadsheet by ID.
function test() {
var s = SpreadsheetApp.openById('your SS ID');
var sheet = s.getSheetByName('your sheet name');
var headers = sheet.getRange(1,1,1,s.getLastColumn()).getValues()[0];
};