从谷歌文档段落中复制的图像插入了两次



我正在尝试将多个Google文档合并为一个,但是原始文档中的图像入了两次。一个位于正确的位置,另一个位于新创建的文档的末尾。

从我所看到的情况来看,这些图像被脚本检测为Paragraph

正如您在下面的代码中看到的那样,我受到了此处类似主题的启发。 其中一个建议在ParagraphElement内搜索子Element,但调试显示没有。文档的相关部分将始终使用 appendT段落 方法插入,因为脚本无法正确检测图像。

这就是为什么我发现的另一个相关主题在这里不起作用的原因:它建议在段落本身之前插入图像,但它无法检测到它。

使用默认Logger和来自 Stackdriver 的console.log进行日志记录将显示类型为段落的对象。 逐步执行未显示任何调用appendParagraph方法的循环两次。

/* chosenParts contains list of Google Documents name */
function concatChosenFiles(chosenParts) {
var folders = DriveApp.getFoldersByName(folderName);
var folder = folders.hasNext() ? folders.next() : false;
var parentFolders = folder.getParents();
var parentFolder = parentFolders.next();
var file = null;
var gdocFile = null;
var fileContent = null;
var offerTitle = "New offer";
var gdocOffer = DocumentApp.create(offerTitle); 
var gfileOffer = DriveApp.getFileById(gdocOffer.getId()); // transform Doc into File in order to choose its path with DriveApp
var offerHeader = gdocOffer.addHeader();
var offerContent = gdocOffer.getBody();
var header = null;
var headerSubPart = null;
var partBody= null;
var style = {};
parentFolder.addFile(gfileOffer); // place current offer inside generator folder
DriveApp.getRootFolder().removeFile(gfileOffer); // remove from home folder to avoid copy
for (var i = 0; i < chosenParts.length; i++) {
// First retrieve Document to combine
file = folder.getFilesByName(chosenParts[i]);
file = file.hasNext() ? file.next() : null;
gdocFile = DocumentApp.openById(file.getId());
header = gdocFile.getHeader();
// set Header from first doc
if ((0 === i) && (null !== header)) {
for (var j = 0; j < header.getNumChildren(); j++) {
headerSubPart = header.getChild(j).copy();
offerHeader.appendParagraph(headerSubPart); // Assume header content is always a paragraph
}
}
fileContent = gdocFile.getBody();
// Analyse file content and insert each part inside the offer with the right method
for (var j = 0; j < fileContent.getNumChildren(); j++) {
// There is a limit somewhere between 50-100 unsaved changed where the script
// wont continue until a batch is commited.
if (j % 50 == 0) {
gdocOffer.saveAndClose();
gdocOffer = DocumentApp.openById(gdocOffer.getId());
offerContent = gdocOffer.getBody();
}
partBody = fileContent.getChild(j).copy();     
switch (partBody.getType()) {
case DocumentApp.ElementType.HORIZONTAL_RULE:
offerContent.appendHorizontalRule();
break;
case DocumentApp.ElementType.INLINE_IMAGE:
offerContent.appendImage(partBody);
break;
case DocumentApp.ElementType.LIST_ITEM:
offerContent.appendListItem(partBody);
break;
case DocumentApp.ElementType.PAGE_BREAK:
offerContent.appendPageBreak(partBody);
break;
case DocumentApp.ElementType.PARAGRAPH:
// Search for image inside parapraph type
if (partBody.asParagraph().getNumChildren() != 0 && partBody.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_IMAGE) 
{
offerContent.appendImage(partBody.asParagraph().getChild(0).asInlineImage().getBlob());
} else {
offerContent.appendParagraph(partBody.asParagraph());
}
break;
case DocumentApp.ElementType.TABLE:
offerContent.appendTable(partBody);
break;
default:
style[DocumentApp.Attribute.BOLD] = true;
offerContent.appendParagraph("Element type '" + partBody.getType() + "' from '" + file.getName() + "' could not be merged.").setAttributes(style);
console.log("Element type '" + partBody.getType() + "' from '" + file.getName() + "' could not be merged.");
Logger.log("Element type '" + partBody.getType() + "' from '" + file.getName() + "' could not be merged.");
}
}
// page break at the end of each part.
offerContent.appendPageBreak();
}
}

