Google表格导出为PDF脚本-为什么导出隐藏行?

时间:2019-07-02 13:31:35

标签: pdf google-apps-script google-sheets

我有一个脚本,可以将单个Google工作表另存为给定文件夹中的pdf文档。

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

直到最近,它一直按要求工作。现在,该函数将隐藏行,但是创建的文件会将行显示为未隐藏。

是否知道这是由于最近对Google Sheets 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 Apps团队建议使用Stackoverflow进行查询,因此已将其删除并重新发布在这里。

2 个答案:

答案 0 :(得分:3)

还有另一种将工作表导出为PDF文件的方法,该方法指示要导出的所需单元格。而且您将不需要隐藏不必要的行。

function exportPDF(ssID,source,options,format){
  var dt=new Date();
  var d=encodeDate(dt.getFullYear(),dt.getMonth(),dt.getDate(),dt.getHours(),dt.getMinutes(),dt.getSeconds());
  var pc=[null,null,null,null,null,null,null,null,null,0,
          source,
          10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
          d,
          null,null,
          options,
          format,
          null,0,null,0];

 var js = " \
    <script> \
      window.open('https://docs.google.com/spreadsheets/d/"+ssID+"/pdf?id="+ssID+"&a=true&pc="+JSON.stringify(pc)+"&gf=[]'); \
      google.script.host.close(); \
    </script> \
  ";

  var html = HtmlService.createHtmlOutput(js)
    .setHeight(10)
    .setWidth(100);
  SpreadsheetApp.getUi().showModalDialog(html, "Save To PDF"); 
}
function myExportPDF(){
  var as = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = as.getActiveSheet();
  exportPDF(as.getId(), // Идентификатор таблицы
    [
      [sheet.getSheetId().toString(), // Sheet ID
       0,                             // vertical start border (from the first line)
       160,                           // vertical end boundary (160th line inclusive)
       0,                             // horizontal start border (from cell A)
       8                              // horizontal end boundary (cell H inclusive)
      ]
    ],
    [
      0,         // Do not show notes
      null,
      1,         // Show grid lines
      0,         // Do not show page numbers
      0,         // Do not show book title
      0,         // Do not show sheet title
      0,         // Do not show date
      0,         // Do not show time
      1,         // Repeat pinned rows
      1,         // Repeat pinned columns
      1,         // Page order down then up
      1,
      null,
      null,
      1,         // Left Alignment
      1          // Top Alignment
    ],
    [
      "A4",      // A4 sheet format
      1,         // Page Orientation Vertical
      2,         // Align to height
      1,
      [
        0.75,    // Top margin 0.75 inch
        0.75,    // Bottom margin 0.75 inch
        0.7,     // Left margin 0.7 inch
        0.7      // Right margin 0.7 inch
      ]
    ]
  );
}

详细说明在我的网站上 https://kandiral.ru/googlescript/eksport_tablic_google_sheets_v_pdf_fajl.html

UPD:上面的代码用于下载PDF文件。这是保存到Google云端硬盘的脚本

function exportPDFtoGDrive(ssID,filename,source,options,format){
  var dt=new Date();
  var d=encodeDate(dt.getFullYear(),dt.getMonth(),dt.getDate(),dt.getHours(),dt.getMinutes(),dt.getSeconds());
  var pc=[null,null,null,null,null,null,null,null,null,0,
          source,
          10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
          d,
          null,null,
          options,
          format,
          null,0,null,0];

  var folder=null;
  var parents = DriveApp.getFileById(ssID).getParents();
  if (parents.hasNext())folder = parents.next();
  else folder = DriveApp.getRootFolder();

  var options = {
    'method': 'post',
    'payload': "a=true&pc="+JSON.stringify(pc)+"&gf=[]",
    'headers': {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
    'muteHttpExceptions': true
  };
  var theBlob = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/"+ssID+"/pdf?id="+ssID, options).getBlob();
  folder.createFile(theBlob).setName(filename+".pdf");
}

function myExportPDFtoGDrive(){
  var as = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = as.getActiveSheet();
  var filename = as.getName()+" "+sheet.getName();
  exportPDFtoGDrive(
    as.getId(),  // Идентификатор таблицы
    filename,    // Имя файла
    [[sheet.getSheetId().toString(),0,160,0,8]],
    [0,null,1,0,0,0,0,0,1,1,1,1,null,null,1,1],
    ["A4",1,2,1,[0.75,0.75,0.7,0.7]]
  );
}

答案 1 :(得分:2)

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

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

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

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