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

时间:2014-02-24 20:08:46

标签: google-apps-script google-sheets

我正在尝试制作一个谷歌脚本,用于将新版本的谷歌电子表格(或表格)导出(或打印)为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" ),它再次失败并显示错误“无法为服务执行授权:google ”。 好吧,这个错误可能是由于 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

提前致谢。

3 个答案:

答案 0 :(得分:8)

这是我的电子表格到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”)。

答案 1 :(得分:4)

(从this answer复制。)

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

有:

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

通过一些研究和努力,您可以连接到在线PDF Merge API,以生成单个PDF文件。除此之外,直到谷歌提供了一种方法来导出一个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);
  }
}

答案 2 :(得分:0)

谢谢!

变体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)

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