How to copy image from one table cell to another within google documents using a google script (programmatically)?

痞子三分冷 提交于 2021-01-29 09:49:53

问题


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.
    1. Copy the source table to the target.
    2. Retrieve paragraphs in a cell.
    3. Retrieve the image.
    4. Delete image from the target cell.
    5. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!