2
votes

I want to get the width of a table in Google Documents. The following screenshot shows a demo document. It has only a table having one row which has only one cell. The table was added by clicking on Insert > Table and then on the option to insert a table with a single row and single cell. The table was not manipulated after being inserted.

In the Class Table from the Google Apps Script Class Table it hasn't a method to get the width, the Class Row either, but the Class Cell has getWidth(), so I tried to use it but it returns null. I'm the document owner, it's stored in My Unit, I'm using the old runtime (Mozilla Rhino), Chrome, a G Suite account. The project was created from the Docs UI by clicking on Tools > Script editor.

Here is the code (the project doesn't include anything else)

function myFunction() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  const tables = body.getTables();
  const table = tables[0];
  const row = table.getRow(0);
  const cell = row.getCell(0);
  const width = cell.getWidth();
  Logger.log(width);
}

The code was run from the script editor. Here is the log

I already searched the issue tracker for getWidth. Some results were returned but none of them looks to be related.

I already searched SO.

Google Apps Script getWidth() for document table cell width returns null While it could look as a duplicate, it's about inserting an image. By the other hand the OP tried

var width = insertPlace.getParent().asParagraph().asTableCell().getWidth();

but that didn't work either. The current answer is about getting the width of an image inserted from Google Drive.

So the question is How can I get the table width?

If getWidth() is buggy, is there another way to find the table width no only when the table uses the default width but also when it is smaller?

3

3 Answers

3
votes

This is a recorded

[email protected]

Status: Won't Fix (Intended Behavior)

Hello, Thanks for your report. The function "getWidth" returns null if the cell's width hasn't changed. You can manually change the width or use the "setWidth" method to adapt it to the image size. More information: https://developers.google.com/apps-script/reference/document/table-cell#setWidth(Number)

[email protected]

Status: Won't Fix (Intended Behavior)

Hi,

Despite all this not being documented, the intended behavior for a new table is to retrieve null for the attributes that aren't set. If you select the cell and modify its formatting (font size, italic, etc), then you'll get the values for those attributes.

For the cell width, when a new table is created all cells comes as “evenly distributed cells”, meaning it doesn’t have a “fixed width”, if you modify the width of a cell it’ll change to a fixed width. If you modify the default width of the entire table, all cells will change to a fixed width. The intended behavior for Google Doc API is to return the width only for cells with a fixed width.

I implemented the following workaround that will log you the width of each cell and the total width of the table (the default width for a new table is 450 points).

Workaround:

/**
 * Code written by [email protected]
 * @see https://issuetracker.google.com/issues/143810853#comment2
 */
function getTabeCellAttributes() {
  var fileId = '[FILE-ID]';
  var textInTableCell = "test";
  var body = DocumentApp.openById(fileId).getBody();  

  var tableRow = body.findText(textInTableCell).getElement().getParent().getParent().getParent().asTableRow();
  var evenlyDistributedCells = 0;
  var defaultTableWidth = 450;
  var totalWidth = 0;
 
  for(var i=0; i<tableRow.getNumChildren(); i++) {
    var tableCell = tableRow.getChild(i).asTableCell();
    var tableCellWidth = tableCell.getWidth();
   
    if(tableCellWidth == null) {
      evenlyDistributedCells++;
    }
    else {
      totalWidth += tableCellWidth;
      defaultTableWidth -= tableCellWidth;
      Logger.log("Width of cell number: " + (i+1) + " is: " + tableCellWidth)
    }
  }
 
  if (evenlyDistributedCells!=0) {
    var evenlyDistributedWidth = defaultTableWidth/evenlyDistributedCells;
    totalWidth += defaultTableWidth;
    Logger.log('There are ' + evenlyDistributedCells + ' evenly distributed cells with a width of: ' + evenlyDistributedWidth)
  }
  else {
    Logger.log("There are no evenly distributed cells, all cells have a fixed width.")
  }
 
  Logger.log('The total width of the table is: ' + totalWidth);
}
  • Code neither belongs to me or written by me, but just a quote from issuetracker.
1
votes

Thanks to @TheMaster for referring to the Issues (I was not able to find them) . Below is a very simple way to get the size of a table that works for a specific case of having a table as a child of the document body.

function myFunction1() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  const attributes = body.getAttributes();
  const width = attributes[DocumentApp.Attribute.PAGE_WIDTH] - attributes[DocumentApp.Attribute.MARGIN_LEFT] - attributes[DocumentApp.Attribute.MARGIN_RIGHT];
  Logger.log(width);
}

The default page size for me is Letter (width = 8.5 inches) and the margins are 1 inch.

The logged table width was 468 points (1 inch = 72 points) =6.5 inches so the the width is was was expected.

1
votes

I believe your goal as follows.

  • You want to retrieve the table width from the table created as the default size using Google Apps Script.

Issue and workaround:

Unfortunately, in the current stage, there are no methods for retrieving the table width from the table created as the default size in Google Document service and Docs API. This has already been mentioned by https://stackoverflow.com/a/63420215 and https://stackoverflow.com/a/63421935 . So in this answer, I would like to propose a workaround for retrieving the table width using Google Apps Script.

In this workaround, I use Microsoft Word. The flow of this workaround is as follows. In this flow, it supposes that a Google Document like your question has been created.

  1. Convert Google Document (DOCX data) to Microsoft Word using Drive API.
  2. Parse DOCX data using Google Apps Script.
    • When the converted DOCX data is unzipped, the data can be analyzed as the XML data. Fortunately, at Microsoft Docs, the detail specification is published as Open XML. So in this case, Microsoft Docs like XLSX, DOCX and PPTX can be analyzed using XmlService of Google Apps Script. I think that this method will be also useful for other situations.
  3. Retrieve the table width from DOCX data.

Sample script:

function myFunction() {
  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 docx = Utilities.unzip(blob);
  const document = docx.filter(b => b.getName() == "word/document.xml");
  if (document.length == 0) return;
  const xml = document[0].getDataAsString();
  const root = XmlService.parse(xml).getRootElement();
  const n1 = root.getNamespace("w");
  const body = root.getChild("body", n1).getChildren("tbl", n1)
  const obj = body.map((e, i) => {
    const temp = {};
    const tblPr = e.getChild("tblPr", n1);
    if (tblPr) {
      const tblW = tblPr.getChild("tblW", n1);
      if (tblW) {
        const w = tblW.getAttribute("w", n1);
        if (w) {
          temp.tableWidth = Number(w.getValue()) / 20;  // Here, the unit of "dxa" is converted to "pt"
        }
      }
    }
    return temp;
  });
  if (obj.length > 0) console.log(obj);

  // DriveApp.getFiles()  // This is used for including the scope of `https://www.googleapis.com/auth/drive.readonly`.
}

Result:

  • When your table is retrieved using this script, tableWidth: 451.3 is retrieved. In this case, the unit is pt.
  • The index of result array means the index of table. For example, 1st table in Google Document is 0.

Note:

  • As the confirmation of above script, when a table is created with the script of DocumentApp.getActiveDocument().getBody().appendTable([[""]]).getCell(0, 0).setWidth(200) and the table is retrieved using above sample script, I could confirm that tableWidth: 200 was retrieved. From this situation, it is considered that the size of table in Google Document is the same with that in DOCX data.

References: