Apps Script для Google Docs позволяет получать доступ к содержимому из любой вкладки документа.
Что такое вкладки?
В Google Docs есть организационный уровень, называемый вкладками . Docs позволяет пользователям создавать одну или несколько вкладок в одном документе, аналогично тому, как вкладки используются в Таблицах Google. Каждая вкладка имеет собственное название и идентификатор (добавляется к URL-адресу). Вкладка также может иметь дочерние вкладки , которые представляют собой вкладки, вложенные в другую вкладку.
Вкладки доступа
Свойства и содержимое вкладок доступны с помощью Document.getTabs()
, который возвращает список Tab
. В последующих разделах представлен краткий обзор класса Tab
; документация по классу Tab также содержит более подробную информацию.
Свойства вкладки
Свойства вкладки можно получить с помощью таких методов, как Tab.getId()
и Tab.getTitle()
.
Содержимое вкладки
Содержимое документа в каждой вкладке можно получить с помощью Tab.asDocumentTab()
. В разделе «Изменения в структуре класса документа» описано, как это можно использовать.
Иерархия вкладок
Дочерние вкладки отображаются в Google 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(tabId)
: возвращает вкладку с указанным идентификатором. -
Document.getActiveTab()
: возвращает активную вкладку пользователя. Работает только в скриптах, привязанных к документу. Более подробно это описано в последующих разделах.
Изменения в структуре класса документа
Раньше в документах не было концепции вкладок, поэтому класс Document предоставлял методы для прямого доступа к текстовому содержимому документа и его изменения. К этой категории относятся следующие методы:
-
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()); } }