Google Docs – Set Background Color for Entire Paragraph

google docsgoogle-apps-script

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 ?

Best Answer

  • 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.

Related Topic