Numbered lists continues when Apps Script appends

2019-08-14 03:28发布

I have an Apps Script that copies the content of an template-file to the end of a document. It works with one minor annoyance: the numbered list continues from one copy to the next.

I have many different templates that users can append to the end of the document. Each template is stored in its own Document.

    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());
      }
    }

It could look like this: ( I want the list to reset for each new copy of the template)

table with name of this template

some raw text

  1. List item1
  2. List item2

table with name of this template

some raw text

  1. List item1
  2. List item2

3条回答
SAY GOODBYE
2楼-- · 2019-08-14 04:13

Do you now that ListItems have an ID, which is a STRING and you can access it via myListItem.getListId().

It seems that all your ListItems have the same ID. If this is the case, the numbering has to be as you described.

Why do they have the same ListID? I don't know. Seems that the body.appendListem method always chooses the same listId.

I didn't test it yet, but you could try to set the listID of the newly append ListItem to that of the original document, if they are different.

Yes, i know, the .copy() method should enclose this information, but the body.appendListItem method may not care.

So, you could try to first save the detached copy of the listItem. Then append it to the new body. And then set the id of the newly appended listItem to that of the detached copy. It's stupid, i know, but it may help. Didn't try it yet.

And i have little experience with listItems, bit what i saw up to now is that there seems to be only one ListId in the body of a document, if you append or insert listItems.

This could be the cause of the problem.

Hope this helps.

查看更多
Juvenile、少年°
3楼-- · 2019-08-14 04:15

Based on the answer from Niklas Ternvall/Richard Gantz, I found a simpler solution for the case of each template having no more than one list.

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
}

Each time you call the function, listID=null is the indicator for whether or not there have been any list items in the template. When you get to the first list item, appending the text 'temp' forces a new list and hence a new listID that you can apply to the list items from the template. After you finish going through the template, mainBody.removeChild(listID) removes 'temp' from the top of your list.

This solution worked for me when using one template 100 times in one document, essentially as a mail merge. I'm fairly new to Apps Script, so I would appreciate any feedback if there is a reason this wouldn't work for a single-list template.

查看更多
一夜七次
4楼-- · 2019-08-14 04:28

After Richard Gantz solved it, It was corrected by this code:

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()
  }
}
查看更多
登录 后发表回答