0

多年来,我一直使用 Google Cloud Print 在我们的校园实验室中使用 Google Apps Script 自定义 HtmlService 表单打印标签(以实现标准化)。

现在 GCP 正在贬值,我正在寻找解决方案。我找到了一些选项,但正在努力将文件转换为其他供应商所需的 pdf。

目前,当您在 GAS 中向 GCP 服务器提交 text/html blob 时,后端会将 blob 转换为 application/pdf(通过查看 Chrome 上 GCP 面板中“内容类型”下的作业详细信息可以证明这一点)。

也就是说,因为这些其他云打印服务需要 pdf 打印,我已经尝试了一段时间让 GAS 在发送到 GCP 之前将文件更改为 pdf 格式,但我总是得到一个奇怪的结果。下面,我将展示一些我使用过的策略,并包含我们使用不同功能生成的一个简单标签的图片。

以下是使用 GCP 多年的票证和有效负载的基本代码

   //BUILD PRINT JOB FOR NARROW TAPES
     var ticket = {
        version: "1.0",
        print: {
          color: {
            type: "STANDARD_COLOR",
            vendor_id: "Color"
          },
          duplex: {
            type: "NO_DUPLEX"
          },
          copies: {copies: parseFloat(quantity)},
          media_size: {
             width_microns: 27940,
             height_microns:40960
          },
          page_orientation: {
            type: "LANDSCAPE"  
          },
           margins: {
             top_microns:0,
             bottom_microns:0,
             left_microns:0,
             right_microns:0
          },
         page_range: {
            interval: 
              [{start:1,
              end:1}]
            
          },
          
        }
      };
     
          
      var payload = {
        "printerid" : QL710,
        "title"     : "Blank Template Label",
        "content"   : HtmlService.createHtmlOutput(html).getBlob(),
        "contentType": 'text/html',
        "ticket"    : JSON.stringify(ticket)
      };

这会生成预期的以下打印输出: 预期产出

尝试使用以下代码转换为 pdf 时:以下是用于转换为 pdf 的代码:

  var blob = HtmlService.createTemplate(html).evaluate().getContent();
  var newBlob = Utilities.newBlob(html, "text/html", "text.html");
  var pdf = newBlob.getAs("application/pdf").setName('tempfile');
  var file = DriveApp.getFolderById("FOLDER ID").createFile(pdf);
  
  
  var payload = {
    "printerid" : QL710,
    "title"     : "Blank Template Label",
    "content"   : pdf,//HtmlService.createHtmlOutput(html).getBlob(),
    "contentType": 'text/html',
    "ticket"    : JSON.stringify(ticket)
  };

出现意想不到的结果:

在此处输入图像描述

这与使用和不使用 .getBlob() 在“内容”字段中直接编码的方式相同:

"content" : HtmlService.createHtmlOutput(html).getAs('application/pdf'),

注意上面代码中用于测试 pdf 的 createFile 行。此文件按预期创建,当然标签打印尺寸错误(不确定如何转换为具有适当边距和页面大小的 pdf?):见下文

上传到云端硬盘显示创建的准确 pdf

我现在尝试采纳尤里的想法;但是,从 html 到文档的转换会丢失格式。

 var blob = HtmlService.createHtmlOutput(html).getBlob();
  var docID = Drive.Files.insert({title: 'temp-label'}, blob, {convert: true}).id
  var file = DocumentApp.openById(docID);
  file.getBody().setMarginBottom(0).setMarginLeft(0).setMarginRight(0).setMarginTop(0).setPageHeight(79.2).setPageWidth(172.8);

这会产生一个看起来像这样的文档(图片也显示了我手中的预期输出)。

在此处输入图像描述

有没有人有见解:

  1. 如何格式化转换后的 pdf 以包含适当的高度、宽度和边距。
  2. 如何以可以正确打印的方式转换为 pdf。

这是一个最小的代码,可以更好地了解上下文https://script.google.com/d/1yP3Jyr_r_FIlt6_aGj_zIf7HnVGEOPBKI0MpjEGHRFAWztGzcWKCJrD0/edit?usp=sharing

