Làm việc với tab

Google Docs API cho phép bạn truy cập vào nội dung từ bất kỳ thẻ nào trong tài liệu.

Thẻ là gì?

Google Tài liệu có một lớp tổ chức gọi là thẻ. Tài liệu cho phép người dùng tạo một hoặc nhiều thẻ trong một tài liệu duy nhất, tương tự như cách có các thẻ trong Trang tính hiện nay. Mỗi thẻ có tiêu đề và mã nhận dạng riêng (được thêm vào URL). Một thẻ cũng có thể có thẻ con, là những thẻ được lồng bên dưới một thẻ khác.

Thay đổi về cấu trúc đối với cách nội dung tài liệu được biểu thị trong Tài nguyên tài liệu

Trước đây, các tài liệu không có khái niệm về thẻ, vì vậy, Tài nguyên Document trực tiếp chứa tất cả nội dung văn bản thông qua các trường sau:

Với hệ thống phân cấp cấu trúc bổ sung của các thẻ, những trường này không còn biểu thị một cách ngữ nghĩa nội dung văn bản từ tất cả các thẻ trong tài liệu nữa. Nội dung dựa trên văn bản hiện được thể hiện ở một lớp khác. Bạn có thể truy cập vào các thuộc tính và nội dung của thẻ trong Google Tài liệu bằng document.tabs. Đây là danh sách các đối tượng Tab, mỗi đối tượng chứa tất cả các trường nội dung văn bản nêu trên. Các phần sau cung cấp thông tin tổng quan ngắn gọn; phần biểu thị JSON của thẻ cũng cung cấp thông tin chi tiết hơn.

Truy cập vào các thuộc tính của thẻ

Truy cập vào các thuộc tính của thẻ bằng cách sử dụng tab.tabProperties, bao gồm những thông tin như mã nhận dạng, tiêu đề và vị trí của thẻ.

Truy cập vào nội dung văn bản trong một thẻ

Nội dung thực tế của tài liệu trong thẻ này sẽ xuất hiện dưới dạng tab.documentTab. Bạn có thể truy cập vào tất cả các trường nội dung văn bản nêu trên bằng cách sử dụng tab.documentTab. Ví dụ: thay vì dùng document.body, bạn nên dùng document.tabs[indexOfTab].documentTab.body.

Hệ phân cấp thẻ

Các thẻ con được biểu thị trong API dưới dạng trường tab.childTabs trên Tab. Để truy cập vào tất cả các thẻ trong một tài liệu, bạn cần phải duyệt qua "cây" của các thẻ con. Ví dụ: hãy xem xét một tài liệu chứa hệ phân cấp thẻ như sau:

Giao diện người dùng Tablist chứa 3 thẻ cấp cao nhất, một số thẻ có thẻ con

Để truy xuất Body từ Mục 3.1.2, bạn sẽ truy cập vào document.tabs[2].childTabs[0].childTabs[1].documentTab.body. Hãy xem các khối mã mẫu trong phần sau. Phần này cung cấp mã mẫu để lặp lại trên tất cả các thẻ trong một tài liệu.

Các thay đổi đối với phương thức

Khi các thẻ được giới thiệu, mỗi phương thức tài liệu đều có một số thay đổi mà bạn có thể phải cập nhật mã.

documents.get

Theo mặc định, không phải tất cả nội dung trên thẻ đều được trả về. Nhà phát triển nên cập nhật mã để truy cập vào tất cả các thẻ. Phương thức documents.get hiển thị một tham số includeTabsContent cho phép định cấu hình xem nội dung từ tất cả các thẻ có được cung cấp trong phản hồi hay không.

  • Nếu includeTabsContent được đặt thành true, phương thức documents.get sẽ trả về Tài nguyên Document có trường document.tabs được điền sẵn. Tất cả các trường văn bản ngay trên document (ví dụ: document.body) sẽ bị bỏ trống.
  • Nếu bạn không cung cấp includeTabsContent, thì các trường văn bản trong Tài nguyên Document (ví dụ: document.body) sẽ chỉ được điền nội dung từ thẻ đầu tiên. Trường document.tabs sẽ trống và nội dung từ các thẻ khác sẽ không được trả về.

documents.create

Phương thức documents.create trả về một Tài nguyên Document đại diện cho tài liệu trống đã được tạo. Tài nguyên Document được trả về sẽ điền sẵn nội dung tài liệu trống trong cả các trường nội dung văn bản của tài liệu cũng như document.tabs.

