当 Apps 脚本将模板内容附加到文档中时,编号列表继续

Numbered lists continues when Apps Script appends template-content into document

我有一个 Apps 脚本,可以将模板文件的内容复制到文档的末尾。它有一个小烦恼:编号列表从一个副本到下一个。

我有许多不同的模板,用户可以将它们附加到文档的末尾。每个模板都存储在自己的文档中。

    function addSub(template_id){
      var mainBody = DocumentApp.getActiveDocument().getBody();
      var tempBody = DocumentApp.openById(template_id).getBody();
      for(var i = 0;i<tempBody .getNumChildren();i++){
        var element = tempBody .getChild(i);
        if(element.getType() == DocumentApp.ElementType.TABLE)
          mainBody.appendTable(element.copy());
        else if(element.getType() == DocumentApp.ElementType.PARAGRAPH)
          mainBody.appendParagraph(element.copy());
        else if(element.getType() == DocumentApp.ElementType.LIST_ITEM)
          mainBody.appendListItem(element.copy());
        else if(element.getType() == DocumentApp.ElementType.PAGE_BREAK)
          mainBody.appendPageBreak(element.copy());
      }
    }

它可能看起来像这样:(我希望为模板的每个新副本重置列表)

table 使用此模板的名称

一些原始文本

  1. 列表项 1
  2. 列表项 2

table 使用此模板的名称

一些原始文本

  1. 列表项 1
  2. 列表项 2

你现在知道 ListItems 有一个 ID,它是一个字符串,你可以通过 myListItem.getListId() 访问它。

您的所有 ListItem 似乎都具有相同的 ID。 如果是这种情况,编号必须与您描述的一样。

为什么他们有相同的ListID? 我不知道。 似乎 body.appendListem 方法总是选择相同的 listId。

我还没有测试,但是你可以尝试将新追加的ListItem的listID设置为原始文档的listID,如果它们不同的话。

是的,我知道,.copy() 方法应该包含此信息,但 body.appendListItem 方法可能不关心。

因此,您可以尝试先保存 listItem 的分离副本。 然后将其附加到新主体。 然后将新附加的 listItem 的 id 设置为分离副本的 id。 这很愚蠢,我知道,但它可能会有所帮助。 还没试过。

而且我对 listItems 的经验很少,到目前为止我看到的是,如果您追加或插入 listItems,文档正文中似乎只有一个 ListId。

这可能是问题的原因。

希望对您有所帮助。

Richard Gantz 解决后,修正为这段代码:

var listItemDictionary = {};//top

...

else if(element.getType() == DocumentApp.ElementType.LIST_ITEM){
  var listCopy = element.copy().asListItem()
  var lcID = listCopy.getListId();
  if (listItemDictionary[lcID] == null){
    var tempLI = mainBody.appendListItem("temp")
    listItemDictionary[lcID] = tempLI;
  }
  Logger.log(lcID)
  mainBody.insertListItem(childIndex+j, listCopy.setListId(listItemDictionary[lcID]));
}

...

if(listItemDictionary){//bottom
  mainBody.appendParagraph("");
  for(var key in listItemDictionary){
    listItemDictionary[key].clear().removeFromParent()
  }
}

根据 Niklas Ternvall/Richard Gantz 的回答,我找到了一个针对每个模板不超过一个列表的情况的更简单的解决方案。

function addSub(template_id) {
  var mainBody = DocumentApp.getActiveDocument().getBody();
  var tempBody = DocumentApp.openById(template_id).getBody();
  var listID = null;                        
  for(var i = 0;i<tempBody.getNumChildren();i++){
    var element = tempBody.getChild(i).copy();  
    var type = element.getType();                
    if(type == DocumentApp.ElementType.TABLE)
      mainBody.appendTable(element);
    else if(type == DocumentApp.ElementType.PARAGRAPH)
      mainBody.appendParagraph(element);
    else if(type == DocumentApp.ElementType.LIST_ITEM){
      if(listID==null)                                  // First list item
        listID = mainBody.appendListItem('temp');       // Define new listID
      mainBody.appendListItem(element).setListId(listID); // Apply to copy 
    }
    else if(type == DocumentApp.ElementType.PAGE_BREAK)
      mainBody.appendPageBreak(element);
  }
  mainBody.removeChild(listID);               // Delete temporary list item
}

每次调用该函数时,listID=null是判断模板中是否存在列表项的指标。当您到达第一个列表项时,附加文本 'temp' 会强制生成一个新列表,从而生成一个新的 listID,您可以将其应用于模板中的列表项。完成模板后,mainBody.removeChild(listID) 会从列表顶部删除 'temp'。

当我在一个文档中使用一个模板 100 次时,这个解决方案对我很有效,主要是作为邮件合并。我是 Apps 脚本的新手,所以如果有任何反馈不适用于单列表模板,我将不胜感激。