Search code examples
stringgoogle-apps-scriptgoogle-docs

Google apps script for docs: Log text selection as string


I'm trying to return the words in a text selection as a string in google docs. I can't figure out how to return anything other than the entire body of text in an element, and it seems like the smallest element is a paragraph. I ned smaller.

Attempt 1:

function printSelection1 () {
var string = DocumentApp.getActiveDocument().getText();
Logger.log(string);
}

This returns the entire body of the document, rather than the selection, as a string.

Attempt 2:

function printSelection2 () {
var selection = DocumentApp.getActiveDocument().getSelection();
var string =selection.asString();
Logger.log(string);
}

Error message: "TypeError: selection.asString is not a function."

Attempt 3:

function printSelection4 () {
var selection = DocumentApp.getActiveDocument().getSelection();
var getelements =selection.getSelectedElements();
var string = getelements.toString();
Logger.log(string);
}

This returns the string "RangeElement," rather than the string of the selection itself.

I feel like I'm close. Or maybe I'm not?


Solution

  • Use Document.getSelection() to get the selected Range and Range.getRangeElements() to get the elements in the Range, including any Text elements therein.

    You are saying that you want to get "only the individual words that are selected." To get text that spans just a portion of an element, such as in the start and end of the selection, use RangeElement.isPartial() together with RangeElement.getStartOffset() and RangeElement.getEndOffsetInclusive(). When isPartial() returns false, you can use RangeElement.getElement().asText().getText() to get all the text in the element.

    Here's an example of how to do this:

    function printSelection() {
      const selectedText = getSelectedText();
      console.log(selectedText ? `The selected text is "${selectedText}".` : `No text is selected.`);
    }
    
    /**
    * Gets the currently selected text in a document.
    *
    * @param {DocumentApp.Range} range Optional. The document range where to get text. Defaults to currently selected text.
    * @return {String} The text in range joined with newlines, or an empty string when the range does not contain text.
    */
    function getSelectedText(range = DocumentApp.getActiveDocument().getSelection()) {
      const result = [];
      if (range) {
        range.getRangeElements().forEach(rangeElement => {
          if (rangeElement.isPartial()) {
            const startIndex = rangeElement.getStartOffset();
            const endIndex = rangeElement.getEndOffsetInclusive();
            result.push(rangeElement.getElement().asText().getText().substring(startIndex, endIndex + 1));
          } else {
            const element = rangeElement.getElement();
            if (element.editAsText) {
              const elementText = element.asText().getText();
              if (elementText) {
                result.push(elementText);
              }
            }
          }
        });
      }
      return result.length ? result.join('\n') : '';
    }
    

    This example is based on the partially outdated Docs quickstart.