问题
I would like to copy the content of one google doc to another. The content includes text, tables and images.
My code copies the text and the tables. However, whatever is contained in table cells is not copied.
I made a simplified version of the code and single document accessible here: https://docs.google.com/document/d/1hcQzBuMA6E15u8VtW2lWGL7XCcU3qVsDhn-5jiznQP4/edit?usp=sharing.
The code simply copy-pastes the content of the google document which includes a table containing a table/images. The same problem occurs. The content of the cell is not copied. see screenshot
Here is the simplified version of the code:
function test() {
// Make Copy of template file
doc = DocumentApp.getActiveDocument();
body =doc.getBody();
/// Copy elements from source file to target file one bich one
var totalElements = body.getNumChildren();
var types = new Array;
for( var iel = 0; iel < totalElements; iel++ ) {
current_body = doc.getBody();
var element = body.getChild(iel).copy();
var type = element.getType();
types.push(type);
switch(type){
case DocumentApp.ElementType.PARAGRAPH:
body.appendParagraph(element);
break;
case DocumentApp.ElementType.TABLE:
var newTable =body.insertTable( body.getNumChildren()-1, element );
CopyTableCellByCell( element, newTable );
break;
case DocumentApp.ElementType.LIST_ITEM:
body.appendListItem(element);
break;
case DocumentApp.ElementType.INLINE_IMAGE:
body.appendImage(element);
break;
}
}
doc.saveAndClose();
}
// recursive function that replaces each cell by first clearing it and Copying the content from the original table
function CopyTableCellByCell( srcTable, dstTable ) {
var numRows = srcTable.getNumRows();
var srcRow, numCells, dstCell, icell;
var types = new Array;
for ( var irow = 0; irow < numRows; irow++ ) {// EACH ROW
srcRow = srcTable.getRow( irow );
dstRow = dstTable.getRow( irow );
numCells = srcRow.getNumCells();
for ( icell = 0; icell < numCells; icell++ ) { // EACH CELL
dstCell = dstRow.getCell( icell );
dstCell.clear();
var srcCell = srcTable.getCell( irow, icell );
var numCellChildren = srcCell.getNumChildren(); // ==> outputs 1 paragraph child instead of a paragraph and a table.
for ( var ich = 0; ich < numCellChildren; ich++ ) { // EACH CHILD
var cellChild = srcCell.getChild( ich );
var childCopy = cellChild.copy();
var type = childCopy.getType();
types.push(type);
switch( type ){
case DocumentApp.ElementType.PARAGRAPH:
dstCell.insertParagraph( ich, childCopy );
break;
case DocumentApp.ElementType.LIST_ITEM:
var atts = childCopy.getAttributes();
var newListItem = dstCell.insertListItem( ich, childCopy );
newListItem.setAttributes( atts );
break;
case DocumentApp.ElementType.TABLE:
var newTable = dstCell.insertTable( ich, childCopy );
CopyTableCellByCell( cellChild, newTable );
break;
case DocumentApp.ElementType.INLINE_IMAGE:
var parpar = childCopy.getParent();
var ttt = parpar.getType();
destImg = parpar.insertInlineImage(l, childCopy.getBlob());
dstImg.setWidth(childCopy.getWidth());
dstImg.setHeight(childCopy.getHeight());
break;
}
}
}
}
}
Thanks for your help.
回答1:
How about this modification? I have experienced the same situation with you. At that time, I used this workaround. I think that there might be several solutions for your situation. So please think of this as one of them.
Modification points:
- In the case that a table is copied, when there are the cells including images, it copies the images from source table to the target table. By this, the image can be seen. The flow is as follows.
- Copy the source table to the target.
- Retrieve paragraphs in a cell.
- Retrieve the image.
- Delete image from the target cell.
- Copy image from the source cell to the target cell.
Modified script:
Please modify as follows.
From:else if( type == DocumentApp.ElementType.TABLE){
body.appendTable(element);
}
To:
else if( type == DocumentApp.ElementType.TABLE){
var dstTable = body.appendTable(element);
var srcTable = element.asTable();
var row = srcTable.getNumRows();
for (var i = 0; i < row; i++) {
var col = srcTable.getRow(i).getNumCells();
for (var j = 0; j < col; j++) {
var cell = srcTable.getCell(i, j);
var c1 = cell.getNumChildren();
for (var k = 0; k < c1; k++) {
var paragraph = cell.getChild(k).asParagraph();
var c2 = paragraph.getNumChildren();
for (var l = 0; l < c2; l++) {
var child = paragraph.getChild(l);
var t = child.getType();
if (t === DocumentApp.ElementType.INLINE_IMAGE) {
var srcImg = child.asInlineImage();
var dstParagraph = dstTable.getCell(i, j).getChild(k).asParagraph().clear();
var dstImg = dstParagraph.insertInlineImage(l, srcImg.getBlob());
dstImg.setWidth(srcImg.getWidth());
dstImg.setHeight(srcImg.getHeight());
}
}
}
}
}
}
References:
- Class Table
- Class TableCell
- Class InlineImage
Although in my environment, I could confirm that this modified script worked when the image in your question was used as the sample situation, if this didn't work in your environment, I'm sorry.
Edit 1:
For your added situation, please modify your script as follows.
From:
else if( type == DocumentApp.ElementType.TABLE){
body.appendTable(element);
}
To:
else if( type == DocumentApp.ElementType.TABLE){
var dstTable = body.appendTable(element);
var srcTable = element.asTable();
copyTable(srcTable, dstTable);
}
And please add a following function.
function copyTable(srcTable, dstTable) {
var row = srcTable.getNumRows();
for (var i = 0; i < row; i++) {
var col = srcTable.getRow(i).getNumCells();
for (var j = 0; j < col; j++) {
var cell = srcTable.getCell(i, j);
var c1 = cell.getNumChildren();
for (var k = 0; k < c1; k++) {
var ty = cell.getChild(k).getType();
if (ty === DocumentApp.ElementType.TABLE) {
srcTable = cell.getChild(k).asTable();
dstTable = dstTable.getCell(i, j).getChild(k).asTable();
return copyTable(srcTable, dstTable);
} else {
var paragraph = cell.getChild(k).asParagraph();
var c2 = paragraph.getNumChildren();
for (var l = 0; l < c2; l++) {
var child = paragraph.getChild(l);
var t = child.getType();
if (t === DocumentApp.ElementType.INLINE_IMAGE) {
var srcImg = child.asInlineImage();
var dstParagraph = dstTable.getCell(i, j).getChild(k).asParagraph().clear();
var dstImg = dstParagraph.insertInlineImage(l, srcImg.getBlob());
dstImg.setWidth(srcImg.getWidth());
dstImg.setHeight(srcImg.getHeight());
}
}
}
}
}
}
}
Edit 2:
For your added situation, please modify your script as follows.
From:
else if( type == DocumentApp.ElementType.TABLE){
body.appendTable(element);
}
To:
else if( type == DocumentApp.ElementType.TABLE){
var dstTable = body.appendTable(element);
var srcTable = element.asTable();
copyTable(srcTable, dstTable);
}
And please add a following function.
function copyTable(srcTable, dstTable) {
var row = srcTable.getNumRows();
for (var i = 0; i < row; i++) {
var col = srcTable.getRow(i).getNumCells();
for (var j = 0; j < col; j++) {
var cell = srcTable.getCell(i, j);
var c1 = cell.getNumChildren();
for (var k = 0; k < c1; k++) {
var ty = cell.getChild(k).getType();
if (ty === DocumentApp.ElementType.TABLE) {
srcTable = cell.getChild(k).asTable();
dstTable = dstTable.getCell(i, j).getChild(k).asTable();
return copyTable(srcTable, dstTable);
} else {
var paragraph = cell.getChild(k).asParagraph();
var c2 = paragraph.getNumChildren();
for (var l = 0; l < c2; l++) {
var child = paragraph.getChild(l);
var t = child.getType();
if (t === DocumentApp.ElementType.INLINE_IMAGE) {
var srcImg = child.asInlineImage();
var dstParagraph = dstTable.getCell(i, j).getChild(k).asParagraph();
dstParagraph.getChild(l).asInlineImage().removeFromParent();
var dstImg = dstParagraph.insertInlineImage(l, srcImg.getBlob());
dstImg.setWidth(srcImg.getWidth());
dstImg.setHeight(srcImg.getHeight());
}
}
}
}
}
}
}
回答2:
The code is almost functioning. The last issue is that the text that is in line with the images does not get copied.
I now restructured the code with additional functions. copyContent() calls copyTable() calls copyCellChild()
copyCellChild(), the function that copies the children of the cells from a source cell to a target cell cause the errors.
copyCellChild() ignores text in line with images.
function copyContent() {
// Make Copy of template file
doc = DocumentApp.getActiveDocument();
body =doc.getBody();
/// Copy elements from source file to target file one bich one
var totalElements = body.getNumChildren();
var types = new Array;
for( var iel = 0; iel < totalElements; iel++ ) {
current_body = doc.getBody();
var element = body.getChild(iel).copy();
var type = element.getType();
types.push(type);
switch(type){
case DocumentApp.ElementType.PARAGRAPH:
body.appendParagraph(element);
break;
case DocumentApp.ElementType.TABLE:
//var newTable =body.insertTable( body.getNumChildren()-1, element );
//CopyTableCellByCell( element, newTable );
var dstTable = body.appendTable(element);
var srcTable = element.asTable();
copyTable(srcTable, dstTable);
break;
case DocumentApp.ElementType.LIST_ITEM:
body.appendListItem(element);
break;
case DocumentApp.ElementType.INLINE_IMAGE:
body.appendImage(element);
break;
}
}
doc.saveAndClose();
}
function copyTable(srcTable, dstTable) {
var row = srcTable.getNumRows();
for (var i = 0; i < row; i++) { // ROW
var col = srcTable.getRow(i).getNumCells();
for (var j = 0; j < col; j++) { // CELL
var srcCell = srcTable.getCell(i, j);
var c1 = srcCell.getNumChildren();
var destCell = dstTable.getCell(i, j);
for (var k = 0; k < c1; k++) { // CHILD
copyCellChild(srcCell,destCell,k);
}
}
}
}
function copyCellChild(srcCell,destCell,k){
var srcChild = srcCell.getChild(k);
var destChild = destCell.getChild(k);
var ty = srcChild.getType();
switch(ty){
case DocumentApp.ElementType.TABLE:
srcTable = srcChild.asTable();
dstTable = destChild.asTable();
return copyTable(srcTable, dstTable);
break;
case DocumentApp.ElementType.INLINE_IMAGE:
var srcImg = srcChild.asInlineImage();
var dstParagraph = destChild.asParagraph();
var dstImg = dstParagraph.insertInlineImage(l, srcImg.getBlob());
dstImg.setWidth(srcImg.getWidth());
dstImg.setHeight(srcImg.getHeight());
break;
case DocumentApp.ElementType.PARAGRAPH:
var paragraph = srcChild.asParagraph();//
var c2 = paragraph.getNumChildren();
for (var l = 0; l < c2; l++) { // PARAGRAPH CHILDREN
try{
var srcParaChild = paragraph.getChild(l);
var t = srcParaChild.getType();
switch(t){
case DocumentApp.ElementType.INLINE_IMAGE:
var srcImg = srcParaChild.asInlineImage();
var dstParagraph = destChild.asParagraph().clear();
//var dstParagraph = destChild.asInlineImage().clear();//clear
var dstImg = dstParagraph.insertInlineImage(l, srcImg.getBlob());
dstImg.setWidth(srcImg.getWidth());
dstImg.setHeight(srcImg.getHeight());
dstImg.setLinkUrl(srcImg.getLinkUrl);
break;
case DocumentApp.ElementType.TEXT:
//var srcTxt = srcChild.getText();
//Logger.log(srcTxt);
//var iii = 1;
//destChild.asText().appendText(srcTxt);
}
}catch(e){// text in line with images
var srcTxt = srcChild.getText();
Logger.log(srcTxt);
var iii = 1;
destChild.asText().appendText(srcTxt);
}
}
}
}
Here is the example google doc where you can run the function : https://docs.google.com/document/d/1hcQzBuMA6E15u8VtW2lWGL7XCcU3qVsDhn-5jiznQP4/edit#
来源:https://stackoverflow.com/questions/53873919/how-to-copy-image-from-one-table-cell-to-another-within-google-documents-using-a