javascriptgoogle-apps-scriptinsertioninline-images

Google Apps Script (Javascript) - findText returns location relative to inline image, not start of paragraph


I am trying to insert an image in the middle of a paragraph from the results of findText, but when there are other images before in the paragraph it doesn't work as planned.

Currently, my code(partially based on the responses to this question) works by finding the place that needs to be inserted, then getting the child index of the paragraph the findText() returned. However, if there is an inline image, the chid index is returned as the start of the paragraph, but the offset from the findText is characters from the end of the image, not the start of the paragraph.

Here is the relevant part of the script:

function placeImage(start, end) {
  var d = DocumentApp.getActiveDocument()
  var s = d.getBody();

  var logoResult = s.findText(start);
  var placeHolderStart = logoResult.getStartOffset(); //position of image insertion
  var logoResult2 = s.findText(end, logoResult);
  var placeHolderEnd = logoResult2.getStartOffset(); //text between placeHolderStart and placeHolderEnd will be permanently deleted

  var textElement = logoResult.getElement();
  var paragraph= textElement.getParent();
  var childIndex = paragraph.getParent().getChildIndex(paragraph);  //gets paragraph number

  var par = s.getChild(childIndex).asParagraph(); //entire paragraph containing point of insertion
  var parcopy = par.copy();
  var totalLen = par.editAsText().getText().length-1;

  par.editAsText().deleteText(placeHolderStart, totalLen); //delete all text after insertion point; some will be added back later from parcopy
  parcopy.editAsText().deleteText(0, placeHolderEnd + 1); //this would be the remaining text that gets pasted at the end

  var resp = UrlFetchApp.fetch("https://www.google.com/images/srpr/logo11w.png");
  var logoBlob = resp.getBlob();
  var img = s.getChild(childIndex).appendInlineImage(logoBlob);
  var toMerge = s.insertParagraph(childIndex+1, parcopy);
  toMerge.merge();
  return 1;
}

Solution

  • A paragraph contains several child elements e.g. strings of text or images. You need to get the index of the text element inside the paragraph, not the index of the paragraph inside the document. Try this

    function placeImage(start, end) {
      var d = DocumentApp.getActiveDocument()
      var s = d.getBody();
    
      var logoResult = s.findText(start);
      var placeHolderStart = logoResult.getStartOffset(); //position of image insertion
      var logoResult2 = s.findText(end, logoResult);
      var placeHolderEnd = logoResult2.getEndOffsetInclusive(); //text between placeHolderStart and placeHolderEnd will be permanently deleted
    
      var textElement = logoResult.getElement(); 
      var text = textElement.getText();
      var paragraph = textElement.getParent();
      var childIndex = paragraph.getChildIndex(textElement);  //gets index of text element in paragaph
    
      var textSecondHalf = text.substring(placeHolderEnd + 1);
      textElement.deleteText(placeHolderStart, text.length-1);
      paragraph.insertText(childIndex+1, textSecondHalf);
    
      var resp = UrlFetchApp.fetch("https://www.google.com/images/srpr/logo11w.png");
      var logoBlob = resp.getBlob();
      paragraph.insertInlineImage(childIndex+1, logoBlob);
    }