تحظى بيئة التطوير فيجوال بيسك للتطبيقات (Visual Basic for Applications – VBA) بمكانة مركزية في أتمتة العمليات الحسابية والمعالجة المتقدمة للبيانات داخل منصة مايكروسوفت إكسيل (Microsoft Excel). ومع تعاظم حجم البيانات المؤسسية وتعقيد النماذج المالية والتحليلية، باتت مسألة إدارة الأخطاء البرمجية والحسابية من الركائز الأساسية التي تفرق بين النظم البرمجية الهشة وتلك المصممة بمعايير هندسية متينة تضمن استمرارية التشغيل ودقة النتائج. ومن بين الأخطاء الحسابية الأكثر شيوعاً في بيئات معالجة الجداول، يبرز الخطأ الشهير #N/A، الذي يشير دلالياً إلى عدم توفر القيمة المطلوبة نتيجة إخفاق آليات الاستعلام أو خوارزميات الفهرسة.
في سياق البرمجة المتقدمة باستخدام VBA، لا يعد ظهور الأخطاء مجرد خلل عابر في واجهة المستخدم، بل يمثل انقطاعاً محتملاً في مسار التنفيذ المنطقي للبرنامج (Execution Flow). وعندما تواجه الإجراءات البرمجية خلايا تحتوي على قيم غير متوفرة، أو عندما تُرجع دوال البحث نتائج سلبية، قد يؤدي ذلك إلى إطلاق استثناءات وقت التشغيل (Runtime Errors) تؤدي إلى انهيار التطبيق إذا لم تُحط بآليات وقائية محكمة. ومن هنا تنبع الأهمية المحورية لاستخدام دالة IfNa، التي تمثل أداة هندسية دقيقة صُممت خصيصاً لاحتواء هذا النوع المحدد من الانحرافات البيانية وتوفير مسارات بديلة رصينة تمنع تعطل العمليات الآلية.
يهدف هذا المرجع المتعمق إلى استعراض الأبعاد النظرية والتطبيقية لتوظيف دالة IfNa في بيئة VBA. سنقوم بتفكيك البنية الرياضية والبرمجية للخطأ #N/A، وتحليل الأنماط المختلفة لاستدعاء الدالة عبر كائنات النظام البرمجي، مع عقد مقارنات موسعة مع الدوال الشقيقة مثل IfError وIsError. كما سنقدم دليلاً تطبيقياً شاملاً مدعوماً بدراسة حالة حقيقية، واستراتيجيات التعامل مع المصفوفات الضخمة في الذاكرة العشوائية، وبناء الدوال المخصصة (UDF)، وصولاً إلى تقنيات التنقيح الاحترافي لضمان أعلى درجات الموثوقية والكفاءة في مشروعات الأتمتة البرمجية.
1. مقدمة تأصيلية لدالة IfNa في بيئة فيجوال بيسك للتطبيقات (VBA)
1.1 مفهوم الخطأ #N/A وأسبابه الرياضية والبرمجية في إكسيل
يُعَدّ الرمز #N/A اختصاراً للمصطلح التقني (Value Not Available)، وهو دلالة قياسية تُعبر عن فشل خوارزمية بحث محددة في العثور على القيمة المستهدفة ضمن نطاق أو مصفوفة مفهرسة. من المنظور الرياضي والمنطقي، لا يعبر هذا الخطأ عن عملية غير معرفة حسابياً كالقسمة على الصفر التي يمثلها الخطأ #DIV/0!، ولا عن عدم توافق في البنية النوعية للبيانات كالذي يمثله الخطأ #VALUE!، وإنما يشير بدقة إلى أن الاستعلام المنطقي الموجه إلى قاعدة البيانات مكتمل الأركان البنائية ولكنه خالٍ من التطابق الفعلي في فضاء البحث المتاح.
برمجياً داخل محرك إكسيل، يتم تمثيل الخطأ #N/A كنوع خاص من البيانات يسمى خطأ داخلي (Error Value)، وهو يحمل رمز الخطأ الرقمي 2042 (المقابل للثابت البرمجي xlErrNA). يظهر هذا الخطأ بكثرة عند إخفاق دوال الاسترجاع الشهيرة مثل VLOOKUP وHLOOKUP وMATCH وXLOOKUP في وضع التطابق التام، حيث تبحث الخوارزمية عن مفتاح أساسي غير موجود في العمود القياسي.
إن تراكم قيم #N/A دون معالجة واعية يمثل خطراً هيكلياً داهماً على سلامة النماذج البرمجية؛ فالأخطاء في إكسيل تتسم بخاصية الانتشار التسلسلي (Propagation)، حيث يؤدي وجود خلية واحدة تحمل هذا الخطأ إلى إفساد كافة المعادلات الإحصائية والتجميعية اللاحقة التي تعتمد عليها، مثل الجمع والضرب والمتوسطات، مما ينتج عنه شلل تام في لوحات التحكم المالية والتقارير التنفيذية التلقائية.
1.2 نشأة دالة IfNa وتطورها المعياري ضمن بيئة التطوير
ظهرت الحاجة الماسة إلى دالة IFNA في الإصدارات الحديثة من إكسيل كاستجابة هندسية مباشرة للقصور التشغيلي الذي شاب استخدام دالة IFERROR التقليدية. تاريخياً، كان المطورون يضطرون إلى استخدام دالة IFERROR لاعتراض حالات فشل البحث، إلا أن هذه الدالة العامة كانت تتسم بشمولية مفرطة وغير منضبطة؛ إذ كانت تقوم بابتلاع كافة الأخطاء بما فيها الأخطاء الناتجة عن تلف المراجع #REF! أو أخطاء كتابة أسماء النطاقات #NAME?، مما كان يحجب عيوباً بنيوية خطيرة في بنية الشيفرة البرمجية ويجعل عمليات التدقيق صعبة ومضللة.
جاء التطور المعياري عبر تقديم دالة متخصصة حصراً في اعتراض الخطأ النمطي #N/A دون سواه. يتيح هذا التخصيص للمطور توفير قيمة بديلة أو رسالة توضيحية عندما تكون القيمة مفقودة فحسب، بينما يسمح للأخطاء التقنية والتركيبية الأخرى بالظهور على السطح ليتم رصدها وإصلاحها فوراً.
ضمن مكتبة دوال ورقة العمل المتاحة لمحرك برمجيات VBA، تم إدراج دالة IfNa لتكون في متناول المبرمجين عبر نموذج كائنات التطبيق (Excel Object Model). وقد سمح هذا الدمج بصياغة أكواد أكثر اتزاناً وموثوقية، تتوافق مع أفضل الممارسات البرمجية العالمية التي تؤكد على مبدأ حصر الاستثناءات (Exception Narrowing) وتفادي المعالجة العشوائية للأخطاء مجهولة المصدر.
1.3 الفرق الجوهري بين استدعاء Application واستدعاء WorksheetFunction
عند استدعاء دوال ورقة العمل داخل محرر فيجوال بيسك (VBE)، يقف المطور أمام مسارين تقنيين مختلفين جوهرياً في كيفية إدارة الذاكرة وتدفق العمليات: المسار الأول يتم عبر كائن Application.WorksheetFunction.IfNa، والمسار الثاني عبر الاستدعاء المباشر من خلال كائن Application.IfNa. ينبع الاختلاف الأساسي بين هذين الأسلوبين من الطريقة التي يتعامل بها كل منهما مع استثناءات وقت التشغيل ونقل مؤشرات الخطأ من محرك إكسيل الأساسي (C++ Core) إلى بيئة استضافة الماكرو.
عند استخدام الكائن المساعد WorksheetFunction، يفرض المحرك صرامة بالغة؛ فإذا واجهت الدالة خطأ داخلياً أو فشلت في تنفيذ مهمتها، فإنها تُطلق خطأ وقت تشغيل من الفئة 1004 (Run-time error 1004)، مما يؤدي إلى توقف تنفيذ الشيفرة البرمجية فوراً وظهور شاشة التصحيح للمستخدم، ما لم تكن هناك بنية معالجة استثناءات مسبقة باستخدام تعليمات مثل On Error Resume Next.
على النقيض من ذلك، فإن استدعاء الدالة عبر كائن التطبيق المباشر Application.IfNa يوفر مرونة استثنائية؛ إذ إنه يعتمد على مبدأ الاستدعاء المتأخر (Late Binding) للوظائف الحسابية، ويقوم بتحويل قيمة الخطأ إلى متغير داخلي من النوع Variant/Error بدلاً من تفجير استثناء يوقف البرنامج. تتيح هذه الآلية للمبرمج فحص النتيجة بسلاسة، واستمرار تدفق العمليات الحسابية دون انقطاع، مما يوفر أداءً أفضل واستهلاكاً أقل لموارد مكدس الاستدعاءات (Call Stack).

