اذهب إلى المحتوى

تصحيح الأخطاء في VBA: الخطأ في الشيفرة


Siba Abo Aloioon

أثناء كتابة شيفرة برمجية باستخدام VBA أو بأية لغة أخرى لابد أن نواجه بعض الأخطاء في كتابة البرنامج، فنادرًا ما نتم كتابة برنامج دون أن نحتاج إلى تصحيح الأخطاء أو التأكد من سلامة سير البرنامج. وتزداد صعوبة اكتشاف مكان الخطأ كلما كانت الشيفرة أطول وأكثر تعقيدًا. يؤمن VBA Excel بعض الأدوات التي تساعد على اكتشاف أماكن الأخطاء وتتبع النتائج. كما تساعد هذه الأدوات على فهم الشيفرات البرمجية التي كتبناها فهمًا أفضل، بالإضافة إلى أهميتها في المساعدة في فهم الشيفرات المكتوبة من قبل مبرمجين آخرين. يمكن استعراض أهم هذه الأدوات من القائمة المنسدلة من شريط القوائم Debug، نلاحظ أن معظم هذه الأدوات لها اختصارات في لوحة المفاتيح مما يساعد على المتابعة والتدقيق بسرعة أكبر.

خيار Debug في VBA Exel

تنفيذ خطوة واحدة من الشيفرة Step Into في VBA Exel

يمكن إعطاء أمرٍ بتنفيذ خطوة واحد من الشيفرة البرمجية في VBA بالنقر على علامة التبويب Debug من شريط القوائم Step Into، ولتنفيذ خطوة جديدة واحدة نكرر العملية لمراقبة التغيرات وإجراء أي تعديلات، يمكن الضغط على زر F8 في كل مرة اختصارًا لأمر Step Into فيُنفذ السطر المميز بالأصفر فقط، ونراقب التغييرات الحاصلة بنتيجة تنفيذ هذا السطر لإجراء التعديلات اللازمة.

عند تنفيذ السطر البرمجي بالأمر Step Into يُميَّز السطر الذي سينفَّذ في الخطوة التالية باللون الأصفر مع سهم أصفر يشير إلى السطر.

يمكن معرفة قيمة أي متغير بتقريب مؤشر الفأرة عليه في زمن التصميم في فترة الإيقاف المؤقت، فتظهر قيمته اللحظية في تلك الخطوة أسفل المؤشر.

ملاحظة: قد تكون الخطوة سطرًا برمجيًا واحدًا إلى الأمام أو قد تكون خطوة تعود إلى بداية الحلقة عند التعليمة Next مثلًا أو إلى سطر معين عند التعليمة GoTo. كما أن التصريح عن المتغيرات لا يعتبر من الخطوات البرمجية فلا يقف عندها البرنامج.

مثال: في الإجراء التالي ينتقل التحديد بين خلايا الجدول B3:D5، وتتلون الخلية بحسب رقم الصف. يحدث الانتقال بين الخلايا عبر حلقتين تكراريتين: الحلقة الأولى ذات المتغير i ينتقل فيها عبر الصفوف، والحلقة الثانية بمتغير j ينتقل بواسطتها عبر الأعمدة. سنستخدم التعليمة Step Into لمراقبة انتقال الأوامر التنفيذية خطوةً خطوة:

Sub CellsLoop()
 For i = 3 To 5
    For j = 2 To 4
        Cells(i, j).Select
        Cells(i, j).Interior.ColorIndex = i
    Next j
 Next i
End Sub

إعطاء الأمر Step Into في VBA Exel

بدأنا بإعطاء الأمر Step Into من القائمة المنسدلة لتنفيذ خطوة واحدة عدة مرات، ثم تابعنا تنفيذ الخطوات التالية واحدة تلو الأخرى بإعطاء نفس الأمر بالضغط على المفتاح F8، إلى أن تنتهي الشيفرة. لاحظ دوران خطوات التنفيذ ضمن الحلقة حتى نهايتها لينتقل التنفيذ بعدها إلى التعليمة التالية.

ملاحظة: إذا كانت الشيفرة البرمجية تحوي استدعاءً لإجراءٍ آخر، فإن إعطاء الأمر Step Into عند سطر الاستدعاء يسبب الدخول في الإجراء المستدعى لتنفيذ خطوة واحدة فيه، وبتكرار الأمر يستمر تنفيذ الإجراء المستدعى خطوة واحدة عند كل أمر Step Into إلى أن ينتهي تنفيذ الإجراء المستدعى فيخرج منه ليعود ويتابع تنفيذ الإجراء الأصلي.

