5

I'm writing an add on for Google Docs to allow users to choose from lists of canned text samples to insert into their document. I want the text inserted like this:

1st_text_insertion

2nd_text_insertion

3rd_text_insertion

However, my code results in the following:

3rd_text_insertion

2nd_text_insertion

1st_text_insertion

The reverse ordering occurs because the cursor position remains in the same place rather than updating to the end of the last text insertion.

Here's the code I'm using:

function insertText(text) {
  var doc = DocumentApp.getActiveDocument();
  var cursor = doc.getCursor();
  newPosition = cursor.insertText(text + '\r');
  doc.setCursor(newPosition);
}

The code needs to be flexible enough to insert text wherever the cursor is placed and then add new entries following a return character. For example, if the user placed their cursor on a blank line between existing text items B and C, the inserted text should appear on new lines between items B and C.

Example before text insertion:

existing_text_A

existing_text_B

existing_text_C

Desired output after text insertion:

existing_text_A

existing_text_B

1st_text_insertion

2nd_text_insertion

3rd_text_insertion

existing_text_C

I've tried several approaches, such as using appendText or getNextSibling, but they don't produce the desired output. Thanks for any help!

Rubén
  • 34,714
  • 9
  • 70
  • 166
STEM FabLab
  • 380
  • 3
  • 13

3 Answers3

4

This will put the cursor at the end of the inserted text.

function insertTextAtCursor(txt){
  var doc=DocumentApp.getActiveDocument();
  var body=doc.getBody();
  var t=doc.getCursor().insertText('\n' + txt);
  var txtEl=doc.getCursor().getElement();
  var txtOff=doc.getCursor().getOffset();
  var pos=doc.newPosition(txtEl, txtOff + 1);//I can't actually explain this.  I figured out based upon the error I was getting in the console log
  doc.setCursor(pos);
}
davidsbro
  • 2,761
  • 4
  • 23
  • 33
Cooper
  • 59,616
  • 6
  • 23
  • 54
0

Cooper, thank you! Your answer worked.

I found I needed to handle special cases with paragraphs and list items. I expanded on your code and I'm sharing this solution to help others.

function insertText(txt){
// Summary: Locates the user's cursor, then inserts new text as either a 
  // new paragraph or a new list item, and then updates the cursor position 
  // after the inserted text.
  var doc=DocumentApp.getActiveDocument();
  var txtPos=doc.getCursor();
  var txtElement=txtPos.getElement();
  var txtElementType=txtElement.getType();
  parentElement = txtElement.getParent();
  childIndex = parentElement.getChildIndex(txtElement);
  // Determines if text is within a paragraph and adds a new paragraph
  if (txtElementType == DocumentApp.ElementType.PARAGRAPH) {
    var t = parentElement.insertParagraph(childIndex + 0,txt);

  // Determines if text is within a list item and adds a new list item
  } else if (txtElementType == DocumentApp.ElementType.LIST_ITEM) {
    txtGlyphType = txtElement.getGlyphType();
    var t = parentElement.insertListItem(childIndex + 0, txt).setGlyphType(txtGlyphType);

  // Determines if text is within a text element (e.g., within a multi-word block of text)
  // and then determines whether the text element is within a paragraph or a list item.
  } else if (txtElementType == DocumentApp.ElementType.TEXT) {
    parentElementType = parentElement.getType();
    parentparentElement = parentElement.getParent();
    parentparentIndex = parentparentElement.getChildIndex(parentElement);

    // Adds a new paragraph if text element is within a paragraph 
    if (parentElementType == DocumentApp.ElementType.PARAGRAPH) {
    var t = parentparentElement.insertParagraph(parentparentIndex + 0,txt); 

      // Adds a new list item if text element is within a list item
    } else if (parentElementType == DocumentApp.ElementType.LIST_ITEM) {
      parentGlyphType = parentElement.getGlyphType();
      var t = parentparentElement.insertListItem(parentparentIndex + 0, txt).setGlyphType(parentGlyphType);
    }
  }
  // Updates the position of the cursor to follow the inserted text
  newPosition = parentElement.getChild(childIndex + 1);
  var pos = doc.newPosition(newPosition, 0);
  doc.setCursor(pos);
}
STEM FabLab
  • 380
  • 3
  • 13
0

A short version:

const doc = DocumentApp.getActiveDocument();
const cursor = doc.getCursor();
doc.setCursor(doc.newPosition(cursor.getElement(), cursor.getOffset() + 1));
gaspar
  • 898
  • 1
  • 13
  • 26