Generate PDF of a specific range [duplicate] - google-apps-script

I have a sheet that I would like to send a specific range (A1:O44) as a pdf document and leave out further information in other cells. Currently, it is all functioning to send these sheets and all is working fine, however, I cannot seem to get the script correct to limit it to a certain range in the sheet.
There are 2 tabs in the sheet and I would like both of those to be sent in one email as part of the same attachment (as is currently set up). The email is generated by clicking the submit button from the custom submit menu on the top:
https://docs.google.com/spreadsheets/d/1EFJKr9281PND_h8TXNeumaCXb8KWLJQw9Itn0i_AZmI/edit#gid=1494149448
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('SUBMIT')
.addItem('SUBMIT', 'menuItem1')
.addToUi();
}
function menuItem1() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
sendSheetToPdfwithA1MailAdress();
}
function sendSheetToPdfwithA1MailAdress(){ // this is the function to call
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("TEAM1"); // it will send sheet 0 which is the first sheet in the spreadsheet.
// if you change the number, change it also in the parameters below
var practiceName = sh.getRange('E2').getValue()
var startDate = sh.getRange('I4:L5').getValue();
var emailBody = sh.getRange('I45').getValue();
var staffName = sh.getRange('c43').getValue()
var shName = Utilities.formatString('%s %s',practiceName, startDate)
var message = "<HTML><BODY>"
+ "<P>Hi,"
+ "<br /><br />"
+ " Please find attached the payroll info for " + practiceName + " for the period " + startDate + "."
+ "<br /><br />"
+ "" + emailBody + "."
+ "<br /><br />"
+ " If you have any question please let me know"
+ "<br /><br />"
+ "Thanks, " + staffName + "."
+ "<br /><br />"
+ "</HTML></BODY>";
sendSpreadsheetToPdf(0, shName, sh.getRange('A46').getValue(),"Payroll Summary", " " + message + " ");
}
function sendSpreadsheetToPdf(sheetNumber, pdfName, email,subject, htmlbody) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("TEAM1");
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var sheetId = sheetNumber ? spreadsheet.getSheets()[sheetNumber].getSheetId() : null;
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var email2 = sh.getRange('A47').getValue();
var email3 = sh.getRange('A48').getValue();
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// following parameters are optional...
+ '&size=A4' // paper size
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=true&printtitle=false&pagenumbers=true' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody, email2:email2
}
MailApp.sendEmail(
email,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
email2,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
email3,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
}
}

Disclaimer: I don't believe the use of query parameters to control the PDF export is officially supported by Google, but this GitHub Gist from Spencer-Easton has the info you need to accomplish your goal.
The issue is in the query parameters stored in url_ext.
You must include the gid, which you can get from the sheet's URL from the sheet editor (/edit#gid=NUMBERS).
You need to add to url_ext:
gid=NUMBERS (look in URL to get numbers)
ir=false (unknown what it refers to)
ic=false (unknown what it refers to)
r1=0 (starting row, zero index)
c1=0 (starting col, zero index)
r2=43 (end row, note change of index)
c2=14 (end col, note change of index)
I added those and was able to email just the selected portions of the selected sheet.

Related

Emailing google sheets via PDF individually [duplicate]

