Apps Script для Google Docs позволяет получать доступ к контенту с любой вкладки документа.
Что такое вкладки?
В Документах Google есть организационный уровень, называемый вкладками . Документы позволяют пользователям создавать одну или несколько вкладок в одном документе, подобно тому, как сегодня существуют вкладки в Таблицах. Каждая вкладка имеет свой заголовок и идентификатор (добавленный в URL-адрес). Вкладка также может иметь дочерние вкладки — вкладки, вложенные под другую вкладку.
Доступ к вкладкам
Свойства и содержимое вкладок доступны с помощью Document.getTabs()
, который возвращает список Tab
s. В последующих разделах дается краткий обзор класса Tab
; документация по классу Tab также предоставляет более подробную информацию.
Свойства вкладки
Свойства вкладки можно получить с помощью таких методов, как Tab.getId()
и Tab.getTitle()
.
Содержимое вкладки
Содержимое документа на каждой вкладке можно получить с помощью Tab.asDocumentTab()
. В разделе «Изменения в структуре класса документа» описывается, как это можно использовать.
Иерархия вкладок
Дочерние вкладки отображаются в скрипте Google Apps через 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(tabId)
: возвращает вкладку с указанным идентификатором. -
Document.getActiveTab()
: возвращает активную вкладку пользователя. Работает только в сценариях, привязанных к документу. В последующих разделах это описано более подробно.
Изменения в структуре класса документа
Раньше в документах не было концепции вкладок, поэтому класс документа предоставлял методы для прямого доступа и изменения текстового содержимого документа. В эту категорию попадают следующие методы:
-
Document.addBookmark(position)
-
Document.addFooter()
-
Document.addHeader()
-
Document.addNamedRange(name, range)
-
Document.getBody()
-
Document.getBookmark(id)
-
Document.getBookmarks()
-
Document.getFooter()
-
Document.getFootnotes()
-
Document.getHeader()
-
Document.getNamedRangeById(id)
-
Document.getNamedRanges()
-
Document.getNamedRanges(name)
-
Document.newPosition(element, offset)
-
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(position)
: устанавливает позицию курсора пользователя в активном документе. Если позиция находится на неактивной вкладке, то активная вкладка пользователя также переключается на вкладку, связанную с этой позицией. -
Document.setSelection(range)
: устанавливает диапазон выбора пользователя в активном документе. Если диапазон находится на неактивной вкладке, то активная вкладка пользователя также переключается на вкладку, связанную с этим диапазоном.
Методы выбора вкладок и варианты использования
С появлением вкладок может оказаться полезным получить и установить активную вкладку пользователя, запускающего скрипт. Это можно сделать с помощью следующих методов:
-
Document.getActiveTab()
: возвращает активнуюTab
пользователя в активном документе. -
Document.setActiveTab(tabId)
: устанавливает выбранную пользователемTab
в текущем документе на вкладку с указанным идентификатором.
Целостный «выбор» пользователя состоит из комбинации активной вкладки и текущей позиции курсора или диапазона выбора. Два шаблона работы с активным выбором — либо явно изменить активную вкладку пользователя на конкретную вкладку, либо использовать активную вкладку пользователя.
Явное изменение активной вкладки пользователя можно выполнить с помощью Document.setActiveTab(tabId)
. Альтернативно, вызов Document.setCursor(position)
или Document.setSelection(range)
с Position
или Range
из неактивной вкладки сделает эту вкладку новой активной.
Если предполагаемое поведение сценария заключается в использовании активной вкладки пользователя без ее изменения, то Document.setActiveTab(tabId)
не требуется. Методы Document.getCursor()
и Document.getSelection()
уже будут работать с активной вкладкой в зависимости от вкладки, с которой пользователь запускает скрипт.
Обратите внимание, что документ не поддерживает выбор нескольких вкладок, а также несколько позиций или диапазонов на разных вкладках. Таким образом, использование Document.setActiveTab(tabId)
очистит предыдущую позицию курсора или диапазон выбора.
Методы положения и диапазона для конкретной вкладки
Конкретная вкладка — это то, что придает смысл концепциям выбора текста Position
и Range
. Другими словами, позиция курсора или диапазон выбора имеют смысл только в том случае, если сценарий знает конкретную вкладку, внутри которой находится позиция или диапазон.
Это достигается с помощью методов DocumentTab.newPosition(element, offset)
и DocumentTab.newRange()
, которые создают позицию или диапазон, нацеленные на конкретную DocumentTab
, из которой вызывается метод. Напротив, Document.newPosition(element, offset)
и 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()); } }