带有内联图像的段落破坏了应用程序脚本,将 sheet 数据合并到文档中

Paragraphs with inline images breaking app script merging sheet data into doc

我有一个 Google 应用程序脚本,它将 sheet 中行的数据值与 template doc 合并。模板文档段落具有内联图像。当我删除图像时,脚本可以完美运行。当我重新添加图像时,出现以下错误:Service unavailable: Documents (line 34, file "Code")

关于我需要做什么的任何想法?仅供参考:第 34 行在下面注释...

function buildGivingStatements() {
  var tempDocID = "1-SAQYP41wwnah6tF15nvT8fSx1rjCHN57T7lECFTCCw";
  var finDocID = "1TnR63Yq9oiUwxxJ5MTHbm-OX3pqvH6iW7bBLcFC2v1w";
  var sheetID = "19Sl61Rp37bPWc_fsCqpu59DFsDdwZF4zxdjHlplA-fI";

  var tempDoc = DocumentApp.openById(tempDocID);
  var finDoc = DocumentApp.openById(finDocID);
  var sheet = SpreadsheetApp.openById(sheetID).getSheetByName("Annual Report");

  var tDATE = Utilities.formatDate(new Date(), "America/Chicago", "EEEE, MMMM dd, yyyy");
  var tYEAR = Utilities.formatDate(new Date(), "America/Chicago", "yyyy");

  var data = sheet.getRange(6,1,1,2).getDisplayValues();
  //var data = sheet.getRange(6,1,sheet.getLastRow()-1,4).getValues();

  var tempPs = tempDoc.getBody().getParagraphs();

  finDoc.getBody().clear();

  data.forEach(function(r){
    replaceTempVars(r[0], r[1], tDATE, tYEAR, finDoc, tempPs);
  });

}



function replaceTempVars(NAME, AMOUNT, tDATE, tYEAR, finDoc, tempPs) {
  tempPs.forEach(function(p){
    var elType = p.getType();
    Logger.log(elType);

    if(elType == "PARAGRAPH") {
      finDoc.getBody().appendParagraph( //LINE 34
        p
          .copy()
          .replaceText("{{NAME}}", NAME)
          .replaceText("{{AMOUNT}}", AMOUNT)
          .replaceText("{{DATE}}", tDATE)
          .replaceText("{{YEAR}}", tYEAR)
      );
    }else if(elType == "LIST_ITEM") {
      finDoc.getBody().appendListItem(
        p
          .copy()
      ).setGlyphType(DocumentApp.GlyphType.BULLET);
    }
  });

  finDoc.getBody().appendPageBreak();
}
  • 您想通过替换文本将模板文档合并到现有 Google 文档。
  • 在您当前的问题中,Service unavailable 的脚本出现在 finDoc.getBody().appendParagraph() 的错误。
    • 删除 Document 顶部的图像时,脚本有效。
  • 您想使用 Google Apps 脚本实现此目的。

如果我的理解是正确的,这个答案怎么样?请将此视为几个可能的答案之一。

修改点:

  • 从您分享的 Google 文档中,我知道您的模板文档使用了定位图像。我认为 Service unavailable 错误的原因是由于定位图像。当复制包含定位图像的段落时,会出现此类错误。
    • 为了避免这个问题,我建议修改你的脚本,将定位的图片和段落分开。
    • 为此,我使用 getNumChildren() 而不是 getParagraphs()。因为我认为需要使用 insert 方法而不是 append 方法。因为当使用append方法时,会在最上面的段落创建空段落。

修改后的脚本:

在你 运行 脚本之前,please enable Google Docs API at Advanced Google services.

function buildGivingStatements() {
  var tempDocID = "1-SAQYP41wwnah6tF15nvT8fSx1rjCHN57T7lECFTCCw";
  var finDocID = "1TnR63Yq9oiUwxxJ5MTHbm-OX3pqvH6iW7bBLcFC2v1w";
  var sheetID = "19Sl61Rp37bPWc_fsCqpu59DFsDdwZF4zxdjHlplA-fI";

  var tempDoc = DocumentApp.openById(tempDocID);
  var finDoc = DocumentApp.openById(finDocID);
  var sheet = SpreadsheetApp.openById(sheetID).getSheetByName("Annual Report");
  var tDATE = Utilities.formatDate(new Date(), "America/Chicago", "EEEE, MMMM dd, yyyy");
  var tYEAR = Utilities.formatDate(new Date(), "America/Chicago", "yyyy");
  var data = sheet.getRange(6,1,1,2).getDisplayValues();

  // I modified below script.
  var finBody = finDoc.getBody();
  finBody.clear();
  var tempBody = tempDoc.getBody();
  var tempNumChildren = tempBody.getNumChildren();
  var pos = 0;
  data.forEach(function(r){
    replaceTempVars(r[0], r[1], tDATE, tYEAR, finBody, tempBody, tempNumChildren, pos);
  });

  // If you want to delete the last empty page, please use the following script. In this case, please enable Docs API at Advanced Google services.
  finDoc.saveAndClose();
  var c = Docs.Documents.get(finDocID, {fields: "body.content"}).body.content.pop();
  Docs.Documents.batchUpdate({requests: [{deleteContentRange: {range: {startIndex: c.startIndex - 1, endIndex: c.endIndex - 1}}}]}, finDocID);
}

function replaceTempVars(NAME, AMOUNT, tDATE, tYEAR, finBody, tempBody, tempNumChildren, pos) {
  for (var i = 0; i < tempNumChildren; i++) {
    var element = tempBody.getChild(i).copy();
    var type = element.getType();
    if (type == DocumentApp.ElementType.PARAGRAPH) {
      var copyPara = element.asParagraph();
      var pImgs = copyPara.getPositionedImages();
      if (pImgs.length > 0) {
        var img = pImgs[0];
        var obj = {id: img.getId(), blob: img.getBlob(), leftOffset: img.getLeftOffset(), topOffset: img.getTopOffset(), width: img.getWidth(), height: img.getHeight(), layout: img.getLayout()};
        copyPara.removePositionedImage(obj.id);
        var texts = copyPara.replaceText("{{NAME}}", NAME).replaceText("{{AMOUNT}}", AMOUNT).replaceText("{{DATE}}", tDATE).replaceText("{{YEAR}}", tYEAR);
        var paragraph = finBody.insertParagraph(pos + i, texts);
        paragraph.addPositionedImage(obj.blob).setWidth(obj.width).setHeight(obj.height).setLayout(obj.layout).setLeftOffset(obj.leftOffset).setTopOffset(obj.topOffset);
      } else {
        var texts = element.asParagraph().replaceText("{{NAME}}", NAME).replaceText("{{AMOUNT}}", AMOUNT).replaceText("{{DATE}}", tDATE).replaceText("{{YEAR}}", tYEAR);
        finBody.insertParagraph(pos + i, texts);
      }
    } else if (type == DocumentApp.ElementType.LIST_ITEM) {
      var glyphType = element.asListItem().getGlyphType();
      finBody.insertListItem(pos + i, element).setGlyphType(glyphType);
    } else if (type == DocumentApp.ElementType.INLINE_IMAGE) {
      finBody.insertImage(pos + i, element);
    }
  }
  pos += tempNumChildren;
}

注:

  • 在这个修改过的脚本中已经编写了测试你的模板文件。如果您想使用其他模板,可能会发生错误。所以请注意这一点。
  • 关于finDocID的Google文档,请使用文档页边距与模板文档相同的文档。如果使用默认的 Google 文档,结果可能不是您所期望的。请注意这一点。

参考文献: