עבודה עם כרטיסיות

‫Google Docs API מאפשר לכם לגשת לתוכן מכל כרטיסייה במסמך.

מהן כרטיסיות?

ב-Google Docs יש שכבת ארגון שנקראת כרטיסיות. ב-Docs, המשתמשים יכולים ליצור כרטיסייה אחת או יותר במסמך אחד, בדומה לכרטיסיות שקיימות היום ב-Sheets. לכל כרטיסייה יש כותרת ומזהה משלה (מצורפים לכתובת ה-URL). בכרטיסייה יכולות להיות גם כרטיסיות צאצא, שהן כרטיסיות שמוטמעות מתחת לכרטיסייה אחרת.

שינויים במבנה של האופן שבו תוכן המסמך מיוצג במשאב Document

בעבר, לא היה במסמכים מושג של כרטיסיות, ולכן המשאב Document הכיל ישירות את כל תוכן הטקסט דרך השדות הבאים:

בגלל ההיררכיה המבנית הנוספת של הכרטיסיות, השדות האלה כבר לא מייצגים מבחינה סמנטית את תוכן הטקסט מכל הכרטיסיות במסמך. התוכן שמבוסס על טקסט מוצג עכשיו בשכבה אחרת. אפשר לגשת למאפיינים ולתוכן של הכרטיסיות ב-Google Docs באמצעות document.tabs, שהיא רשימה של אובייקטים מסוג Tab, שכל אחד מהם מכיל את כל שדות התוכן של הטקסט שצוינו למעלה. בקטעים הבאים מופיעה סקירה כללית קצרה, וייצוג ה-JSON של הכרטיסייה מספק מידע מפורט יותר.

גישה למאפייני כרטיסייה

אפשר לגשת למאפיינים של כרטיסייה באמצעות tab.tabProperties, שכולל מידע כמו המזהה, הכותרת והמיקום של הכרטיסייה.

גישה לתוכן טקסט בכרטיסייה

התוכן בפועל של המסמך בכרטיסייה מוצג כ-tab.documentTab. אפשר לגשת לכל שדות התוכן הטקסטואלי שצוינו למעלה באמצעות tab.documentTab. לדוגמה, במקום להשתמש ב-document.body, צריך להשתמש ב-document.tabs[indexOfTab].documentTab.body.

היררכיית הכרטיסיות

כרטיסיות צאצא מיוצגות ב-API כשדה tab.childTabs ב-Tab. כדי לגשת לכל הכרטיסיות במסמך, צריך לעבור על 'העץ' של כרטיסיות הצאצא. לדוגמה, נניח שיש מסמך שמכיל היררכיית כרטיסיות כפי שמוצג בהמשך:

ממשק משתמש של רשימת כרטיסיות שמכיל שלוש כרטיסיות ברמה העליונה, שחלקן כוללות כרטיסיות צאצא

כדי לאחזר את Body מכרטיסייה 3.1.2, צריך לגשת אל document.tabs[2].childTabs[0].childTabs[1].documentTab.body. בהמשך המאמר יש דוגמאות לקטעי קוד לדוגמה, שמראות איך להריץ איטרציה על כל הכרטיסיות במסמך.

שינויים בשיטות

עם השקת הכרטיסיות, בוצעו כמה שינויים בכל אחת מהשיטות של המסמך, ולכן יכול להיות שתצטרכו לעדכן את הקוד.

documents.get

כברירת מחדל, לא מוחזר כל התוכן של הכרטיסיות. מפתחים צריכים לעדכן את הקוד שלהם כדי לגשת לכל הכרטיסיות. ה-method‏ documents.get חושפת פרמטר includeTabsContent שמאפשר להגדיר אם התוכן מכל הכרטיסיות יסופק בתשובה.

  • אם הערך של includeTabsContent הוא true, השיטה documents.get תחזיר משאב Document עם השדה document.tabs מאוכלס. כל שדות הטקסט ישארו ריקים ישירות ב-document (למשל, document.body).
  • אם לא מספקים את includeTabsContent, שדות הטקסט במשאב Document (לדוגמה, document.body) יאוכלסו בתוכן מהכרטיסייה הראשונה בלבד. השדה document.tabs יהיה ריק ותוכן מכרטיסיות אחרות לא יוחזר.

documents.create

