更新/替换Google文档上的内嵌图片

时间:2014-10-27 21:43:26

标签: google-apps-script

我正在尝试设置一项功能来更新Google文档上的图片,就像Lucidchart Add-on在其“更新的插入图表”功能上所做的那样。为此,我现在正在做以下事情:

  • 创建命名范围并将其id与文档属性一起存储,以生成图像,以便以后检索。
  • 更新时,调用body.getNamedRangeById()并将元素替换为新生成的图像。

这很有效,但我有以下Lucidchart不会发生的问题:

  • 每次更新,图像后都会添加一个空行。
  • 如果用户将图像拖放到文档中以便重新定位,则命名范围将消失,我以后无法检索它。
  • 如果用户集中图像,更新后图像将返回到左侧位置,甚至复制其属性

有没有人知道更换/更新Google文档中引用图片的好策略,就像Lucidchart附加更新功能一样有效?

由于

2 个答案:

答案 0 :(得分:5)

当移动范围时,NamedRanges确实会丢失,因此它们对您的方案不太好。但是没有其他方法可以识别元素(这是Google Docs的一个很好的错误)。

对于图像,您可以使用其LINK_URL来识别它,这似乎是Lucidchart使用的。它不会妨碍用户,所以它可能是一个很好的解决方案。

关于在插入图片时获取空行并丢失属性,我想(因为您还没有共享任何代码),您需要将图像直接插入文档正文而不是段落。然后会自动创建一个段落来包装图像,从而产生空行并丢失属性。

以下是一些代码示例:

function initialInsert() {
  var data = Charts.newDataTable().addColumn(
    Charts.ColumnType.STRING, 'Fruits').addColumn(
    Charts.ColumnType.NUMBER, 'Amount').addRow(
    ['Apple',15]).addRow(
    ['Orange',6]).addRow(
    ['Banana',14]).build();
  var chart = Charts.newPieChart().setDataTable(data).build();

  var body = DocumentApp.getActiveDocument().getBody()
  body.appendImage(chart).setLinkUrl('http://mychart');
  //here we're inserting directly in the body, a wrapping paragraph element will be created for us
}

function updateImage() {
  var data = Charts.newDataTable().addColumn(
    Charts.ColumnType.STRING, 'Fruits').addColumn(
    Charts.ColumnType.NUMBER, 'Amount').addRow(
    ['Apple',Math.floor(Math.random()*31)]).addRow( //random int between 0 and 30
    ['Orange',Math.floor(Math.random()*31)]).addRow(
    ['Banana',Math.floor(Math.random()*31)]).build();
  var chart = Charts.newPieChart().setDataTable(data).build();

  var img = getMyImg(DocumentApp.getActiveDocument().getBody(), 'http://mychart');
  //let's insert on the current parent instead of the body 
  var parent = img.getParent(); //probably a paragraph, but does not really matter
  parent.insertInlineImage(parent.getChildIndex(img)+1, chart).setLinkUrl('http://mychart');
  img.removeFromParent();
}

function getMyImg(docBody, linkUrl) {
  var imgs = docBody.getImages();
  for( var i = 0; i < imgs.length; ++i )
    if( imgs[i].getLinkUrl() === linkUrl )
      return imgs[i];
  return null;
}

关于link_url,您当然可以像Lucidchart那样做并链接回您的网站。所以它不仅仅为用户而破坏。

答案 1 :(得分:2)

看一下名为PlantUML Gizmo的加载项。

这里是插入图片功能的代码,如果已经选择了图片,则会处理替换图片:

function insertImage(imageDataUrl, imageUrl) {
  /*
   * For debugging cursor info
   */
//  var cursor = DocumentApp.getActiveDocument().getCursor();
//  Logger.log(cursor.getElement().getParent().getType());
//  throw "cursor info: " + cursor.getElement().getType() + " offset = " + cursor.getOffset() + " surrounding text = '" + cursor.getSurroundingText().getText() + "'  parent's type = " + 
//    cursor.getElement().getParent().getType();
  /*
   * end debug
   */
  var doc = DocumentApp.getActiveDocument();
  var selection = doc.getSelection();
  var replaced = false;
  if (selection) {
    var elements = selection.getSelectedElements();
    // delete the selected image (to be replaced)
    if (elements.length == 1 &&
        elements[0].getElement().getType() ==
        DocumentApp.ElementType.INLINE_IMAGE) {
          var parentElement = elements[0].getElement().getParent();  // so we can re-insert cursor
          elements[0].getElement().removeFromParent();
          replaced = true;
          // move cursor to just before deleted image
          doc.setCursor(DocumentApp.getActiveDocument().newPosition(parentElement, 0));
     } else {
          throw "Please select only one image (image replacement) or nothing (image insertion)"
     }
  }
  var cursor = doc.getCursor();
  var blob;

  if (imageDataUrl != "") {
    blob = getBlobFromBase64(imageDataUrl);
  } else {
    blob = getBlobViaFetch(imageUrl);
  }

  var image = cursor.insertInlineImage(blob);  

  image.setLinkUrl(imageUrl);

  // move the cursor to after the image
  var position = doc.newPosition(cursor.getElement(), cursor.getOffset()+1);
  doc.setCursor(position);

  if (cursor.getElement().getType() == DocumentApp.ElementType.PARAGRAPH) {
    Logger.log("Resizing");
    // resize if wider than current page
    var currentParagraph = DocumentApp.getActiveDocument().getCursor().getElement().asParagraph();
    var originalImageWidth = image.getWidth();  // pixels
    var documentWidthPoints = DocumentApp.getActiveDocument().getBody().getPageWidth() - DocumentApp.getActiveDocument().getBody().getMarginLeft() - DocumentApp.getActiveDocument().getBody().getMarginRight();
    var documentWidth = documentWidthPoints * 96 / 72;  // convert to pixels (a guess)
    var paragraphWidthPoints = documentWidthPoints - currentParagraph.getIndentStart() - currentParagraph.getIndentEnd();
    var paragraphWidth = paragraphWidthPoints * 96 / 72;  // convert to pixels (a guess)

    if (originalImageWidth > paragraphWidth) {
      image.setWidth(paragraphWidth);
      // scale proportionally
      image.setHeight(image.getHeight() * image.getWidth() / originalImageWidth);  
    }

  }

}