无论合并多少文件,使用一个文件就足以重现,都会出现问题。

如果文件中只有一个图像(周围没有空格或换行符),并且之后不使用"appendPageBreak",则不会发生。当某些文本位于图像旁边时,图像将被复制。

最后一件事:有人建议这是"由于格式的自然继承",但我没有找到如何防止这种情况。

非常感谢所有能够查看此:)

编辑:我在@ziganotschka建议后调整了段落部分

它与此主题非常相似,只是它的解决方案在这里不起作用。

这是一段新的代码:


case DocumentApp.ElementType.PARAGRAPH:
// Search for image inside parapraph type
if(partBody.asParagraph().getPositionedImages().length) {
// Assume only one image per paragraph (@TODO : to improve)
tmpImage = partBody.asParagraph().getPositionedImages()[0].getBlob().copyBlob();
// remove image from paragraph in order to add only the paragraph
partBody.asParagraph().removePositionedImage(partBody.asParagraph().getPositionedImages()[0].getId());
tmpParagraph = offerContent.appendParagraph(partBody.asParagraph());
// Then add the image afterward, without text
tmpParagraph.addPositionedImage(tmpImage);
} else if (partBody.asParagraph().getNumChildren() != 0 && partBody.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_IMAGE) {
offerContent.appendImage(partBody.asParagraph().getChild(0).asInlineImage().getBlob());
} else {
offerContent.appendParagraph(partBody.asParagraph());
}
break;

不幸的是,它仍然复制了图像。如果我评论插入图像的行(tmpParagraph.addPositionedImage(tmpImage);),则根本没有插入图像。

编辑2:这是谷歌应用脚本中的一个已知错误

https://issuetracker.google.com/issues/36763970

有关一些解决方法,请参阅注释。

您的图片以"自动换行"的形式嵌入,而不是Inline image

这就是为什么您无法使用getBody().getImages();检索它的原因

相反,您可以使用getBody().getParagraphs();[index].getPositionedImages()

我不确定为什么您的图像被复制两次,但作为一种解决方法,您可以制作图像的副本并将其作为内联图像插入

getBody().insertImage(childIndex, getBody().getParagraphs()[index].getPositionedImages()[index].copy());

随后

getBody().getParagraphs()[index].getPositionedImages()[index].removeFromParent();

显然,您需要遍历所有段落并检查每个段落是否嵌入了定位图像,以便使用正确的索引检索它们并继续。

在添加所有其他元素后,在脚本末尾添加定位图像。根据我的经验,如果在图像定位段落之后将其他元素添加到文档中,将添加额外的图像。

您可以完成此操作,我存储了对将用作图像持有者的段落元素的引用,以及任何信息(高度,宽度等)以及图像中的blob。然后在脚本结束时,只需迭代存储的引用并添加图像。

var imageParagraphs = [];    
...
case DocumentApp.ElementType.PARAGRAPH:
var positionedImages = element.getPositionedImages();  
if (positionedImages.length > 0){
var imageData = [];
for each(var image in positionedImages){
imageData.push({
height: image.getHeight(),
width: image.getWidth(),
leftOffset: image.getLeftOffset(),
topOffset: image.getTopOffset(),
layout: image.getLayout(),
blob: image.getBlob()
});
element.removePositionedImage(image.getId());
}  
var p = merged_doc_body.appendParagraph(element.asParagraph());
imageParagraphs.push({element: p, imageData: imageData});
}
else
merged_doc_body.appendParagraph(element);
break; 
...
for each(var p in imageParagraphs){
var imageData = p.imageData
var imageParagraph = p.element      
for each(var image in imageData){
imageParagraph.addPositionedImage(image.blob)
.setHeight(image.height)
.setWidth(image.width)
.setLeftOffset(image.leftOffset)
.setTopOffset(image.topOffset)
.setLayout(image.layout);                
}
}

最新更新