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

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

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

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

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

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

تمت إضافة ملفات 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" الذي تم تحويله في كل مكان تم فيه استخدام واجهة برمجة التطبيقات الأصلية في رمز VBA.

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

إليك المثال في الرمز:

رمز VBA الأصلي

Window.activate()

إضافة رمز النص البرمجي للتطبيقات المحوَّلة في سطر الأوامر

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

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

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

مثال: name()

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

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

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

إليك المثال في الرمز:

رمز VBA الأصلي

a = Selection.name

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

إضافة رمز النص البرمجي للتطبيقات المحوَّلة في سطر الأوامر

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

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

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

إذا كنت تستخدم وقت تشغيل 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. فوق الدالة، اقرأ التعليق الذي تمت إضافته. في بعض الحالات، يشير التعليق إلى كيفية تنفيذ واجهة برمجة التطبيقات في "برمجة التطبيقات".
  3. إذا لم تتمكن من إيجاد طريقة لتنفيذ واجهة برمجة التطبيقات في "برمجة التطبيقات"، يمكنك إزالتها من الرمز.
  4. إذا لم تتمكّن من العثور على حل بديل أو إزالة واجهة برمجة التطبيقات هذه من رمزك وعرضت وحدة الماكرو هذا الخطأ، لا يمكنك تحويل وحدة الماكرو هذه.

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

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

المثال 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() API إلى دالة جديدة في ملف variant_resolution.gs
  2. كيفية استدعاء الدالة الجديدة في الرمز المحوَّل.
  3. كيفية إنشاء حل بديل لـ CommandBar، نوع عنصر غير متوافق، في "برمجة التطبيقات".

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()` لكائن متغيّر، لا تتعرّف التعليمة البرمجية المحوَّلة على نوع الكائن في وقت الإحالة الناجحة. سيستدعي رمز برمجة التطبيقات المحوَّلة الدالة `__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 محدّد.
بما أنّ نوع العنصر هذا غير متوافق مع "برمجة التطبيقات"، يُنشئ الرمز المحوَّل الدوال التالية في ملف "unimplemented_structs.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 هي من تركيبات اللغة غير المطبَّقة الأكثر شيوعًا. يمكنك استبدال بعض عبارات GoTo VBA باستخدام التكرارات الحلقية. فيما يلي مثالان على استخدام التكرارات الحلقية بدلاً من عبارات 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
رمز "برمجة التطبيقات المكافئة"
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: استبدال GoTo بـ for التكرار

رمز 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
رمز "برمجة التطبيقات المكافئة"
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);
}

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

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

على سبيل المثال، يتم استخدام legend_position في VBA API لتعريف وسيلة الإيضاح في الرسم البياني في 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. إذا لم تتمكّن من العثور على طريقة لاستبدال القيمة غير المتوافقة، لا يمكنك تحويل وحدة الماكرو هذه.

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

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

في ما يلي مثال على رمز 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 إلى "برمجة تطبيقات 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 API أدناه:

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 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

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

/**
* 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
رمز برمجة التطبيقات التي تم تحويلها (قبل إضافة خطأ الاستثناء)
var arr;
arr = ["apple", "orange"];
Browser.msgBox(arr[5]);
Will return this value and not throw an error:
undefined
تمت إضافة رمز "برمجة تطبيقات Google" لعرض خطأ الاستثناء
/**
* 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));