I'm trying to use the script below to send the first sheets in a Google Sheets document to an email as PDF. The email to send to, is listed in cell A1.
However, this script send the entire spreadsheet as an PDF and not just the first sheet. I have been trying to use some of the other scripts from Stack Overflow, but this is the only one that actually sends an email.
/* Email Google Spreadsheet as PDF */
function emailGoogleSpreadsheetAsPDF() {
// Send the PDF of the spreadsheet to this email address
var email = "amit#labnol.org";
// Get the currently active spreadsheet URL (link)
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Subject of email message
var subject = "PDF generated from spreadsheet " + ss.getName();
// Email Body can be HTML too
var body = "Install the <a href='http://www.labnol.org/email-sheet'>Email Spreadsheet add-on</a> for one-click conversion.";
var blob = DriveApp.getFileById(ss.getId()).getAs("application/pdf");
blob.setName(ss.getName() + ".pdf");
// If allowed to send emails, send the email with the PDF attachment
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments:[blob]
});
}
below is a working version with a few useful parameters you may want to use.
UPDATED CODE
function sendSheetToPdfwithA1MailAdress(){ // this is the function to call
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheets()[0]; // it will send sheet 0 wich is the first sheet in the spreadsheet.
// if you change the number, change it also in the parameters below
var shName = sh.getName()
sendSpreadsheetToPdf(0, shName, sh.getRange('A1').getValue(),"test email with the adress in cell A1 ", "This is it !");
}
function sendSpreadsheetToPdf(sheetNumber, pdfName, email,subject, htmlbody) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var sheetId = sheetNumber ? spreadsheet.getSheets()[sheetNumber].getSheetId() : null;
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// following parameters are optional...
+ '&size=A4' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=true&printtitle=false&pagenumbers=true' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody
}
MailApp.sendEmail(
email,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
Session.getActiveUser().getEmail(),
"FRWD "+subject+" (" + pdfName +")",
"html content only",
mailOptions);
}
}
Excellent answer already accepted. I had a question about emailing just to a range and took the opportunity to add a few improvements from Serge's excellent answer above.
Mail range not whole sheet - apps script
/*
shNum = 0 for whole workbook or '0', or 0,1,2,etc for specific tab/sheet
shRng = A1 address for desired range, eg 'E1:L25', ignored if not a single sheet shNum
pdfName = text on top of pdf
*/
function mailPdf(shNum,shRng,pdfName,email,subject,htmlbody) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssId = ss.getId();
var shId = shNum ? ss.getSheets()[shNum].getSheetId() : null;
var url_base = ss.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (shId ? ('&gid=' + shId) : ('&id=' + ssId))
+ (shRng ? ('&range=E1:L25') : null)
+ '&format=pdf' //export format
+ '&size=letter' //A3/A4/A5/B4/B5/letter/tabloid/legal/statement/executive/folio
//+ '&portrait=false' //true= Potrait / false= Landscape
//+ '&scale=1' //1= Normal 100% / 2= Fit to width / 3= Fit to height / 4= Fit to Page
//+ '&top_margin=0.00' //All four margins must be set!
//+ '&bottom_margin=0.00' //All four margins must be set!
//+ '&left_margin=0.00' //All four margins must be set!
//+ '&right_margin=0.00' //All four margins must be set!
+ '&gridlines=false' //true/false
//+ '&printnotes=false' //true/false
//+ '&pageorder=2' //1= Down, then over / 2= Over, then down
//+ '&horizontal_alignment=CENTER' //LEFT/CENTER/RIGHT
+ '&vertical_alignment=TOP' //TOP/MIDDLE/BOTTOM
//+ '&printtitle=false' //true/false
//+ '&sheetnames=false' //true/false
//+ '&fzr=false' //true/false frozen rows
//+ '&fzc=false' //true/false frozen cols
//+ '&attachment=false' //true/false
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
'muteHttpExceptions': true
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody
}
MailApp.sendEmail(
// email + "," + Session.getActiveUser().getEmail() // use this to email self and others
email, // use this to only email users requested
subject+' (' + pdfName +')',
'html content only',
mailOptions);
}
}
Here I found an extremely simple way to send the spreadsheet by email as pdf
https://spreadsheet.dev/automatically-email-google-sheet-as-pdf-attachment
Problem: it is sending the whole document and I only want to send a particular sheet, the active one.
So I modified the original code from this
//===============
function sendReport() {
var message = {
to: "spreadsheetdevdemo#gmail.com",
subject: "Monthly sales report",
body: "Hi team,\n\nPlease find the monthly report attached.\n\nThank you,\nBob",
name: "Bob",
attachments: [SpreadsheetApp.getActiveSpreadsheet().getAs(MimeType.PDF).setName("Monthly sales report")]
}
MailApp.sendEmail(message);
}
//===============
To this
Note: I took some code from Google spreadsheet script export active sheet only to PDF
//===============
// Define your variables here
var recipient="your#email.com";
var subject=SpreadsheetApp.getActiveSpreadsheet().getName();
var body="Hello,\n\nPlease find attached the document.\n\nThank you,\nYOURNAME";
var nameOfSender="YOURNAME";
// End of the stuff you need to edit
// Below, the sheet is converted to pdf in a blob object and that object
// is sent by email with the email-parameters above.
// Other stuff
var ss = SpreadsheetApp.getActiveSpreadsheet();
//var ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//var sheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
//var sheetId = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
// Base URL
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ss.getId());
/* Specify PDF export parameters
From: https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579
*/
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=A4' // 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='; // the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext + sheet.getSheetId(), {
headers : {
'Authorization' : 'Bearer ' + token
}
}).getBlob().setName(sheet.getName() + ".pdf");
sheet_as_pdf_blob_document=response;
// Here we send the email
function sendReport() {
var message = {
to: recipient,
subject: subject,
body: body,
name: nameOfSender,
attachments: [sheet_as_pdf_blob_document]
}
MailApp.sendEmail(message);
}
//===============

