title: Copied Image from Google Document Paragraph inserted twice
body: <p>I'm trying to combine several Google Document inside one, but images inside the originals documents are inserted twice. One is at the right location, the other one is at the end of the newly created doc.</p>
  
  <p>From what I saw, these images are detected as <code>Paragraph</code> by the script.</p>
  
  <p>As you might see in my code below, I've been inspired by similar topics found here. 
  One of them suggested searching for child <code>Element</code> inside the <code>Paragraph</code> <code>Element</code>, but debugging showed that there is none. The concerned part of the doc will always be inserted with appendParagraph method as the script is not able to properly detect the image.</p>
  
  <p>This is why the other relevant topic I found cannot work here : it suggested inserting the image before the paragraph itself but it cannot detects it.</p>
  
  <p>Logging with both default <code>Logger</code> and <code>console.log</code> from Stackdriver will display an object typed as Paragraph.
  The execution step by step did not show displayed any loop calling the <code>appendParagraph</code> method twice.</p>
  
  <pre class="lang-js prettyprint-override"><code>/* 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 &lt; 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) &amp;&amp; (null !== header)) {
        for (var j = 0; j &lt; 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 &lt; 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 &amp;&amp; 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();
    }
  }
  </code></pre>
  
  <p>The problem occurs no matter how much files are combined, using one is enough to reproduce.</p>
  
  <p>If there's only one image in the file (no spaces nor line feed around) and if the "appendPageBreak" is not used afterward, it will not occur. When some text resides next to the image, then the image is duplicated.</p>
  
  <p>One last thing : Someone suggested that it is "due to natural inheritance of formatting", but I did not find how to prevent that.</p>
  
  <p>Many thanks to everyone who'll be able to take a look at this :)</p>
  
  <p><strong>Edit : I adapted the paragraph section after @ziganotschka suggestions</strong></p>
  
  <p>It is very similar to <a href="https://stackoverflow.com/questions/55597075/image-duplicates-itself-when-using-appendparagraph-in-google-script">this subject</a> except its solution does not work here.</p>
  
  <p>Here is the new piece of code :</p>
  
  <pre class="lang-js prettyprint-override"><code>
          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 &amp;&amp; partBody.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_IMAGE) {
              offerContent.appendImage(partBody.asParagraph().getChild(0).asInlineImage().getBlob());
            } else {
              offerContent.appendParagraph(partBody.asParagraph());
            }
            break;
  
  </code></pre>
  
  <p>Unfortunately, it stills duplicate the image. And if I comment the line inserting the image (<code>tmpParagraph.addPositionedImage(tmpImage);</code>) then no image is inserted at all.</p>
  
  <p><strong>Edit 2 : it is a known bug in Google App Script</strong></p>
  
  <p><a href="https://issuetracker.google.com/issues/36763970" rel="nofollow noreferrer">https://issuetracker.google.com/issues/36763970</a></p>
  
  <p>See comments for some workaround.</p>