2. البنية النحوية والصياغة البرمجية لدالة IfNa في VBA
2.1 الصيغة العامة ومعاملات دالة IfNa
تتطابق البنية النحوية لدالة IfNa في بيئة فيجوال بيسك للتطبيقات مع نظيرتها المستخدمة في واجهة المعادلات الحسابية لإكسيل، وتأخذ الصيغة المعيارية التالية:
Application.IfNa(Value, Value_if_na)
تتطلب الدالة معاملين إجباريين لضمان عملها بشكل سليم من الناحية التركيبية:
- المعامل الأول (Value): يمثل التعبير البرمجي، أو القيمة الرقمية، أو ناتج استدعاء دالة بحث أخرى (مثل VLOOKUP أو MATCH) التي يراد فحص مخرجاتها للتأكد مما إذا كانت تنتهي إلى الخطأ #N/A.
- المعامل الثاني (Value_if_na): يمثل القيمة التعويضية أو الإجراء البديل الذي يجب إرجاعه وتطبيقه في حال أثمر تقييم المعامل الأول عن قيمة خطأ عدم التوفر المنطقي.
تدعم الدالة إسناد مختلف أنواع البيانات لكلا المعاملين، بما يشمل النصوص (Strings)، والأرقام الصحيحة أو العشرية (Long, Double)، والقيم المنطقية (Boolean)، فضلاً عن مصفوفات الخلايا وكائنات النطاقات (Range Objects). ويشترط المحرر البرمجي VBE صياغة الأقواس بصورة منضبطة ومراعاة قواعد الفصل بين الوسائط باستخدام الفاصلة العادية أو المنقوطة وفقاً للإعدادات الإقليمية للنظام المشغل.
2.2 آليات تمرير الوسائط وتحديد أنواع البيانات المرجعة
تقتضي الممارسات الهندسية الدقيقة في كتابة أكواد VBA التصريح الصريح عن المتغيرات التي تستقبل نتائج دالة IfNa. ونظراً لأن مخرجات الدالة قد تتراوح ديناميكياً بين قيمة رقمية مسترجعة، أو قيمة نصية مخصصة، أو حتى كود خطأ في حالات خاصة، فإن النوع البياني الأنسب لحمل هذه النتائج هو نوع المتغير المرن Variant. يتيح استخدام المتغير Variant للمحرك تخزين أي نوع دون إجبار النظام على إجراء تحويلات قسرية قد تنتهي بأخطاء عدم تطابق الأنواع.
عند رغبة المطور في ترك الخلية فارغة عند غياب البيانات، يمكن تمرير سلسلة نصية خالية كمعامل ثانٍ عبر كتابة vbNullString أو زوج من علامات التنصيص المزدوجة "". يتميز الثابت vbNullString بتفوقه في إدارة الذاكرة، حيث إنه يمثل مؤشراً صفرياً (Null Pointer) لا يحجز مساحة تخزينية جديدة في جدول السلاسل النصية على عكس السلاسل الفارغة التي تحجز بايتين لعلامة الإنهاء.
في المقابل، إذا كانت الخلية المستهدفة ذات تنسيق رقمي مسبق (كتنسيق العملات أو النسب المئوية)، فإن إسناد نص بديل مثل “غير متوفر” قد يؤدي إلى تنبيهات بصرية للمستخدم؛ لذا يجب مراعاة ملاءمة النوع البياني المرجع مع طبيعة النظام التحليلي القائم، إما عبر إرجاع القيمة الصفرية 0 أو عبر استخدام دوال التحويل القياسية مثل CStr وCDbl قبل التعيين النهائي.
2.3 إدارة الأخطاء الصامتة مقابل إثارة الاستثناءات البرمجية
تعتبر استراتيجية التعامل مع الاستثناءات من أهم المعايير المعمارية في تطوير البرمجيات المؤسسية. يمثل استخدام Application.IfNa آلية من آليات “العزل الصامت للخطأ”، حيث يتم امتصاص الخطأ المتوقع وتحييد أثره على واجهة المستخدم وسير الماكرو. يمنح هذا الأسلوب النظام مظهراً انسيابياً واحترافياً، حيث يتفادى المستخدم النهائي مواجهة نوافذ التحذير البرمجية المعقدة التي قد توحي بوجود خلل في المنظومة.
ومع ذلك، يبرز هنا تحدٍ هندسي يتمثل في الموازنة بين المعالجة الانسيابية وبين جودة تكامل البيانات (Data Integrity). فالإفراط في حجب الأخطاء بصمت دون توثيق قد يخفي اختلالات خطيرة في جداول البيانات الأساسية، مثل التغييرات المفاجئة في بنية الجداول، أو وجود مسافات بادئة غير مرئية تؤدي إلى إخفاق البحث الدائم.
لحل هذه المعضلة، يُوصى بتطبيق نمط التصميم القائم على “المعالجة مع التوثيق الموازي” (Handled with Logging)؛ حيث تُستخدم دالة IfNa لتوفير القيمة البديلة للمستخدم، بينما يقوم الإجراء البرمجي في الوقت ذاته بتسجيل تفاصيل السجل المفقود وقيمته المفتاحية وتاريخ المحاولة في ملف سجل خارجي (Log File) أو في ورقة عمل خفية مخصصة لأغراض التدقيق البرمجي.
3. مقارنة تحليلية: IfNa مقابل IfError وIsError في بيئة VBA
3.1 الاختلاف الوظيفي بين معالجة أخطاء #N/A والأخطاء العامة
يكمن التباين الجوهري بين IfNa وIfError في النطاق الوظيفي والمستهدف التشغيلي لكل منهما. صُممت دالة IfError لتكون مظلة شمولية تعترض كل خطأ حسابي أو هيكلي تطلقه محركات إكسيل بلا استثناء؛ فهي تتفاعل مع الأخطاء: #N/A، #VALUE!، #REF!، #DIV/0!، #NUM!، #NAME?، و#NULL!. ورغم أن هذا الشمول قد يبدو جذاباً للمطور المبتدئ لتفادي توقف الكود، إلا أنه ينطوي على مخاطر برمجية جسيمة.
إذا قمت بحذف عمود أساسي بالخطأ ضمن قاعدة البيانات، فإن معادلات البحث ستطلق الخطأ #REF!. في حال استخدام IfError، سيتم إخفاء هذا الخطأ الجسيم وستظهر القيمة البديلة المخصصة للمطابقة المفقودة، مما يوهم متخذ القرار بأن البيانات خالية ولكنها صحيحة تركيبياً، في حين أن النموذج الرياضي برمته أصبح تالفاً.
أما دالة IfNa، فإنها تتجاهل تماماً كافة الأخطاء التركيبية وتسمح لها بالمرور والتفجر في بيئة الماكرو، بينما تتدخل حصرياً وفقط عندما يكون الخلل ناتجاً عن غياب القيمة المفتاحية. يضمن هذا التدخل الانتقائي المحافظة على النزاهة الهندسية للنظام؛ فالمشكلات الهيكلية يتم اكتشافها وحلها، بينما يتم التعامل مع حالات الغياب الطبيعي للبيانات بكل هدوء وانسيابية.
3.2 الكفاءة الحسابية واستهلاك الموارد في قواعد البيانات الكبيرة
عند معالجة مجموعات البيانات الضخمة التي تتجاوز مئات الآلاف من الصفوف في بيئة VBA، تصبح مسألة الكفاءة الزمنية واستهلاك دورات المعالج (CPU Cycles) ذات أولوية قصوى. من الناحية الحسابية، تختلف تكلفة دالة IfNa المدمجة عن الأسلوب التقليدي القديم الذي يعتمد على اقتران دالتي IF مع دالة التحقق المنطقي ISERROR أو ISNA.
في النمط الكلاسيكي:
IF(ISNA(VLOOKUP(...)), "Not Found", VLOOKUP(...))
يضطر محرك الحساب إلى تقييم وتنفيذ دالة البحث مرتين في أسوأ السيناريوهات (عند العثور على القيمة): المرة الأولى داخل دالة الفحص ISNA، والمرة الثانية لجلب القيمة الفعلية. يؤدي ذلك إلى مضاعفة الجهد الحاسوبي بنسبة تقترب من 100%، مما يتسبب في بطء واضح في استجابة الماكرو.
في المقابل، تعمل دالة IfNa وفق آلية التقييم على مرحلة واحدة؛ حيث يُمرر التعبير الحسابي للمعالج، فإذا نجح في إرجاع قيمة صحيحة تُعتمد فوراً ويتم تخطي المعامل الثاني، وإذا أرجع الخطأ #N/A يُستبدل فوراً بالمعامل البديل. يقلل هذا التدفق الخطي من استهلاك الذاكرة المؤقتة ويقلص زمن التنفيذ بنسب تتراوح بين 30% إلى 50% في المشاريع الكبرى.
3.3 معايير الاختيار الهندسي بين الدوال البديلة في المشاريع الضخمة
تتطلب هندسة البرمجيات الاحترافية في بيئات المؤسسات تبني مصفوفة قرار محددة لاختيار الأداة المناسبة لمعالجة الأخطاء، كما يوضح الجدول التحليلي التالي:
- دالة IfNa: الخيار الأمثل والوحيد لعمليات البحث والمطابقة (VLOOKUP, MATCH, INDEX) عندما يكون عدم وجود السجل أمراً طبيعياً ومتوقعاً ضمن دورة حياة العمل، مع ضرورة الحفاظ على يقظة النظام تجاه أي تلف مرجعي أو خطأ صيغي.
- دالة IfError: تُستخدم بحذر شديد وفقط في العمليات الحسابية النهائية (كالنسب والمعدلات) لمنع أخطاء القسمة على الصفر
#DIV/0!الناتجة عن حقول فارغة مؤقتاً، ويُحظر استخدامها في تغليف دوال الاستعلام الحيوية في الأنظمة المصرفية أو الطبية. - دالة IsError / IsNA (المنطقية): تُستخدم عندما يتطلب المنطق البرمجي اتخاذ قرارات شرطية متفرعة داخل كتل
If...Else...End Ifفي كود الماكرو، حيث لا نحتاج إلى إرجاع قيمة فورية بل إلى توجيه تدفق البرنامج إلى إجراءات فرعية مختلفة بناءً على حالة الخطأ.
إن الالتزام بهذه المعايير يرفع من درجات الامتثال البرمجي ويسهل اختبارات عدم الانحدار (Regression Testing) ويقلل تكلفة الصيانة المستقبلية للشفرات من قبل فرق التطوير الأخرى.
4. التكامل البرمجي بين IfNa ودالة البحث العمودي VLOOKUP
4.1 تحليل سلوك VLOOKUP عند غياب القيمة المفتاحية
تعتمد خوارزمية دالة VLOOKUP في إكسيل على مسح العمود الأول من مصفوفة البحث المحددة بحثاً عن تطابق مع القيمة المفتاحية. عند ضبط معامل البحث على التطابق التام، وهو المعيار الآمن برمجياً عبر تمرير False أو 0، يعمل المحرك وفق منطق ثنائي صارم: إما العثور على التطابق الدقيق واستخراج الخلية المقابلة وفق رقم العمود المحدد، أو الفشل التام وإطلاق القيمة الخطئية #N/A.
عندما يتم استدعاء دالة VLOOKUP داخل كود VBA دون توفير حماية مسبقة، وتفشل في العثور على العنصر، تقع مشكلة هيكلية حرجة؛ إذ يحاول المحرك كتابة الخطأ أو إسناده لمتغير نصي أو رقمي غير مهيأ لاستيعاب الأنواع الخطئية. يؤدي ذلك إلى إثارة استثناء “عدم تطابق الأنواع” (Type Mismatch)، مما يتسبب في توقف تنفيذ الماكرو وترك مصنف العمل في حالة غير مستقرة، قد تتضمن تعطيل تحديث الشاشة أو بقاء العمليات معلقة في الذاكرة.
تنشأ هذه المشكلة تحديداً لأن محرك VBA يفرق بصرامة بين الكائنات النصية والقيم الداخلية التابعة للنظام، ولذلك يصبح دمج دالة الحماية IfNa أمراً حتمياً وليس مجرد خيار تجميلي للكود.
4.2 صياغة الكود التكاملي لنطاق البيانات المعياري
لتحقيق التكامل الهندسي بين الدالتين، يتم تغليف دالة VLOOKUP لتكون المعامل الأول المباشر لدالة IfNa. تتطلب هذه العملية تعيين نطاقات الخلايا بعناية فائقة باستخدام كائنات النطاق Range وتحديد مصفوفة الجدول بدقة.
تأخذ الشيفرة الهيكلية المتكاملة النمط التالي:
Dim resultValue As Variant
resultValue = Application.IfNa(Application.VLookup(SearchKey, SourceRange, ColIndex, False), "القيمة البديلة")
في هذا البناء، يقوم المحرك أولاً بتقييم دالة البحث Application.VLookup. فإذا نجحت في العثور على السجل، تم تمرير القيمة المستخرجة مباشرة إلى Application.IfNa، والتي تقر بدورها بصحة القيمة وتمررها إلى المتغير resultValue دون الالتفات إلى المعامل الثاني. أما إذا فشلت عملية البحث، فإن VLookup ستنتج الخطأ الداخلي #N/A، وهنا تلتقطه دالة IfNa فوراً وتمنعه من الخروج إلى بيئة التشغيل، مستبدلة إياه بسلسلة “القيمة البديلة”.
4.3 فهم كتلة البناء With Application وأهميتها في ترشيد الكود
في مشروعات التطوير المتقدمة، يُعد تكرار كتابة الكائن الأساسي Application أمراً غير مستحب برمجياً، لما يسببه من تشويش بصري وزيادة في عدد مرات الوصول المتأخر إلى واجهات الكائنات (COM Object Interfaces). تبرز هنا الأهمية المعمارية لاستخدام كتلة البناء With…End With.
عند فتح كتلة With Application، يتم إنشاء مرجع مباشر وثابت لكائن التطبيق في قمة مكدس العمليات، مما يتيح استدعاء الدوال المتداخلة باستخدام النقطة . مباشرة دون الحاجة لإعادة كتابة اسم الكائن في كل استدعاء. لا يقتصر هذا الإجراء على ترشيد الشيفرة وتحسين وضوحها وقابليتها للقراءة فحسب، بل يمتد أثره الإيجابي إلى الأداء؛ إذ يقلل من عمليات البحث الهرمي التي يقوم بها مفسر الأكواد للوصول إلى الدوال المستهدفة، مما يسرع من وتيرة التنفيذ اللحظي.
5. دراسة حالة تطبيقية: استرجاع إحصاءات لاعبي كرة السلة برمجياً
5.1 تصميم جدول البيانات الافتراضي وهيكلة النطاقات
لتجسيد هذا المفهوم على أرض الواقع، سنفترض وجود نظام لإدارة إحصاءات دوري كرة السلة للمحترفين مدون في ورقة عمل إكسيل. تم تصميم مصفوفة البيانات في النطاق A2:C11، حيث تتوزع الأعمدة على النحو المعياري التالي:
- العمود A (A2:A11): يمثل اسم الفريق (Team Name)، وهو حقل البحث والمفتاح الأساسي للعملية (مثل: Hawks, Celtics, Bulls, Kings, Lakers).
- العمود B (B2:B11): يتضمن اسم اللاعب الممثل للفريق (Player Name).
- العمود C (C2:C11): يحتوي على إحصائية عدد التمريرات الحاسمة (Assists) التي حققها اللاعب، وهي قيمة رقمية صحيحة تمثل الهدف المراد استخراجه.
تم تخصيص الخلية E2 في ورقة العمل لتكون خلية الإدخال المرجعية التي يقوم المستخدم أو النظام بكتابة اسم الفريق المراد الاستعلام عنه بداخلها، بينما تم تحديد الخلية F2 لتكون خلية الإخراج النهائية لعرض عدد التمريرات الحاسمة المسترجعة، أو إظهار رسالة تفيد بتعذر العثور على الفريق في حال إدخال اسم غير مدرج.