document.batchUpdate

Mỗi Request đều có cách chỉ định các thẻ để áp dụng bản cập nhật. Theo mặc định, nếu bạn không chỉ định thẻ, thì Request sẽ được áp dụng cho thẻ đầu tiên trong tài liệu trong hầu hết các trường hợp. ReplaceAllTextRequest, DeleteNamedRangeRequestReplaceNamedRangeContentRequest là 3 yêu cầu đặc biệt sẽ áp dụng cho tất cả các thẻ theo mặc định.

Tham khảo tài liệu về Request để biết thông tin cụ thể.

Người dùng có thể tạo đường liên kết nội bộ đến các thẻ, dấu trang và tiêu đề trong tài liệu. Khi tính năng thẻ được ra mắt, các trường link.bookmarkIdlink.headingId trong tài nguyên Link không còn thể hiện dấu trang hoặc tiêu đề trong một thẻ cụ thể trong tài liệu nữa.

Nhà phát triển nên cập nhật mã để sử dụng link.bookmarklink.heading trong các thao tác đọc và ghi. Các đối tượng này hiển thị các đường liên kết nội bộ bằng cách sử dụng các đối tượng BookmarkLinkHeadingLink, mỗi đối tượng chứa mã của dấu trang hoặc tiêu đề và mã của thẻ mà dấu trang hoặc tiêu đề đó nằm trong. Ngoài ra, link.tabId còn hiển thị các đường liên kết nội bộ đến các thẻ.

Nội dung của đường liên kết trong phản hồi documents.get cũng có thể thay đổi tuỳ thuộc vào tham số includeTabsContent:

  • Nếu includeTabsContent được đặt thành true, tất cả đường liên kết nội bộ sẽ hiển thị dưới dạng link.bookmarklink.heading. Các trường cũ sẽ không còn được dùng nữa.
  • Nếu không có includeTabsContent, thì trong các tài liệu chứa một thẻ duy nhất, mọi đường liên kết nội bộ đến dấu trang hoặc tiêu đề trong thẻ duy nhất đó vẫn tiếp tục được hiển thị dưới dạng link.bookmarkIdlink.headingId. Trong các tài liệu có nhiều thẻ, đường liên kết nội bộ sẽ xuất hiện dưới dạng link.bookmarklink.heading.

Trong document.batchUpdate, nếu một đường liên kết nội bộ được tạo bằng một trong các trường cũ, thì dấu trang hoặc tiêu đề sẽ được coi là thuộc mã nhận dạng thẻ được chỉ định trong Request. Nếu không có thẻ nào được chỉ định, thì thẻ đó sẽ được coi là thẻ đầu tiên trong tài liệu.

Phần trình bày JSON của đường liên kết cung cấp thông tin chi tiết hơn.

Các mẫu sử dụng thẻ phổ biến

Các mẫu mã sau đây mô tả nhiều cách tương tác với các thẻ.

Đọc nội dung thẻ từ tất cả các thẻ trong tài liệu

Bạn có thể di chuyển mã hiện có đã thực hiện việc này trước khi có tính năng thẻ để hỗ trợ thẻ bằng cách đặt tham số includeTabsContent thành true, di chuyển hệ phân cấp cây thẻ và gọi các phương thức getter từ TabDocumentTab thay vì Document. Mẫu mã một phần sau đây dựa trên đoạn mã tại Trích xuất văn bản từ tài liệu. Ví dụ này cho thấy cách in tất cả nội dung văn bản từ mọi thẻ trong một tài liệu. Bạn có thể điều chỉnh mã di chuyển bằng phím Tab này cho nhiều trường hợp sử dụng khác mà không cần quan tâm đến cấu trúc thực tế của các thẻ.

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/workspace/docs/api/samples/extract-text">Extract
 * the text from a document</a>.
 */
private static String readStructuralElements(List<StructuralElement> elements) {
  ...
}

Đọc nội dung của thẻ từ thẻ đầu tiên trong tài liệu

Thao tác này tương tự như thao tác đọc tất cả các thẻ.

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()));
}

Đưa ra yêu cầu cập nhật thẻ đầu tiên

Mẫu mã một phần sau đây cho thấy cách nhắm đến một thẻ cụ thể trong Request. Mã này dựa trên mẫu trong hướng dẫn Chèn, xoá và di chuyển văn bản.

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();
}