Is there a way to force page breaks when exporting PDF?

I am using this script to automatically send a sheet to email in cell A1.
The problem is that when I print it manually, I have set page breaks.
When I export in the script, it does not respect the page breaks..
Is there a way to modify the script so that it will respect the custom page breaks that I have?
function sendSheetToPdfwithA1MailAdress(){ // this is the function to call
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheets()[3]; // it will send sheet 0 which is the first sheet in the spreadsheet.
// if you change the number, change it also in the parameters below
var shName = sh.getName()
sendSpreadsheetToPdf(3, shName, sh.getRange('A1').getValue(),"test email with the adress in cell A1 ", "This is it !");
}
function sendSpreadsheetToPdf(sheetNumber, pdfName, email,subject, htmlbody) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var sheetId = sheetNumber ? spreadsheet.getSheets()[3].getSheetId() : null;
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// following parameters are optional...
+ '&size=A4' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=true&printtitle=false&pagenumbers=true' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody
}
MailApp.sendEmail(
email,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
Session.getActiveUser().getEmail(),
"FRWD "+subject+" (" + pdfName +")",
"html content only",
mailOptions);
}
}

Using script to send one sheet in Google sheets not working

I am using this code: https://stackoverflow.com/a/45781391/13875010
I only want to send sheet #3 to the email address located in cell A1 on sheet three.
I run the script and nothing happens.
What am I doing wrong?
function sendSheetToPdfwithA1MailAdress(){ // this is the function to call
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheets()[3]; // it will send sheet 0 which is the first sheet in the spreadsheet.
// if you change the number, change it also in the parameters below
var shName = sh.getName()
sendSpreadsheetToPdf(3, shName, sh.getRange('A1').getValue(),"test email with the address in cell A1 ", "This is it !");
}
function sendSpreadsheetToPdf(sheetNumber, pdfName, email,subject, htmlbody) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var sheetId = sheetNumber ? spreadsheet.getSheets()[3].getSheetId() : null;
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// following parameters are optional...
+ '&size=A4' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=true&printtitle=false&pagenumbers=true' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody
}
MailApp.sendEmail(
email,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
Session.getActiveUser().getEmail(),
"FRWD "+subject+" (" + pdfName +")",
"html content only",
mailOptions);
}
}
I was using the wrong number...Sheet 3 is number 2.

How to include a specific range only in a pdf exported from a Google Sheets spreadsheet

