【问题标题】:Update/Replace inline image on Google Document更新/替换 Google 文档上的内嵌图片
【发布时间】:2014-10-27 21:43:25
【问题描述】:

我正在尝试设置一项功能来更新 Google 文档上的图像,就像 Lucidchart 插件在其“更新插入图表”功能上所做的那样。为此,我目前正在执行以下操作:

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

这行得通,但我有以下 Lucidchart 不会发生的问题:

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

是否有人知道替换/更新 Google Docs 上引用图像的好策略,就像 Lucidchart 附加更新功能的工作方式一样?

谢谢

【问题讨论】:

    标签: google-apps-script google-docs


    【解决方案1】:

    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 那样做并链接回您的网站。因此,它不仅对用户不利。

    【讨论】:

    • 完美!链接策略就像一个魅力!即使用户移动图像,数据也会继续。而且,此外,即使在导出为 pdf 时,我也会在每个图像的上下文中将图像上的链接指向应用程序。非常感谢! :)
    • 顺便说一句,空行正是因为这个,所以,在替换图像时,我也替换了自动创建的父段落。再次感谢:)
    • @mael Link 也是我在PlantUML Gizmo 中使用的。您应该让用户知道更改布局会默默地删除链接(Google Docs 的另一个错误功能)。我把它放在我的常见问题解答中:sites.google.com/site/plantumlgizmo/…
    • 感谢@Fuhrmanator!替换图像通过添加“编辑”功能来补充解决方案。我们还将警告用户有关限制。 PlanUML Gizmo 是一个很棒的附加组件!恭喜! :)
    【解决方案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);  
        }
    
      }
    
    }
    

    【讨论】:

    • 谢谢!替换图像通过添加“编辑”功能来补充解决方案。顺便说一句,很棒的附加组件!恭喜! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    • 2022-01-17
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多