Нумерованные списки продолжаются, когда скрипт приложений добавляет содержимое шаблона в документ.

У меня есть скрипт приложений, который копирует содержимое файла шаблона в конец документа. Он работает с одной небольшой неприятностью: нумерованный список продолжается от одной копии к другой.

У меня есть много разных шаблонов, которые пользователи могут добавлять в конец документа. Каждый шаблон хранится в отдельном документе.

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

Это может выглядеть так: (Я хочу, чтобы список сбрасывался для каждой новой копии шаблона)

таблица с названием этого шаблона

какой-то сырой текст

  1. Элемент списка1
  2. Элемент списка2

таблица с названием этого шаблона

какой-то сырой текст

  1. Элемент списка1
  2. Элемент списка2

person Niklas Ternvall    schedule 13.05.2016    source источник


Ответы (3)


Теперь у ListItems есть идентификатор, который является STRING, и вы можете получить к нему доступ через myListItem.getListId().

Кажется, что все ваши ListItems имеют одинаковый идентификатор. В этом случае нумерация должна быть такой, как вы описали.

Почему у них одинаковый ListID? Я не знаю. Кажется, что метод body.appendListem всегда выбирает один и тот же listId.

Я еще не проверял это, но вы можете попробовать установить listID недавно добавленного ListItem в исходный документ, если они разные.

Да, я знаю, метод .copy() должен содержать эту информацию, но методу body.appendListItem может быть все равно.

Итак, вы можете попытаться сначала сохранить отсоединенную копию listItem. Затем добавьте его к новому телу. А затем установите идентификатор только что добавленного listItem в идентификатор отдельной копии. Это глупо, я знаю, но это может помочь. Еще не пробовал.

И у меня мало опыта работы с listItems, но до сих пор я видел, что в теле документа кажется только один ListId, если вы добавляете или вставляете listItems.

Это может быть причиной проблемы.

Надеюсь это поможет.

person Richard Gantz    schedule 16.05.2016
comment
Ты прав. Они разделяют ID. Я предполагаю, что это скопировано из документа-шаблона. - person Niklas Ternvall; 17.05.2016

После того, как Ричард Ганц решил это, это было исправлено этим кодом:

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()
  }
}
person Niklas Ternvall    schedule 17.05.2016
comment
Мне потребовалось немного времени, чтобы понять, что делает этот код: каждый раз, когда код видит новый listId, он создает новый временный listItem в целевом документе, чтобы получить новый listId для этого документа (сохраняя временный listItem, чтобы Id не t получить повторно) и присвоение нового listId скопированному элементу. Словарь сохраняет все listId скопированных элементов, сопоставленных с созданными временными элементами, и позволяет сопоставлять listId скопированных элементов с тем же временным элементом. Затем код в конце очищает все временные элементы списка. - person Von; 13.07.2016

Основываясь на ответе Никласа Тернвалла/Ричарда Ганца, я нашел более простое решение для случая, когда каждый шаблон имеет не более одного списка.

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» приведет к созданию нового списка и, следовательно, нового идентификатора списка, который вы можете применить к элементам списка из шаблона. После того, как вы закончите работу с шаблоном, mainBody.removeChild(listID) удалит "temp" из верхней части вашего списка.

Это решение сработало для меня при использовании одного шаблона 100 раз в одном документе, по сути, как слияние. Я новичок в Apps Script, поэтому буду признателен за любые отзывы, если есть причина, по которой это не сработает для шаблона с одним списком.

person Tiffany G. Wilson    schedule 24.07.2016