Работа с вкладками

API Google Docs позволяет получать доступ к содержимому из любой вкладки документа.

Что такое вкладки?

В Google Docs есть организационный уровень, называемый вкладками . Docs позволяет пользователям создавать одну или несколько вкладок в одном документе, аналогично тому, как вкладки используются в Таблицах. Каждая вкладка имеет собственное название и идентификатор (добавляется к URL-адресу). Вкладка также может иметь дочерние вкладки , которые представляют собой вкладки, вложенные в другую вкладку.

Структурные изменения в представлении содержимого документа в ресурсе документа

Раньше в документах не было концепции вкладок, поэтому ресурс Document напрямую содержал все текстовое содержимое в следующих полях:

Благодаря дополнительной структурной иерархии вкладок эти поля больше не семантически представляют текстовое содержимое всех вкладок документа. Текстовое содержимое теперь представлено на отдельном слое. Свойства и содержимое вкладок в Google Docs доступны с помощью document.tabs — списка объектов Tab , каждый из которых содержит все вышеупомянутые поля текстового содержимого. В последующих разделах представлен краткий обзор; JSON-представление Tab также содержит более подробную информацию.

Свойства вкладки «Доступ»

Доступ к свойствам вкладки осуществляется с помощью tab.tabProperties , который включает в себя такую ​​информацию, как идентификатор, заголовок и расположение вкладки.

Доступ к текстовому содержимому во вкладке

Фактическое содержимое документа во вкладке отображается как tab.documentTab . Все вышеупомянутые текстовые поля доступны через tab.documentTab . Например, вместо document.body следует использовать document.tabs[indexOfTab].documentTab.body .

Иерархия вкладок

Дочерние вкладки представлены в API как поле tab.childTabs в Tab . Для доступа ко всем вкладкам в документе требуется пройти по «дереву» дочерних вкладок. Например, рассмотрим документ, содержащий следующую иерархию вкладок:

Пользовательский интерфейс списка вкладок, содержащий три вкладки верхнего уровня, некоторые из которых имеют дочерние вкладки

Чтобы получить Body из вкладки 3.1.2 , необходимо обратиться к document.tabs[2].childTabs[0].childTabs[1].documentTab.body . Примеры блоков кода см. в следующем разделе, где представлен пример кода для итерации по всем вкладкам документа.

Изменения в методах

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

documents.get

По умолчанию возвращается не всё содержимое вкладок. Разработчикам следует обновить код, чтобы получить доступ ко всем вкладкам. Метод documents.get предоставляет параметр includeTabsContent , который позволяет настроить, будет ли в ответе представлено содержимое всех вкладок.

  • Если параметр includeTabsContent установлен в true , метод documents.get вернет ресурс Document с заполненным полем document.tabs . Все текстовые поля непосредственно в document (например, document.body ) останутся пустыми.
  • Если includeTabsContent не указан, текстовые поля в ресурсе Document (например, document.body ) будут заполнены содержимым только из первой вкладки. Поле document.tabs будет пустым, а содержимое других вкладок не будет возвращено.

документы.создать

Метод documents.create возвращает ресурс Document , представляющий созданный пустой документ. Возвращаемый ресурс Document заполняет текстовые поля документа и document.tabs .

document.batchUpdate

Каждый Request позволяет указать вкладки, к которым применяется обновление. По умолчанию, если вкладка не указана, Request в большинстве случаев применяется к первой вкладке документа. ReplaceAllTextRequest , DeleteNamedRangeRequest и ReplaceNamedRangeContentRequest — это три специальных запроса, которые по умолчанию применяются ко всем вкладкам.

Подробную информацию см. в документации по Request .

Пользователи могут создавать внутренние ссылки на вкладки, закладки и заголовки в документе. С появлением функции вкладок поля link.bookmarkId и link.headingId в ресурсе Link больше не могут представлять закладку или заголовок на конкретной вкладке документа.

Разработчикам следует обновить свой код, чтобы использовать link.bookmark и link.heading в операциях чтения и записи. Внутренние ссылки предоставляются с помощью объектов BookmarkLink и HeadingLink , каждый из которых содержит идентификатор закладки или заголовка и идентификатор вкладки, в которой он находится. Кроме того, link.tabId предоставляет внутренние ссылки на вкладки.

Содержимое ссылки в ответе documents.get также может различаться в зависимости от параметра includeTabsContent :

  • Если includeTabsContent задано значение true , все внутренние ссылки будут отображаться как link.bookmark и link.heading . Устаревшие поля больше не будут использоваться.
  • Если includeTabsContent не указан, то в документах, содержащих одну вкладку, любые внутренние ссылки на закладки или заголовки внутри этой вкладки будут отображаться как link.bookmarkId и link.headingId . В документах, содержащих несколько вкладок, внутренние ссылки будут отображаться как link.bookmark и link.heading .

В document.batchUpdate , если внутренняя ссылка создаётся с использованием одного из устаревших полей, закладка или заголовок будут считаться принадлежащими к идентификатору вкладки, указанному в Request . Если вкладка не указана, будет считаться, что она относится к первой вкладке документа.

Представление Link JSON предоставляет более подробную информацию.

Распространенные шаблоны использования вкладок

В следующих примерах кода описываются различные способы взаимодействия с вкладками.

Прочитать содержимое всех вкладок в документе

Существующий код, который выполнял эту функцию до появления вкладок, можно мигрировать для поддержки вкладок, установив параметр includeTabsContent в значение true , пройдя по иерархии дерева вкладок и вызвав методы получения Tab и DocumentTab вместо Document . Следующий фрагмент кода основан на фрагменте из раздела « Извлечение текста из документа» . Он показывает, как вывести всё текстовое содержимое каждой вкладки документа. Этот код обхода вкладок можно адаптировать для множества других случаев, где фактическая структура вкладок не важна.

Ява

/** Prints all text contents from all tabs in the document. */
static void printAllText(Docs service, String documentId) throws IOException {
  // Fetch the document with all of the tabs populated, including any nested
  // child tabs.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  List<Tab> allTabs = getAllTabs(doc);

  // Print the content from each tab in the document.
  for (Tab tab: allTabs) {
    // Get the DocumentTab from the generic Tab.
    DocumentTab documentTab = tab.getDocumentTab();
    System.out.println(
        readStructuralElements(documentTab.getBody().getContent()));
  }
}

/**
 * Returns a flat list of all tabs in the document in the order they would
 * appear in the UI (top-down ordering). Includes all child tabs.
 */
private List<Tab> getAllTabs(Document doc) {
  List<Tab> allTabs = new ArrayList<>();
  // Iterate over all tabs and recursively add any child tabs to generate a
  // flat list of Tabs.
  for (Tab tab: doc.getTabs()) {
    addCurrentAndChildTabs(tab, allTabs);
  }
  return allTabs;
}

/**
 * Adds the provided tab to the list of all tabs, and recurses through and
 * adds all child tabs.
 */
private void addCurrentAndChildTabs(Tab tab, List<Tab> allTabs) {
  allTabs.add(tab);
  for (Tab tab: tab.getChildTabs()) {
    addCurrentAndChildTabs(tab, allTabs);
  }
}

/**
 * Recurses through a list of Structural Elements to read a document's text
 * where text may be in nested elements.
 *
 * <p>For a code sample, see
 * <a href="https://developers.google.com/workspace/docs/api/samples/extract-text">Extract
 * the text from a document</a>.
 */
private static String readStructuralElements(List<StructuralElement> elements) {
  ...
}

Прочитать содержимое первой вкладки документа

Это похоже на чтение всех вкладок.

Ява

/** Prints all text contents from the first tab in the document. */
static void printAllText(Docs service, String documentId) throws IOException {
  // Fetch the document with all of the tabs populated, including any nested
  // child tabs.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  List<Tab> allTabs = getAllTabs(doc);

  // Print the content from the first tab in the document.
  Tab firstTab = allTabs.get(0);
  // Get the DocumentTab from the generic Tab.
  DocumentTab documentTab = firstTab.getDocumentTab();
  System.out.println(
      readStructuralElements(documentTab.getBody().getContent()));
}

Оформить запрос на обновление первой вкладки

Следующий фрагмент кода показывает, как выбрать конкретную вкладку в Request . Этот код основан на примере из руководства «Вставка, удаление и перемещение текста» .

Ява

/** Inserts text into the first tab of the document. */
static void insertTextInFirstTab(Docs service, String documentId)
    throws IOException {
  // Get the first tab's ID.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  Tab firstTab = doc.getTabs().get(0);
  String tabId = firstTab.getTabProperties().getTabId();

  List<Request>requests = new ArrayList<>();
  requests.add(new Request().setInsertText(
      new InsertTextRequest().setText(text).setLocation(new Location()
                                                            // Set the tab ID.
                                                            .setTabId(tabId)
                                                            .setIndex(25))));

  BatchUpdateDocumentRequest body =
      new BatchUpdateDocumentRequest().setRequests(requests);
  BatchUpdateDocumentResponse response =
      docsService.documents().batchUpdate(DOCUMENT_ID, body).execute();
}