Google 文件的 Apps Script 可讓您從文件的任何分頁存取內容。
什麼是分頁?
Google 文件提供了組織層,稱為「分頁」。文件可讓使用者在單一文件中建立一或多個分頁,類似於現今試算表中的分頁。每個分頁都有專屬的標題和 ID (附加在網址中)。分頁也可以有子分頁,也就是嵌在其他分頁下的分頁。
存取分頁
您可以使用 Document.getTabs()
存取分頁屬性和內容,該函式會傳回 Tab
清單。後續章節會提供 Tab
類別的簡要總覽;分頁類別說明文件也提供更詳細的資訊。
分頁屬性
您可以使用 Tab.getId()
和 Tab.getTitle()
等方法擷取分頁屬性。
分頁內容
您可以使用 Tab.asDocumentTab()
擷取每個分頁中的文件內容。請參閱「文件類別結構變更」一節,瞭解如何使用這項功能。
分頁階層
子分頁會透過 Tab.getChildTabs()
在 Google Apps Script 中公開。您必須逐一檢查子分頁的「樹狀結構」,才能從所有分頁存取內容。例如,假設文件包含分頁階層,如下所示:
如要存取 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)
:傳回含有指定 ID 的 Tab。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
類別上的這些現有方法會從目前分頁 (在指令碼中繫結至特定文件) 或第一個分頁 (如果沒有有效的分頁) 存取或修改內容。
存取特定分頁中的文字內容
建議您改用 DocumentTab
類別所提供的方法 (可透過 Tab.asDocumentTab()
方法取得),而不要使用 Document
以外的文字方法。例如:
// 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
類別提供 getter 和 setter,用於管理使用者在有效文件中選取的文字位置。這些方法會在執行指令碼的使用者使用中的分頁內運作。
Document.getCursor()
:傳回使用者在有效分頁中的游標位置。Document.getSelection()
:在active tab 中傳回使用者的選取範圍。Document.setCursor(position)
:設定使用者在有效文件中的游標位置。如果位置位於非活動分頁中,使用者的活動分頁也會切換至與該位置相關聯的分頁。Document.setSelection(range)
:設定使用者在使用中文件中選取的範圍。如果範圍位於非活動分頁中,使用者的活動分頁也會切換至與該範圍相關聯的分頁。
分頁選取方法和用途
推出分頁後,針對執行指令碼的使用者取得及設定使用中的分頁可能非常實用。可使用下列方法完成:
Document.getActiveTab()
:在有效文件中傳回使用者的有效Tab
。Document.setActiveTab(tabId)
:將使用者在目前文件中選取的Tab
設為具有指定 ID 的分頁。
使用者的整個「選取」動作,是由使用中的分頁以及目前的遊標位置或選取範圍組合而成。處理現有選擇的兩種模式,是明確修改使用者使用中的分頁至特定分頁,或使用使用者使用中的分頁。
您可以使用 Document.setActiveTab(tabId)
明確變更使用者的有效分頁。或者,如果從閒置分頁中使用 Position
或 Range
呼叫 Document.setCursor(position)
或 Document.setSelection(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()
會建構以目前分頁為目標的 Position 或 Range (如果指令碼未繫結,則為第一個分頁)。
請參閱後續章節中的程式碼區塊範例,其中提供使用選取項目的程式碼範例。
常見的分頁使用模式
以下程式碼範例說明與分頁互動的各種方式。
讀取文件中所有分頁的分頁內容
在分頁功能推出前,如果現有程式碼已執行這項操作,您可以透過遍歷分頁樹狀結構,並呼叫 Tab
和 DocumentTab
的 getter 方法 (而非 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()); } }