5.2 تفكيك الكود البرمجي للإجراء UseVLOOKUP سطراً بسطر
فيما يلي الشيفرة البرمجية الكاملة للإجراء الفرعي المصمم لأداء هذه المهمة، يليه تحليل تفكيكي دقيق لمكوناته البنيوية:
Sub UseVLOOKUP()
With Application
Range("F2").Value = .IfNa(.VLookup(Range("E2").Value, Range("A2:C11"), 3, False), "No Value Found")
End With
End Sub
يبدأ الإجراء بالإعلان المعياري Sub UseVLOOKUP()، وهو تصريح عن إجراء فرعي عام يتمتع بنطاق وصول على مستوى المشروع. يتبعه سطر فتح البنية الهرمية With Application، الذي ينشئ سياق العمل المباشر مع بيئة تشغيل إكسيل.
السطر الجوهري في الكود هو سطر الإسناد، وفيه يتم توجيه الناتج الحسابي مباشرة إلى الخاصية Value للخلية Range("F2"). تم استدعاء دالة .IfNa وبداخلها تم تمرير دالة .VLookup كمعامل أول. تأخذ دالة البحث قيمة الخلية Range("E2").Value كمدخل استعلامي، وتبحث عنها في النطاق المحكم Range("A2:C11"). تم تحديد الرقم 3 كمعامل الفهرسة لجلب البيانات من عمود التمريرات الحاسمة، مع فرض التطابق الدقيق عبر المعامل المنطقي False.
في حالة إخفاق VLookup، يعترض المعامل الثاني لدالة IfNa، وهو النص الصريح "No Value Found"، مسار الفشل ويوضع مباشرة في الخلية F2. ينتهي الإجراء بإغلاق الكتلة عبر End With يليه End Sub لإنهاء العملية وتفريغ مكدس التعليمات.
5.3 اختبار السيناريوهات الميدانية ومقارنة المخرجات
للتحقق من سلامة الأداء وموثوقية الشيفرة، يتم إخضاع الماكرو للاختبار العملي تحت سيناريوهين ميدانيين مختلفين:
السيناريو الأول (المطابقة الناجحة): يقوم المستخدم بإدخال القيمة النصية “Kings” في الخلية E2، ثم يقوم بتشغيل الإجراء UseVLOOKUP. يقوم المحرك بمسح العمود A حتى يعثر على السجل في الصف الخامس، ويستخرج القيمة المقابلة في العمود الثالث وهي الرقم 3. تُمرر هذه القيمة بنجاح عبر IfNa وتستقر في الخلية F2 كقيمة رقمية نقية تدل على اكتمال الاستعلام بنجاح.
السيناريو الثاني (غياب السجل): يقوم المستخدم بإدخال اسم فريق غير مسجل في النطاق مثل “Spurs” أو “Warriors” في الخلية E2. عند تشغيل الماكرو، تخفق دالة VLookup في العثور على الاسم وتنتج القيمة الخطئية #N/A. هنا يتدخل صمام الأمان لدالة IfNa ليمنع تصدع الإجراء، ويكتب النص البديل “No Value Found” داخل الخلية F2 بصورة فورية وسلسة، دون ظهور أي رسائل تحذيرية أو توقف مفاجئ للماكرو.
6. معالجة البيانات المتقدمة وتطبيق IfNa على النطاقات والمصفوفات الديناميكية
6.1 تنفيذ دالة IfNa عبر الحلقات التكرارية (Loops)
في البيئات الإنتاجية الواقعية، نادراً ما يقتصر العمل على استعلام خلية واحدة؛ بل يتطلب الأمر معالجة آلاف السجلات بصورة دفعية. لتحقيق ذلك، يتم توظيف الحلقات التكرارية للمرور على قوائم البحث وتطبيق منطق IfNa بشكل تتابعي.
لضمان ديناميكية الكود، يجب احتساب آخر صف نشط في ورقة العمل تلقائياً باستخدام الدالة المتقدمة End(xlUp)، مما يضمن تكيف الماكرو مع تزايد أو تناقص مدخلات المستخدم تلقائياً:
Dim lastRow As Long, i As Long
lastRow = Cells(Rows.Count, "E").End(xlUp).Row
With Application
For i = 2 To lastRow
Cells(i, "F").Value = .IfNa(.VLookup(Cells(i, "E").Value, Range("A2:C1000"), 3, False), "غير متوفر")
Next i
End With
تسمح حلقة For...Next بتنفيذ المعالجة لكل صف على حدة بصورة منتظمة، مما يحمي التطبيق من الانهيار عند مواجهة خلايا مفردة مفقودة داخل قائمة استعلام طويلة، ويضمن تحديث النتائج لجميع الصفوف بكفاءة معيارية.
6.2 معالجة البيانات في مصفوفات الذاكرة لتفادي البطء
على الرغم من فاعلية الحلقات التكرارية المباشرة على الخلايا، إلا أنها تتسم بنقطة ضعف جوهرية في الأداء عند التعامل مع مجموعات البيانات الكبيرة (أكثر من 10,000 صف)، نظراً للتكلفة العالية لعمليات القراءة والكتابة المتكررة عبر واجهة ورقة العمل (COM Bridge Overhead). يكمن الحل الهندسي الأرقى في نقل المعالجة بالكامل إلى مصفوفات الذاكرة العشوائية (In-Memory Arrays).
في هذا الأسلوب، يتم تفريغ نطاق البحث ونطاق الإدخال بالكامل داخل مصفوفات من النوع Variant بضغطة واحدة، وتُجرى عمليات البحث والتحقق من الخطأ #N/A وتطبيق القيم البديلة افتراضياً داخل ذاكرة الوصول العشوائي RAM:
Dim inputData As Variant, outputData As Variant
inputData = Range("E2:E" & lastRow).Value
ReDim outputData(1 To UBound(inputData, 1), 1 To 1)
' إجراء عمليات التحقق والمعالجة البرمجية داخل الذاكرة
Range("F2:F" & lastRow).Value = outputData
إن إعادة تفريغ مصفوفة النتائج دفعة واحدة إلى النطاق المستهدف يختصر زمن التنفيذ من دقائق إلى أجزاء من الثانية، وهو ما يمثل تحسيناً هائلاً في الأداء يلبي متطلبات الأنظمة المصرفية والتحليلية العملاقة.
6.3 التوافق مع النطاقات الديناميكية والجداول المهيكلة (ListObjects)
تمثل الجداول المهيكلة أو ما يُعرف برمجياً بكائنات ListObjects المعيار الحديث لإدارة الجداول في إكسيل. توفر هذه الكائنات إمكانية الإشارة إلى الأعمدة والصفوف باستخدام التسميات الهيكلية المنطقية بدلاً من الإحداثيات الثابتة.
تتوافق دالة IfNa تماماً مع هذا النمط الحديث، حيث يمكن استدعاؤها بالاعتماد على خاصية DataBodyRange:
Dim targetTable As ListObject
Set targetTable = ActiveSheet.ListObjects("BasketballStats")
Range("F2").Value = Application.IfNa(Application.VLookup(Range("E2").Value, targetTable.DataBodyRange, 3, False), "غير مدرج")
يضمن استخدام الجداول المهيكلة تكيف الكود التلقائي مع تمدد قاعدة البيانات عند إضافة لاعبين أو فرق جديدة، مما يلغي تماماً الحاجة إلى تعديل نطاقات الشيفرة البرمجية يدوياً عند كل تحديث للبيانات.
7. التكامل مع دوال البحث البديلة: INDEX & MATCH و XLOOKUP
7.1 توظيف IfNa لمعالجة أخطاء اقتران دالتي INDEX و MATCH
يُعتبر الاقتران الشهير بين دالتي INDEX وMATCH البديل الهندسي الأكثر قوة ومرونة لدالة VLOOKUP الكلاسيكية، نظراً لقدرته الفائقة على إجراء البحث العكسي (من اليمين إلى اليسار أو العكس) وتحرره من شرط ثبات رقم عمود الاسترجاع. ومع ذلك، فإن هذا الاقتران عرضة أيضاً لخطأ عدم التوفر المنطقي.
يصدر الخطأ #N/A في هذا الاقتران حصراً عن دالة MATCH عندما تعجز عن تحديد الموقع النسبي لمفتاح البحث داخل مصفوفة الفحص. وعندما يتم تمرير هذا الخطأ إلى دالة INDEX، ينهار التعبير بأكمله.
يتم تحصين هذا التركيب برمجياً بتغليفه داخل Application.IfNa بالشكل التالي:
Dim matchResult As Variant
With Application
matchResult = .IfNa(.Index(Range("C2:C11"), .Match(Range("E2").Value, Range("A2:A11"), 0)), "مطابقة مفقودة")
End With
يوفر هذا النمط حماية مطلقة للمعادلة مع الاستفادة من السرعة العالية لدالة MATCH ومرونة INDEX الاستثنائية في قراءة البيانات من أي موقع في المصنف.
7.2 المقارنة مع ميزة المعالجة الذاتية في دالة XLOOKUP الحديثة
قدمت مايكروسوفت دالة XLOOKUP كجيل جديد كلياً يتجاوز كافة القيود التاريخية لدوال البحث السابقة. ومن بين أبرز المزايا الهيكلية المدمجة في هذه الدالة وجود معامل رابع اختياري مخصص أصالة لمعالجة حالات الغياب، وهو المعامل [if_not_found].
عند استخدام XLOOKUP برمجياً في البيئات التي تعتمد إصدارات إكسيل الحديثة (Microsoft 365 أو Office 2021 وما بعدها)، يمكن للمطور الاستغناء عن دالة IfNa المستقلة؛ إذ يتم تمرير القيمة البديلة مباشرة داخل الدالة نفسها:
Range("F2").Value = Application.XLookup(Range("E2").Value, Range("A2:A11"), Range("C2:C11"), "غير موجود")
ومع ذلك، تظل المعرفة المعمقة بدالة IfNa ضرورة قصوى للمطورين المحترفين لسببين رئيسيين: الأول هو ضمان التوافق العكسي (Backward Compatibility) مع المنشآت التي لا تزال تستخدم إصدارات أقدم من إكسيل، والسبب الثاني هو أن IfNa تظل الأداة القياسية لمعالجة أخطاء عدم التوفر الناتجة عن دوال رياضية وإحصائية أخرى لا تتضمن معاملات حماية مدمجة.
7.3 صياغة استعلامات متعددة المعايير محصنة ضد الخطأ
في السيناريوهات المعقدة، قد تتطلب الأعمال البحث بناءً على أكثر من معيار واحد (مثل: البحث عن اللاعب بناءً على اسم الفريق واسم المركز معاً). يتم تحقيق ذلك برمجياً عبر دمج المصفوفات المنطقية أو استخدام دالة MATCH المتقدمة مع ضرب المصفوفات الشرطية.
تتضاعف احتمالية ظهور الخطأ #N/A في الاستعلامات المتعددة، نظراً لأن غياب أي شرط من الشروط يؤدي بالضرورة إلى فشل المطابقة الكلية للمصفوفة. يضمن تغليف هذه الاستعلامات المعقدة بدالة IfNa استقرار الكود وتقديم رسائل خطأ تفاعلية ذكية تحدد للمدقق أن التوليفة المركبة من المعايير غير متوفرة، مما يمنع الشكوك حول تعطل النظام البرمجي.
8. إنشاء دوال مخصصة للمستخدم (UDF) تعتمد على منطق IfNa
8.1 بناء دالة معرفة مسبقاً لحماية المعادلات على مستوى الخلية
تتيح بيئة VBA للمطورين توسيع قدرات إكسيل الحسابية عبر بناء دوال مستخدم مخصصة (User-Defined Functions – UDF). يمكن إنشاء دالة متخصصة تقوم بدمج منطق البحث مع الحماية التلقائية بواسطة IfNa، مما يوفر للمستخدمين النهائيين واجهة مبسطة وموحدة لاسترجاع البيانات دون الحاجة لكتابة معادلات مركبة ومعقدة داخل الخلايا.
يوضح الكود التالي كيفية إنشاء دالة UDF احترافية:
Public Function SafePlayerLookup(ByVal TeamName As String, ByVal SearchRange As Range, ByVal ColIdx As Long, Optional ByVal FallbackText As String = "غير متوفر") As Variant
With Application
SafePlayerLookup = .IfNa(.VLookup(TeamName, SearchRange, ColIdx, False), FallbackText)
End With
End Function
بمجرد وضع هذا الكود في وحدة نمطية قياسية (Standard Module)، تصبح الدالة متاحة للاستخدام المباشر في أي ورقة عمل، حيث يمكن للمستخدم استدعاؤها مثل أي دالة قياسية:
=SafePlayerLookup(E2, A2:C11, 3, "فريق غير مدرج")
8.2 كتابة وتوثيق كود UDF احترافي قابل لإعادة الاستخدام
تتطلب البرمجة المؤسسية ضبط الدوال المخصصة لتكون متينة وقابلة لإعادة الاستخدام عبر مشاريع متعددة. يشمل ذلك التحقق من صحة المدخلات قبل معالجتها، والتعامل الحذر مع القيم الصفرية أو النطاقات التالفة.
يجب ضبط المتغيرات المدخلة لتفادي أخطاء المراجع الفارغة؛ فإذا تم تمرير نطاق فارغ، يجب أن تعيد الدالة تحذيراً واضحاً. كما يُفضل تعطيل خاصية التطاير (Volatility) في الدالة وتجنب استخدام Application.Volatile إلا عند الضرورة القصوى، لأن إعلان تطاير الدالة يجبر إكسيل على إعادة حسابها مع كل حركة في المصنف، مما يتسبب في هبوط كارثي في أداء النظام ككل.
8.3 تخصيص الرسائل التفاعلية الذكية لتحسين تجربة المستخدم
بدلاً من الاكتفاء بإرجاع رسائل نصية ثابتة ومبهمة، يمكن توسيع منطق دالة UDF لإرجاع إشعارات سياقية تفاعلية. على سبيل المثال، يمكن للدالة فحص ما إذا كان اسم الفريق المدخل يحتوي على مسافات زائدة (Trailing Spaces) عبر دالة Trim وتنبيه المستخدم بأن القيمة المدخلة قد تتضمن خطأ مطبعياً منع عملية المطابقة.
كذلك، يمكن دمج رموز تعبيرية بصرية (مثل علامة التنبيه التحذيرية) أو تنسيقات شرطية مرافقة ترشد مدققي الحسابات إلى السجلات التي تستوجب مراجعة فورية لقواعد البيانات المصدرية، مع إمكانية دعم لغات متعددة في الرسائل المرتجعة وفقاً للإعدادات الإقليمية للمستخدم المشغل للنظام.
9. الأخطاء الشائعة واستراتيجيات تنقيح الشيفرات وتصحيحها (Debugging)
9.1 أخطاء عدم تطابق الأنواع (Type Mismatch – Run-time error 13)
يُعَدّ خطأ وقت التشغيل رقم 13 (Run-time error 13: Type Mismatch) من أكثر العثرات شيوعاً عند التعامل مع دوال البحث والأخطاء في VBA. ينشأ هذا الخلل في الغالب عندما يحاول المطور إسناد ناتج دالة إكسيل الحسابية إلى متغير مصرح عنه بنوع بياني مقيد، مثل String أو Long، في حين أن الدالة أرجعت قيمة خطئية من النوع Variant/Error.
على سبيل المثال، الشيفرة التالية ستنهار فوراً إذا فشل البحث:
Dim result As String
result = Application.VLookup(...) ' ينهار برمز الخطأ 13 عند ظهور #N/A
لتفادي هذا الانهيار، يجب الالتزام بقاعدتين برمجيتين: أولاً، التصريح الدائم عن المتغير المستقبل للبحث كنوع Variant. ثانياً، التحقق من طبيعة القيمة المسترجعة باستخدام الدالة المنطقية IsError أو فحص هويتها النوعية باستخدام الدالة TypeName قبل محاولة استخدامها في أي عمليات دمج نصوص أو عمليات حسابية لاحقة.
9.2 الخلل الناتج عن المراجع غير المؤهلة (Unqualified References)
من الأخطاء الكارثية في مشاريع الأتمتة الاعتماد على “المراجع غير المؤهلة” عند تحديد كائنات النطاقات (Range Objects). عندما يكتب المطور داخل الماكرو:
Range("A2:C11")
فإن محرك VBA يفترض أن المقصود هو ورقة العمل النشطة حالياً (ActiveSheet). إذا قام المستخدم بالانتقال إلى ورقة عمل أخرى أثناء تشغيل الماكرو، أو إذا كان الماكرو يعمل في الخلفية، فسيتم تطبيق دالة IfNa والبحث في النطاق الخاطئ كلياً، مما ينتج عنه مخرجات مضللة أو إتلاف لبيانات أوراق أخرى.
العلاج البرمجي الصارم يقتضي “التأهيل الكامل للمراجع” (Fully Qualified References)، عبر تحديد المصنف وورقة العمل بدقة متناهية:
ThisWorkbook.Sheets("StatsData").Range("A2:C11")
يضمن هذا التأهيل انحصار عمليات البحث والمعالجة في مستودع البيانات الصحيح بصرف النظر عن حالة واجهة المستخدم أو الورقة النشطة وقت التنفيذ.