4

3 回答 3

1

我已经制作了模板(80 x 40 毫米——抱歉,我不知道你的尺寸):

在此处输入图像描述

https://docs.google.com/document/d/1vA93FxGXcWLIEZBuQwec0n23cWGddyLoey-h0WR9weY/edit?usp=sharing

还有脚本:

function myFunction() {

  // input data
  var matName     = '<b>testing this to <u>see</u></b> if it <i>actually</i> works <i>e.coli</i>'
  var disposeWeek = 'end of semester'
  var prepper     = 'John Ruppert';
  var className   = 'Cell and <b>Molecular</b> Biology <u>Fall 2020</u> a few exercises a few exercises a few exercises a few exercises';
  var hazards     = 'Lots of hazards';

  // make a temporary Doc from the template
  var copyFile = DriveApp.getFileById('1vA93FxGXcWLIEZBuQwec0n23cWGddyLoey-h0WR9weY').makeCopy();
  var doc = DocumentApp.openById(copyFile.getId());
  var body = doc.getBody();

  // replace placeholders with data
  body.replaceText('{matName}',     matName);
  body.replaceText('{disposeWeek}', disposeWeek);
  body.replaceText('{prepper}',     prepper);
  body.replaceText('{className}',   className);
  body.replaceText('{hazards}',     hazards);

  // make Italics, Bold and Underline
  handle_tags(['<i>', '</i>'], body);
  handle_tags(['<b>', '</b>'], body);
  handle_tags(['<u>', '</u>'], body);

  // save the temporary Doc
  doc.saveAndClose();

  // make a PDF
  var docblob = doc.getBlob().setName('Label.pdf');
  DriveApp.createFile(docblob);

  // delete the temporary Doc
  copyFile.setTrashed(true);
}


// this function applies formatting to text inside the tags
function handle_tags(tags, body) {

  var start_tag = tags[0].toLowerCase();
  var end_tag   = tags[1].toLowerCase();
  var found     = body.findText(start_tag);

  while (found) {
    var elem    = found.getElement();
    var start   = found.getEndOffsetInclusive();
    var end     = body.findText(end_tag, found).getStartOffset()-1;

    switch (start_tag) {
      case '<b>': elem.setBold(start, end, true); break;
      case '<i>': elem.setItalic(start, end, true); break;
      case '<u>': elem.setUnderline(start, end, true); break;
    }

    found = body.findText(start_tag, found);
  }

  body.replaceText(start_tag, ''); // remove tags
  body.replaceText(end_tag, '');
}

该脚本仅使用数据更改 {placeholders} 并将结果保存为 PDF 文件 (Label.pdf)。PDF 看起来像这样:

在此处输入图像描述

有一件事,我不确定是否有可能——动态更改文本的大小以使其适合单元格,就像在“autosize.html”中所做的那样。粗略地说,您可以在单元格中获取一段文本,如果它大于某个数字,则可以使字体大小更小一些。可能您可以使用“autosize.html”中的 jquery texfill 函数来获得最佳尺寸并在文档中应用该尺寸。

于 2020-11-03T15:07:11.910 回答
0

这是脚本的一种变体,如果标签不适合一页,它会更改其中一个单元格中的字体大小。

function main() {

  // input texts
  var text = {};
  text.matName     = '<b>testing this to <u>see</u></b> if it <i>actually</i> works <i>e.coli</i>';
  text.disposeWeek = 'end of semester';
  text.prepper     = 'John Ruppert';
  text.className   = 'Cell and <b>Molecular</b> Biology <u>Fall 2020</u> a few exercises a few exercises a few exercises a few exercises';
  text.hazards     = 'Lots of hazards';
  
  // initial max font size for the 'matName'
  var size = 10;
  var doc_blob = set_text(text, size);

  // if we got more than 1 page, reduce the font size and repeat
  while ((size > 4) && (getNumPages(doc_blob) > 1)) {
    size = size-0.5;
    doc_blob = set_text(text, size);
  }

  // save pdf
  DriveApp.createFile(doc_blob);

}

