Apps Script для Google Docs позволяет получать доступ к контенту с любой вкладки документа.
Что такое вкладки?
В Документах Google есть организационный уровень, называемый вкладками . Документы позволяют пользователям создавать одну или несколько вкладок в одном документе, подобно тому, как сегодня существуют вкладки в Таблицах. Каждая вкладка имеет свой заголовок и идентификатор (добавленный в URL-адрес). Вкладка также может иметь дочерние вкладки — вкладки, вложенные под другую вкладку.
Поддержка API для дочерних вкладок доступна уже сегодня, но поддержка пользовательского интерфейса появится в ближайшее время. Вы можете обрабатывать дочерние вкладки в своем коде уже сегодня, чтобы при запуске поддержки пользовательского интерфейса вам не приходилось вносить дальнейшие обновления кода.
Доступ к вкладкам
Свойства и содержимое вкладок доступны с помощью 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());
}
}