我正在尝试将包含多个工作表的Google电子表格转换为PDF文件。下面的脚本有效,但它只使用电子表格的最后一页创建PDF。
function savePDFs() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var url = ss.getUrl();
//remove the trailing 'edit' from the url
url = url.replace(/edit$/,'');
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' + //export as pdf
//below parameters are optional...
'&size=letter' + //paper size
'&portrait=false' + //orientation, false for landscape
'&fitw=true' + //fit to width, false for actual size
'&sheetnames=false&printtitle=false&pagenumbers=false' + //hide optional
'&gridlines=false' + //false = hide gridlines
'&fzr=false' + //do not repeat row headers (frozen rows) on each page
'&gid='; //leave ID empty for now, this will be populated in the FOR loop
var token = ScriptApp.getOAuthToken();
//make an empty array to hold your fetched blobs
var blobs = [];
//.fetch is called for each sheet, the response is stored in var blobs[]
for(var i = 0; i < sheets.length; i++) {
var sheetname = sheets[i].getName();
//if the sheet is one that you don't want to process,
//continue' tells the for loop to skip this iteration of the loop
if(sheetname == "Team Member Numbers")
continue;
//grab the blob for the sheet
var response = UrlFetchApp.fetch(url + url_ext + sheets[i].getSheetId(), {
headers: {
'Authorization': 'Bearer ' + token
}
});
//convert the response to a blob and store in our array
blobs.push(response.getBlob().setName(sheets[i].getName() + '.pdf'));
var array_blob = response.getBlob().setName(sheets[i].getName() + '.pdf');
}
//from here you should be able to use and manipulate the blob to send and
//email or create a file per usual.
// send email
var subject = "Enter Subject"
var message = "See attached PDF"
MailApp.sendEmail("email addy here", subject, message,{attachments:[array_blob]});
}
答案 0 :(得分:5)
我稍微调整了@Mogsdad代码,将整个电子表格打印为一张PDF。关键是调整导出参数。基本上取代
'&gid=' + sheet.getSheetId() //the sheet's Id
与
(optSheetId ? ('&gid=' + sheet.getSheetId()) : ('&id=' + ss.getId())) // Print either the entire Spreadsheet or the specified sheet if optSheetId is provided
所以上面的代码减去循环看起来像:
function savePDFs( optSSId, optSheetId ) {
// 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();
// 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();
}
//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=' + sheet.getSheetId()) : ('&id=' + ss.getId()))
// 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("https://docs.google.com/spreadsheets/" + url_ext, options);
var blob = response.getBlob().setName(ss.getName() + '.pdf');
//from here you should be able to use and manipulate the blob to send and email or create a file per usual.
//In this example, I save the pdf to drive
folder.createFile(blob);
}
顺便说一句,谢谢 - 我一直在寻找解决方案很长一段时间!
答案 1 :(得分:3)
此功能是对“ianshedd ...”here提供的脚本的改编。
有:
只需要“正常”授权操作;无需激活高级服务(嗯......您确实需要一些,请参阅this )或摆弄oAuthConfig
。
OAuth2通过ScriptApp.getOAuthToken()
授予检索电子表格PDF的fetch()
调用授权,该授权为我们提供了当前用户的OAuth 2.0访问令牌。
通过一些研究和努力,您可以连接到在线PDF Merge API,以生成单个PDF文件。除此之外,直到Google提供了一种方法来导出一个PDF中的所有工作表,你就会遇到单独的文件。请参阅Gilbert的调整以获得多张工作表!
脚本:
/**
* Export one or all sheets in a spreadsheet as PDF files on user's Google Drive,
* in same folder that contained original spreadsheet.
*
* Adapted from https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579#c25
*
* @param {String} optSSId (optional) ID of spreadsheet to export.
* If not provided, script assumes it is
* sheet-bound and opens the active spreadsheet.
* @param {String} optSheetId (optional) ID of single sheet to export.
* If not provided, all sheets will export.
*/
function savePDFs( optSSId, optSheetId ) {
// 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();
// Get URL of spreadsheet, and remove the trailing 'edit'
var url = ss.getUrl().replace(/edit$/,'');
// 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();
}
// Get array of all sheets in spreadsheet
var sheets = ss.getSheets();
// Loop through all sheets, generating PDF files.
for (var i=0; i<sheets.length; i++) {
var sheet = sheets[i];
// If provided a optSheetId, only save it.
if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&gid=' + sheet.getSheetId() //the sheet's Id
// 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 + url_ext, options);
var blob = response.getBlob().setName(ss.getName() + ' - ' + sheet.getName() + '.pdf');
//from here you should be able to use and manipulate the blob to send and email or create a file per usual.
//In this example, I save the pdf to drive
folder.createFile(blob);
}
}
/**
* Dummy function for API authorization only.
* From: https://stackoverflow.com/a/37172203/1677912
*/
function forAuth_() {
DriveApp.getFileById("Just for authorization"); // https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579#c36
}
答案 2 :(得分:3)
我还没有评论的声誉,但吉尔伯特W提交的上述最佳答案似乎有一个小问题......虽然我很难理解某些事情。
该解决方案包括
行 + (optSheetId ? ('&gid=' + sheet.getSheetId()) : ('&id=' + ss.getId()))
但是,在此之前的代码中尚未定义“工作表”。在Mogsdad的代码中,“sheet”在被删除的循环中定义:
for (var i=0; i<sheets.length; i++) {
var sheet = sheets[i];
“表格”定义为
var sheets = ss.getSheets();
该解决方案适用于想要打印整个电子表格的人,这是提出的问题。但是,代码不再适用于想要打印单个页面的人。
Gilbert更新代码的另一个问题是HTML请求包含对工作表ID的引用,但不包括电子表格本身。如果您提供了特定的工作表ID,则会导致响应失败,但如果未提供工作表ID,则可以正常工作。我通过将URL基础恢复为Mogsdad的方式再次使用它。
另一个调整:吉尔伯特的代码自动将新的.PDF命名为电子表格的名称。同时,Mogsdad的代码一次打印出每张纸,用电子表格名称后跟当前工作表的名称命名每个.PDF。我想打印带有单页名称的PDF(如果适用),并且还为用户提供了指定输出名称的功能。
由于“getSheetById”不存在任何方法,因此根据代码的上下文,函数采用“optSheetName”而不是“optSheetID”可能更有意义。如果需要,可以从“getSheetByName”中获取工作表ID,在我看来,用户通常更有可能拥有工作表的名称而不是工作表的ID。可以从绑定脚本以编程方式获取名称和ID,但只能使用该名称来获取特定的现有工作表。
我还添加了一个可选的电子邮件参数,以便您可以同时打印PDF和发送电子邮件。
这是我的版本:
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});
}
答案 3 :(得分:0)
根据Queso博士的回答,这是我对这个主题的变化。
所有参数(在代码中描述)都是可选的,如果没有指定,则使用活动电子表格,将所有选项卡转换为以电子表格命名的单个PDF,不会通过电子邮件发送PDF。
function test() {
// Create a PDF containing all the tabs in the active spreadsheet, name it
// after the spreadsheet, and email it
convertSpreadsheetToPdf('user@email.com')
// Create a PDF containing all the tabs in the spreadsheet specified, name it
// after the spreadsheet, and email it
convertSpreadsheetToPdf('user@email.com', '1r9INcnsyvSQmeduJWVYAvznOOYei9jeAjsy0acA3G1k')
// Create a PDF just containing the tab 'Sheet2' in the active spreadsheet, specify a name, and email it
convertSpreadsheetToPdf('user@email.com', null, 'Sheet2', 'PDF 3')
}
/*
* Save spreadsheet as a PDF
*
* @param {String} email Where to send the PDF [OPTIONAL]
* @param {String} spreadsheetId Or the active spreadsheet[OPTIONAL]
* @param {String} sheetName The tab to output [OPTIONAL]
* @param {String} PdfName [OPTIONAL]
*/
function convertSpreadsheetToPdf(email, spreadsheetId, sheetName, pdfName) {
var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();
spreadsheetId = spreadsheetId ? spreadsheetId : spreadsheet.getId()
var sheetId = sheetName ? spreadsheet.getSheetByName(sheetName).getSheetId() : null;
var pdfName = pdfName ? pdfName : spreadsheet.getName();
var parents = DriveApp.getFileById(spreadsheetId).getParents();
var folder = parents.hasNext() ? parents.next() : DriveApp.getRootFolder();
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
// Print either the entire Spreadsheet or the specified sheet if optSheetId is provided
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// 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(pdfName + '.pdf');
folder.createFile(blob);
if (email) {
var mailOptions = {
attachments:blob
}
MailApp.sendEmail(
email,
"Here is a file named " + pdfName,
"Please let me know if you have any questions or comments.",
mailOptions);
}
} // convertSpreadsheetToPdf()
注意:如果隐藏工作表,则不起作用。使用activate()取消隐藏工作表。