使用分頁

Google 文件 API 可讓您存取文件中任何分頁的內容。

什麼是分頁?

Google 文件提供名為「分頁」的層級組織功能。Google 文件允許使用者在單一文件中建立一或多個分頁,類似於現今試算表中的分頁。每個分頁都有專屬的標題和 ID (附加在網址中)。分頁也可以有子分頁,也就是巢狀在其他分頁下的分頁。

文件資源中文件內容的結構變更

過去,文件並未有分頁的概念,因此 Document 資源會透過下列欄位直接包含所有文字內容:

由於分頁的結構層級有所增加,這些欄位在語意上不再代表文件中所有分頁的文字內容。文字內容現在會以不同的圖層呈現。您可以使用 document.tabs 存取 Google 文件中的分頁屬性和內容,這是 Tab 物件的清單,每個物件都包含上述所有文字內容欄位。後續章節將簡要介紹這項功能;分頁 JSON 表示法也會提供更詳細的資訊。

存取分頁屬性

使用 tab.tabProperties 存取分頁屬性,其中包含分頁的 ID、標題和位置等資訊。

存取分頁中的文字內容

分頁中的實際文件內容會以 tab.documentTab 的形式顯示。所有上述文字內容欄位都可以使用 tab.documentTab 存取。例如,請改用 document.tabs[indexOfTab].documentTab.body,而非 document.body

分頁階層

子分頁在 API 中會以 Tab 上的 tab.childTabs 欄位呈現。如要存取文件中的所有分頁,就必須遍歷子分頁的「樹狀結構」。舉例來說,請考量包含下列分頁階層的文件:

分頁清單 UI,其中包含三個頂層分頁,其中部分分頁有子分頁

如要從 分頁 3.1.2 擷取 Body,您必須存取 document.tabs[2].childTabs[0].childTabs[1].documentTab.body。請參閱後續章節中的程式碼範例區塊,其中提供用於在文件中遍歷所有分頁的程式碼範例。

方法異動

隨著分頁的推出,每個文件方法都會有一些變更,可能需要您更新程式碼。

documents.get

根據預設,系統不會傳回所有分頁內容。開發人員應更新程式碼,以便存取所有分頁。documents.get 方法會公開 includeTabsContent 參數,可用於設定回應中是否提供所有分頁的內容。

  • 如果 includeTabsContent 設為 truedocuments.get 方法會傳回已填入 document.tabs 欄位的 Document 資源。所有直接位於 document 上的文字欄位 (例如 document.body) 都會保留為空白。
  • 如果未提供 includeTabsContent,則 Document 資源 (例如 document.body) 中的文字欄位只會填入第一個分頁中的內容。document.tabs 欄位會為空白,且不會傳回其他分頁的內容。

documents.create

documents.create 方法會傳回 Document 資源,代表已建立的空白文件。傳回的 Document 資源會在文件的文字內容欄位和 document.tabs 中填入空白的文件內容。

document.batchUpdate

每個 Request 都包含一種方法,可用來指定要套用更新的分頁。根據預設,如果未指定分頁,Request 在大多數情況下會套用至文件中的第一個分頁。ReplaceAllTextRequestDeleteNamedRangeRequestReplaceNamedRangeContentRequest 是三項特殊要求,預設會套用至所有分頁。

詳情請參閱 Request 說明文件。

使用者可以建立文件內分頁、書籤和標題的內部連結。隨著分頁功能的推出,Link 資源中的 link.bookmarkIdlink.headingId 欄位,將無法再代表文件中特定分頁中的書籤或標題。

開發人員應更新程式碼,在讀取和寫入作業中使用 link.bookmarklink.heading。這些物件會使用 BookmarkLinkHeadingLink 物件公開內部連結,每個物件都包含書籤或標題的 ID,以及所屬分頁的 ID。此外,link.tabId 會公開分頁的內部連結。

documents.get 回應的連結內容也可能因 includeTabsContent 參數而異:

  • 如果將 includeTabsContent 設為 true,所有內部連結都會顯示為 link.bookmarklink.heading。系統將不再使用舊版欄位。
  • 如果未提供 includeTabsContent,在包含單一分頁的文件中,任何指向該單一分頁內書籤或標題的內部連結,仍會以 link.bookmarkIdlink.headingId 顯示。在包含多個分頁的文件中,內部連結會顯示為 link.bookmarklink.heading