השיטה documents.create מחזירה משאב Document שמייצג את המסמך הריק שנוצר. המשאב Document שמוחזר יאכלס את תוכן המסמך הריק בשדות של תוכן הטקסט של המסמך וגם ב-document.tabs.

document.batchUpdate

כל Request כולל דרך לציין את הכרטיסיות שבהן יחול העדכון. כברירת מחדל, אם לא מציינים כרטיסייה, הפקודה Request תוחל ברוב המקרים על הכרטיסייה הראשונה במסמך. ‫ReplaceAllTextRequest, DeleteNamedRangeRequest, and ReplaceNamedRangeContentRequest הן שלוש בקשות מיוחדות שיוחלו כברירת מחדל על כל הכרטיסיות.

מידע נוסף מפורט במסמכי התיעוד של Request.

המשתמשים יכולים ליצור קישורים פנימיים לכרטיסיות, לסימניות ולכותרות במסמך. עם השקת התכונה 'כרטיסיות', השדות link.bookmarkId ו-link.headingId במשאב Link לא יכולים יותר לייצג סימנייה או כותרת בכרטיסייה מסוימת במסמך.

מפתחים צריכים לעדכן את הקוד שלהם כדי להשתמש ב-link.bookmark וב-link.heading בפעולות קריאה וכתיבה. הם חושפים קישורים פנימיים באמצעות אובייקטים של BookmarkLink ושל HeadingLink, שכל אחד מהם מכיל את המזהה של הסימנייה או הכותרת ואת המזהה של הכרטיסייה שבה הוא נמצא. בנוסף, link.tabId חושף קישורים פנימיים לכרטיסיות.

התוכן של תגובת documents.get יכול להשתנות גם בהתאם לפרמטר includeTabsContent:

  • אם המדיניות includeTabsContent מוגדרת לערך true, כל הקישורים הפנימיים יוצגו כ-link.bookmark ו-link.heading. לא יהיה יותר שימוש בשדות מדור קודם.
  • אם לא מצוין ערך ל-includeTabsContent, אז במסמכים שמכילים כרטיסייה אחת, כל הקישורים הפנימיים לסימניות או לכותרות בתוך הכרטיסייה היחידה הזו ממשיכים להיחשף כ-link.bookmarkId ו-link.headingId. במסמכים שמכילים כמה כרטיסיות, קישורים פנימיים יוצגו כ-link.bookmark ו-link.heading.

ב-document.batchUpdate, אם נוצר קישור פנימי באמצעות אחד משדות מדור קודם, הסימנייה או הכותרת ייחשבו ככאלה שמגיעים ממזהה הכרטיסייה שצוין ב-Request. אם לא מציינים כרטיסייה, המערכת תתייחס לנתונים כאילו הם מהכרטיסייה הראשונה במסמך.

ייצוג הקישור ב-JSON מספק מידע מפורט יותר.

דפוסי שימוש נפוצים בכרטיסיות

בדוגמאות הקוד הבאות מתוארות דרכים שונות לאינטראקציה עם כרטיסיות.

קריאת תוכן הכרטיסייה מכל הכרטיסיות במסמך

אפשר להעביר קוד קיים שעשה את זה לפני שהוספנו את התכונה 'כרטיסיות' כדי לתמוך בכרטיסיות. לשם כך, צריך להגדיר את הפרמטר includeTabsContent לערך true, לעבור על ההיררכיה של עץ הכרטיסיות ולקרוא לשיטות getter מתוך Tab ו-DocumentTab במקום מתוך Document. דוגמת הקוד החלקי הבאה מבוססת על קטע הקוד במאמר שליפת הטקסט ממסמך. הוא מסביר איך להדפיס את כל התוכן הטקסטואלי מכל כרטיסייה במסמך. אפשר להתאים את הקוד הזה של מעבר בין כרטיסיות לתרחישי שימוש רבים אחרים שלא מתייחסים למבנה בפועל של הכרטיסיות.

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(<var>DOCUMENT_ID</var>).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) {
  ...
}

קריאת תוכן הכרטיסייה מהכרטיסייה הראשונה במסמך

זה דומה לקריאה של כל הכרטיסיות.

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(<var>DOCUMENT_ID</var>).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(<var>DOCUMENT_ID</var>).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(<var>DOCUMENT_ID</var>, body).execute();
}