您可以透過 Google 文件的 Apps Script 存取文件中任何分頁的內容。
什麼是分頁?
Google 文件提供名為「分頁」的層級組織功能。文件可讓使用者在單一文件中建立一或多個分頁,類似於現今試算表中的分頁。每個分頁都有專屬的標題和 ID (附加在網址中)。分頁也可以有子分頁,也就是在其他分頁下方巢狀分頁。
存取分頁
您可以使用 Document.getTabs()
存取分頁屬性和內容,該函式會傳回 Tab
清單。後續章節將簡要介紹 Tab
類別;Tab 類別說明文件也提供更詳細的資訊。
分頁屬性
您可以使用 Tab.getId()
和 Tab.getTitle()
等方法擷取分頁屬性。
分頁內容
您可以使用 Tab.asDocumentTab()
擷取每個分頁中的文件內容。請參閱「文件類別結構變更」一節,瞭解如何使用這項功能。
分頁階層
子分頁會透過 Tab.getChildTabs()
在 Google Apps Script 中公開。您必須逐一檢查子分頁的「樹狀結構」,才能從所有分頁存取內容。舉例來說,假設文件包含下列分頁階層:
如要存取 Tab 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 的分頁。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
類別上的這些現有方法會從目前分頁 (在指令碼中繫結至特定文件) 或第一個分頁 (如果沒有有效的分頁) 存取或修改內容。
存取特定分頁中的文字內容
建議您改用 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()
:在活動分頁中傳回使用者的選取範圍。Document.setCursor(position)
:設定使用者在有效文件中的游標位置。如果位置位於非活動分頁中,使用者的活動分頁也會切換至與該位置相關聯的分頁。Document.setSelection(range)
:設定使用者在有效文件中的選取範圍。如果範圍位於非活動分頁中,使用者的活動分頁也會切換至與該範圍相關聯的分頁。
分頁選取方法和用途
隨著分頁的推出,取得及設定執行指令碼的使用者所屬的有效分頁可能會很有幫助。您可以使用下列方法完成這項操作:
Document.getActiveTab()
:在有效文件中傳回使用者的有效Tab
。Document.setActiveTab(tabId)
:將使用者在目前文件中選取的Tab
設為具有指定 ID 的分頁。
使用者的整體「選取項目」是由目前的活動分頁,以及目前游標位置或選取範圍組成。使用有效選取項目的兩種模式,是明確將使用者的有效分頁修改為特定分頁,或是使用使用者的有效分頁。
您可以使用 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()
會建構以目前分頁為目標的 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()); } }