带有内联图像的段落破坏了应用程序脚本,将 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 文档,结果可能不是您所期望的。请注意这一点。
参考文献:
我有一个 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 文档,结果可能不是您所期望的。请注意这一点。