有没有办法将电子表格的多个选项卡(但不是全部)打印为一个 pdf?

Is there a way to print multiple tabs of a spreadsheet (but not all of them) as a single pdf?

我已经做了一些研究,但还没有找到任何方法来做到这一点。尝试按照安德鲁·罗伯茨 (Andrew Roberts) 在此处 http://www.andrewroberts.net/2017/03/apps-script-create-pdf-multi-sheet-google-sheet/ 的解释将点差 sheet(或特定标签)转换为 pdf:

    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=A4'      // 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 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);
  }

看评论,他建议添加以下代码,我把它放在另一个函数中:

  function printtwopdfs() {

  var sheetNames = ["Table1,"Table2"]

  sheetNames.forEach(function(sheetName) {
  convertSpreadsheetToPdf(TEST_EMAIL, "xxxxxx", sheetName, 
  "pdfteste")
  })}

但我得到的是 每个 sheet 分别打印为一个 pdf。

隐藏除我想要的以外的所有选项卡并打印跨页sheet 对我来说不是一个选项,因为它有太多选项卡(大约 15 个)。除此之外,我不太可能将选定的 sheet 复制到新的传播 sheet 中,因为该函数将花费太长时间到 运行,除非我可以非常快地完成此操作。关于如何进行的任何想法?

如果我理解正确的话:

  • 您想在单个 PDF 中打印部分而不是所有工作表。
  • 您可以通过隐藏不需要的工作表并打印整个电子表格(仅打印未隐藏的工作表)来实现。
  • 每次要打印 PDF 时隐藏和显示不需要的工作表很不舒服,特别是当有很多工作表时。

如果以上正确,那么您可以使用脚本首先隐藏不需要的工作表,然后打印 PDF,最后再次显示这些不需要的工作表。可以通过以下方式完成(查看内联注释以获取更多详细信息):

function convertSpreadsheetToPdf(email, spreadsheetId, sheetsToPrint) {
  var ss = SpreadsheetApp.openById(spreadsheetId);
  // Get the names of all sheets in the spreadsheet:
  var allSheets = ss.getSheets().map(function(sheet) {
    return sheet.getName();
  });
  // Get the names of the sheets to ignore:
  var sheetsToHide = allSheets.filter(function(sheetName) {
    return sheetsToPrint.indexOf(sheetName) === -1;
  });
  // Hide the sheets to ignore:
  sheetsToHide.forEach(function(sheetName) {
    var sheet = ss.getSheetByName(sheetName);
    sheet.hideSheet();
  })
  var pdfName = ss.getName();
  var parents = DriveApp.getFileById(spreadsheetId).getParents();
  var folder = parents.hasNext() ? parents.next() : DriveApp.getRootFolder();
  var url_base = ss.getUrl().replace(/edit$/,'');  
  var url_ext = 'export?exportFormat=pdf&format=pdf'   //export as pdf  
  // Print either the entire Spreadsheet (only unhidden sheets):
  + '&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=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);
  }
  // Show the ignored sheets:
  sheetsToHide.forEach(function(sheetName) {
    var sheet = ss.getSheetByName(sheetName);
    sheet.showSheet();
  })    
}

此函数接受 emailspreadsheetId 和由要打印的工作表名称组成的数组作为参数。可能的调用可能是这样的:

convertSpreadsheetToPdf("your-email@your-domain", "your-spreadsheet-id", ["Sheet1","Sheet2","Sheet5"])

为了解决这个问题,我稍微简化了这段代码(PDF 的名称始终是电子表格的名称,您始终必须提供电子表格 ID),但随时可以还原这些更改.

参考:

希望对您有所帮助。

  • 您想通过 selecting 来自 Google 电子表格的表格来创建 PDF 文件。
    • Google 电子表格有 15 张。
    • 例如,您想要 select 2 张 "Table1" 和 "Table2",并希望将它们创建为一个 PDF 文件。然后,PDF 文件作为电子邮件发送。
  • 您想降低实现上述过程的成本。
    • 您想在 20 秒内完成 运行 脚本。
  • 您想使用 Google Apps 脚本实现此目的。

从你的提问和回复来看,我大概理解了上面的意思。如果我的理解是正确的,那么这个答案呢?请将此视为几个可能的答案之一。

在这种情况下,我认为除了要使用的工作表之外隐藏其他工作表可能是合适的。为此,在这里,我想建议在SheetsAPI中使用spreadsheets.batchUpdate的方法隐藏sheets。因为我认为在这种情况下,Sheets API 的处理成本可以低于 Spreadsheet 服务

流量:

修改后的脚本流程如下

  1. 隐藏工作表,但要创建为 PDF 文件的工作表除外。
  2. 从电子表格创建 PDF 文件。
  3. 显示所有工作表。

修改后的脚本:

在您 运行 脚本 please enable Sheets API at Advanced Google services 之前。请设置sheetNamesemailspreadsheetId的变量。以及运行printtwopdfs().

的功能
function convertSpreadsheetToPdf(email, spreadsheetId, pdfName) {
  var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();
  var spreadsheetId = spreadsheetId ? spreadsheetId : spreadsheet.getId();
  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
  + '&id=' + spreadsheetId
  + '&size=A4'      // 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 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);
  }
}

// Please run this function.
function printtwopdfs() {
  var sheetNames = ["Table1", "Table2"];
  var email = "###";  // Please set email address.
  var spreadsheetId = "###";  // Please set Spreadsheet ID.

  // Hide sheets.
  var allSheets = SpreadsheetApp.openById(spreadsheetId).getSheets();
  var hiddenResource = allSheets.map(function(s) {
    var obj = {updateSheetProperties: {properties: {sheetId: s.getSheetId(), hidden: true}, fields: "hidden"}};
    if (sheetNames.indexOf(s.getSheetName()) != -1) obj.updateSheetProperties.properties.hidden = false;
    return obj;
  });
  Sheets.Spreadsheets.batchUpdate({requests: hiddenResource}, spreadsheetId);

  // Create PDF file.
  convertSpreadsheetToPdf(email, spreadsheetId, "pdfteste");

  // Show all sheets.
  var showResource = allSheets.map(function(s) {return {updateSheetProperties: {properties: {sheetId: s.getSheetId(), hidden: false}, fields: "hidden"}}});
  Sheets.Spreadsheets.batchUpdate({requests: showResource}, spreadsheetId);
}

注:

  • 在我的环境中,当上述脚本用于 Google 电子表格(包括 20 个在单元格中具有值的表格)时,获得了大约 5 秒的处理时间。但是我不确定这是否可以用于您的实际情况。对此我深表歉意。

参考文献: