【问题标题】:Export (or print) with a google script new version of google spreadsheets to pdf file, using pdf options使用 pdf 选项使用 google 脚本将新版本的 google 电子表格导出(或打印)为 pdf 文件
【发布时间】:2014-02-24 20:08:46
【问题描述】:

我正在尝试制作一个 google 脚本,用于将新版本的 google 电子表格(或工作表)导出(或打印)为 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”参数。新版本的正确 url 必须像 "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); 行出现了一个新错误:“Error OAuth”……我不知道如何继续……我已经测试了数百种变体,但没有得到很好的结果。

有什么想法吗? docs.google.com/feeds 新版本电子表格的范围是否正确? oauthConfig 是否正确?

提前致谢。

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    这是我的电子表格到 pdf 的脚本。它适用于新的 Google 电子表格 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 扩展名的文件,以获取带有最终 url ("https://docs.google.com/a/"+url+"/spreadsheets/d/"+id+"/export"+params") 的“永久移动”页面。

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

    【讨论】:

    • 嗨,船员风格!你的代码工作正常!我的问题是正确的范围https://docs.google.com/feeds/ 非常感谢!
    • 工作得很好!由于我不在一个与 google 勾结的组织中,因此不得不对其进行一些修改,但几乎是开箱即用的。谢谢!!
    • 不错的解决方案!您可以使用的其他一些参数仅限于带有gid= 的特定工作表,并通过使用行和列索引指定范围来进行选择,例如r1=0&c1=0&r2=55&c2=16
    • @crewstyle。当我执行上述代码时,怎么会得到一个 Failed to authenticate for service: google 。我已经授权匿名了。
    • 谢谢!有没有办法水平打印 pdf 或对 pdf 不起作用? &portrait=false 不起作用。需要水平解决方案。
    【解决方案2】:

    (复制自this answer。)

    这个函数是对“ianshedd...”here提供的脚本的改编。

    它:

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

    通过一些研究和努力,您可以连接到在线 PDF 合并 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);
      }
    }
    

    【讨论】:

      【解决方案3】:

      谢谢!

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

      我可以通过列出的参数完美地更改图像大小、方向等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多