使用pdf选项将谷歌脚本新版谷歌电子表格导出(或打印)为pdf文件

问题描述 投票:6回答:3

我正在尝试制作一个谷歌脚本,用于将新版本的谷歌电子表格(或表格)导出(或打印)为pdf,页面参数(纵向/横向,......)

我研究了这个,并找到了一个可能的解决方案here。有几个类似的解决方案,但只能使用旧版本的谷歌电子表格。

请考虑以下代码:

function exportAsPDF() {
  //This code runs from a NEW version of spreadsheet 

  var oauthConfig = UrlFetchApp.addOAuthService("google");
  oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://spreadsheets.google.com/feeds/");
  oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oauthConfig.setConsumerKey("anonymous");  oauthConfig.setConsumerSecret("anonymous");
  var requestData = { "method": "GET", "oAuthServiceName": "google","oAuthUseToken": "always" };

  var ssID1="0AhKhywpH-YlQdDhXZFNCRFROZ3NqWkhBWHhYTVhtQnc"; //ID of an Old version of spreadsheet
  var ssID2="10xZX9Yz95AUAPu92BkBTtO0fhVk9dz5LxUmJQsJ7yPM"; //ID of a NEW version of spreadsheet 

  var ss1 = SpreadsheetApp.openById(ssID1);  //Old version ss object
  var ss2 = SpreadsheetApp.openById(ssID2);  //New version ss object
  var sID1=ss1.getActiveSheet().getSheetId().toString();  // old version sheet id
  var sID2=ss2.getActiveSheet().getSheetId().toString();  // new version sheet id

  //For Old version, this runs ok.
  var url1 = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="+ssID1+"&gid="+sID1+"&portrait=true"+"&exportFormat=pdf";
  var result1 = UrlFetchApp.fetch(url1 , requestData);
  var contents1=result1.getBlob();
  var pdfFile1=DriveApp.createFile(contents1).setName("FILE1.pdf");

  //////////////////////////////////////////////
  var url2 = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="+ssID2+"&gid="+sID2+"&portrait=true"+"&exportFormat=pdf";
  var result2 = UrlFetchApp.fetch(url2 , requestData);
  var contents2=result2.getBlob();
  var pdfFile2=DriveApp.createFile(contents2).setName("FILE2.pdf");
}

它工作正常并生成文件“FILE1.pdf”,可以正确打开。但是对于新版本的电子表格,它会在“var result2 = UrlFetchApp.fetch(url2,requestData);”处导致错误302(截断的服务器响应)。好吧,没关系,因为新版本的url格式不包含“key”参数。新版本的正确网址必须与"https://docs.google.com/spreadsheets/d/"+ssID2+"/export?gid="+sID2+"&portrait=true&format=pdf"相同

使用它为url2(var url2 = "https://docs.google.com/spreadsheets/d/"+ssID2+"/export?gid="+sID2+"&portrait=true&format=pdf")它再次失败,错误“无法为服务执行授权:谷歌”。好吧,这个错误可能是由于RequestTokenUrl的范围不正确。我找到了替代范围https://docs.google.com/feeds并设置它:oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://docs.google.com/feed/");代码再次运行后,UrlFetchApp.fetch(url2 , requestData);行出现了一个新错误:“错误OAuth”......我不知道如何继续......我已经测试了数百种变体没有好结果。

有任何想法吗?对于新版电子表格,docs.google.com/feeds的范围是否正确? oauthConfig是对的吗?

提前致谢。

google-apps-script google-sheets
3个回答
9
投票

这是我的电子表格到pdf脚本。它适用于新的Google Spreadsheet API。

// Convert spreadsheet to PDF file.
function spreadsheetToPDF(id,index,url,name)
{
  SpreadsheetApp.flush();

  //define usefull vars
  var oauthConfig = UrlFetchApp.addOAuthService("google");
  var scope = "https://docs.google.com/feeds/";

  //make OAuth connection
  oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
  oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oauthConfig.setConsumerKey("anonymous");
  oauthConfig.setConsumerSecret("anonymous");

  //get request
  var request = {
    "method": "GET",
    "oAuthServiceName": "google",
    "oAuthUseToken": "always",
    "muteHttpExceptions": true
  };

  //define the params URL to fetch
  var params = '?gid='+index+'&fitw=true&exportFormat=pdf&format=pdf&size=A4&portrait=true&sheetnames=false&printtitle=false&gridlines=false';

  //fetching file url
  var blob = UrlFetchApp.fetch("https://docs.google.com/a/"+url+"/spreadsheets/d/"+id+"/export"+params, request);
  blob = blob.getBlob().setName(name);

  //return file
  return blob;
}

我必须使用“muteHttpExceptions”参数来确切地知道新的URL。使用此参数,我下载了带有HTML扩展名的文件,以获得带有我的最终网址的“永久移动”页面(“https://docs.google.com/a/”+ url +“/ spreadsheets / d /”+ id +“/ export”+ params“)。

请注意我在一个组织中。所以我必须指定其域名(“url”参数,即“mydomain.com”)。


4
投票

(从this answer复制。)

此功能是由“ianshedd ...”here提供的脚本的改编。

它:

  • 在电子表格中生成所有工作表的PDF,并将它们存储在包含电子表格的同一文件夹中。 (它假设只有一个文件夹可以做到这一点,尽管Drive确实允许多次收容。)
  • 使用电子表格和工作表名称命名pdf文件。
  • 使用Drive服务(不推荐使用DocsList。)
  • 可以使用可选的电子表格ID在任何工作表上操作。默认情况下,它希望在包含脚本的“活动电子表格”上工作。
  • 只需“正常”授权操作;无需激活高级服务或摆弄oAuthConfig

通过一些研究和努力,您可以连接到在线PDF Merge API,以生成单个PDF文件。除此之外,直到Google提供了一种方法来导出一个PDF中的所有工作表,你就会遇到单独的文件。

脚本:

/**
 * 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);
  }
}

0
投票

谢谢!

Variant 2与我合作,提供以下选项:

var requestData = {
  "oAuthServiceName": "spreadsheets",
  "oAuthUseToken": "always"
};

然后:

var ssID = ss.getId();
var sID = ss.getSheetByName(name).getSheetId();

//creating pdf  
var pdf = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/" + ssID + "/export?gid=" + sID + "&portrait=false&size=A4&format=pdf", requestData).getBlob();

//folder to created pdf in
var folder = DriveApp.getFolderById(id);

//creating pdf in this folder with given name
folder.createFile(pdf).setName(name);

我可以完美地使用列出的参数更改图像大小,方向等。

© www.soinside.com 2019 - 2024. All rights reserved.