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

ב-Apps Script for Google Docs אפשר לגשת לתוכן מכל כרטיסייה במסמך.

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

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

גישה לכרטיסיות

אפשר לגשת לתכונות ולתוכן של הכרטיסייה באמצעות Document.getTabs(), שמחזירה רשימה של Tab. בחלקים הבאים מוצגת סקירה כללית קצרה של הכיתה Tab. גם במאמרי העזרה בנושא הכיתה בכרטיסייה יש מידע מפורט יותר.

מאפייני הכרטיסייה

אפשר לאחזר את מאפייני הכרטיסייה באמצעות methods כמו Tab.getId() ו-Tab.getTitle().

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

אפשר לאחזר את תוכן המסמך בכל כרטיסייה באמצעות הפונקציה Tab.asDocumentTab(). בקטע שינויים במבנה של Document Class מוסבר איך אפשר להשתמש באפשרות הזו.

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

כרטיסיות צאצא מוצגות ב-Google Apps Script דרך Tab.getChildTabs(). כדי לגשת לתוכן מכל הכרטיסיות, צריך לעבור דרך 'העץ' של כרטיסיות הצאצאים. לדוגמה, נניח שיש מסמך שמכיל היררכיית כרטיסיות באופן הבא:

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

כדי לגשת לכרטיסייה 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): החזרת הכרטיסייה עם המזהה שצוין.
  • Document.getActiveTab(): החזרת הכרטיסייה הפעילה של המשתמש. הפונקציה פועלת רק בסקריפטים שמוצמדים למסמך. בקטעים הבאים מוסבר על כך בפירוט.

שינויים במבנה של Document Class

בעבר, לא היו למסמכים כרכים, ולכן בכיתה Document נחשפו שיטות לגישה ישירה לתוכן הטקסט של המסמך ולשינוי שלו. השיטות הבאות נכללות בקטגוריה הזו:

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

השיטות הקיימות האלה בכיתה Document יעניקו גישה לתוכן בכרטיסייה הפעילה (בסקריפטים המאוגדים למסמך מסוים) או ישנו תוכן בכרטיסייה הראשונה (אם הכרטיסייה הפעילה לא זמינה).

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

במקום להשתמש בשיטות הטקסט של Document, מומלץ להשתמש בשיטות שזמינות במחלקה DocumentTab (שזמינה באמצעות השיטה Tab.asDocumentTab()). לדוגמה:

// 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 לניהול המקום במסמך הפעיל שבו המשתמש בוחר טקסט. ה-methods האלה פועלות בהקשר של הכרטיסייה הפעילה של המשתמש שמריץ את הסקריפט.

  • Document.getCursor(): הפונקציה מחזירה את מיקום הסמן של המשתמש בכרטיסייה הפעילה.
  • Document.getSelection(): הפונקציה מחזירה את טווח הבחירה של המשתמש בכרטיסייה הפעילה.
  • Document.setCursor(position): הגדרת מיקום הסמן של המשתמש במסמך הפעיל. אם המיקום נמצא בכרטיסייה לא פעילה, גם הכרטיסייה הפעילה של המשתמש תוחלף לכרטיסייה שמשויכת למיקום הזה.
  • Document.setSelection(range): מגדיר את טווח הבחירה של המשתמש במסמך הפעיל. אם הטווח נמצא בכרטיסייה לא פעילה, גם הכרטיסייה הפעילה של המשתמש עוברת לכרטיסייה שמשויכת לאותו הטווח.

שיטות לבחירת כרטיסיות ותרחישי שימוש

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

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

אפשר לשנות באופן מפורש את הכרטיסייה הפעילה של המשתמש באמצעות Document.setActiveTab(tabId). לחלופין, אפשר להפעיל כרטיסייה לא פעילה על ידי קריאה ל-Document.setCursor(position) או ל-Document.setSelection(range) עם Position או Range.

אם הסקריפט אמור להשתמש בכרטיסייה פעילה של המשתמש בלי לשנות אותה, אז לא צריך לשנות את Document.setActiveTab(tabId). השיטות Document.getCursor() ו-Document.getSelection() כבר יפעלו בכרטיסייה הפעילה, על סמך הכרטיסייה שממנה המשתמש מפעיל את הסקריפט.

חשוב לזכור שמסמך לא תומך בבחירת כמה כרטיסיות, או בכמה מיקומים או טווחים בכרטיסיות שונות. לכן, השימוש ב-Document.setActiveTab(tabId) ימחק את מיקום הסמן הקודם או את טווח הבחירה הקודם.

שיטות מיקום וטווח לכרטיסייה ספציפית

הכרטיסייה הספציפית היא זו שמעניקה משמעות למושגים של בחירת הטקסט Position ו-Range. במילים אחרות, למיקום של הסמן או לטווח הבחירה יש משמעות רק אם הסקריפט מזהה את הכרטיסייה הספציפית שבה נמצאים המיקום או הטווח.

כדי לעשות זאת, משתמשים ב-methods‏ DocumentTab.newPosition(element, offset) ו-DocumentTab.newRange(), שמאפשרים ליצור מיקום או טווח שמטרגטים את ה-DocumentTab הספציפי שממנו ה-method נקרא. לעומת זאת, הפונקציות Document.newPosition(element, offset) ו-Document.newRange() ייצרו מיקום או טווח שמטרגטים את הכרטיסייה הפעילה (או את הכרטיסייה הראשונה, אם הסקריפט לא מקושר).

בקטע הבא מופיעים בלוקים של קוד לדוגמה, עם קוד לדוגמה לעבודה עם בחירות.

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

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

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

כדי להעביר קוד קיים שביצע את הפעולה הזו לפני שהופיעה התכונה 'כרטיסיות', עליכם לעבור על עץ הכרטיסיות ולקרוא לשיטות getter מ-Tab ו-DocumentTab במקום מ-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()); } }