Here my maybe not very elegant workaround. The problem was that body.getChild(index) lost nested images inside a table cell.
This also happened when I inserted or appended a table as a whole, no matter if the source was a body child or from body.getTables(). The images got corrupted.
I now run manually through the table cell by cell in the aftermath and replace each corrupted inline imgage (placeholders with exclamation mark) with the belonging image from body.getTables(). Now they are displayed correctly. Very strange.
Be careful: If a table is nested inside a table, it will be an additional entry in the array body.getTables() but NOT be part of the body children body.getChild(index)(--> only top level tables). I had to link the two in a way that the indices don't get mixed up.
Here my code:
function mergeDocs() {
var dstBody = DocumentApp.openById("1XmWwK2ni2JyX4Ii1ow19AehLqPkdYGOsj5XFSrlkaw4").getBody(); //Doc to append content to
var srcBody = DocumentApp.openById("1ygNn1kgiFchuSf1mBs6RiS4GiBx3KPcKK07E_WWlsBE").getBody(); //Source Doc to be copied
var totalElements = srcBody.getNumChildren();
for (var j = 0; j < totalElements; ++j) {
var dstChild = srcBody.getChild(j).copy();
var type = dstChild.getType();
if (type == DocumentApp.ElementType.PARAGRAPH) dstBody.appendParagraph(dstChild);
else if (type == DocumentApp.ElementType.TABLE){
var allSrcTables = srcBody.getTables();
var tableIndex;
var tables = allSrcTables.forEach(function(table){
// !! getChildIndex(table) will crash if a table is nested inside is a table --> nested tables are part of body.getTables() but NOT part of the body children (body.getChild(j)): No belonging body child index can be found for a subtable!!
//only execude the method getChildIndex() if a table is not nested inside another table
if(table.getParent().getType() !== DocumentApp.ElementType.TABLE_CELL){
var childIndex = srcBody.getChildIndex(table);
if (childIndex == j){
tableIndex = allSrcTables.indexOf(table);
}
}
});
var srcTable = allSrcTables[tableIndex];
var newTable = dstBody.insertTable( dstBody.getNumChildren()-1, srcTable.copy());
//replace all corrupted inline images with working ones from srcBody.getTables();
replaceCorruptedImages(srcTable, newTable);
}
else if (type == DocumentApp.ElementType.LIST_ITEM) dstBody.appendListItem(dstChild);
else throw new Error('Unknown element type: ' + type);
}
}
function replaceCorruptedImages(srcTable, dstTable) {
var numRows = dstTable.getNumRows();
var dstRow, numCells, dstCell, actCellIndex;
for (var actRowIndex = 0; actRowIndex < numRows; actRowIndex++) {
dstRow = dstTable.getRow(actRowIndex);
numCells = dstRow.getNumCells();
for (actCellIndex = 0; actCellIndex < numCells; actCellIndex++) {
dstCell = dstRow.getCell(actCellIndex);
//dstCell.clear();
var srcCell = srcTable.getCell(actRowIndex, actCellIndex);
var numCellChildren = srcCell.getNumChildren();
for (var y = 0; y < numCellChildren; y++) {
var cellChild = srcCell.getChild(y);
var childCopy = cellChild.copy();
switch(childCopy.getType()) {
case DocumentApp.ElementType.INLINE_IMAGE:
dstCell.getChild(y).removeFromParent();
dstCell.appendInlineImage(childCopy);
//images may be nested inside a paragraph
case DocumentApp.ElementType.PARAGRAPH:
var numParaChildren = childCopy.getNumChildren();
for (var z = 0; z < numParaChildren; z++){
var paraChild = childCopy.getChild(z);
var paraChildCopy = paraChild.copy();
if (paraChildCopy.getType() == DocumentApp.ElementType.INLINE_IMAGE){
dstCell.getChild(y).getChild(z).removeFromParent();
dstCell.getChild(y).appendInlineImage(paraChildCopy);
}
}
break;
// recursive function in case a table is nested inside a table
case DocumentApp.ElementType.TABLE:
replaceCorruptedImages(cellChild, dstCell.getChild(y));
break;
}
}
}
}
}