Zoran Kalinić
Zoran Kalinić

Reputation: 317

Google Apps Script getWidth() for document table cell width returns null

I'd like to insert image in the Google document by using Google Apps Script, and to spread it (the image) to the width of the page - margins or to insert it in the table cell and spread it to the width of the cell.

The code goes like this:

var image = DriveApp.getFileById(fileId).getBlob();
var insertPlace = body.findText(searchText).getElement();
insertPlace.asText().setText("");
var insertedImage = insertPlace.getParent().asParagraph().insertInlineImage(0, image);
var h = insertedImage.getHeight();
var w = insertedImage.getWidth();
insertedImage.setWidth(width).setHeight(width * h / w);

And where is the problem?

width!

How to find width of the table cell or body?

I have tried with

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

but got null although cell is in the single column of the table, and table takes all the width of the page-margins.

Anyone got the idea about how to get width of the cell?

Also, how to get page width, margins etc...

UPDATE

I have discovered that the issue must be with the Google code about this. Actually, they have made differently handling with tables in slides compared to document:

https://developers.google.com/apps-script/reference/slides/table-cell https://developers.google.com/apps-script/reference/document/table-cell

In slides version there is, for example, getParentColumn(), which is not available for the document... any many similar discrepancies.

What are doing these guys at Google?!?!?

Upvotes: 1

Views: 1818

Answers (2)

kenjiuno
kenjiuno

Reputation: 359

This is my version of getWidth so that we can compute new good width value for newly inserted image.

function getWidthOf(element, pageWidth) {
  if (!element) {
    return 0;
  }
  const type = element.getType() + "";
  const parent = element.getParent();
  if (false) { }
  else if (type === "TABLE_CELL") {
    const atts = element.getAttributes();
    let width = element.asTableCell().getWidth();
    if (width === null) {
      width = getWidthOf(parent, pageWidth);
    }
    return width - (atts["PADDING_LEFT"] || 0) - (atts["PADDING_RIGHT"] || 0);
  }
  else if (type === "TABLE_ROW") {
    const cx = element.asTableRow().getNumCells();
    return getWidthOf(parent, pageWidth) / cx;
  }
  else if (type === "TABLE") {
    const atts = element.getAttributes();
    return getWidthOf(parent, pageWidth) - (atts["BORDER_WIDTH"] || 0);
  }
  else if (type === "BODY_SECTION") {
    const atts = element.getAttributes();
    return pageWidth - atts["MARGIN_LEFT"] - atts["MARGIN_RIGHT"];
  }
  else {
    return getWidthOf(parent, pageWidth);
  }
}

Usage:

function insertImageTest() {
  const templateDoc = DocumentApp.openByUrl("https://docs.google.com/document/d/YOUR_DOCUMENT_ID/edit");
  const templateFile = DriveApp.getFileById(templateDoc.getId());
  const document = DocumentApp.openById(templateFile.getId());
  const body = document.getBody();
  const found = body.findText("HERE!");
  if (!found) {
    throw new Error("No insert point found!");
  }

  const imageBlob = DriveApp.getFileById("YOUR_IMAGE_FILE_ID_IN_DRIVE").getBlob();

  const paragraph = found.getElement().getParent().asParagraph();
  paragraph.clear();
  const img = paragraph.appendInlineImage(imageBlob);
  const newWidth = getWidthOf(paragraph, body.getAttributes()["PAGE_WIDTH"]) * 1.33;
  const newHeight = img.getHeight() * newWidth / img.getWidth();
  img.setWidth(newWidth).setHeight(newHeight);
}

Notes:

  • Paper metric unit is pt. However Image's setWidth and setHeight work in pixel unit.
  • This conversion (pixels = pt * 1.33) works but I don't know whether this is right or not.

Upvotes: 0

Cooper
Cooper

Reputation: 64040

This is not perfect but it seems to get me pretty close. May be you could work with it some more and get the rest of the way. I thought that the PAGE_WIDTH and PAGE_HEIGHT were in points but when I look at the number it seemed rather large so I used them as pixels instead. And it appears to work for me the image is centered in the page and goes from left margin to right margin. I didn't adjust the page height because my image looked ok but you might wish to do that.

function insertImage() {
  var doc=DocumentApp.getActiveDocument();
  var body=doc.getBody();
  var atts=body.getAttributes();
  for(var att in atts) {
    Logger.log(att + ':' + atts[att]);
  }
  var folderId="Folder ID";
  var files=DriveApp.getFolderById(folderId).getFiles();
  while(files.hasNext()) {
    var file=files.next();
    if(file.getName()=="Image File Name") {
      var image=file.getBlob().getAs('image/png');//may need to change content type
      var img=body.appendImage(image);
      var h=img.getHeight();
      var w=img.getWidth();
      var mr=atts['MARGIN_RIGHT'];
      var ml=atts['MARGIN_LEFT'];
      var sw=atts['PAGE_WIDTH'];
      var sh=atts['PAGE_HEIGHT'];
      img.setHeight(sw*h/w);
      img.setWidth((sh-mr-ml)*w/h);
    }
  }
}

Upvotes: 2

Related Questions