Скрипт Google Apps Script для Google Docs позволяет получать доступ к содержимому с любой вкладки документа.
Что такое вкладки?
В Docs есть организационный слой, называемый вкладками . Docs позволяет пользователям создавать одну или несколько вкладок в одном документе, аналогично тому, как сейчас работают вкладки в Google Sheets. Каждая вкладка имеет свой заголовок и идентификатор (добавляется в URL-адрес). Вкладка также может иметь дочерние вкладки , которые вложены под другую вкладку.
Вкладки доступа
Свойства и содержимое вкладок доступны с помощью Document.getTabs , который возвращает список Tab . В последующих разделах дается краткий обзор класса Tab ; более подробная информация также содержится в документации к классу Tab .
Свойства вкладки
Свойства вкладок можно получить с помощью таких методов, как Tab.getId и Tab.getTitle .
Содержимое вкладки
Содержимое документа в каждой вкладке можно получить с помощью Tab.asDocumentTab . В разделе «Изменения в структуре класса Document» описано, как это можно использовать.
Иерархия вкладок
Дочерние вкладки в Apps Script доступны через Tab.getChildTabs . Для доступа к содержимому всех вкладок необходимо пройтись по «дереву» дочерних вкладок. Например, рассмотрим документ, содержащий следующую иерархию вкладок:

Для доступа к вкладке 3.1.2 выполните следующие действия:
// Print the ID of Tab 3.1.2.
const doc = DocumentApp.getActiveDocument();
const tab = doc.getTabs()[2].getChildTabs()[0].getChildTabs()[1];
console.log(tab.getId());
Примеры кода, выполняющие итерацию по всем вкладкам документа, приведены в последующих разделах.
Другие способы восстановления вкладок
Есть еще два способа получить доступ к вкладкам:
-
Document.getTab: Возвращает вкладку с указанным ID. -
Document.getActiveTab: Возвращает активную вкладку пользователя. Работает только в скриптах, привязанных к документу. Более подробно это описано в последующих разделах.
Изменения в структуре класса документа.
Раньше в документах не существовало понятия вкладок, поэтому класс Document предоставил методы для прямого доступа к текстовому содержимому документа и его изменения. К этой категории относятся следующие методы:
-
Document.addBookmark -
Document.addFooter -
Document.addHeader -
Document.addNamedRange -
Document.getBody -
Document.getBookmark -
Document.getBookmarks -
Document.getFooter -
Document.getFootnotes -
Document.getHeader -
Document.getNamedRangeById -
Document.getNamedRanges -
Document.getNamedRanges -
Document.newPosition -
Document.newRange
С добавлением структурной иерархии вкладок эти методы больше не представляют текстовое содержимое всех вкладок документа семантически. Текстовое содержимое теперь будет представлено на другом уровне; все вышеупомянутые методы работы с текстом доступны через DocumentTab .
Существующие методы класса Document позволяют получать доступ к содержимому или изменять его либо с активной вкладки (в скриптах, привязанных к конкретному документу), либо с первой вкладки (если активная вкладка недоступна).
Доступ к текстовому содержимому в определенной вкладке
Вместо текстовых методов класса Document рекомендуется использовать методы, доступные в классе DocumentTab (которые доступны через метод Tab.asDocumentTab ). Например:
// Print the text from the body of the active tab.
const doc = DocumentApp.getActiveDocument();
const documentTab = doc.getActiveTab().asDocumentTab();
const body = documentTab.getBody();
console.log(body.getText());
Изменения в выборе пользователя
Концепция выбора пользователя актуальна и может использоваться или изменяться только скриптами, привязанными к документу.
Методы выделения текста
Класс Document предоставляет геттеры и сеттеры для управления местоположением выделенного пользователем фрагмента текста в активном документе. Эти методы работают в контексте активной вкладки пользователя, запускающего скрипт.
-
Document.getCursor: Возвращает положение курсора пользователя на активной вкладке . -
Document.getSelection: Возвращает диапазон выделения пользователя на активной вкладке . -
Document.setCursor: Устанавливает положение курсора пользователя в активном документе. Если положение находится в неактивной вкладке, то активная вкладка пользователя также переключается на вкладку, связанную с этим положением. -
Document.setSelection: Задает диапазон выделения пользователя в активном документе. Если диапазон находится на неактивной вкладке, то активная вкладка пользователя также переключается на вкладку, связанную с этим диапазоном.
Методы выбора с помощью клавиши Tab и варианты их использования
С появлением вкладок, получите и установите активную вкладку пользователя, запускающего скрипт. Используйте следующие методы:
-
Document.getActiveTab: Возвращает активнуюTabпользователя в активном документе. -
Document.setActiveTab: УстанавливаетTabвыбранную пользователем в текущем документе, на вкладку с указанным ID.
Целостное «выделение» пользователя представляет собой комбинацию активной вкладки и текущего положения курсора или диапазона выделения. Существует два способа работы с активным выделением: либо явное изменение активной вкладки пользователя на конкретную вкладку, либо использование активной вкладки пользователя.
Явно изменить активную вкладку пользователя можно с помощью Document.setActiveTab . В качестве альтернативы, вызов Document.setCursor или Document.setSelection с указанием Position или Range из неактивной вкладки сделает эту вкладку новой активной.
Если предполагается, что скрипт будет использовать активную вкладку пользователя, не изменяя её, то метод Document.setActiveTab не нужен. Методы Document.getCursor и Document.getSelection работают с активной вкладкой, в зависимости от того, с какой вкладки пользователь запускает скрипт.
Документ не поддерживает множественный выбор вкладок, а также множественные позиции или диапазоны на разных вкладках. Поэтому использование Document.setActiveTab очищает предыдущую позицию курсора или диапазон выделения.
Методы позиционирования и определения диапазона для конкретной вкладки
Конкретная вкладка придает смысл понятиям выделения текста: Position и Range . Положение курсора или диапазон выделения имеют смысл только в том случае, если скрипт знает конкретную вкладку, в пределах которой находится это положение или диапазон.
Это достигается с помощью методов DocumentTab.newPosition и DocumentTab.newRange , которые создают позицию или диапазон, нацеленные на конкретную DocumentTab , из которой вызывается метод. В отличие от них, Document.newPosition и Document.newRange создают позицию или диапазон внутри активной вкладки (или первой вкладки, если скрипт не привязан).
Примеры кода для работы с выделенными фрагментами приведены в последующих разделах.
Типичные модели использования вкладок
Приведенные ниже примеры кода описывают различные способы взаимодействия с вкладками.
Прочитать содержимое всех вкладок документа.
Существующий код, который делал это до появления функции вкладок, можно перевести на поддержку вкладок, пройдясь по дереву вкладок и вызвав методы-геттеры из Tab и DocumentTab вместо Document . Следующий фрагмент кода показывает, как распечатать все текстовые данные из каждой вкладки в документе. Этот код обхода вкладок можно адаптировать для многих других случаев использования, которым не важна фактическая структура вкладок.
/** Logs all text contents from all tabs in the active document. */ function logAllText() { // Generate a list of all the tabs in the document, including any // nested child tabs. DocumentApp.openById('abc123456') can also // be used instead of DocumentApp.getActiveDocument(). const doc = DocumentApp.getActiveDocument(); const allTabs = getAllTabs(doc); // Log the content from each tab in the document. for (const tab of allTabs) { // Get the DocumentTab from the generic Tab object. const documentTab = tab.asDocumentTab(); // Get the body from the given DocumentTab. const body = documentTab.getBody(); // Get the body text and log it to the console. console.log(body.getText()); } } /** * Returns a flat list of all tabs in the document, in the order * they would appear in the UI (i.e. top-down ordering). Includes * all child tabs. */ function getAllTabs(doc) { const allTabs = []; // Iterate over all tabs and recursively add any child tabs to // generate a flat list of Tabs. for (const tab of 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. */ function addCurrentAndChildTabs(tab, allTabs) { allTabs.push(tab); for (const childTab of tab.getChildTabs()) { addCurrentAndChildTabs(childTab, allTabs); } }
Прочитайте содержимое первой вкладки документа.
Это похоже на чтение всех вкладок.
/** * Logs all text contents from the first tab in the active * document. */ function logAllText() { // Generate a list of all the tabs in the document, including any // nested child tabs. const doc = DocumentApp.getActiveDocument(); const allTabs = getAllTabs(doc); // Log the content from the first tab in the document. const firstTab = allTabs[0]; // Get the DocumentTab from the generic Tab object. const documentTab = firstTab.asDocumentTab(); // Get the body from the DocumentTab. const body = documentTab.getBody(); // Get the body text and log it to the console. console.log(body.getText()); }
Обновите содержимое первой вкладки.
Приведенный ниже фрагмент кода демонстрирует, как при внесении изменений выбрать определенную вкладку.
/** Inserts text into the first tab of the active document. */ function insertTextInFirstTab() { // Get the first tab's body. const doc = DocumentApp.getActiveDocument(); const firstTab = doc.getTabs()[0]; const firstDocumentTab = firstTab.asDocumentTab(); const firstTabBody = firstDocumentTab.getBody(); // Append a paragraph and a page break to the first tab's body // section. firstTabBody.appendParagraph("A paragraph."); firstTabBody.appendPageBreak(); }
Обновить содержимое активной или выбранной вкладки
Приведенный ниже фрагмент кода показывает, как выбрать активную вкладку при внесении изменений.
/** * Inserts text into the active/selected tab of the active * document. */ function insertTextInActiveTab() { // Get the active/selected tab's body. const doc = DocumentApp.getActiveDocument(); const activeTab = doc.getActiveTab(); const activeDocumentTab = activeTab.asDocumentTab(); const activeTabBody = activeDocumentTab.getBody(); // Append a paragraph and a page break to the active tab's body // section. activeTabBody.appendParagraph("A paragraph."); activeTabBody.appendPageBreak(); }
Задайте положение курсора или диапазон выделения на активной вкладке.
Приведённый ниже фрагмент кода демонстрирует, как обновить положение курсора или диапазон выделения в активной вкладке пользователя. Это актуально только для связанных скриптов.
/** * Changes the user's selection to select all tables within the tab * with the provided ID. */ function selectAllTables(tabId) { const doc = DocumentApp.getActiveDocument(); const tab = doc.getTab(tabId); const documentTab = tab.asDocumentTab(); // Build a range that encompasses all tables within the specified // tab. const rangeBuilder = documentTab.newRange(); const tables = documentTab.getBody().getTables(); for (let i = 0; i < tables.length; i++) { rangeBuilder.addElement(tables[i]); } // Set the document's selection to the tables within the specified // tab. Note that this actually switches the user's active tab as // well. doc.setSelection(rangeBuilder.build()); }
Установить активную или выбранную вкладку
Приведённый ниже фрагмент кода демонстрирует, как изменить активную вкладку пользователя. Это актуально только для связанных скриптов.
/** * Changes the user's selected tab to the tab immediately following * the currently selected one. Handles child tabs. * *Only changes the selection if there is a tab following the
* currently selected one. */ function selectNextTab() { const doc = DocumentApp.getActiveDocument(); const allTabs = getAllTabs(doc); const activeTab = doc.getActiveTab(); // Find the index of the currently active tab. let activeTabIndex = -1; for (let i = 0; i < allTabs.length; i++) { if (allTabs[i].getId() === activeTab.getId()) { activeTabIndex = i; } } // Update the user's selected tab if there is a valid next tab. const nextTabIndex = activeTabIndex + 1; if (nextTabIndex < allTabs.length) { doc.setActiveTab(allTabs[nextTabIndex].getId()); } }