GAS is it possible to replace getActiveDocument().getSelection() at once?
Asked Answered
S

1

6

My User has the following selection in his Gdoc.

enter image description here

Now from the sidebar he wants to to replace the selection he made on the document.
The GAS question is if it is possible to do that at once, something like:
var selection = DocumentApp.getActiveDocument().getSelection() selection.replace("newtext")
Or do I have to loop through selection.getRangeElements() in order to delete them (or replace them) and than in someway place the new text in that position?

Scrub answered 6/2, 2014 at 18:35 Comment(1)
BTW when I just select the image I do not know how to replace it...Scrub
C
8

Not, that's not possible (well, if it is, it's not documented).

You have to loop through the selected elements, mainly because the selection may take part of paragraphs, forcing you to manage that. i.e. deleting just the selected part. And for completed selected elements, you can just remove them entirely (like images).

Here's an implementation on how to do this (part of the Kaylan's Translate script modified by me to properly replace images and partially selected paragraphs.

function replaceSelection(newText) {
  var selection = DocumentApp.getActiveDocument().getSelection();
  if (selection) {
    var elements = selection.getRangeElements();
    var replace = true;
    for (var i = 0; i < elements.length; i++) {
      if (elements[i].isPartial()) {
        var element = elements[i].getElement().asText();
        var startIndex = elements[i].getStartOffset();
        var endIndex = elements[i].getEndOffsetInclusive();
        var text = element.getText().substring(startIndex, endIndex + 1);
        element.deleteText(startIndex, endIndex);
        if( replace ) {
          element.insertText(startIndex, newText);
          replace = false;
        }
      } else {
        var element = elements[i].getElement();
        if( replace && element.editAsText ) {
          element.clear().asText().setText(newText);
          replace = false;
        } else {
          if( replace && i === elements.length -1 ) {
            var parent = element.getParent();
            parent[parent.insertText ? 'insertText' : 'insertParagraph'](parent.getChildIndex(element), newText);
            replace = false; //not really necessary since it's the last one
          }
          element.removeFromParent();
        }
      }
    }
  } else
    throw "Hey, select something so I can replace!";
}
Chasseur answered 6/2, 2014 at 20:24 Comment(7)
So when I loop through the elements I do element.deleteText(startIndex, endIndex); element.insertText(startIndex, address); for the partial elements and for the full elements I do elements[i].getElement().removeFromParent();. But how do I know where to put the replacing text, as I do not have a way to place the cursor? previousElement.getEndOffsetInclusive()maybe?Scrub
About the cursor issue 3039Scrub
You don't need the cursor, just replace the text on the first possible element, I'm assuming there's at least some text selected. I updated my answer with some code showing how to do that. But this code does not take care of the situation where there's not even a single text element selected.Chasseur
in case the only element selected is not a text but an image for example... how do you replace it, in your script you get to remove the element but how do you change the image for a text? I removed the image and placed the newText at the end of the previousElement.Scrub
I edited again to enhance the code for the situation where there's just an image or other non-text element selected.Chasseur
It also resolves the blank end of line selection! :-)Scrub
now eight years later there is still no simpler solution? :(Bekha

© 2022 - 2024 — McMap. All rights reserved.