使用云打印打印 Google 电子表格范围

Print Google Spreadsheet Range using Cloud Print

我正在尝试将打印作业发送到我在云打印中的一台打印机。

我要打印的信息是用户在电子表格中选择的当前范围。

为此,我使用了本指南: https://www.labnol.org/code/20061-google-cloud-print-with-apps-script 以便使用 GAS 设置打印机。

第一步:获取要打印的信息

来源:How to Print sheet/range using .gs script in Google Sheets?

说明:carlesgg97 的解决方案会打开一个模式 window,它将显示我们导出为 PDF 的电子表格范围。从那时起,用户将需要手动打印作业。

但是,信息是通过脚本发送到 Html。

代码改编:

var PRINT_OPTIONS = {
  'size': 7,               // paper size. 0=letter, 1=tabloid, 2=Legal, 3=statement, 4=executive, 5=folio, 6=A3, 7=A4, 8=A5, 9=B4, 10=B
  'fzr': false,            // repeat row headers
  'portrait': false,        // false=landscape
  'fitw': true,            // fit window or actual size
  'gridlines': false,      // show gridlines
  'printtitle': false,
  'sheetnames': false,
  'pagenum': 'UNDEFINED',  // CENTER = show page numbers / UNDEFINED = do not show
  'attachment': false
}

var PDF_OPTS = objectToQueryString(PRINT_OPTIONS);

function printSelectedRange() {
  SpreadsheetApp.flush();
  var ss = SpreadsheetApp.getActiveSpreadsheet(); //Our Spreadsheet
  var sheet = ss.getActiveSheet(); //Our Active Sheet
  var range = sheet.getActiveRange(); // Our Active Range

  var gid = sheet.getSheetId();
  var printRange = objectToQueryString({
    'c1': range.getColumn() - 1,
    'r1': range.getRow() - 1,
    'c2': range.getColumn() + range.getWidth() - 1,
    'r2': range.getRow() + range.getHeight() - 1
  });
  //Here is variable that we will send to the htmlTemplate
  //We will build the HtmlTemplate using this url 
  var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + 
                PDF_OPTS + printRange + "&gid=" + gid;
  var htmlTemplate = HtmlService.createTemplateFromFile('js');

  //Here I'm wrongly trying to get the content from the Html.
  //What I'll get is the content of js.html and not the info from the url
  var pdf_html = htmlTemplate.evaluate().getContent(); 

  //The blob needs to be build using an object. 
  //However I don't know how to access the pdf I'm exporting inside the url var
  var blob = Utilities.newBlob(pdf_html, MimeType.HTML, 'temp').getAs(MimeType.PDF);
  //random printer ID
  var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';

  printGoogleDocument(blob, printerID, 1);

}

function objectToQueryString(obj) {
  return Object.keys(obj).map(function(key) {
    return Utilities.formatString('&%s=%s', key, obj[key]);
  }).join('');
}

js.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <script>
      window.open('<?=url?>', '_blank', 'width=800, height=600');
      google.script.host.close();
    </script>
  </body>
</html>

第 2 步:打印作业

function printGoogleDocument(docBlob, printerID, docName) {
  var ticket = {
    version: "1.0",
    print: {
      color: {
        type: "STANDARD_COLOR",
        vendor_id: "Color"
      },
      duplex: {
        type: "NO_DUPLEX"
      }
    }
  };

  var payload = {
    "printerid" : printerID,
    "title"     : docName,
    "content"   : docBlob,
    "contentType": "application/pdf",
    "ticket"    : JSON.stringify(ticket)
  };

  var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/submit', {
    method: "POST",
    payload: payload,
    headers: {
      Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
    },
    "muteHttpExceptions": true
  });

  response = JSON.parse(response);

  if (response.success) {
    Logger.log("%s", response.message);
  } else {
    Logger.log("Error Code: %s %s", response.errorCode, response.message);
  }
}

我认为我需要修改的是Html模板的构建方式,以便我可以创建正确的 BLOB 并将其发送到打印机。

编辑

应用 Tanaike 的建议,当我直接从脚本编辑器调用函数时它工作得很好。

虽然在我们想使用另一个函数调用此函数 printSelectedRange() 的情况下,我得到了以下错误:

Exception: Request failed for https://docs.google.com returned code 500.
Truncated server response: <!DOCTYPE html><html lang="en"><head> 
<metaname="description" content="Web word processing, presentations and 
spreadsheets"><meta name="viewport" c... (use muteHttpExceptions option to` 
examine full response)`

错误指向这行代码

var blob = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " + 
ScriptApp.getOAuthToken()}}).getBlob();

为了避免这种情况,我更新了 UrlFetchApp 的参数:

  var htmlTemplate = HtmlService.createTemplateFromFile('js');
  htmlTemplate.url = url;

  var params = {
    headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()},
    muteHttpExceptions: true
  };

  var blob = UrlFetchApp.fetch(url, params).getBlob(); 
  var printerID = 'randomprinterID';

  printGoogleDocument(blob, printerID, 1);

这个修改怎么样?

在此修改中,blob直接从url中检索为PDF数据。

发件人:

var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + 
            PDF_OPTS + printRange + "&gid=" + gid;
var htmlTemplate = HtmlService.createTemplateFromFile('js');

//Here I'm wrongly trying to get the content from the Html.
//What I'll get is the content of js.html and not the info from the url
var pdf_html = htmlTemplate.evaluate().getContent(); 

//The blob needs to be build using an object. 
//However I don't know how to access the pdf I'm exporting inside the url var
var blob = Utilities.newBlob(pdf_html, MimeType.HTML, 'temp').getAs(MimeType.PDF);
//random printer ID
var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';

printGoogleDocument(blob, printerID, 1);

收件人:

var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + PDF_OPTS + printRange + "&gid=" + gid;
var blob = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()}}).getBlob();
var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';
printGoogleDocument(blob, printerID, 1);