مثال: ينتقل الإجراء التالي الذي اسمه CellsLoop بين الصفوف من 3 إلى 5 ضمن الحلقة الأولى i، كلما وصل إلى صف رقمه i يدخل حلقة جديدة j يتنقل فيها في خلايا ذلك الصف بين العمود B والعمود D بتغيير رقم العمود j ليلون خلاياها واحدة تلو الأخرى، ينتهي تلوين خلايا الصف بانتهاء الحلقة j والخروج منها وهو لايزال في نفس الحلقة i وقيمة i لم تتغير بعد، ثم يستدعي إجراءً فرعيًا اسمه Sub Values ولا تزال قيمة i نفسها أي أن الصف لم يتغير، فيدخل حلقة جديدة j يتنقل فيها بين خلايا الصف i نفسه بتغيير رقم العمود j ليملأ خلاياه خلية تلو الأخرى بثنائيات القيم إلى أن ينتهي من ملء خلايا الصف بانتهاء الحلقة j وخروجه منها وهو لايزال في نفس الحلقة i حيث أن قيمة i لم تتغير بعد فيملأ خلاياه بثنائيات من القيم تمثل رقم الصف ورقم العمود.

إن عدم تعريفنا للمتغير j يعني أنه متغير على مستوى الإجراء فقط، وعند الانتقال من إجراء لآخر أثناء الاستدعاء يُفَرَّغ المتغير j من قيمته ليبدأ كمتغير جديد.

نعرف بدايةً متغيرًا عامًّا i، ويكون التعريف خارج الإجراءات لتكون المتغيرات عامة على مستوى الوحدة البرمجية Module فيكون i صالحًا للاستخدام في كافة الإجراءات في تلك الوحدة البرمجية عند استدعاء أكثر من إجراء في تلك الوحدة يتضمن ذلك المتغير. ثم نكتب الإجراء الأول CellsLoop وبداخله استدعاء للإجراء الثاني Sub Values الذي يكتب بعده.

Public i As Integer

Sub CellsLoop()
  For i = 3 To 5
     For j = 2 To 4
        Worksheets("Sheet1").Cells(i, j).Interior.ColorIndex = i + 2
     Next j
     Call SubValues
  Next i
End Sub

Sub SubValues()
  For j = 2 To 4
      Worksheets("Sheet1").Cells(i, j) = i & "," & j
  Next j
End Sub

تنفيذ خطوة واحدة من الشيفرة Step Into

تنفيذ خطوة واحدة من الإجراء الأصلي أو كامل الإجراء الفرعي Step Over في VBA Exel

إذا كانت الشيفرة في VBA تستدعي إجراءً آخر ، فقد لا نرغب في التنقل عبر كل سطر من التعليمات البرمجية في الإجراء الفرعي الذي نستدعيه. فيمكن استدعاء الإجراء الفرعي ككتلة واحدة باستخدام Step Over والاستمرار فورا في الخطوة التالية في تنفيذ الشيفرة في الإجراء الأصلي.

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

لتنفيذ خطوة برمجية واحدة ضمن الإجراء الأساسي ننقر على علامة التبويب Debug من شريط القوائم Step Over، ولتنفيذ خطوة جديدة واحدة نكرر العملية لمراقبة التغيرات وإجراء أي تعديلات، يمكن الضغط على زري SHIFT + F8 معًا اختصارًا لـ Step Over في كل مرة نريد فيها تنفيذ خطوة برمجية واحدة داخل الإجراء لمراقبة التغييرات الحاصلة.

ملاحظة: يجدر الإشارة أن Step Over لا تكون مفعلة إلا في وضع الإيقاف المؤقت لذلك لتنفيذ خطوة احدة أول مرة نبدأ بالأمر Step Into أول مرة ثم نستطيع أن نكمل بالأمر Step Over. وكما في الأمر Step Into، يُميَّز سطر الخطوة التالية باللون الأصفر مع سهم أصفر يشير إلى السطر عند تنفيذ السطر البرمجي بالأمر Step Over.

مثال: بتطبيق الأمر Step Over على الشيفرة في المثال السابق:

تطبيق الأمر Step Over على الشيفرة في VBA Exel

لاحظ كيف تنفذ Step Over السطر Call Sub Values كوحدة واحدة لتكتب الثنائيات في السطر i دون أن تدخل في تفاصيل الإجراء الفرعي.

الخروج من الشيفرة Step Out في VBA Exel

ينفذ الأمر Step Out في اكسل VBA الأسطر البرمجية المتبقية من الإجراء ويخرج منه، فإذا كان الإجراء أساسيًا أكمل تنفيذ الشيفرة كاملة بما تحويه من استدعاءات للإجراءات الفرعية، أما إن كان الإجراء فرعيًا فيُتم تنفيذ كل التعليمات البرمجية بين نقطة التنفيذ الحالية ونهاية الإجراء الفرعي لينهيه، وينتقل إلى الإجراء الأصلي Sub 1 عند العبارة البرمجية التي تلي استدعاء الإجراء الفرعي Call Sub 2 ليلونها بالأصفر.

