1

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;
}
Community
  • 1
  • 1
John Targaryen
  • 1,109
  • 1
  • 13
  • 29

1 Answers1

2

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);
}
Tesseract
  • 8,049
  • 2
  • 20
  • 37
  • I changed my child element insertion to yours; now it completely fails and identifies the wrong child index. Also, `var textSecondHalf = text.substring (placeHolderEnd + 1);` will delete all images in front of the place i want to insert, right; I would like to keep images AND text in the rest of the paragraph. – John Targaryen Jun 03 '15 at 04:31
  • Also, getStartOffset is used to get the index of the text in the paragraph, and childIndex is for the index of the paragraph inside the body. Both are needed for image insertion. Can you please elaborate on how I am doing it wrong? – John Targaryen Jun 03 '15 at 04:33
  • 1
    getStartOffset gets the index of the letter inside the text element. And childIndex is the index of the text element inside the paragraph. You don't need the index of the paragraph. A text element never contains images so editing it can't possibly delete any. A paragraph can contain several text elements and images. So to make it more clear - the child elements of a document are paragraphs. The child elements of a paragraph can be text elements, images, etc. – Tesseract Jun 03 '15 at 14:48
  • 1
    Could you give me an example document where my function fails? – Tesseract Jun 03 '15 at 14:54
  • Ah, thanks for the longer explanation. I fixed my code, and now it works! I didn't realize that it is possible to insert an inline image in the middle of a paragraph as long as the child index is known. – John Targaryen Jun 03 '15 at 21:43
  • However, I still don't understand how your script keeps all the inline images in the rest of the paragraph after placeHolderEnd. You say `var text = textElement.getText(); ... var textSecondHalf = text.substring(placeHolderEnd + 1);`, but wouldn't that take the substring of the only the _text_ and delete all the inline images?? – John Targaryen Jun 03 '15 at 21:45
  • Also, for a case that doesn't work, if you put some text inside a table where the only thing in the document is the table, then you run the script, it returns that childIndex is invalid. – John Targaryen Jun 03 '15 at 22:03
  • 1
    The images are not contained in the text element. They are seperate elements in the paragraph. So I can modify the text as much as I want without deleting any images. Also I tried it with a table and it works fine. Of course start and end have to be in the same table cell. – Tesseract Jun 03 '15 at 23:09
  • Thanks! Also, when you say `paragraph.insertInlineImage(childIndex+1, logoBlob);`, why is it different from `s.getChild(childIndexParagraph).insertInlineImage(childIndex+1, logoBlob);`? Why does the latter return an error? Why is there a difference? – John Targaryen Jun 04 '15 at 01:25
  • 1
    If the paragraph is inside a table then it is not a direct child element of the document. This works just like folders on your disk. If you have a folder called `C:\table1\tablerow1\tablecell1\paragraph1` and you then try to access `C:\paragraph1`, it's not the same folder. – Tesseract Jun 04 '15 at 02:00
  • Thanks for all the really useful help. One last question. When you say `var textSecondHalf = text.substring(placeHolderEnd + 1); textElement.deleteText(placeHolderStart, text.length-1); paragraph.insertText(childIndex+1, textSecondHalf);`, won't that delete all the formatting for this deleted text? – John Targaryen Jul 18 '15 at 17:38