I\'m trying to convert a Google spreadsheet with multiple sheets to a PDF file. The script below works, but it only creates a PDF with the last page of the spreadsheet.
I do not yet have the reputation to comment, but there seems to be a minor issue with the top answer above as submitted by Gilbert W... though it's just as likely that I failed to understand something.
That solution includes the line
+ (optSheetId ? ('&gid=' + sheet.getSheetId()) : ('&id=' + ss.getId()))
However, "sheet" has not been defined in the code prior to this point. In Mogsdad's code, "sheet" is defined within the loop that was removed:
for (var i=0; i
And "sheets" was defined as
var sheets = ss.getSheets();
The solution works for someone who wants to print the entire spreadsheet, which is the question that was asked. However, the code no longer works for someone who wants to print a single page.
Another issue with Gilbert's updated code was that the HTML request included a reference to the sheet ID, but not the spreadsheet itself. This caused the response to fail if you provided a specific sheet ID, though it works fine if no sheet ID was provided. I got it to work again by reverting the URL base to the way Mogsdad had it.
Another tweak: Gilbert's code automatically names the new .PDF as whatever the spreadsheet was named. Meanwhile, Mogsdad's code prints out every sheet one at a time, naming each .PDF with the spreadsheet name followed by the name of the current sheet. I wanted to print the PDF with the name of the single sheet, if applicable, and also provide the user the ability to specify an output name.
Since no method exists to "getSheetById", depending on the context of your code, it probably makes more sense for the function to take "optSheetName" instead of "optSheetID." The sheet ID can be grabbed from "getSheetByName" if needed, and it seems to me a user is generally more likely to have the sheet's name than the sheet's ID. Both the name and the ID can be obtained programmatically from a bound script, but only the name can be used to get a specific existing sheet.
I also added an optional email parameter so that you can print and email the PDF at the same time.
Here is my version:
function savePDFs( optSSId , optSheetName , optOutputName, optEmail) {
// If a sheet ID was provided, open that sheet, otherwise assume script is
// sheet-bound, and open the active spreadsheet.
var ss = (optSSId) ? SpreadsheetApp.openById(optSSId) : SpreadsheetApp.getActiveSpreadsheet();
var optSheetId = ss.getSheetByName(optSheetName).getSheetId();
var outputName = (optOutputName ? optOutputName : (optSheetName ? optSheetName : ss.getName()))
// Get folder containing spreadsheet, for later export
var parents = DriveApp.getFileById(ss.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
}
else {
folder = DriveApp.getRootFolder();
}
var url_base = ss.getUrl().replace(/edit$/,'');
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
// Print either the entire Spreadsheet or the specified sheet if optSheetId is provided
+ (optSheetId ? ('&gid=' + optSheetId) : ('&id=' + ss.getId())) // Print either the entire Spreadsheet or the specified sheet if optSheetId is provided
// following parameters are optional...
+ '&size=letter' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false&pagenumbers=false' //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((outputName)+ '.pdf');
folder.createFile(blob);
GmailApp.sendEmail(optEmail, "Here is a file named " + outputName, "Please let me know if you have any questions or comments.", {attachments:blob});
}