لإكمال تنفيذ كامل الإجراء الحالي ننقر على علامة التبويب Debug من شريط القوائم Step Over، أو اختصارًا نضغط على الأزرار CTRL + SHIFT + F8.

كما في Step Over نلاحظ أن الخيار Step Out متوفر في وضع الإيقاف المؤقت break mode فقط.

مثال: لتنفيذ الشيفرة السابقة حتى النقطة التي تسبق سطر الاستدعاء نضع المؤشر عند السطر الذي يحوي الاستدعاء ونعطي الأمر Run to Cursor بالنقر عليه من قائمة Debug من شريط القوائم. وبإعطاء الأمر Step Out من نفس القائمة نلاحظ أن البرنامج يتابع تنفيذ الشيفرة إلى نهايتها بما فيها استدعاء الإجراء الفرعي Sub Values.

نمسح النتائج في إكسل ونعيد تنفيذ الشيفرة حتى النقطة التي تسبق سطر الاستدعاء بوضع المؤشر عند سطر الاستدعاء وإعطاء الأمر Run to Cursor بالضغط على مفاتيح الاختصار CTRL + F8، ثم نضغط F8 مرة أو مرتين لتنفيذ خطوة برمجية واحدة في كل مرة بحيث نصبح داخل الإجراء الفرعي Sub Values، ثم نعطي الأمر Step Out بالضغط على مفاتيح الاختصار CTRL + SHIFT + F8، نلاحظ البرنامج ينفذ الإجراء الفرعي Sub Values كاملًا ويخرج منه ثم يعود إلى السطر الذي يلي سطر الاستدعاء في الإجراء الأصلي CellsLoop، وبضغط مفاتيح الاختصار CTRL + SHIFT + F8 مرة ثانية ينهي الأمر Step Out تنفيذ الإجراء الأصلي أيضًا ويخرج منه.

الخروج من الشيفرة Step Out

ملاحظة: يجب الانتباه عند تنفيذ الإجراءات المرتبطة في VBA، حيث أن تشغيل الإجراء الفرعي فقط دون استدعائه من الإجراء الأساسي يؤدي إلى خطأ في حال كان الإجراء الفرعي يحوي متغيرًا تنتج قيمته في الإجراء الأساسي. فإذا تم تشغيل الإجراء الأساسي بالكامل وخرج منه، تحتفظ المتغيرات على مستوى الوحدة البرمجية Module بآخر قيمة مخزنة فيها لتُستخدم تلك القيمة في الإجراءات الفرعية التي تشغل بعدها. أما إذا لم يشغَّل الإجراء الأساسي أولًا، أو إذا أعدنا تهيئة المتغيرات بالنقر على زر Reset، تبقى قيم جميع المتغيرات فارغة حتى تعطى قيمة داخل الإجراء.

مثال: بتنفيذ الإجراء CellsLoop كاملًا في الشيفرة السابقة مع إجرائه الفرعي يخزِّن آخر قيمة فرضها للمتغير i ضمن الحلقة (تتراوح قيم المتغير i في الحلقة بين 3 و 5، فتتوقف الحلقة عن الدوران عندما i=6 لأنها تجاوزت المجال المعطى، وتبقى قيمة i=6 مخزنة حتى بعد إنهاء الإجراء والخروج منه لأنه متغير على مستوى الوحدة النمطية Module)، فإذا نفذنا الإجراء الفرعي وحده Sub Values بعد اكتمال تنفيذ الإجراء الأساسي، ينفذ الإجراء الفرعي باعتماد قيمة i المخزنة التي تساوي 6.

تنفيذ الإجراء CellsLoop كاملا في الشيفرة

ننقر على زر Reset لتفريغ المتغيرات من قيمها المخزنة لنبدأ من جديد وكأننا لم نشغل أي إجراء من قبل، ثم نشغل الإجراء الفرعي فتظهر رسالة خطأ فيها خيار Debug ننقر عليه فيتوقف البرنامج مؤقتًا في مكان الخطأ ويميَّز بالأصفر. نمرر مؤشر الفأرة فوق المتغيرات ببطء فتظهر قيمها أسفل المؤشر، فنلاحظ أن قيمة المتغير i تساوي الصفر الأمر الذي سبب الخطأ.

اكتشاف سبب الخطأ في الشيفرة في VBA

خاتمة

يُسهِّل الخطو في الشيفرة في VBA باستخدام الأدوات السابقة متابعة وتدقيق الشيفرة المكتوبة. وكلما كان المبرمج أكثر احترافًا ومرونة باستخدام هذه الأدوات ومعرفة تفاصيلها ومعرفة تفاصيلها الدقيقة، سهل عليه الإحاطة بنقاط الضعف أو الخلل في البرنامج لتصحيح الأخطاء وتصويب المسار.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...