التعامل مع علامات التبويب

يتيح لك Apps Script في "مستندات Google" الوصول إلى المحتوى من أي علامة تبويب في المستند.

ما هي علامات التبويب؟

تتضمّن "مستندات Google" طبقة تنظيمية تُعرف باسم علامات التبويب. تسمح "مستندات Google" للمستخدمين بإنشاء علامة تبويب واحدة أو أكثر ضمن مستند واحد، تمامًا كما هو الحال مع علامات التبويب في "جداول بيانات Google" اليوم. تحتوي كل علامة تبويب على عنوان ومعرّف (مُرفَق في عنوان URL). يمكن أن تحتوي علامة التبويب أيضًا على علامات تبويب فرعية، وهي علامات تبويب متداخلة أسفل علامة تبويب أخرى.

الوصول إلى علامات التبويب

يمكن الوصول إلى سمات علامات التبويب ومحتوى باستخدام Document.getTabs()، التي تعرض قائمة بالعناصر Tab. تقدّم الأقسام اللاحقة نظرة عامة موجزة على فئة Tab، كما تقدّم مستندات فئة Tab معلومات أكثر تفصيلاً.

خصائص علامة التبويب

يمكن استرداد سمات علامات التبويب باستخدام طرق مثل Tab.getId() و Tab.getTitle().

محتوى علامة التبويب

يمكن استرداد محتوى المستند ضمن كل علامة تبويب باستخدام Tab.asDocumentTab(). يوضّح قسم التغييرات في بنية فئة المستند كيفية استخدام هذه الميزة.

التسلسل الهرمي لعلامات التبويب

يتم عرض علامات التبويب الفرعية في 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(): يعرض علامة التبويب النشطة للمستخدم. لا تعمل إلا في النصوص البرمجية التي تكون مرتبطة بمستند. توضّح الأقسام التالية ذلك بمزيد من التفصيل.

تغييرات في بنية فئة المستندات

في السابق، لم تكن المستندات تتضمّن مفهوم علامات التبويب، لذا كانت فئة المستند تعرِض طرقًا للوصول مباشرةً إلى محتوى النص في المستند وتعديله. تندرج الطرق التالية ضمن هذه الفئة:

مع التسلسل الهرمي الهيكلي الإضافي للعلامات التبويب، لم تعُد هذه الطرق representدلاليًا لمحتوى النص من جميع علامات التبويب في المستند. سيتم الآن تمثيل محتوى النص في طبقة مختلفة، ويمكن الوصول إلى جميع طرق النص المذكورة أعلاه من خلال DocumentTab.

ستتمكّن هذه الطرق الحالية في فئة Document من الوصول إلى المحتوى أو تعديله من علامة التبويب النشطة (في النصوص البرمجية المرتبطة بأحد المستندات) أو علامة التبويب الأولى (إذا لم تكن علامة تبويب نشطة متاحة).

الوصول إلى محتوى نصي ضمن علامة تبويب معيّنة

بدلاً من استخدام طرق النصوص من Document، ننصحك باستخدام methods التي تتوفّر من فئة 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 وظائف الحصول والضبط لإدارة الجزء الذي يختار فيه المستخدِم النص ضمن المستند النشط. تعمل هذه الطرق ضمن سياق علامة التبويب النشطة للمستخدم الذي يشغّل النص البرمجي.

  • Document.getCursor(): يعرض موضع مؤشر المستخدم في علامة التبويب النشطة.
  • Document.getSelection(): يعرض نطاق اختيار المستخدم في علامة التبويب "نشط".
  • Document.setCursor(position): يضبط موضع مؤشر المستخدم في المستند النشط. إذا كان الموضع في علامة تبويب غير نشطة، سيتم أيضًا تبديل علامة التبويب النشطة للمستخدم إلى علامة التبويب المرتبطة بهذا الموضع.
  • Document.setSelection(range): يضبط نطاق اختيار المستخدم في المستند النشط. إذا كان النطاق في علامة تبويب غير نشطة، سيتم أيضًا تبديل علامة التبويب النشطة للمستخدم إلى علامة التبويب المرتبطة بهذا النطاق.

طرق اختيار علامات التبويب وحالات استخدامها

مع إدخال علامات التبويب، قد يكون من المفيد الحصول على علامة التبويب النشطة ل المستخدم الذي يشغّل النص البرمجي وضبطها. ويمكن إجراء ذلك باستخدام الطرق التالية:

  • Document.getActiveTab(): يعرض Tab النشط للمستخدم في المستند النشط.
  • Document.setActiveTab(tabId): يضبط Tab الذي اختاره المستخدم في المستند الحالي على علامة التبويب التي تحتوي على المعرّف المحدّد.

يتكون "الاختيار" الشامل للمستخدم من علامة التبويب النشطة بالإضافة إلى موضع المؤشر الحالي أو نطاق الاختيار. إنّ النمطَين للعمل مع اختيار نشط هما إما تعديل علامة التبويب النشطة للمستخدم على نحو صريح إلى علامة تبويب معيّنة أو استخدام علامة التبويب النشطة للمستخدم.

يمكن تغيير علامة التبويب النشطة للمستخدم بشكل صريح باستخدام 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() سينشئان موضعًا أو نطاقًا يستهدف علامة التبويب النشطة (أو علامة التبويب الأولى، إذا لم يكن النص البرمجي مرتبطًا).

اطّلِع على أقسام التعليمات البرمجية النموذجية في الأقسام اللاحقة، والتي تقدّم رمزًا نموذجيًا ل العمل مع الاختيارات.

أنماط الاستخدام الشائعة لعلامات التبويب

توضّح عيّنات الرموز البرمجية التالية طرقًا مختلفة للتفاعل مع علامات التبويب.

قراءة محتوى علامة التبويب من جميع علامات التبويب في المستند

يمكن نقل الرمز البرمجي الحالي الذي كان ينفّذ ذلك قبل إتاحة ميزة علامات التبويب لكي يتوافق مع علامات التبويب من خلال التنقّل في شجرة علامات التبويب واستدعاء طرق الحصول على 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()); } }