إصلاح الأخطاء في الرمز الذي تم تحويله

تعمل الإضافة "محوّل ماكرو" على أتمتة معظم عملية التحويل، ولكن قد تحتاج إلى إجراء تعديلات على بعض واجهات برمجة التطبيقات والعناصر الأخرى لوضع اللمسات الأخيرة على الرمز.

يمكنك استخدام هذا الدليل لفهم ملفات "برمجة تطبيقات Google" (ملفات GS) التي تمت إضافتها إلى المشروع وتفسير أنواع الأخطاء المختلفة والتعرّف على كيفية إصلاح الأخطاء.

التعرّف على ملفات "برمجة تطبيقات Google" المضافة إلى مشروعك

تتم إضافة ملفات GS إضافية إلى مشروع "برمجة تطبيقات Google" للمساعدة في ما يلي:

  • حدِّد ثوابت وقيم VBA غير المتوفّرة في "برمجة تطبيقات Google".
  • تنفيذ واجهات برمجة التطبيقات التي لم يتم تحويلها.
  • حلّ خيارات المنتج

تمت إضافة ملفات GS التالية إلى مشروع "برمجة تطبيقات Google":

  • Library.gs
  • Unimplemented_constructs.gs
  • Variant_resolutions.gs

Library.gs

بشكل عام، لا تحتاج إلى تعديل أي عنصر في ملف library.gs.

يحدّد ملف library.gs الدوال والثوابت التي تم استخدامها في رمز VBA غير المتوفّرة في "برمجة تطبيقات Google". يساعد ذلك رمز برمجة التطبيقات الجديد في أن يشبه رمز VBA بشكل أفضل. بالإضافة إلى ذلك، لن تحتاج إلى تكرار التعريفات في كل مرة يتم فيها استخدام دوال أو ثوابت من ملف library.gs.

Unimplemented_constructs.gs

يعالج ملف unimplemented_constructs.gs التركيبات أو ��اجهات برمجة التطبيقات التي تعذّر تحويلها باستخدام محوّل الماكرو. قد تحتاج إلى تعديل هذا الملف لجعل التعليمة البرمجية تعمل على النحو المنشود.

مثلاً: Window.Activate()

في ما يلي مثال على واجهة برمجة تطبيقات غير متوافقة تُسمى Window.Activate(). ينشئ محوّل الماكرو دالة جديدة لبرمجة تطبيقات Google باسم مشابه ويعرّفها في ملف unimplemented_constructs.gs. بما أنّ وظيفة VBA غير متوافقة، تطرح وظيفة "برمجة تطبيقات Google" الجديدة استثناءً.

تتم إضافة الوظيفة الجديدة إلى رمز "برمجة تطبيقات Google" المُحوَّل في كل مكان تم فيه استخدام واجهة برمجة التطبيقات الأصلية في رمز VBA.

إذا عثرت على حل بديل لإعادة إنشاء سلوك واجهة برمجة التطبيقات الأصلية، ما عليك سوى تعديل تعريف الدالة في ملف unimplemented_constructs.gs. بعد تحديد الدالة هناك، سيتم تطبيقها في كل مكان تظه�� فيه الدالة في مشروع "برمجة تطبيقات Google".

فيما يلي مثال على التعليمة البرمجية:

رمز VBA الأصلي

Window.activate()

رمز "برمجة تطبيقات Google" المحوَّلة، مضاف بشكل مضمّن

_api_window_activate();

تمت إضافة تعريف الدالة إلى ملف unimplemented_constructs.gs

/**
 * Could not convert window.activate API. Please add relevant code in the
 * following function to implement it.
 * This API has been used at the following locations in the VBA script.
 *     module1 : line 3
 *
 * We couldn't find an equivalent API in Apps Script for this VBA API. Please
 * reconsider if this function call is critical, otherwise consider implementing
 * it in a different way.
 */
function _api_window_activate(CallingObject) {
  ThrowException("API window.activate not supported yet.");
}

Variant_resolutions.gs

تتم إضافة ملف variant_resolutions.gs إلى مشروع "برمجة تطبيقات Google" إذا تعذَّر تحديد نوع الكائن. وقد يحدث ذلك لعدة أسباب، مثل توفّر أنواع إرجاع متعددة من واجهة برمجة التطبيقات أو الإعلان عن العنصر على أنّه خيار منتج نفسه.

يضيف محوّل الماكرو دالة جديدة إلى هذا الملف تُسمى __handle_resolve_<api>()، وهي تحلّ محلّ واجهة برمجة التطبيقات المعنيّة وتساعد في تحديد نوع الكائن.