9.3 تقنيات التتبع المتقدمة باستخدام نوافذ المحرر VBE
يوفر محرر فيجوال بيسك (VBE) ترسانة من الأدوات التحليلية المتقدمة لتعقب وتصحيح سلوك دالة IfNa أثناء مرحلة التطوير:
- نافذة التنفيذ المباشر (Immediate Window): تتيح اختبار تقييم تعابير IfNa بشكل لحظي دون الحاجة لتشغيل الماكرو بالكامل، وذلك عبر كتابة الأوامر مسبوقة بعلامة الاستفهام، مثل:
?Application.IfNa(CVErr(xlErrNA), "Success")للتحقق من سلامة استجابة الدالة. - نافذة المراقبة (Watch Window): تُعد الأداة المثالية لمراقبة المتغيرات الحاملة لقيم الاستعلام، حيث تعرض بدقة النوع الحقيقي للمتغير وتغيراته اللحظية وقيمته الداخلية، مما يسهل رصد لحظة تحول المتغير إلى
Error 2042. - نقاط التوقف (Breakpoints) والتنفيذ السطري (F8): يتيح استخدام مفتاح
F8تتبع مسار تنفيذ كود IfNa سطراً بسطر، مما يكشف للمطور المسار الفعلي الذي اتخذه المحرك وما إذا كانت الشروط البديلة قد نُفذت في التوقيت والصف الصحيحين.
10. أفضل الممارسات البرمجية لتحسين الأداء وضمان استدامة الأكواد
10.1 إدارة إعدادات بيئة إكسيل البرمجية لرفع كفاءة المعالجة
تتطلب كتابة أكواد VBA الاحترافية السيطرة الكاملة على البيئة التشغيلية لمحرك إكسيل أثناء تنفيذ الإجراءات الكثيفة. يقوم إكسيل في الوضع الافتراضي بإعادة رسم الشاشة بعد كل تعديل يطرأ على الخلايا، وإعادة حساب كافة معادلات المصنف فور كتابة أي قيمة جديدة، مما يتسبب في هدر هائل للوقت والموارد.
لرفع كفاءة تنفيذ الشيفرات التي تحتوي على عمليات استعلام متعددة بدالة IfNa، يجب اتباع البروتوكول القياسي لتعطيل خدمات البيئة مؤقتاً في بداية الإجراء وإعادة تفعيلها بدقة في نهايته:
' تعطيل الخدمات المستهلكة للموارد
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
' [تنفيذ عمليات البحث ومعالجة البيانات باستخدام IfNa]
' استعادة الإعدادات الأصلية للنظام
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
يضمن هذا التكنيك تسريع زمن معالجة الماكرو بمعدلات قد تصل إلى عشرة أضعاف، ويوفر للمستخدم تجربة تفاعلية سلسة تخلو من الوميض المزعج للشاشة أثناء تحديث البيانات.
10.2 التوثيق البرمجي وقابلية الصيانة المستمرة للأكواد المؤسسية
تعتبر قابلية القراءة والصيانة (Maintainability) المعيار الذهبي لجودة البرمجيات المؤسسية. يجب أن تخضع الشيفرات البرمجية التي تطبق حلول IfNa لقواعد توثيق دقيقة وفق معايير التسمية القياسية، مثل تدوين الملاحظات القياسية (Hungarian Notation)، كاستخدام البادئة rng لكائنات النطاقات (مثل rngLookupTable) والبادئة vnt لمتغيرات الفاريانت المرنة (مثل vntAssistResult).
علاوة على ذلك، يجب كتابة تعليقات توضيحية داخل الشيفرة تشرح بدقة الأسباب الهندسية لاختيار دالة IfNa بدلاً من IfError، مع توثيق الهيكل العام للأعمدة المستهدفة وأرقام الفهارس. يسهل هذا التوثيق الداخلي المهمة على المطورين اللاحقين وفرق التدقيق البرمجي لتعديل النطاقات وتوسيع قواعد التحقق دون التسبب في أخطاء غير مقصودة في هيكل النظام.
10.3 بناء هيكل استثنائي متكامل يجمع IfNa مع معالجات الأخطاء المتقدمة
لا يُغني استخدام دالة IfNa التخصصية عن بناء منظومة شاملة لمعالجة الأخطاء غير المتوقعة لنظام التشغيل أو البيئة المادية للحاسوب (مثل امتلاء الذاكرة، أو فقدان الاتصال بقواعد البيانات الخارجية).
تتحقق الحصانة البرمجية القصوى عبر الدمج المتناغم بين المعالجة السلسة على مستوى الدوال الفردية بواسطة IfNa، واحتواء الكود بالكامل داخل هيكل اعتراضي معزز بتعليمات On Error GoTo:
Sub SafeExecutionPipeline()
On Error GoTo CriticalErrorHandler
' العمليات التشغيلية المحمية بدالة IfNa
With Application
Range("F2").Value = .IfNa(.VLookup(Range("E2").Value, Range("A2:C11"), 3, False), "غير متوفر")
End With
Exit Sub
CriticalErrorHandler:
' معالجة الاستثناءات الكارثية غير المتوقعة وتأمين الخروج الآمن
MsgBox "حدث استثناء برمجي غير متوقع: " & Err.Description, vbCritical, "خطأ نظام"
' إعادة تفعيل خدمات التطبيق وتفريغ الكائنات من الذاكرة
Application.ScreenUpdating = True
End Sub
يضمن هذا النمط المتكامل الفصل التام بين معالجة القيمة المفقودة المتوقعة، والتي يتم التعامل معها بسلاسة دون إزعاج المستخدم، وبين الأعطال البرمجية والتقنية الحرجة التي تتطلب تدخلاً فورياً وإشعاراً للمسؤولين، مما يوفر بيئة برمجية متينة ومستقرة تلبي أعلى المعايير الهندسية المعاصرة.
خاتمة
تُعد دالة IfNa في بيئة فيجوال بيسك للتطبيقات (VBA) أداة هندسية لا غنى عنها لبناء نماذج بيانات متقدمة ومستقرة داخل منصة مايكروسوفت إكسيل. من خلال قدرتها المتخصصة على عزل ومعالجة خطأ عدم التوفر المنطقي #N/A دون حجب أو إخفاء الأخطاء الهيكلية والتركيبية الأخرى، تمنح هذه الدالة المطورين وسيلة دقيقة للحفاظ على سلامة النماذج التحليلية وتدفق العمليات البرمجية بانسيابية متناهية.
لقد استعرض هذا الدليل المتكامل الأبعاد الهندسية العميقة لاستخدام الدالة، بدءاً من تفكيك طبيعة الخطأ #N/A وأسبابه في خوارزميات المطابقة، مروراً بالتمييز التشغيلي الدقيق بين استدعاء Application واستدعاء WorksheetFunction، وتحليل الفوارق الجوهرية مع دوال مثل IfError وIsError. كما أوضحت دراسة الحالة التطبيقية لكيفية استرجاع إحصاءات لاعبي كرة السلة مرونة الدالة في الاندماج مع دالة VLOOKUP، وكيفية توسيع نطاق المعالجة ليشمل المصفوفات فائقة السرعة في الذاكرة العشوائية والجداول المهيكلة والدوال المخصصة للمستخدم (UDF).
إن الالتزام بأفضل الممارسات البرمجية المتمثلة في إدارة إعدادات البيئة، والتأهيل الصريح للمراجع، وإحكام الرقابة على الأنواع البيانية، ودمج معالجات الاستثناءات الشاملة، يضمن للمؤسسات تطوير حلول أتمتة مستدامة تتسم بأعلى درجات الكفاءة الزمنية والموثوقية التشغيلية، وتصمد أمام التحديات المتزايدة لضخامة البيانات في العصر الرقمي.
المراجع
- Microsoft. (2023). WorksheetFunction.IfNa method (Excel). Microsoft Learn. https://learn.microsoft.com/en-us/office/vba/api/excel.worksheetfunction.ifna
- Microsoft. (2023). VLOOKUP function. Microsoft Support. https://support.microsoft.com/en-us/office/vlookup-function-0bbc8083-26fe-4963-8ab8-93a18ad188a1
- Walkenbach, J. (2015). Excel 2016 Power Programming with VBA. John Wiley & Sons.
- Alexander, M., & Kusleika, R. (2019). Excel 2019 Bible. John Wiley & Sons.
- Korol, J. (2018). Microsoft Excel 2019 Programming by Example with VBA, XML, and ASP. Mercury Learning and Information.