Google 文档 IncludeText 字段

Google Docs IncludeText field

Google Docs 有什么方法可以将一个 Google Doc 的内容插入另一个?在 Microsoft Word 中,有 IncludeText field,您只需 link 您想要包括的其他 Word 文档,它就会被包括在内。

用例:例如,如果您有一个自定义 header,您希望在每个文件的开头都有一个自定义 header。如果您只是将 copy-paste 和 header 添加到您的文件中,那么如果您想要更改它,那么您需要在每个文件中更改它,这是一个巨大的痛苦。理想情况下,您可以在每个文件的顶部放置 {{header}},然后您可以激活插入其他文件的内容。

我的解决方案是创建一个 Google Apps 脚本来复制当前文档并将 {{header}} 的每个实例替换为另一个 Google 文档的内容。这是有效的,除了唯一明显的方法只插入纯文本,我需要插入格式化文本(和表格,列表, 和内联图像)。

我当前的脚本:

function runReplace() {
  var currentDoc = DocumentApp.getActiveDocument();
  var currentBody = currentDoc.getBody();

  // Make a copy of the current doc with the name "[current doc name] filled"
  var newFile = DriveApp.getFileById(currentDoc.getId()).makeCopy(currentDoc.getName() + " filled");

  var newDoc = DocumentApp.openById(newFile.getId());

  var willReplaceWith = DocumentApp.openByUrl(URL_GOES_HERE);
  var replaceString = '{{header}}';
  newDoc.getBody().replaceText(replaceString, willReplaceWith.getBody().getText())
}

我认为格式化文本的最佳解决方案可能是找到段落中字符串的所有位置,并针对每个位置检查 header 文档的每个元素,并在新文档的 body 上调用每个特定的插入函数。

This Whosebug answer 显示了其中涉及的一些内容。虽然这当然不是不可能的,但似乎应该有更好的方法来做到这一点。

编辑:

这个版本似乎是我最好的解决方案。还有一些问题,但基本上是我想要的:

function runReplace() {

  var currentDoc = DocumentApp.getActiveDocument();

  // Make a copy of the doc with the name "Filled: [current doc name]"
  var newFile = DriveApp.getFileById(currentDoc.getId()).makeCopy("Filled: " + currentDoc.getName());

  var targetDoc = DocumentApp.openById(newFile.getId());

  var targetBody = targetDoc.getBody();

  var sourceDoc = DocumentApp.openByUrl(URL_GOES_HERE);
  var replaceTag = '{{KEY}}';

  // Find where to copy to
  var replaceTagRangeElement = targetBody.findText(replaceTag);
  var replaceTagElement = replaceTagRangeElement.getElement();
  var replaceTagParent = replaceTagElement.getParent();
  var replaceTagLocation = replaceTagParent.getParent().getChildIndex(replaceTagParent);

  var replaceInto = replaceTagParent.getParent();

  var replaceIntoLocation = replaceTagLocation + 1;

  // Copy into the target document
  try {
    for (var j = 0; j < sourceDoc.getBody().getNumChildren(); ++j) {
      var element = sourceDoc.getChild(j).copy();
      var type = element.getType();

      // Insert whichever thing needs to be inserted
      if (type == DocumentApp.ElementType.INLINE_IMAGE) {
        replaceInto.insertImage(replaceIntoLocation, element);
      } else if (type == DocumentApp.ElementType.PARAGRAPH) {
        if (j == 0 && replaceTagParent.getType() == DocumentApp.ElementType.LIST_ITEM) {
          // If this is a tag inside of a list item
          //  the first paragraph is added as text for the list item
          replaceTagParent.appendText(element.getText());
          replaceIntoLocation--;
        } else {
          var par = replaceInto.insertParagraph(replaceIntoLocation, element);
          // Merge the first paragraph with the previous one 
          //  so that tags don't start with newlines
          if (j == 0 && par.getPreviousSibling().getType() == DocumentApp.ElementType.PARAGRAPH) {
            par.merge();
            replaceIntoLocation--;
          }
        }
      } else if (type == DocumentApp.ElementType.TABLE) {
        replaceInto.insertTable(replaceIntoLocation, element);
      } else if (type == DocumentApp.ElementType.LIST_ITEM) {
        replaceInto.insertListItem(replaceIntoLocation, element);
      }
      replaceIntoLocation++;
    }
  } catch (e) {
    Logger.log(e);
  }

  var replaceTagRangeElement = targetBody.findText(replaceTag);
  var replaceTagElement = replaceTagRangeElement.getElement();
  replaceTagElement.replaceText(replaceTag, "");

}

解决方案是将您的 HTML 变成一个 blob 并插入,或者拥有一个标记有您要插入到目标文档中的格式化代码的源文档。

标记源文档解决方案。

  1. 在您的源代码周围添加开始和结束标记。
  2. 搜索开始标签并获取其位置。
  3. 搜索结束标记并获取其位置。
  4. 复制标签之间的所有代码。
  5. 删除标签并添加到源文档中。

可能的代码

   function findTag(){ 

   var thisDoc = DocumentApp.getActiveDocument();
   var targetDoc = DocumentApp.getActiveDocument();
   try{
    var sourceDoc = DocumentApp.openById(FILEID); 
   } catch (e) {
    return e;
   }

   var startTag = "<<start>>";     
   var firstTag = sourceDoc.getBody().findText(startTag); 
   var startTagElement = firstTag.getElement();   
   var parent = startTagElement.getParent();
   var startPoint = parent.getParent().getChildIndex(parent);  

   var endTag = tag.replace('start', 'finish'); 
   var lastTag = sourceDoc.getBody().findText(endTag);
   var endTagElement = lastTag.getElement();
   var endParent = endTagElement.getParent();
   var endPoint = endParent.getParent().getChildIndex(endParent);

   // copy into the target document
   try {
      for( var j = startPoint; j <= endPoint; ++j ) {    
        var body = targetDoc.getBody();
        var element = sourceDoc.getChild(j).copy();
        var type = element.getType();

        if( type == DocumentApp.ElementType.INLINE_IMAGE ){
          body.insertImage(start, element);          
        }      
        else if( type == DocumentApp.ElementType.PARAGRAPH ){    
          body.insertParagraph(start, element);      
        }

        else if( type == DocumentApp.ElementType.TABLE){        
          body.insertTable(start, element);
        }       
        else if( type == DocumentApp.ElementType.INLINE_IMAGE ){ 
          var blob = body.getChild(j).asInlineImage().getBlob();
          body.insertImage(start, blob); }

        else if( type == DocumentApp.ElementType.LIST_ITEM){
          body.insertListItem(start, element);
        }
        start ++;
      }
    }
    catch(e){
    return e;   
    }        
     // Delete the tags
     body.replaceText(endTag, ""); 
     body.replaceText(startTag, "");
}