I have a sheet that I would like to send a specific range (A1:O44) as a pdf document and leave out further information in other cells. Currently, it is all functioning to send these sheets and all is working fine, however, I cannot seem to get the script correct to limit it to a certain range in the sheet.
There are 2 tabs in the sheet and I would like both of those to be sent in one email as part of the same attachment (as is currently set up). The email is generated by clicking the submit button from the custom submit menu on the top:
https://docs.google.com/spreadsheets/d/1EFJKr9281PND_h8TXNeumaCXb8KWLJQw9Itn0i_AZmI/edit#gid=1494149448
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('SUBMIT')
.addItem('SUBMIT', 'menuItem1')
.addToUi();
}
function menuItem1() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
sendSheetToPdfwithA1MailAdress();
}
function sendSheetToPdfwithA1MailAdress(){ // this is the function to call
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("TEAM1"); // it will send sheet 0 which is the first sheet in the spreadsheet.
// if you change the number, change it also in the parameters below
var practiceName = sh.getRange('E2').getValue()
var startDate = sh.getRange('I4:L5').getValue();
var emailBody = sh.getRange('I45').getValue();
var staffName = sh.getRange('c43').getValue()
var shName = Utilities.formatString('%s %s',practiceName, startDate)
var message = "<HTML><BODY>"
+ "<P>Hi,"
+ "<br /><br />"
+ " Please find attached the payroll info for " + practiceName + " for the period " + startDate + "."
+ "<br /><br />"
+ "" + emailBody + "."
+ "<br /><br />"
+ " If you have any question please let me know"
+ "<br /><br />"
+ "Thanks, " + staffName + "."
+ "<br /><br />"
+ "</HTML></BODY>";
sendSpreadsheetToPdf(0, shName, sh.getRange('A46').getValue(),"Payroll Summary", " " + message + " ");
}
function sendSpreadsheetToPdf(sheetNumber, pdfName, email,subject, htmlbody) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("TEAM1");
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var sheetId = sheetNumber ? spreadsheet.getSheets()[sheetNumber].getSheetId() : null;
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var email2 = sh.getRange('A47').getValue();
var email3 = sh.getRange('A48').getValue();
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// following parameters are optional...
+ '&size=A4' // paper size
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=true&printtitle=false&pagenumbers=true' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var response = UrlFetchApp.fetch(url_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
if (email) {
var mailOptions = {
attachments:blob, htmlBody:htmlbody, email2:email2
}
MailApp.sendEmail(
email,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
email2,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
MailApp.sendEmail(
email3,
subject+" (" + pdfName +")",
"html content only",
mailOptions);
}
}
Disclaimer: I don't believe the use of query parameters to control the PDF export is officially supported by Google, but this GitHub Gist from Spencer-Easton has the info you need to accomplish your goal.
The issue is in the query parameters stored in url_ext.
You must include the gid, which you can get from the sheet's URL from the sheet editor (/edit#gid=NUMBERS).
You need to add to url_ext:
gid=NUMBERS (look in URL to get numbers)
ir=false (unknown what it refers to)
ic=false (unknown what it refers to)
r1=0 (starting row, zero index)
c1=0 (starting col, zero index)
r2=43 (end row, note change of index)
c2=14 (end col, note change of index)
I added those and was able to email just the selected portions of the selected sheet.

App Scripts - Spreadsheet to Gmail "Invalid Email <>" Error

I'm a teacher and new to AppScript. I have created a spreadsheet to automatically send feedback to students via gmail from a google spreadsheet. It does work and the emails get sent from the spreadsheet but I get the following error 'Invalid Email <>' on the spreadsheet.
If anybody could help it'd be much appreciated.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menu = [{
name: "Send Email",
functionName: "uiSendEmail"
}];
ss.addMenu("Send Email", menu);
}
function uiSendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
range = range.offset(1, 0, range.getNumRows()-1);
range.getValues().forEach( function( recipient, index, data ){
var msgHtml = "Hi " + recipient[0] + "," + "<p>" + "Atttitude to Learning Grade is: " + "<b><u>" + recipient[5] + "</b></u>" + "<p>" + "Feedback: " + recipient[6] + "<p>" + "Improvements to be made: " + recipient[7] + "<p>" + "Overall Grade: " + recipient[8];
var subject = recipient[3] + " - Teacher Feedback";
var msgPlain = msgHtml.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
GmailApp.sendEmail(recipient[0] + " " + recipient[1] + "<" + recipient[2] + ">", subject, msgPlain, { htmlBody: msgHtml });
});
}
This was from long ago, so I assume you figured something out... (I stumbled upon this trying to solve a related problem).
From your above code and the error, I can see the that the recipient array contains no data.