// this function takes texts and a size and put the texts into fields
function set_text(text, size) {
  
  // make a copy
  var copyFile = DriveApp.getFileById('1vA93FxGXcWLIEZBuQwec0n23cWGddyLoey-h0WR9weY').makeCopy();
  var doc  = DocumentApp.openById(copyFile.getId());
  var body = doc.getBody();
  
  // replace placeholders with data
  body.replaceText('{matName}',     text.matName);
  body.replaceText('{disposeWeek}', text.disposeWeek);
  body.replaceText('{prepper}',     text.prepper);
  body.replaceText('{className}',   text.className);
  body.replaceText('{hazards}',     text.hazards);
  
  // set font size for 'matName'
  body.findText(text.matName).getElement().asText().setFontSize(size);
  
  // make Italics, Bold and Underline
  handle_tags(['<i>', '</i>'], body);
  handle_tags(['<b>', '</b>'], body);
  handle_tags(['<u>', '</u>'], body);
  
  // save the doc
  doc.saveAndClose();
  
  // delete the copy
  copyFile.setTrashed(true);
  
  // return blob
  return docblob = doc.getBlob().setName('Label.pdf');
}

// this function formats the text beween html tags
function handle_tags(tags, body) {

  var start_tag = tags[0].toLowerCase();
  var end_tag   = tags[1].toLowerCase();
  var found     = body.findText(start_tag);

  while (found) {
    var elem    = found.getElement();
    var start   = found.getEndOffsetInclusive();
    var end     = body.findText(end_tag, found).getStartOffset()-1;

    switch (start_tag) {
      case '<b>': elem.setBold(start, end, true); break;
      case '<i>': elem.setItalic(start, end, true); break;
      case '<u>': elem.setUnderline(start, end, true); break;
    }

    found = body.findText(start_tag, found);
  }

  body.replaceText(start_tag, '');
  body.replaceText(end_tag, '');
}

// this funcion takes saved doc and returns the number of its pages
function getNumPages(doc) {
  var blob  = doc.getAs('application/pdf');
  var data  = blob.getDataAsString();
  var pages = parseInt(data.match(/ \/N (\d+) /)[1], 10);
  Logger.log("pages = " + pages);
  return pages; 
}

它看起来相当可怕和绝望。原来,谷歌文档没有页码计数器。您需要将文档转换为 PDF 并计算 PDF 文件的页数。总的!

下一个问题,即使你设法计算了页数,你也不知道哪个单元格溢出了。这个脚本只需要一个单元格,改变它的字体大小,计算页数,再次改变字体大小等等。但它不会成功,因为里面可能有另一个单元格有长文本。您可以减小所有文本的字体大小,但这看起来也不是一个好主意。

于 2020-11-05T21:22:35.450 回答
0

我不确定我是否正确。您需要制作 PDF 并将其保存在 Google Drive 上吗?您可以在 Google 文档中进行操作。

例如:

  • 使用您的表格和文本制作一个新文档。像这样的东西

在此处输入图像描述

  • 将此脚本添加到您的文档中:
function myFunction() {
  var copyFile = DriveApp.getFileById(ID).makeCopy();
  var newFile = DriveApp.createFile(copyFile.getAs('application/pdf')); 
  newFile.setName('label');
  copyFile.setTrashed(true);
}

每次运行此脚本时,它都会在您的 Google Drive 上生成文件“label.pdf”。

在此处输入图像描述

此 pdf 的大小将与您的文档的页面大小相同。您可以使用附加组件制作任何大小的页面:Page Sizer https://webapps.stackexchange.com/questions/129617/how-to-change-the-size-of-paper-in-google-docs-to-自定义大小

如果您需要在生成 pdf 之前更改标签中的文本或/并且您需要更改生成文件的名称,您也可以通过脚本来完成。

于 2020-10-29T16:40:03.947 回答