في بعض الحالات، قد تحتاج إلى تعديل الدالة __handle_resolve_<api>() للإعلان يدويًا عن نوع الكائن. راجِع نوع الكائن غير المتوافق.

مثلاً: name()

تحدّد العديد من أنواع العناصر في VBA واجهة برمجة تطبيقات name(). عادةً ما يكو�� مكافئ "برمجة تطبيقات Google" هو getName()، ولكن ليس لكل نوع من أنواع الكائنات يمكن أن تحدث حالات بديلة متعددة:

  • يُطلق على واجهة برمجة التطبيقات المكافئة للعنصر اسمًا مختلفًا عن getName().
  • لا يحتوي العنصر على واجهة برمجة تطبيقات لبرمجة التطبيقات للحصول على اسمه.
  • ليس هناك كائن "برمجة تطبيقات Google" مكافئ.

عندما لا يتم تحديد نوع الكائن، ينشئ محوّل الماكرو دالة جديدة تُسمى __handle_resolve_name في ملف variant_resolutions.gs.

فيما يلي مثال على التعليمة البرمجية:

رمز VBA الأصلي

a = Selection.name

وفي هذه الحالة، يتم استدعاء واجهة برمجة التطبيقات name() في الاختيار الحالي. قد يكون التحديد كائن ورقة أو كائن شكل. إذا كان كائن ورقة، ستكون الترجمة هي getName()، أما إذا كانت كائن شكل، فلن يكون هناك مكافئ في برمجة التطبيقات.

رمز "برمجة تطبيقات Google" المحوَّلة، مضاف بشكل مضمّن

a = __handle_resolve_name({}, getActiveSelection(), {});

وتتم إضافة الدالة __handle_resolve_name() الواردة أدناه إلى ملف variant_resolution.gs لحل أنواع مختلفة من الكائنات. تتحقّق الدالة من نوع الكائن، ثم تستخدم getName() إذا كان متوافقًا، أو تعرض خطأ إذا لم يكن getName() متاحًا.

تمت إضافة تعريف الدالة إلى ملف variant_resolution.gs

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
  var found_api_variant = false;
  var return_value;
  if (String(CallingObject) == "Sheet") {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (CallingObject instanceof ChartInSheet) {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (!found_api_variant) {
    ThrowException("API .name not supported yet.");
  }
  return return_value;
}

العثور على الأخطاء

عند مواجهة خطأ في رمز "برمجة تطبيقات Google" المحوَّل، تحدِّد الرسالة نوع الخطأ وموقعه. يعتمد تنسيق رسالة الخطأ على وقت تشغيل "برمجة تطبيقات Google" الذي تستخدمه.

إذا كنت تستخدم بيئة التشغيل التلقائية V8، سيظهر لك خطأ يبدو كالتالي:

_api_windows_active (unimplemented_constructs:2:3)

وهذا يعني أن الخطأ يقع في ملف unimplemented_constructs.gs في السطر 2، الحرف 3.

إذا كنت في بيئة تشغيل Rhino المتوقّفة، سيظهر لك خطأ يبدو كما يلي:

unimplemented_constructs:2 (_api_windows_active)

وهذا يعني أنّ الخطأ يقع في ملف unimplemented_constructs.gs في السطر 2.

أنواع الأخطاء

يمكنك إصلاح معظم الأخطاء التي تواجهها في ملفَّي unimplemented_constructs.gs وvariant_resolution.gs الموضّحين أعلاه.

تشمل أنواع الأخطاء التي قد تواجهها ما يلي:

واجهة برمجة تطبيقات غير مُنفذة

واجهة برمجة التطبيقات غير المنفذة هي واجهة برمجة تطبيقات لا يمكن لمحول الماكرو تحويلها من VBA إلى برمجة تطبيقات، وليس هناك حل بديل معروف لواجهة برمجة التطبيقات.

تتم عادةً إضافة واجهات برمجة التطبيقات غير المنفذة إلى ملف unimplemented_constructs.gs كدوال فارغة، وقد تكون أحيانًا بتوقيعات فارغة. إذا تعذّر تحديد نوع الكائن، قد تتم إضافة واجهة برمجة تطبيقات لم يتم تنفيذها إلى ملف variant_resolution.gs بدلاً من ذلك.

في تقرير التوافق الذي أنشأته قبل الإحالة الناجحة، يتم تصنيف واجهة برمجة التطبيقات هذه على أنّها تحتاج إلى مزيد من التحقيق.

في حال عدم إصلاح هذا النوع من واجهة برمجة التطبيقات في رمز VBA قبل تحويل ملفك، إليك كيفية ظهوره في مشروع "برمجة تطبيقات Google":

/**
* Could not convert . Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*      : 
* We couldn't find an equivalent API in Apps Script for this VBA API. Please
* reconsider if this function call is critical, otherwise consider implementing
* it in a different way.
* @param param1 {}
* @param param2 {}
* ...
* @return {}
*/
function _api_(param1, param2, ....) {
  ThrowException("API  not supported yet.");
}

إصلاح أخطاء واجهة برمجة التطبيقات غير المنفذة

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

  1. افتح رمز "برمجة تطبيقات Google" المحوَّلة في مكان الخطأ. راجِع البحث عن الأخطاء.
  2. فوق الدالة، اقرأ التعليق الذي تمت إضافته. في بعض الحالات، يشير التعليق إلى طريقة تنفيذ واجهة برمجة التطبيقات في "برمجة تطبيقات Google"
  3. إذا لم تتمكن من العثور على طريقة لتنفيذ واجهة برمجة التطبيقات في "برمجة تطبيقات Google"، ننصحك بإزالتها من الرمز.
  4. إذا لم تتمكّن من العثور على حل بديل أو إزالة واجهة برمجة التطبيقات هذه من الرمز البرمجي وظهرت وحدة الماكرو هذا الخطأ، لن تتمكّن من تحويل وحدة الماكرو هذه.

أمثلة على أخطاء واجهة برمجة التطبيقات التي لم يتم تنفيذها

في ما يلي أمثلة على سيناريوهات غير منفّذة لواجهة برمجة التطبيقات وكيفية إصلاحها:

  • ما مِن لغة برمجة تطبيقات مكافئة: تعرض حلاً غير مباشر لـ Chart.Protect، وهي واجهة برمجة تطبيقات غير متوفّرة في "برمجة تطبيقات Google".
  • نوع عنصر غير معروف: يعرض كيفية التعامل مع نوع كائن متغيّر وكيفية تنفيذ نوع كائن غير متوافق يمكن إعادة إنشائه في "برمجة تطبيقات Google".
المثال 1: ما مِن برمجة تطبيقات مكافئة أو واجهة برمجة تطبيقات غير معروفة

في هذا المثال، لم يتم تحويل Chart.Protect تلقائيًا لأنّه لا تتوفّر طريقة لحماية رسم بياني في "جداول بيانات Google".

/**
* Could not convert chart.protect API. Please add relevant code in the following
* function to implement it.
*
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
* You can use the following Apps Script APIs to convert it.
*
* Comments : Auto conversion of Chart.Protect is not supported yet. If the API is
* critical for the workflow the user can implement the unimplemented handler
* method in the generated code, else comment out the throw statement.
*
* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} Password
* @param {boolean} DrawingObjects
* @param {boolean} Contents
* @param {boolean} Scenarios
* @param {boolean} UserInterfaceOnly
*
*/
function _api_chart_protect(
   CallingObject, Password, DrawingObjects, Contents, Scenarios,
   UserInterfaceOnly) {
 ThrowException('API chart.protect not supported yet.');
}
بالرغم من أنه لا يمكنك حماية مخطط، إلا أنه يمكنك حماية نطاق بيانات المخطط بحيث لا يمكن تغيير البيانات.

في ما يلي نموذج لتنفيذ حماية النطاق:
/**
* Could not convert chart.protect API. Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
*
* You can use the following Apps Script APIs to convert it.
* Comments : Auto conversion of Chart.Protect is not supported yet. If the API
* is critical for the workflow the user can implement the unimplemented handler
* method in the generated code, else comment out the throw statement.
*
* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} Password
* @param {boolean} DrawingObjects
* @param {boolean} Contents
* @param {boolean} Scenarios
* @param {boolean} UserInterfaceOnly
*/
function _api_chart_protect(
  CallingObject, Password, DrawingObjects, Contents, Scenarios, UserInterfaceOnly) {
var ranges = CallingObject.getChart().getRanges();
for (var i = 0; i < ranges.length; i++) {
  // Note that this does not lock the range for the document owner.
  ranges[i].protect();
}
}
المثال 2: نوع الكائن غير المتوافق

عندما يكون نوع الكائن غير معروف، تتم إضا��ة الخطأ الذي لم يتم تنفيذه في واجهة برمجة التطبيقات إلى الملف variant_resolution.gs. يتوسع المثال التالي في مثال واجهة برمجة تطبيقات name() VBA أعلاه. يمكنك الاطّلاع على variant_resolution.gs.

في هذا المثال، ستتعرف على:

  1. طريقة تحويل واجهة برمجة التطبيقات name() إلى دالة جديدة في ملف variant_resolution.gs
  2. كيفية استدعاء الدالة الجديدة في الرمز المحوَّل.
  3. كيفية إنشاء حل بديل لـ CommandBar، نوع كائن غير متوافق، في "برمجة تطبيقات Google".

1- وبما أنّ الرمز المحوَّل لا يمكنه تحديد نوع الكائن الذي يتم استدعاؤه name()، ينشئ محوّل الماكرو دالة جديدة تُسمى __handle_resolve_name، كما هو موضّح أدناه.

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
 var found_api_variant = false;
 var return_value;
  if (String(CallingObject) == "Sheet") {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (CallingObject instanceof ChartInSheet) {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (!found_api_variant) {
    ThrowException('API .name not supported yet.');
  }
  return return_value;
}

2- لنفترض أنّ رمز VBA يحدّد دالة PrintName() تستدعي واجهة برمجة تطبيقات name(). في ما يلي رمز VBA:

‘Defining a function that prints the name of the object in parameter
Sub PrintName(obj as Variant)
  Debug.Print obj.Name
End Sub
بما أنّ الدالة "name()" يتم استدعاءها في كائن متغيّر، فإنّ الرمز البرمجي المحوَّل لا يعرف نوع الكائن في وقت التحويل. سيستدعي رمز "برمجة تطبيقات Google" المحولة الدالة `__handle_resolve_name`:
function PrintName(obj) {
  Logger.log(_handle_resolve_name(obj));
}

3- لنفترض أنّ رمز VBA يستدعي الدالة PrintName() على نوع الكائن CommandBar. في ما يلي رمز VBA:

PrintName Application.CommandBars.item("Standard")
لا يتوافق CommandBar مع "برمجة تطبيقات Google"، ونتيجةً لذلك، لا تتوافق الطريقتان المستخدمتان في رمز VBA أعلاه أيضًا.
  • Application.CommandBars(): في VBA، يؤدي ذلك إلى عرض قائمة بجميع كائنات CommandBar.
  • CommandBars.item(): في VBA، يؤدي ذلك إلى عرض عنصر CommandBar محدّد.
بسبب عدم توافق هذا النوع من الكائنات في "برمجة تطبيقات Google"، يُنشئ الرمز المحوَّل الدوال التالية في ملف "unimplemented_builds.gs" الذي تحتاج إلى تعريفه.
  • _api_application_commandbars()
  • _api_commandbars_item()
يتم استدعاء الدوال في الرمز المحوَّل على النحو الموضّح أدناه:
PrintName(_api_commandbars_item(_api_application_commandbars(), "Standard")))

Here’s how the new functions are added to the unimplemented_construct.gs file:

function _api_application_commandbars(CallingObject) {
  ThrowException('API application.commandbars not supported yet.');
}
function _api_commandbars_item(CallingObject, index) {
  ThrowException('API commandbars.item not supported yet.');
}

لتشغيل الدوال الجديدة، اتبع الخطوات التالية:

3.1 حدِّد نوع عناصر جديدًا ينشئ وظائف CommandBars ومجموعة جديدة من CommandBars مماثلة لتلك المتوفّرة في VBA.

3.2 أضِف طريقة getName() لنوع الكائن الجديد.

يتم عرض الخطوتين 3.1 و3.2 في الرمز التالي. ويتم إنشاء كائنات القائمة كنوع كائن جديد يحاكي سلوك CommandBars.

// Our Implementation of CommandBar using Menu objects.

function CommandBar(name) {
  this.name = name;
  // Create a menu object to represent the commandbar.
  this.menu = SpreadsheetApp.getUi().createMenu(name);
  // Create methods for retrieving or updating the name of the object
  this.getName = function() {
    return this.name;
  };
  this.updateName = function(name) {
    this.name = name;
  };
  // ========================================================================
  // Implement other methods of CommandBar objects that are used in the script.
  // =====================================================================
  return this;
}
// Our implementation of the collection of CommandBars that exists in VBA
function CommandBars() {
  this.commandBars = [];
  this.getCommandBar = function(name) {
    for (var i = 0; i < this.commandBars.length; i++) {
      if (!this.commandBars[i].getName() == name) {
        return this.commandBars[i];
      }
    }
    // No commandBar with the name exists, create a new one and return.
    var commandBar = new CommandBar(name);
    this.commandBars.push(commandBar);
    return commandBar;
  };
  return this;
}
// Create a global object that represents CommandBars collection.
var GlobalCommandBars = new CommandBars();

3.3 عدِّل الدالة __handle_resolve_name في ملف variant_resolution.gs للتعامل مع نوع الكائن الجديد. أضف قسمًا إلى الدالة، كما هو موضح أدناه:

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
 var found_api_variant = false;
 var return_value;
 if (String(CallingObject) == "Sheet") {
   if (!ExecutionContext.isLhs) {
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 if (CallingObject instanceof ChartInSheet) {
   if (!ExecutionContext.isLhs) {
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 // New section added below
 // ========================================================================
 if (CallingObject instanceof CommandBar) {
   objectExtend(params_map, {VALUETOSET: params_map.param0});
   if (ExecutionContext.isLhs) {
     // Call the setter method.
     CallingObject.updateName(params_map.VALUETOSET);
     found_api_variant = true;
   } else {
     // Getter is called, return the commandbar name,
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 // ========================================================================
 // New section added above
 if (!found_api_variant) {
   ThrowException('API .name not supported yet.');
 }
 return return_value;
}

3.4 حدِّد الدالتين اللتين تم إنشاؤهما في ملف unimplemented_constructs.gs (_api_application_commandbars()، _api_commandbars_item()). تضمن هذه الخطوة أن تعمل الطلبات الأصلية للدالة.

//This is straightforward based on the implementation of a CommandBar and the
// CommandBars collection above:
function _api_application_commandbars(CallingObject) {
 return GlobalCommandBars;
}
function _api_commandbars_item(CallingObject, index) {
 return CallingObject.getCommandBar(index);
}

بُنى اللغة غير المستخدَمة

construct هي عنصر في لغة الرمز البرمجي يتحكّم في مسار التنفيذ أو عرض البيانات. على سبيل المثال، التكرارات الحلقية والتسميات والأحداث وانتقالات. في ما يلي قائمة بجميع تصاميم VBA.

ستنشِئ هذه الدالة أنّه لا يمكن لمحوّل الماكرو تحويله، وهي تعتبر بُنى لغة غير مُطبَّقة.

يتم إدراج تعليق TODO عندما يقرّر محوّل الماكرو وجود تركيبة لغة غير مُفعَّلة.

ولا يُسمح باستخدام بُنى VBA التالية:

إصلاح أخطاء إنشاء اللغة التي لم يتم تنفيذها

  1. حدِّث الرمز البرمجي بحيث لا يعتمد منطقك على بنية اللغة غير المتاحة.
  2. افتح رمز "برمجة تطبيقات Google" المحوَّلة في مكان الخطأ. يُرجى الاطّلاع على البحث عن الأخطاء.
  3. وبناءً على منطق الرمز، يجب تحديثه بطريقة لا تتطلب بنية لغة غير متوافقة.
  4. إذا لم تتمكن من العثور على طريقة لإعادة كتابة الرمز بدون إنشاء لغة غير متاحة، لا يمكنك تحويل وحدة الماكرو هذه.

أمثلة على أخطاء إنشاء اللغة التي لم يتم تنفيذها

إحدى التركيبات اللغوية الأكثر شيوعًا غير المُنفَّذة هي عبارة GoTo. يمكنك استبدال بعض عبارات VBA GoTo بالتكرارات. في ما يلي مثالان على استخدام التكرارات الحلقية بدلاً من عبارات GoTo.

المثال 1: استبدال GoTo بـ While Loop

رمز VBA الأصلي
Sub Test()
 a = 0
 start: Debug.Print a
 While a < 100
   a = a + 1
   If a Mod 3 == 0
     Goto start
   End If
 Wend
End Sub
رمز "برمجة تطبيقات Google" المكافئة
function test() {
 var a = 0;
 start: do {
   console.log(a);
   while (a < 100) {
     a = a + 1;
     if (a % 3 == 0) {
       continue start;
     }
   }
   break start;
 } while (true);
}

المثال 2: استبدال "الانتقال إلى" بـ "لحلقة"

رمز VBA الأصلي
Sub Test()
 a = 0
 For i = 1 to 100
   For j = 1 to 10
     a =a a + 1
     If i + j > 50
       GoTo endLoop
     End If
   Next j
 Next i
 endLoop: MsgBox a
End Sub
رمز "برمجة تطبيقات Google" المكافئة
function test() {
 var a = 0;
 endLoop: for (var i = 1; i <= 100; i++) {
    for  (var j = 0; j <=10; j++) {
      If (i + j > 50) {
        break endLoop;
      }
    }
 }
 Browser.msgBox(a);
}

   break start;
 } while (true);
}

واجهة برمجة التطبيقات المتوافقة جزئيًا

بالنسبة إلى واجهات برمجة التطبيقات المتوافقة جزئيًا، تكون بعض معلمات الإدخال متاحة في "برمجة تطبيقات Google" وبعضها غير متاح.

على سبيل المثال، يتم استخدام VBA API legend_position لتعريف وسيلة الإيضاح في الرسم البياني لـ Excel. ويتيح هذا التنسيق أنواعًا متعدّدة من قيم الإدخال، بما في ذلك:

  • xlLegendPositionBottom: يضع وسيلة الإيضاح في أسفل الرسم البياني.
  • xlLegendPositionCorner: وضع وسيلة الإيضاح في زاوية الرسم البياني
  • xlLegendPositionCustom: وضع وسيلة الإيضاح في مواضع مخصّصة على الرسم البياني

تحتوي "برمجة التطبيقات" على رمز مكافئ يتيح بعض هذه القيم فقط. القيم التالية غير متاحة:

  • xlLegendPositionCorner
  • xlLegendPositionCustom

لوضع علامة على القيم غير المتوا��قة لواجهات برمجة التطبيقات المتوافقة جزئيًا في الرمز المحوَّل، تتم إضافة شرط تحقُّق إلى ملف library.gs الذي يتحقّق من هذه القيم. مثلاً:

if (position == xlLegendPositionCorner ||
     position == xlLegendPositionCustom) {
   position = _handle_legend_position_error(position);
}

إذا عثر شرط التحقق من الصحة على إحدى القيم غير المسموح بها، سيتم إنشاء دالة معالِج الأخطاء، _handle_<API_name>_error، في ملف unimplemented_constructs.gs.

تعرض الدالة خطأ المستخدم ولن تستبدل القيمة بقيمة مسموح بها. مثلاً:

/**
* Throw error message for unsupported legend position.
* The VBA API Legend.Position which can take values xlLegendPositionTop,
* xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight,
* xlLegendPositionCorner, xlLegendPositionCustom. It is partially supported in
* Apps Scripts that supports only a subset of the values (does not support
* xlLegendPositionCorner and xlLegendPositionCustom).
* @param {string} position
*/
function _handle_legend_position_error(position) {
// Please comment the throw statement and return a supported position value
// instead.
// Values that are supported here are xlLegendPositionTop,
// xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight.
throw new Error(
   'Google Sheets does not support legend position: ' + position);
}

إصلاح أخطاء واجهة برمجة التطبيقات المتوافقة جزئيًا

حدِّد الدالة _handle_<API_name>_error لاستبدال القيم غير المسموح بها بحل بديل مقبول وفقًا لاحتياجاتك.

  1. افتح رمز "برمجة تطبيقات Google" المحوَّلة في مكان الخطأ. راجِع البحث عن الأخطاء.
  2. اقرأ التعليق فوق الدالة لفهم القيم المدعومة والقيم غير المدعومة.
  3. بالنسبة إلى القيم غير المسموح بها، حدِّد القيم المسموح بها التي يمكن أن تكون بديلاً مناسبًا.
  4. عدِّل الدالة _handle_<API_name>_error لعرض قيمة مسموح بها بدلاً من ذلك.
  5. إذا لم تتمكن من العثور على طريقة لاستبدال القيمة غير المسموح بها، لا يمكنك تحويل هذا الماكرو.

مثال على خطأ في واجهة برمجة التطبيقات متاح جزئيًا

يتطرق المثال التالي إلى legend_position واجهة برمجة تطبيقات VBA API المذكورة أعلاه. راجِع واجهة برمجة التطبيقات المتوافقة جزئيًا.

في ما يلي مثال على رمز VBA الأصلي الذي يستخدم قيمة غير مسموح بها، xlLegendPositionCustom.

Charts(1).Legend.Position = xlLegendPositionCustom

يضيف محوّل الماكرو الدالة التالية إلى ملف unimplemented_constructs.gs:

/**
* Throw error message for unsupported legend position.
* The VBA API Legend.Position which can take values xlLegendPositionTop,
* xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight,
* xlLegendPositionCorner, xlLegendPositionCustom. It is partially supported in
* Apps Scripts that supports only a subset of the values (does not support
* xlLegendPositionCorner and xlLegendPositionCustom).
* @param {string} position
*/
function _handle_legend_position_error(position) {
// Please comment the throw statement and return a supported position value
// instead.
// Values that are supported here are xlLegendPositionTop,
// xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight.
throw new Error(
   'Google Sheets does not support legend position: ' + position);
}

يجب تنفيذ عمل يدوي

يعني الإجراء اليدوي أنّه يمكن تحويل واجهة VBA API إلى "برمجة تطبيقات Google"، ولكنّها تحتاج إلى حل بديل.

في تقرير التوافق الذي أنشأته قبل التحويل، يتم تصنيف هذا النوع من واجهات برمجة التطبيقات على أنّه متوافق م�� الحلول البديلة.

في حال عدم إصلاح هذا النوع من واجهة برمجة التطبيقات في رمز VBA قبل تحويل ملفك، إليك كيفية ظهوره في مشروع "برمجة تطبيقات Google":

/**
* Could not convert  API. Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*      : 
*
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : 
* Apps Script documentation links : 
*
* @param param1 {}
* @param param2 {}
* ...
* @return {}
*/
function _api_(param1, param2, ....) {
 ThrowException("API  not supported yet.");
}

إصلاح الأخطاء المطلوبة في العمل اليدوي

يمكنك تنفيذ حل بديل لواجهة برمجة التطبيقات لكي تعمل واجهة برمجة التطبيقات على النحو المطلوب. 1- افتح رمز "برمجة تطبيقات Google" المحوَّلة في مكان الخطأ. راجِع القسم البحث عن الأخطاء. 1- اقرأ التعليق أعلاه للدالة لمعرفة واجهات برمجة التطبيقات التي يمكن استخدامها كحل بديل. 1- إذا لم تتمكن من العثور على حل مناسب، ننصحك بإزالة واجهة برمجة التطبيقات من الرمز. 1- إذا لم تتمكّن من العثور على حل بديل أو إزالة واجهة برمجة التطبيقات هذه من الرمز البرمجي وظهرت وحدة الماكرو خطأ، لا يمكنك تحويل وحدة الماكرو هذه.

أمثلة على الأخطاء المطلوبة في حالة "العمل اليدوي"

في ما يلي أمثلة على واجهات برمجة التطبيقات التي تعرض أخطاءً مرتبطة بالعمل اليدوي وكيفية إصلاحها:

المثال 1: Autocorrect.Addreplacement

في المثال التالي، يمكن تحويل Autocorrect.Addreplacement في VBA API، ولكن يجب اتّخاذ حل بديل. يقترح محول الماكرو كيفية تنفيذ الدالة في تعليقات التعليمة البرمجية.

/**
* Could not convert autocorrect.addreplacement API. Please add relevant code in
* the following function to implement it.
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : FindReplaceRequest , onEdit
* Apps Script documentation links :
* https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest

* Comments : AutoCorrect.AddReplacement was not converted, but there is an
* equivalent option you can implement manually. Use onEdit and FindReplaceRequest
* APIs instead, see https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* and https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest.
* For more information on API manual implementation, see
* https://developers.google.com/apps-script/guides/macro-converter/fix-conversion-errors.

* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} What
* @param {string} Replacement
* @return {string}
*/

function _api_autocorrect_addreplacement(CallingObject, What, Replacement) {
  ThrowException('API autocorrect.addreplacement not supported yet.');

}

في ما يلي طريقة تنفيذ واجهة برمجة التطبيقات Autocorrect.Addreplacement:

var AUTO_CORRECTIONS = "AUTO_CORRECTIONS";
// Need to get the autocorrections set in previous sessions and use them.
var savedAutoCorrections = PropertiesService.getDocumentProperties().getProperty(AUTO_CORRECTIONS);
var autoCorrections = savedAutoCorrections ? JSON.parse(savedAutoCorrections) : {};
function onEdit(e) {
autoCorrect(e.range);
}
function autoCorrect(range) {
for (key in autoCorrections) {
// Replace each word that needs to be auto-corrected with their replacements.
range.createTextFinder(key)
.matchCase(true)
.matchEntireCell(false)
.matchFormulaText(false)
.useRegularExpression(false)
.replaceAllWith(autoCorrections[key]);
}
}
/**
* Could not convert autocorrect.addreplacement API. Please add relevant code in
* the following function to implement it.
* This API has been used at the following locations in the VBA script.
* sheet1 : line 3
*
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : createTextFinder , onEdit
* Apps Script documentation links : https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit ,
createTextFinder
* Comments : AutoCorrect.AddReplacement was not converted, but there is an
* equivalent option you can implement manually. Use onEdit and FindReplaceRequest
* APIs instead, see https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* and createTextFinder. For more information on API manual implementation, see
* https://developers.google.com/apps-script/guides/macro-converter/fix-conversion-errors.
*
* @param {Object} CallingObject represents the parent object using which the API has been called.
* @param {string} What
* @param {string} Replacement
*
* @return {string}
*/

function _api_autocorrect_addreplacement(CallingObject, What, Replacement) {
autoCorrections[What] = Replacement;
// Store the updated autoCorrections in the properties so that future executions use the correction.
PropertiesService.getDocumentProperties().setProperty(AUTO_CORRECTIONS, JSON.stringify(autoCorrections));
}

المثال 2: Workbook.open()

تفتح واجهة برمجة تطبيقات VBA API workbook.open() ملفًا محليًا استنادًا إلى مسار الملف.

لنفترض أنّ هناك ملفَين يفتحهما workbook.open() في رمز VBA:

  • الملف رقم 1: C:\Data\abc.xlsx
  • الملف رقم 2: C:\Data\xyz.xlsx

يوضح ما يلي كيف يستبدل محول الماكرو Workbook.open() بالنص البرمجي للتطبيقات في كل مكان يتم فيه استخدام Workbook.open() لفتح الملف 1:

var spreadSheetId =
   _handle_mso_excel_get_google_spreadsheet_id("C:\Data\abc.xlsx");
var spreadSheet = SpreadsheetApp.openById(spreadSheetId);
تمت إضافة الخطأ التالي إلى ملف unimplemented_constructs.gs في مشروع "برمجة تطبيقات Google":
/**
* Method to return the spreadsheet id manually.
*
* @param {string} FileName ID of the spreadsheet to be opened.
* @return {string} return the spreadsheet id.
*/
function _handle_mso_excel_get_google_spreadsheet_id(FileName) {
 // Upload the Excel files being opened by the API to Google Drive and convert
 // them to Google Sheets.
 // Determine the spreadsheet ID of the Google Sheets file created.
 // Implement this method to return the corresponding spreadsheet ID when given
 //the original file path as parameter.
 throw new Error('Please return the spreadsheet ID corresponding to filename: ' + FileName);
 return '';
}

وفقًا لتعليمات التعليقات الواردة في النموذج أعلاه، تحتاج إلى تحويل الملفات المستهدفة إلى ملفات "جداول بيانات Google" على Google Drive.

تكون معرفات جداول بيانات Google المقابلة بخط غامق أدناه:

  • الملف رقم 1: يصبح C:\Data\abc.xlsx https://docs.google.com/spreadsheets/d/abc123Abc123Abc123abc
  • الملف رقم 2: يصبح C:\Data\abc.xlsx https://docs.google.com/spreadsheets/d/xyz456Xyz456xYz456xyZ

بعد ذلك، عدّل الرمز في دالة "برمجة تطبيقات Google" لفتح الملفات حسب رقم التعريف، كما هو موضّح أدناه:

/**
* Method to return the spreadsheet id manually.
*
* @param {string} FileName ID of the spreadsheet to be opened.
* @return {string} return the spreadsheet id.
*/
function _handle_mso_excel_get_google_spreadsheet_id(FileName) {
 // Upload the Excel files being opened by the API to Google Drive and convert
 //them to Google Sheets.
 // Determine the spreadsheet ID of the Google Sheets file created.
 // Implement this method to return the corresponding spreadsheet ID when given
 //the original file path as parameter
 if (Filename.indexOf("abc.xlsx") >= 0) {
   return "abc123Abc123Abc123abc";
 } else if (Filename.indexOf("xyz.xlsx") >= 0) {
   return "xyz456Xyz456xYz456xyZ";
 }

خطأ متعمّد

تتم إضافة الأخطاء المتعمدة إلى الرمز المحوَّل لمحاكاة سلوك خطأ رمز VBA الأصلي. لا تحتاج إلى تعديل هذه الأخطاء.

مثال على خطأ متعمّد

إذا حاولت الوصول إلى عنصر خارج حدود صفيف في VBA، تعرض التعليمة البرمجية استثناء. في "برمجة تطبيقات Google"، يعرض الرمز قيمة غير محدّدة.

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

يظهر هذا المثال في الرمز البرمجي أدناه:

رمز VBA الأصلي
Dim arr
arr = Array("apple", "orange")
MsgBox arr(5)
Will throw the following error:
Subscript out of range
رمز "برمجة تطبيقات Google" المحوَّلة (قبل إضافة خطأ الاستثناء)
var arr;
arr = ["apple", "orange"];
Browser.msgBox(arr[5]);
Will return this value and not throw an error:
undefined
تمت إضافة رمز برمجة التطبيقات لعرض خطأ الاستثناء
/**
* Extend the regular JS array to support VB style indexing with a get method.
* @returns{*} value at the index
*/
Array.prototype.get = function() {
 var curr_res = this;
 for (var i = 0; i < arguments.length; i++) {
   if (!Array.isArray(curr_res) || curr_res.length < arguments[i]) {
     throw new Error(‘Converted VBA Error (Intentional Error): Subscript out of range’);
   }
   curr_res = curr_res[arguments[i]];
 }
 return curr_res;
};
var arr;
arr  = ["apple", "orange"];
Browser.msgBox(arr.get(5));