1

In Google docs, this function changes the selected text to black

function selectedFontColorBlack() {
//   DocumentApp.getUi().alert('selectedFontColorBlack');
   var sel = DocumentApp.getActiveDocument().getSelection();
   var elements = sel.getRangeElements();
   for (var i = 0; i < elements.length; i++) {
      var element = elements[i];

      // Only modify elements that can be edited as text; skip images and other non-text elements.
      if(element.getElement().editAsText) {
         var text = element.getElement().editAsText();

       // Bold the selected part of the element, or the full element if it's completely selected.
       if (element.isPartial()) {
         text.setForegroundColor(element.getStartOffset(), element.getEndOffsetInclusive(), "#000000");
       } else {
         text.setForegroundColor("#000000");
       }
     }
   }
}

This function changes the entire paragraph in which the cursor (or selection) exists to uppercase:

function uppercaseSelected() {
//  DocumentApp.getUi().alert('uppercaseSelected');
   var sel = DocumentApp.getActiveDocument().getSelection();
   var elements = sel.getRangeElements();
   for (var i = 0; i < elements.length; i++) {
      var element = elements[i];

      // Only modify elements that can be edited as text; skip images and other non-text elements.
      if(element.getElement().editAsText) {
         var text = element.getElement().editAsText();
         text.setText(text.getText().toUpperCase());
       }
   }
}

I don't see any corresponding setText function that works on the selection's "offset", as does the setForegroundColor(Integer,Integer,String). (Both of these functions are in class Text.)

How can I change the actually selected text to uppercase, and not the entire paragraph in which the selection exists?

Thank you.

aliteralmind
  • 19,847
  • 17
  • 77
  • 108

2 Answers2

3

Try using the setAttributes(startOffset, endOffsetInclusive, attributes) method. Check out the documentation [EDIT: my bad, i don't think that'll do it. I'll look a bit longer tho]
The gem hidden in the post that @Mogsdad is referring to is this: var selectedText = elementText.substring(startOffset,endOffset+1);.
to be little more verbose on how this is used: you can use the string method substring on objects such as DocumentApp.getActiveDocument().getSelection().getSelectedElements()[i].getElement().editAsText().getText() so, essentially, grab that substring, convert it to uppercase, delete the text in the range (selectedElement.getstartOffset,selectedElement.endOffsetInclusive) and insert the bolded text at selectedElement.getstartOffset

Tada! check it out:

function uppercaseSelected() {
   // Try to get the current selection in the document. If this fails (e.g.,
   // because nothing is selected), show an alert and exit the function.
   var selection = DocumentApp.getActiveDocument().getSelection();
   if (!selection) {
      DocumentApp.getUi().alert('Cannot find a selection in the document.');
      return;
   }

   var selectedElements = selection.getSelectedElements();
   for (var i = 0; i < selectedElements.length; ++i) {
      var selectedElement = selectedElements[i];

      // Only modify elements that can be edited as text; skip images and other
      // non-text elements.
      var text = selectedElement.getElement().editAsText();

      // Change the background color of the selected part of the element, or the
      // full element if it's completely selected.
      if (selectedElement.isPartial()) {
        var bitoftext = text.getText().substring(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive() + 1);
        text.deleteText(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive());
        text.insertText(selectedElement.getStartOffset(), bitoftext.toUpperCase());
      }  else  {
        text.setText(text.getText().toUpperCase());
      }
   }
}
danyamachine
  • 1,848
  • 1
  • 18
  • 21
  • That seems to be what I need for some other stuff though, so good information. – aliteralmind Jul 19 '14 at 19:01
  • i haven't figure it out yet! it's a very sandboxed API – danyamachine Jul 19 '14 at 20:05
  • This works beautifully, as long as the selection does not span multiple paragraphs. This may actually be an acceptable solution, just as it is, though. I wonder if it's possible to make this work with a multi-paragraph selection. Either way, though, this is definitely what I need! Thank you. – aliteralmind Jul 19 '14 at 22:09
  • @aliteralmind i fixed it. the contents of the `else` codeblock were broken – danyamachine Jul 20 '14 at 08:21
2

Started with the code from Google App script Document App get selected lines or words?, and made this almost a year ago. I'm happy if it helps you.

The "trick" is that you need to delete the original text and insert the converted text.

This script produces a menu with options for UPPER, lower and Title Case. Because of the delete / insert, handling more than one paragraph needs special attention. I've left that to you!

function onOpen() {
  DocumentApp.getUi().createMenu('Change Case')
    .addItem("UPPER CASE", 'toUpperCase' )
    .addItem("lower case", 'toLowerCase' )
    .addItem("Title Case", 'toTitleCase' )
    .addToUi();
}

function toUpperCase() {
  _changeCase(_toUpperCase);
}

function toLowerCase() {
  _changeCase(_toLowerCase);
}

function toTitleCase() {
  _changeCase(_toTitleCase);
}

function _changeCase(newCase) {
  var doc = DocumentApp.getActiveDocument();
  var selection = doc.getSelection();
  var ui = DocumentApp.getUi();
  var report = "";  // Assume success

  if (!selection) {
    report = "Select text to be modified.";
  }
  else {
    var elements = selection.getSelectedElements();
    if (elements.length > 1) {
      report = "Select text in one paragraph only.";
    }
    else {
      var element = elements[0].getElement();
      var startOffset = elements[0].getStartOffset();      // -1 if whole element
      var endOffset = elements[0].getEndOffsetInclusive(); // -1 if whole element
      var elementText = element.asText().getText();       // All text from element
      // Is only part of the element selected?
      if (elements[0].isPartial())
        var selectedText = elementText.substring(startOffset,endOffset+1);
      else
        selectedText = elementText;

      // Google Doc UI "word selection" (double click)
      // selects trailing spaces - trim them
      selectedText = selectedText.trim();
      endOffset = startOffset + selectedText.length - 1;

      // Convert case of selected text.
      var convertedText = newCase(selectedText);
      element.deleteText(startOffset, endOffset);
      element.insertText(startOffset, convertedText);
    }
  }
  if (report !== '') ui.alert( report );
}

function _toUpperCase(str) {
  return str.toUpperCase();
}

function _toLowerCase(str) {
  return str.toLowerCase();
}

// https://stackoverflow.com/a/196991/1677912
function _toTitleCase(str)
{
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
Community
  • 1
  • 1
Mogsdad
  • 44,709
  • 21
  • 151
  • 275