Google Apps Script doc.getBody().getPageWidth() returning the same number whether portrait or landscape

Viewed 174

I'm trying to determine if a page is in portrait or landscape view. There's no direct method for such, so I figured using doc.getBody().getPageWidth() and doc.getBody().getPageHeight() would get me there and I could just look at which number is larger. 2 problems I'm having:

  1. There doesn't seem to be a way to specify which page/section I'm checking, just the body itself. Since each page can have its own orientation, I don't know how to check per page;
  2. More importantly, even on a single-page document the points are always width = 612 height = 792 no matter the orientation. So it looks like it's always in Portrait and even changing it to Landscape doesn't help.

Right now my code is literally just this while I'm figuring it out:

function myFunction() {
  const doc = DocumentApp.getActiveDocument();
  Logger.log(doc.getBody().getPageWidth());
  Logger.log(doc.getBody().getPageHeight());
}
2 Answers

I believe your goal as follows.

  • You want to retrieve the page size and the orientation of Google Document.
  • You want to achieve this using Google Apps Script.

Issue and workaround:

  • In the current stage, when the page size is retrieved using Document service and Google Docs API, the width and height are the constant even when the orientation is changed from portrait to landscape. This has already been mentioned in your question and an answer. I think that this might be the current situation or a bug.
  • But, fortunately, Google Document can be converted to DOCX data. And, DOCX data can be parsed using XmlService. Ref Because the format of DOCX data has already been published. Ref

By this, in this answer, I would like to propose the following flow as a workaround.

  1. Convert Google Document to DOCX data.
  2. Parse the DOCX data using XmlService.
  3. Retrieve the page size of each page.

When this flow is reflected to Google Apps Script, it becomes as follows.

Sample script:

function myFunction() {
  const documentId = "###"; // Please set the Document ID.
  // or you can also use const documentId = DocumentApp.getActiveDocument().getId();

  const url = "https://docs.google.com/feeds/download/documents/export/Export?exportFormat=docx&id=" + documentId;
  const blob = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()}}).getBlob().setContentType(MimeType.ZIP);
  const documentXml = Utilities.unzip(blob).filter(b => b.getName() == "word/document.xml")[0];
  const xml = XmlService.parse(documentXml.getDataAsString());
  const root = xml.getRootElement();
  const nsw = root.getNamespace("w");
  const res = root.getChild("body", nsw).getChildren("p", nsw).reduce((ar, e) => {
    const pPr = e.getChild("pPr", nsw);
    if (pPr) {
      const sectPr = pPr.getChild("sectPr", nsw);
      if (sectPr) {
        const pgSz = sectPr.getChild("pgSz", nsw);
        ar.push({width: pgSz.getAttribute("w", nsw).getValue() / 20, height: pgSz.getAttribute("h", nsw).getValue() / 20, orientation: pgSz.getAttribute("orient", nsw).getValue()});
      }
    }
    return ar;
  }, [])
  console.log(res)
}

Result:

When above script is run, the following result is obtained. When the orientation of the page is changed, the object is added as follows.

[
  { width: 612, height: 792, orientation: 'portrait' },
  { width: 792, height: 612, orientation: 'landscape' },
  { width: 612, height: 792, orientation: 'portrait' },
  ,
  ,
  ,
]

Note:

  • In this case, the page size can be retrieved for portrait and landscape pages. But, I couldn't retrieve the page number. I think that the reason of this might be due to the DOCX is managed by the paragraph.

References:

It looks like Google Docs still nave no such option in 2021. As a way around for some cases there is add-on "Page Sizer" (and alike) on Marketplace. It can set page width and height and, surprisingly, after that the functions getWidth() and getHeight() show correct real sizes.

Just in case, another way to get page sizes:

function myFunction() {
  var body = DocumentApp.getActiveDocument().getBody();
  var attributes = body.getAttributes();
  var width = attributes["PAGE_WIDTH"];
  var height = attributes["PAGE_HEIGHT"];
  Logger.log(width);
  Logger.log(height);
}

But it works wrong as well.

The snippet was obtained from source doc of another add-on "Set A* Page Size": https://docs.google.com/document/d/1V3ktkm6qcpgG5S8TKwUmxlfErDWZlW3Sfoir7RLM-3w/edit

Related