Skip to content

Instantly share code, notes, and snippets.

@tanaikech
Last active October 23, 2020 00:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tanaikech/d430543089cc687e5d9c2bc96d3178ff to your computer and use it in GitHub Desktop.
Save tanaikech/d430543089cc687e5d9c2bc96d3178ff to your computer and use it in GitHub Desktop.
Modifying 1st-Page Header in Google Document using Google Apps Script

Modifying 1st-Page Header in Google Document using Google Apps Script

These are sample scripts for modifying the 1st-page header in Google Document using Google Apps Script. Unfortunately, in the current stage, the 1st-page header cannot be modified by Document service. In this case, it is required to use Google Docs API. Here, I would like to introduce 2 sample scripts for modifying the 1st page header using Docs API.

When you use this, please enable Google Docs API at Advanced Google services.

Flow

The flow of this is as follows.

  1. Enable the 1st-page header of Google Document with useFirstPageHeaderFooter:true.
  2. Retrieve the 1st-page header ID.
  3. Modify the 1st-page header using the header ID.

Sample 1

In this sample, all texts of the 1st-page header is replaced with new texts.

Script

function myFunction() {
  const replace1stPageHeader = (documentId, newText) => {
    const resource1 = {
      requests: [
        {
          updateDocumentStyle: {
            documentStyle: { useFirstPageHeaderFooter: true },
            fields: "useFirstPageHeaderFooter",
          },
        },
      ],
    };
    Docs.Documents.batchUpdate(resource1, documentId);
    const obj = Docs.Documents.get(documentId);
    const headerId = obj.documentStyle.firstPageHeaderId;
    const endIndex = obj.headers[headerId].content.pop().endIndex - 1;
    const resource2 = {
      requests: [
        {
          deleteContentRange: {
            range: { segmentId: headerId, startIndex: 0, endIndex: endIndex },
          },
        },
        {
          insertText: {
            location: { segmentId: headerId, index: 0 },
            text: newText,
          },
        },
      ],
    };
    Docs.Documents.batchUpdate(resource2, documentId);
  };

  const newText = "New text of 1st page header.";
  const documentId = "###"; // Please set the Document ID.
  replace1stPageHeader(documentId, newText);
}

Sample 2

In this sample, the part of texts of the 1st-page header is replaced with new texts.

Script

function myFunction() {
  const replace1stPageHeader = (documentId, repObj) => {
    const resource1 = {
      requests: [
        {
          updateDocumentStyle: {
            documentStyle: { useFirstPageHeaderFooter: true },
            fields: "useFirstPageHeaderFooter",
          },
        },
      ],
    };
    Docs.Documents.batchUpdate(resource1, documentId);
    const obj = Docs.Documents.get(documentId);
    const headerId = obj.documentStyle.firstPageHeaderId;
    const hObj = obj.headers[headerId].content;
    const existingText = hObj.reduce((s, { paragraph }) => {
      paragraph.elements.forEach(({ textRun }) => (s += textRun.content));
      return s;
    }, "");
    const newText = Object.entries(repObj).reduce(
      (s, [k, v]) => s.replace(new RegExp(k, "g"), v),
      existingText
    );
    const resource2 = {
      requests: [
        {
          deleteContentRange: {
            range: {
              segmentId: headerId,
              startIndex: 0,
              endIndex: hObj.pop().endIndex - 1,
            },
          },
        },
        {
          insertText: {
            location: { segmentId: headerId, index: 0 },
            text: newText,
          },
        },
      ],
    };
    Docs.Documents.batchUpdate(resource2, documentId);
  };

  const documentId = "###"; // Please set the Document ID.
  const replaceObject = {
    "{{sample1}}": "new text 1",
    "{{sample2}}": "new text 2",
  };
  replace1stPageHeader(documentId, replaceObject);
}
  • In this sample, {{sample1}} and {{sample2}} in the 1st page header are replaced with new text 1 and new text 2, respectively.

References

@Max-Makhrov
Copy link

Thank you very much for this sample. Please note that the script gives an error in certain conditions:

  • I've got the error on the line paragraph.elements.forEach(({ textRun }) => (s += textRun.content)); if the header contained a table. When I deleted the table, the script worked perfectly.

I'm sorry, but I did not investigate this error in depth. I'll write further if I find a solution.

@Max-Makhrov
Copy link

I've commited that it's possible to accomplish with this sample script:

function test_replaceAllInFootersAndHeaders() {
  var doc = DocumentApp.getActiveDocument();
  var d = doc.getHeader().getParent();
  
  for (var i = 0; i < 4; i++) {
    d.getChild(i).replaceText('{{foo}}', 'bar');
    Logger.log(d.getChild(i).getType());
    // BODY_SECTION
    // HEADER_SECTION
    // HEADER_SECTION
    // FOOTER_SECTION
  }
}

I've posted it here:
https://stackoverflow.com/a/64479428/5372400

This script does not require connecting service.

@tanaikech
Copy link
Author

Thank you for your comment. In my sample script, I didn't suppose that a table is included in the header. About this, I have to apologize.

Although I'm not sure whether I could correctly understand about your comment, it seems that when the script of DocumentApp.getActiveDocument().getHeader().getParent().getChild(i).asText().getText() is used, the texts of 1st page header (the 1st page header and 2nd page header are different.) are included. But in this case, I couldn't confirm which the type of HEADER_SECTION is the 1st page or 2nd page. So I have proposed the method for using Docs API. Of course, when it has already been found the values including in the retrieved HEADER_SECTION, the 1st page header can be confirmed using the text. For example, I thought that when the same values are used for both 1st page header and 2nd page header, Docs API might be suitable.

If I misunderstood your comment, I apologize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment