2

I want to programmatically style a paragraph with a background color to make a "code area", just like when using a triple backquote around a paragraph in Stackoverflow, or like in this question. I tried tweaking the scripts and gists in this question, but although the background color changed, it only did around the selected portion of text and not the entire paragraph taking up the entire width of the page.

A suggested workaround is to create a Table, but I do not want to do that.

I know it is possible because you can select a paragraph by hand, then go to Format > Paragraph styles > Borders and shading, change the background color from there and it does exactly whant I want.

What I did that only applied the color to a limited portion is (checking that element is an instance of Paragraph):

const selection = DocumentApp.getActiveDocument().getSelection();
const rangeElements = selection.getRangeElements();
const element = rangeElements[0].getElement();
element.setBackgroundColor('#D0FAF0');

How do I do what I want to do ? Is it even possible ?

  • Make a 1x1 table cell and move this paragraph inside it. Then, you have the option to fill the background with desired color. – Sam Chats yesterday
3
  • You want to modify the shading color of the selected paragraph on Google Document using Google Apps Script.
  • You want to modify the color of the entire paragraph taking up the entire width of the page.

If my understanding is correct, how about this sample script? Unfortunately, in the current stage, there are no methods for modifying the shading color of a paragraph in Document Service, yet. I think that this might be achieved with Document Service by the future update. But as a current workaround, I thought that Google Docs API released recently might be able to be used for achieving this. So I challenged this.

In order to use the following sample script, before you run the script, please enable Google Docs API at API console as follows.

Enable Google Docs API at API console:

  • On script editor
    • Resources -> Cloud Platform project
    • View API console
    • At Getting started, click "Explore and enable APIs".
    • At left side, click Library.
    • At "Search for APIs & services", input "Docs". And click "Google Docs API".
    • Click Enable button.
    • If API has already been enabled, please don't turn off.

Flow:

The flow of sample script is as follows.

  1. You select a paragraph on Google Document.
  2. Retrieve all contents from Google Document using the get method of Google Docs API.
    • Each content is corresponding to each paragraph of Document.
  3. Retrieve the selected content using the getSelection method of Document Service.
  4. Modify shading color of selected content using the batchUpdate method of Google Docs API.

Sample script:

The sample script is for the container-bound script with Google Document. Please copy and paste the following script to the script editor, and please select a text on Google Document run myFunction() after Google Docs API was enabled.

function myFunction() {
  var color = "#D0FAF0"; // Please set a color with hex.

  var doc = DocumentApp.getActiveDocument();
  var selection = doc.getSelection();
  if (selection) {
    var hex2rgb = function(hex) {
      var str = hex[0] === "#" ? hex.slice(1) : hex;
      var rgb = str.split(/(.{2})/).reduce(function(ar, e) {
        if (e) ar.push(Math.round(1000 * parseInt(e, 16) / 255) / 1000);
        return ar;
      }, []);
      return {red: rgb[0], green: rgb[1], blue: rgb[2]};
    }(color);
    var body = doc.getBody();
    var id = doc.getId();
    var baseUrl = "https://docs.googleapis.com/v1/documents/";
    var headers = {"Authorization": "Bearer " + ScriptApp.getOAuthToken()};
    var params = {headers: headers};

    // Retrieve all contents from Google Document.
    var res = UrlFetchApp.fetch(baseUrl + id + "?fields=*", params);
    var obj = JSON.parse(res.getContentText());

    // Retrieve selected content.
    var rangeElements = selection.getRangeElements();
    var selectedContents = rangeElements.reduce(function(ar, e) {
      var p = e.getElement();
      if (p.getType() == DocumentApp.ElementType.TEXT) p = p.getParent();
      if (p.getType() == DocumentApp.ElementType.PARAGRAPH || p.getType() == DocumentApp.ElementType.LIST_ITEM) ar.push(obj.body.content[body.getChildIndex(p) + 1]);
      return ar;
    }, []);

    // Modify shading of selected content.
    if (selectedContents.length > 0) {
      var range = selectedContents.length == 1 ? {startIndex: selectedContents[0].startIndex, endIndex: selectedContents[0].endIndex} : {startIndex: selectedContents[0].startIndex, endIndex: selectedContents[selectedContents.length - 1].endIndex};
      var resource = {requests: [{updateParagraphStyle: {
        paragraphStyle: {shading: {backgroundColor: {color: {rgbColor: hex2rgb}}}},
        range: range,
        fields: "shading.backgroundColor",
      }}]};
      params.method = "post";
      params.contentType = "application/json";
      params.payload = JSON.stringify(resource);
      UrlFetchApp.fetch(baseUrl + id + ":batchUpdate", params);
    }
  }
}

Result:

enter image description here

  • In the sample script, #39b966 was used as the color.

References:

If I misunderstood your question and this workaround was not what you want, I apologize.

| improve this answer | |
  • Thank you so much for your answer that just blew my mind ! If I could vote several times I would. It totally works. I am struck by the quality of your answer. And I wouldn't have suspected that there was an alternative API exposing different functionalities. Keep it up ! :D – deb0ch Mar 22 '19 at 8:23
  • 1
    @deb0ch Thank you for replying. I'm glad your issue was resolved. Also I could study from your question. Thank you, too. – Tanaike Mar 22 '19 at 23:21
  • I've tried this function and looks like it's only highlighting the last line, is there an update needed? – Mavi Domates Sep 2 at 19:02
  • @Mavi Domates I deeply apologize for the inconvenience. When I tested this script, the background of the selected paragraph is changed. So I cannot replicate the situation of only highlighting the last line. I apologize for this. Can you provide the detail flow for replicating it? – Tanaike Sep 2 at 22:27
  • I got it to work - but needed to explicitly add the scopes to the manifest, including the Doc service one. Only after that it worked. – Mavi Domates Sep 3 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.