Generate and Email PDF From a Range of Cells in Google Sheets - google-apps-script

This is my first time posting a question and I'm a complete novice so I apologize upfront if I don't include all the information you may need.
I have a Google Sheet that contains several tabs of data that is hand-keyed into a table. For eg:
Data Entry Table in Sheet
Within each sheet, there are numerous tables where the data from each "company" is entered that falls within a specific region.
What I'm trying to do is adjust a script that will go to the sheet specified, grab a range of cells for a specific table, convert it to a PDF and email it using the email address listed in another tab of the same sheet. I have searched online and found the following script:
function emailSpreadsheetAsPDF() {
DocumentApp.getActiveDocument();
DriveApp.getFiles();
// This is the link to my spreadsheet with the Form responses and the Invoice Template sheets
// Add the link to your spreadsheet here
// or you can just replace the text in the link between "d/" and "/edit"
// In my case is the text: 17I8-QDce0Nug7amrZeYTB3IYbGCGxvUj-XMt8uUUyvI
const ss = SpreadsheetApp.openByUrl("SHEETURLGOESHERE/edit");
// We are going to get the email address from the cell "B7" from the "Invoice" sheet
// Change the reference of the cell or the name of the sheet if it is different
const value = ss.getSheetByName("emails").getRange("A2").getValue();
const email = value.toString();
// Subject of the email message
const subject = ss.getSheetByName("emails").getRange("B2").getValue();
// Email Text. You can add HTML code here - see ctrlq.org/html-mail
const body = "Sent via Generate Invoice from Google Form and print/email it";
// Again, the URL to your spreadsheet but now with "/export" at the end
// Change it to the link of your spreadsheet, but leave the "/export"
const url = 'SHEETURLGOESHERE/export?';
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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=879200050' // the sheet's Id. Change it to your sheet ID.
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20';
// You can find the sheet ID in the link bar.
// Select the sheet that you want to print and check the link,
// the gid number of the sheet is on the end of your link.
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
// Generate the PDF file
var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();
// Send the PDF file as an attachement
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments: [{
fileName: ss.getSheetByName("emails").getRange("B2").getValue() + ".pdf",
content: response.getBytes(),
mimeType: "application/pdf"
}]
});
// Save the PDF to Drive. The name of the PDF is going to be the name of the Company (cell B5)
const nameFile = ss.getSheetByName("01_Allegany_R3").getRange("A52").getValue().toString() +".pdf"
DriveApp.createFile(response.setName(nameFile));
}
While the above code does create the PDF and email it, it's not generating the PDF from the range I enter here:
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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=879200050' // the sheet's Id. Change it to your sheet ID.
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20';
If anyone is able to provide some help to me, I'd greatly appreciate it but I am a novice and not familiar with writing scripts so please be patient, if possible :)
Thank you

You need to put the gid parameter at the end of the export options:
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20'+
'&gid=879200050'; // the sheet's Id. Change it to your sheet ID.

Related

Fixing TypeError "range.getAs is not a function" with Apps Script's blob [duplicate]

This is my first time posting a question and I'm a complete novice so I apologize upfront if I don't include all the information you may need.
I have a Google Sheet that contains several tabs of data that is hand-keyed into a table. For eg:
Data Entry Table in Sheet
Within each sheet, there are numerous tables where the data from each "company" is entered that falls within a specific region.
What I'm trying to do is adjust a script that will go to the sheet specified, grab a range of cells for a specific table, convert it to a PDF and email it using the email address listed in another tab of the same sheet. I have searched online and found the following script:
function emailSpreadsheetAsPDF() {
DocumentApp.getActiveDocument();
DriveApp.getFiles();
// This is the link to my spreadsheet with the Form responses and the Invoice Template sheets
// Add the link to your spreadsheet here
// or you can just replace the text in the link between "d/" and "/edit"
// In my case is the text: 17I8-QDce0Nug7amrZeYTB3IYbGCGxvUj-XMt8uUUyvI
const ss = SpreadsheetApp.openByUrl("SHEETURLGOESHERE/edit");
// We are going to get the email address from the cell "B7" from the "Invoice" sheet
// Change the reference of the cell or the name of the sheet if it is different
const value = ss.getSheetByName("emails").getRange("A2").getValue();
const email = value.toString();
// Subject of the email message
const subject = ss.getSheetByName("emails").getRange("B2").getValue();
// Email Text. You can add HTML code here - see ctrlq.org/html-mail
const body = "Sent via Generate Invoice from Google Form and print/email it";
// Again, the URL to your spreadsheet but now with "/export" at the end
// Change it to the link of your spreadsheet, but leave the "/export"
const url = 'SHEETURLGOESHERE/export?';
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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=879200050' // the sheet's Id. Change it to your sheet ID.
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20';
// You can find the sheet ID in the link bar.
// Select the sheet that you want to print and check the link,
// the gid number of the sheet is on the end of your link.
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
// Generate the PDF file
var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();
// Send the PDF file as an attachement
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments: [{
fileName: ss.getSheetByName("emails").getRange("B2").getValue() + ".pdf",
content: response.getBytes(),
mimeType: "application/pdf"
}]
});
// Save the PDF to Drive. The name of the PDF is going to be the name of the Company (cell B5)
const nameFile = ss.getSheetByName("01_Allegany_R3").getRange("A52").getValue().toString() +".pdf"
DriveApp.createFile(response.setName(nameFile));
}
While the above code does create the PDF and email it, it's not generating the PDF from the range I enter here:
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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=879200050' // the sheet's Id. Change it to your sheet ID.
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20';
If anyone is able to provide some help to me, I'd greatly appreciate it but I am a novice and not familiar with writing scripts so please be patient, if possible :)
Thank you
You need to put the gid parameter at the end of the export options:
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=letter' + // paper size letter / You can use A4 or legal
'&landscape=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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
'&if=false' +
'&ic=false' +
'&r1=51' +
'&c1=0' +
'&r2=102' +
'&c2=20'+
'&gid=879200050'; // the sheet's Id. Change it to your sheet ID.