document.batchUpdate 中,如果使用其中一個舊版欄位建立內部連結,系統會將書籤或標題視為來自 Request 中指定的分頁 ID。如果未指定分頁,系統會認為是來自文件中的第一個分頁。

連結 JSON 表示法會提供更詳細的資訊。

分頁的常見使用模式

以下程式碼範例說明與分頁互動的各種方式。

讀取文件中所有分頁的分頁內容

在分頁功能推出前,如果現有程式碼已執行上述操作,您可以將 includeTabsContent 參數設為 true,並透過遍歷分頁樹狀結構層級,以及呼叫 TabDocumentTab 而非 Document 的 getter 方法,來遷移至支援分頁的程式碼。以下程式碼範例的部分內容取自「從文件中擷取文字」一文中的程式碼片段。這項功能會顯示如何列印文件中每個分頁的所有文字內容。這段分頁瀏覽程式碼可用於許多其他用途,不必考量分頁的實際結構。

Java

/** Prints all text contents from all tabs in the document. */
static void printAllText(Docs service, String documentId) throws IOException {
  // Fetch the document with all of the tabs populated, including any nested
  // child tabs.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  List<Tab> allTabs = getAllTabs(doc);

  // Print the content from each tab in the document.
  for (Tab tab: allTabs) {
    // Get the DocumentTab from the generic Tab.
    DocumentTab documentTab = tab.getDocumentTab();
    System.out.println(
        readStructuralElements(documentTab.getBody().getContent()));
  }
}

/**
 * Returns a flat list of all tabs in the document in the order they would
 * appear in the UI (top-down ordering). Includes all child tabs.
 */
private List<Tab> getAllTabs(Document doc) {
  List<Tab> allTabs = new ArrayList<>();
  // Iterate over all tabs and recursively add any child tabs to generate a
  // flat list of Tabs.
  for (Tab tab: 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.
 */
private void addCurrentAndChildTabs(Tab tab, List<Tab> allTabs) {
  allTabs.add(tab);
  for (Tab tab: tab.getChildTabs()) {
    addCurrentAndChildTabs(tab, allTabs);
  }
}

/**
 * Recurses through a list of Structural Elements to read a document's text
 * where text may be in nested elements.
 *
 * <p>For a code sample, see
 * <a href="https://developers.google.com/docs/api/samples/extract-text">Extract
 * the text from a document</a>.
 */
private static String readStructuralElements(List<StructuralElement> elements) {
  ...
}

讀取文件中第一個分頁的分頁內容

這與讀取所有分頁類似。

Java

/** Prints all text contents from the first tab in the document. */
static void printAllText(Docs service, String documentId) throws IOException {
  // Fetch the document with all of the tabs populated, including any nested
  // child tabs.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  List<Tab> allTabs = getAllTabs(doc);

  // Print the content from the first tab in the document.
  Tab firstTab = allTabs.get(0);
  // Get the DocumentTab from the generic Tab.
  DocumentTab documentTab = firstTab.getDocumentTab();
  System.out.println(
      readStructuralElements(documentTab.getBody().getContent()));
}

提出更新第一個分頁的要求

以下程式碼範例說明如何在 Request 中指定特定分頁。這段程式碼是以「插入、刪除及移動文字」指南中的範例為基礎。

Java

/** Inserts text into the first tab of the document. */
static void insertTextInFirstTab(Docs service, String documentId)
    throws IOException {
  // Get the first tab's ID.
  Document doc =
      service.documents().get(documentId).setIncludeTabsContent(true).execute();
  Tab firstTab = doc.getTabs().get(0);
  String tabId = firstTab.getTabProperties().getTabId();

  List<Request>requests = new ArrayList<>();
  requests.add(new Request().setInsertText(
      new InsertTextRequest().setText(text).setLocation(new Location()
                                                            // Set the tab ID.
                                                            .setTabId(tabId)
                                                            .setIndex(25))));

  BatchUpdateDocumentRequest body =
      new BatchUpdateDocumentRequest().setRequests(requests);
  BatchUpdateDocumentResponse response =
      docsService.documents().batchUpdate(DOCUMENT_ID, body).execute();
}