首页 > 解决方案 > Google Sheets Export to PDF Script - 为什么要导出隐藏的行?

问题描述

我有一个脚本,用于将单个 google 工作表保存为给定文件夹中的 pdf 文档。

由于工作表的内容是动态的,并且有时底部有大量空网格行,因此我提供了一种在导出文件之前隐藏没有内容的行的方法。

直到最近,这才按要求工作。现在该函数隐藏了行,但创建的文件将这些行显示为未隐藏。

知道这是否是由于最近更改了 google sheet api 造成的,我能做些什么来恢复旧功能吗?

这是我以前工作的代码块:

// API function for saving a single sheet without hiding sheets
// *******************************************************************************


function singleSheetAPIExport(){

  // Get active spreadsheet URL
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheetName = 'Example';
  var main = ss.getSheetByName(sheetName)
  var folderID = '1wsxxxxxxblahblah' // Google Drive Folder ID

  Logger.log('maxrows: ' + main.getMaxRows());
  Logger.log('last row: ' + main.getLastRow());

  // 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();

  // Hide All Empty Rows in the Print Sheet
  var maxRows = main.getMaxRows(); 
  var lastRow = main.getLastRow();
  if (maxRows-lastRow != 0){
    main.hideRows(lastRow+1, maxRows-lastRow);
  }

  // Get the response for your specific sheet that can later be converted to blob
  var response = UrlFetchApp.fetch(url + url_ext + main.getSheetId(), {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  });

  // Save pdf version
  var saveFolder = 'PDF';
  var parentFolder = DriveApp.getFolderById(folderID);
  var folder, folders = DriveApp.getFoldersByName(saveFolder);
   if (folders.hasNext()) {
     folder = folders.next();
   } else {
     folder = parentFolder.createFolder(saveFolder);
   }
  var name = main.getRange("B8").getValue(); 
  var cleanName = name.replace(/([^a-zA-Z0-9() #%~-])/g, "-");
  folder.createFile(response.getBlob().setName(cleanName));

  // Unhide the rows again
  var fullSheetRange = main.getRange(1,1,main.getMaxRows(), main.getMaxColumns());
  main.unhideRow(fullSheetRange); 

}

该功能在 6 月 17 日至 19 日之间发生了变化,这可能表明 api 发生了变化,但我无法找到任何证据表明这种变化。

我之前在 Stack Exchange 的 Web 应用程序站点上发布了此内容,但由于我看到 google 应用程序团队推荐 Stackoverflow 进行查询,我已将其删除并重新发布到此处。

标签: pdfgoogle-apps-scriptgoogle-sheets

解决方案


我在您提供的测试表上测试了您的代码,它按预期工作。但是,如果我创建大量额外的行 - 实际上我可以重现您的隐藏行被导出的错误。

您的代码中的问题是您在隐藏空行后立即创建文件并在创建文件后立即取消隐藏行:

您必须知道这createFile()是一个异步请求 - 就像所有 Google API 调用一样。这意味着如果文件较大,创建可能需要更长的时间,您的unhideRow()方法可能会在创建文件之前执行。

类似地,如果您在隐藏所有行之前执行调用,这将导致同样的问题。解决方案在于使用SpreadsheetApp.flush();确保仅在前一个函数完成后才执行函数的函数。SpreadsheetApp.flush(); 在之前和之后插入folder.createFile(response.getBlob().setName(cleanName));可以解决您的问题。


推荐阅读