Script download google spreadsheet to pdf - images missing

Is there any way to include overgrid images in the spreadsheet when downloading as PDF with the script provided by #ZektorH on the question Script to download a range of cells in google sheet as PDF to local computer and other automation scripts? ? I've been trying for a while now with no success.
Script in question:
function downloadRangeToPdf() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:E20");
//Create temporary Spreadsheet
var tempSpreadsheet = SpreadsheetApp.create("tempSheetInvoiceExport", range.getValues().length, range.getValues()[0].length);
var tempSheet = tempSpreadsheet.getSheets()[0];
var tempRange = tempSheet.getRange("A1:E20");
tempRange.setValues(range.getDisplayValues());
tempRange.setTextStyles(range.getTextStyles());
tempRange.setBackgrounds(range.getBackgrounds());
tempRange.setFontColors(range.getFontColors());
tempRange.setFontFamilies(range.getFontFamilies());
tempRange.setFontLines(range.getFontLines());
tempRange.setFontStyles(range.getFontStyles());
tempRange.setFontWeights(range.getFontWeights());
tempRange.setHorizontalAlignments(range.getHorizontalAlignments());
tempRange.setNumberFormats(range.getNumberFormats());
tempRange.setTextDirections(range.getTextDirections());
tempRange.setTextRotations(range.getTextRotations());
tempRange.setVerticalAlignments(range.getVerticalAlignments());
tempRange.setWrapStrategies(range.getWrapStrategies());
SpreadsheetApp.flush(); //Force changes to be written before proceeding.
//Generate Download As PDF Link
var url = 'https://docs.google.com/spreadsheets/d/{ID}/export?'.replace('{ID}', tempSpreadsheet.getId());
var exportOptions = '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
'&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
'&gid=' + tempSheet.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url + exportOptions, {
headers: {
Authorization: 'Bearer '+token
}
}).getBlob().setName(tempSpreadsheet.getName()+".pdf");
var pdfFile = DriveApp.createFile(blob);
var downloadLink = HtmlService
.createHtmlOutput('<p>Download your file here.</p>')
.setWidth(200)
.setHeight(100);
SpreadsheetApp.getUi().showModalDialog(downloadLink, "Download PDF");
DriveApp.getFileById(tempSpreadsheet.getId()).setTrashed(true); //Place temporary sheet on trash
}
The reason why the image was not included in your pdf file is because you did not copy the image available in your source sheet to your temporary sheet. You only copied the cell values in this line tempRange.setValues(range.getDisplayValues());
You can actually export a range to pdf just by adding this option &range=<SheetRange>
Sample Code:
function downloadRangeToPdf() {
var sheet = SpreadsheetApp.getActiveSheet();
var pdfRange = "A1:H50"
//Generate Download As PDF Link
var url = 'https://docs.google.com/spreadsheets/d/{ID}/export?'.replace('{ID}', SpreadsheetApp.getActiveSpreadsheet().getId());
var exportOptions = '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
'&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
'&gid=' + sheet.getSheetId() + // the sheet's Id
'&range='+pdfRange; // Sheet range
var token = ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url + exportOptions, {
headers: {
Authorization: 'Bearer '+token
}
}).getBlob().setName("tempSheetInvoiceExport.pdf");
var pdfFile = DriveApp.createFile(blob);
var downloadLink = HtmlService
.createHtmlOutput('<p>Download your file here.</p>')
.setWidth(200)
.setHeight(100);
SpreadsheetApp.getUi().showModalDialog(downloadLink, "Download PDF");
}
What it does?
Get the active sheet and define a pdfRange to be exported
Generate an pdf export link with sheet range options '&range='+pdfRange
Create a pdf file from the fetched blob
Display the pdf file url
Output:

Everything works but the subject line blank... why? What am I missing?

I think this must be very easy to see, but I cannot see it! This script sends out a sheet as a PDF. It works well, except that the subject line is blank. I've tried substituting an actual string for the variable in the class gmailApp at the bottom, but the subject line is still blank when the email arrives. Help! Thank you.
P.S.-- note that I took out the email address for privacy.
function emailPDF(email, subject, body, sheetName) {
var email = "...";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Client');
var cost = sheet.getSheetValues(1,1,1,1).toLocaleString();
var subject = ss.getName();
var body = "Hi Serenity, the material cost is $" + cost +" Thank you!";
// 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=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='; // the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext + sheet.getSheetId(), {
headers : {
'Authorization' : 'Bearer ' + token
}
}).getBlob().setName(ss.getName() + ".pdf");
// save PDF to drive
// var newFile = DriveApp.createFile(response).setName(sheet.getName() + ".pdf")
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
htmlBody : body,
attachments : [response]
});
}
I've figured it out... this was just petty error. The spreadsheet has a lot of scripts. I picked up this script from a month ago, started from scratch and accidentally gave it the same function name. Both scripts were being called simultaneously, causing this result. Everything works now.
I appreciate your comment Lamblichus... I was so focused on the script being wrong that I didn't realize what was happening. Then I realized that it can't be wrong. You got me thinking the right way. Best.

print spreadsheet as pdf with no margins

I am trying to make things easier for my team so I want to have them print out a given area from my Google Sheets document into a pdf with predefined margins/printing settings. The printed area is not on the active spreadsheet.
I just moved over from Excel to Spreadsheets. I know some VBA but do not really know that much about GAS. I did quite a lot of research but all the samples I found are based on UiApp which not supported any longer.
I found some threads (where I think messages are missing?):
https://plus.google.com/u/1/115432608459317672860/posts/DQTbozyTsKk?cfem=1&pageId=none
Google Apps Script print sheet with margins
The last one I found was this one (PDF margins - Google Script) where I added the settings for margins (does it work that way though? I could not try it out yet because I do not know how to download the pdf. I tried do research but couldn't find anything..
var report = SpreadsheetApp.getActive();
var pdfName = "Angebot";
var sheetName = "Angebot";
var sourceSheet = report.getSheetByName(sheetName);
SpreadsheetApp.getActiveSpreadsheet().toast('Creating the PDF');
// export url
var url = 'https://docs.google.com/spreadsheets/d/'+report.getId()+'/export?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' // 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='+sourceSheet.getSheetId(); // the sheet's Id
+ '&top_margin=0'
+ '&left_margin=0'
+ '&right_margin=0'
+ '&bottom_margin=0'
var token = ScriptApp.getOAuthToken();
// request export url
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var theBlob = response.getBlob().setName(pdfName+'.pdf');
//var attach = {fileName:'Monthly Report.pdf',content:pdf, mimeType:'application/pdf'};
var name = report.getRange("H1:H1").getValues(); // Get Name
var emailTo = report.getRange("H2:H2").getValues(); // Get email
var period = report.getRange("H3:H3").getValues(); // Get Reporting Period
var subject = " - TEST Monthly Report - " + period; // Construct the Subject Line
var message = "Hi " + name + ", here is your latest report for " + period; // email body text
// download pdf
}

how to wrap the the text in the pdf output file

I have converted a temporary google sheet to pdf with exportOptions. However, I want to keep the font size for the text fixed. This causes the text in each row to spill over to the next page. I believe using text wrapping might solve that but I don't know what the code for it is and don't know how to use it in the codes either. I am a novice in programming.
I have tried using commands such as font size, wrap, text-wrap, researched using google and read the documentation for exportOptions, blob, and text sizing as well.
const url =
'https://docs.google.com/spreadsheets/d/SS_ID/export?'.replace('SS_ID',
target_ss);
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf / csv / xls / xlsx
'&size=A4' + // paper size legal / letter / A4
'&portrait=false' + // orientation, false for landscape
'&fitw=false' + // fit to page width, false for actual size
'&sheetnames=false&printtitle=false' + // hide optional headers and footers
'&pagenumbers=false&gridlines=true' + // hide page numbers and gridlines
'&fzr=false' + // do not repeat row headers (frozen rows) on each page
'&gid='; // the sheet's Id
const token = ScriptApp.getOAuthToken();
const response = UrlFetchApp.fetch(url + exportOptions + target_sheet_Id, {
headers: {
Authorization: 'Bearer ' + token
}});
var blob = response.getBlob().setName(pdfName + '.pdf');
var newFile = folder.createFile(blob);
No error messages but no change in output either probably because those commands don't apply for the exportOptions format.
Iterate through your cells and set the cell wrap of each cell to true using Range.setWrap(true):
var target_ss = "your-spreadsheet-id";
var ss_sheets = SpreadsheetApp.openById(target_ss).getSheets();
for (var i = 0; i < ss_sheets.length; i++){
Logger.log(ss_sheets[i].getDataRange().setWrap(true));
}