برمجة وتطويرتحليل البيانات

VBA: كيفية التحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة أخرى

دليل أكاديمي شامل يشرح كيفية التحقق من احتواء السلاسل النصية على نصوص فرعية في VBA باستخدام دالة InStr والتقنيات البديلة مع أمثلة عملية لتحليل البيانات.

Mohammed looti أكاديمي وباحث متخصص في علم النفس
تاريخ النشر
تمت المراجعة العلمية · د. مروة عبد العظيم · 12 سبتمبر، 2026
مراجعة وتدقيق علمي معتمد تاريخ التدقيق: 12 سبتمبر، 2026
د. مروة عبد العظيم دكتوراه
أستاذة علم النفس جامعة كربلاء
معايير التدقيق والاعتماد السريري

يخضع هذا المحتوى لمعايير ضبط الجودة والتدقيق العلمي والأكاديمي الصارمة في شبكة علم النفس العربي، لضمان صحة المعلومات ودقتها السريرية ومطابقتها لأحدث الأدلة والبراهين الصادرة عن الجمعيات النفسية والطبية المعتمدة (APA / WHO).

تُعد معالجة النصوص والتحقق من محتواها إحدى الركائز الأساسية التي تقوم عليها هندسة البرمجيات وأتمتة العمليات المكتبية في بيئات العمل الحديثة. وفي نظام مايكروسوفت إكسيل، الذي يمثل العمود الفقري لإدارة البيانات وتحليلها في المؤسسات حول العالم، تبرز لغة Visual Basic for Applications (VBA) كأداة قوية لتحويل جداول البيانات من مجرد سجلات ساكنة إلى بيئات حوسبية ديناميكية قادرة على اتخاذ القرارات ومعالجة كميات ضخمة من المعلومات غير المهيكلة. إن عملية التحقق مما إذا كانت سلسلة نصية معينة تحتوي على سلسلة نصية أخرى ليست مجرد عملية مقارنة بدائية؛ بل هي استعلام خوارزمي يتقاطع فيه فهم إدارة الذاكرة، وبنية البيانات النصية، وحساسية المحارف، مع كفاءة المعالجة الحسابية.

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

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

1. الأسس النظرية لمعالجة النصوص والبحث عن السلاسل الفرعية في بيئة VBA

1.1 مفهوم السلاسل النصية كبنى بيانات في Visual Basic for Applications

تُعرّف السلسلة النصية في النظرية الحاسوبية بأنها متتالية خطية مرتبة من الرموز المأخوذة من أبجدية محددة. ومن الناحية البرمجية داخل بيئة Microsoft Learn VBA، لا تقتصر السلسلة النصية على مجرد كونها صفاً بسيطاً من البايتات، بل تخضع لبنية هيكلية أكثر تعقيداً تُعرف تاريخياً في أنظمة ويندوز بنوع البيانات BSTR (Basic String)، وهو المعيار المعتمد ضمن معمارية كائنات أتمتة OLE Automation. يتكون نمط BSTR برمجياً من مؤشر ذاكري يشير إلى أول بايت من السلسلة المحرفية، ولكن يسبقه مباشرة في الذاكرة بادئة ذات طول أربعة بايتات (32 بت) تحتوي على قيمة عددية صحيحة تمثل الطول الدقيق للسلسلة بالبايت، ويُختتم النص بمحرف صفري مزدوج (Null Terminator). يمنح هذا التمثيل المعماري لغة VBA القدرة على معرفة الطول الإجمالي للنص بصورة فورية بزمن تعقيد خوارزمي ثابت قدره $O(1)$ عبر دالة Len، دون الحاجة إلى مسح السلسلة بأكملها بحثاً عن نهاية النص كما هو الحال في لغات برمجية أخرى مثل C.

تتعامل لغة VBA مع نوعين رئيسيين من السلاسل النصية: السلاسل ذات الطول الديناميكي (Variable-Length Strings) والسلاسل ذات الطول الثابت (Fixed-Length Strings). عند الإعلان عن سلسلة ديناميكية باستخدام الكلمة المحجوزة Dim str As String، فإن مفسر اللغة يخصص متغيراً في الذاكرة كحاوية للمؤشر، بينما تُدار المساحة الفعلية للنص في الذاكرة الديناميكية العامة (Heap) عبر استدعاءات نظام ويندوز مثل SysAllocStringLen وSysFreeString. هذه الطبيعة الديناميكية تعني أنه في كل مرة تُدمج فيها نصوص أو تُعدل، يُعاد تخصيص مساحة جديدة وتفريغ القديمة، مما يولد حملاً تشغيلياً خفياً يجب مراعاته عند التعامل مع نصوص ضخمة. أما السلاسل الثابتة، التي يُعلن عنها بتحديد الحجم مسبقاً (مثل Dim str As String * 30)، فتُخصص مساحتها مباشرة ضمن إطار المكدس (Stack) أو ككتلة ثابتة في الذاكرة، ويتم حشو الفراغات فيها بمسافات فارغة (Spaces) تلقائياً عند قصر النص المدخل.

تعتمد لغة VBA في تمثيلها الداخلي للنصوص على معيار الترميز المزدوج Unicode UTF-16 LE (Little Endian)، مما يعني أن كل محرف يشغل مساحة قدرها بايتان (16 بت). يضمن هذا النموذج قدرة اللغة على استيعاب المحارف الدولية المتعددة اللغات، بما فيها الحروف العربية والرموز الخاصة، دون تشويه بنيوي. ومن منظور تنقية البيانات وتدقيق الجودة، فإن التحقق من وجود سلسلة نصية داخل سلسلة أخرى يشكل الخطوة الأولى في تقييم مدى صحة البيانات؛ حيث يتيح للبرامج التنقيب في الحقول النصية غير المنظمة، وفصل المدخلات، وتطبيق قواعد التدقيق المنطقي الصارمة قبل ترحيل البيانات إلى مستودعات البيانات المؤسسية أو قواعد البيانات العلائقية.

1.2 تصنيف خوارزميات البحث والمطابقة في بيئات التطوير المكتبية

تتنوع خوارزميات البحث في السلاسل النصية من حيث درجة التعقيد والكفاءة التشغيلية تبعاً للمنهجية الرياضية المتبعة في فحص التطابق. في أبسط صورها، يعتمد محرك المطابقة على البحث الخطي الساذج (Naive String Search)، والذي يقوم بوضع السلسلة الفرعية المراد البحث عنها بمحاذاة السلسلة المستهدفة والبدء في مقارنة المحارف واحداً تلو الآخر من اليسار إلى اليمين. في حالة حدوث عدم تطابق عند محرف معين، يُزاح المؤشر بمقدار محرف واحد في السلسلة الأصلية، وتُعاد المقارنة من جديد من بداية السلسلة الفرعية. يتسم هذا المنهج بسهولة تنفيذه على مستوى النواة البرمجية، وتصل كفاءته الزمنية في أسوأ الحالات إلى تعقيد حوسبي قدره $O((N – M + 1) \times M)$، حيث يمثل $N$ طول السلسلة المستهدفة، بينما يمثل $M$ طول السلسلة الفرعية المراد البحث عنها.

على النقيض من البحث الخطي البسيط، طوّر علماء الحاسوب خوارزميات متقدمة للمطابقة تُجنب النظام تكرار فحص المحارف التي سبق التحقق منها، ولعل أشهر هذه الخوارزميات خوارزمية كنوث-موريس-برات (Knuth-Morris-Pratt) وخوارزمية بوير-مور (Boyer-Moore). تعتمد هذه الخوارزميات المتقدمة على مرحلة معالجة مسبقة للسلسلة الفرعية لإنشاء جدول إزاحات (Shift Table)، بحيث إذا واجه المحرك عدم تطابق عند محرف معين، يستطيع القفز بمؤشر البحث مسافة تتجاوز عدة محارف دفعة واحدة بناءً على البنية الداخلية للكلمة المفتاحية. وعلى الرغم من أن دوال البحث المدمجة في VBA تعتمد على استدعاءات منخفضة المستوى ومكتوبة بلغة C++ عالية التحسين لتنفيذ المطابقات، إلا أن فهم آلية عمل المؤشر الموضعي يبقى أمراً جوهرياً للمبرمج؛ فالمؤشر الداخلي يتتبع إحداثيات البايتات لتحديد الإزاحة الموضعية الصحيحة بدقة، مما يتيح استخراج المقاطع المحيطة أو تقسيم الجمل.

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

2. التحليل البنيوي والمعاملات التشغيلية لدالة InStr

2.1 الصيغة العامة لدالة InStr وتفكيك معاملاتها

تمثل دالة InStr حجر الزاوية والأداة القياسية الأولى في VBA المخصصة لاكتشاف مواقع السلاسل النصية الفرعية ضمن نصوص أخرى. تأتي تسمية الدالة اختصاراً لعبارة “In String”، وتقوم وظيفتها الرياضية على مسح سلسلة نصية والبحث عن أول ظهور لنص فرعي، لتعيد بعد ذلك رقماً صحيحاً من نوع Long يمثل الفهرس الموضعي لأول محرف في ذلك النص الفرعي المكتشف. تتميز الدالة بمرونة تركيبية؛ حيث تمتلك صيغة عامة تتألف من أربعة معاملات رئيسية تتبع الترتيب التالي:

InStr([Start], String1, String2, [Compare])

يُعد المعامل الأول، Start، معاملاً اختيارياً في حال إسقاط معامل المقارنة، ولكنه يصبح إجبارياً في حال الرغبة في تحديد وضعية المقارنة Compare. يُحدد هذا المعامل نقطة الانطلاق الفهرسية داخل السلسلة المستهدفة؛ فإذا كانت قيمته 1 (وهي القيمة الافتراضية عند الحذف)، يبدأ البحث من المحرف الأول للنص. أما إذا حُددت قيمة أكبر، ولتكن 5 على سبيل المثال، فإن مفسر VBA سيتجاهل تماماً المحارف الأربعة الأولى ويبدأ المسح الموضعي انطلاقاً من المحرف الخامس، ومع ذلك، فإن الفهرس النهائي المعاد يُحسب دائماً بالرجوع إلى البداية المطلقة للسلسلة الأصلية وليس انطلاقاً من نقطة البدء الجزئية.

يمثل المعامل الثاني، String1، السلسلة النصية الحاضنة أو المستهدفة بالبحث (Haystack)، وهي السلسلة الأكبر التي يُفترض أنها تحتوي على المعلومة المطلوبة. أما المعامل الثالث، String2، فيمثل السلسلة النصية الفرعية المبحوث عنها (Needle)، وهي السلسلة الأقصر التي يُراد إثبات وجودها وتحديد موقعها. وأخيراً، يتيح المعامل الاختياري الرابع، Compare، ضبط المعيار الميكانيكي للمقارنة، والذي يحدد ما إذا كانت العملية ستتم عبر مطابقة ثنائية صارمة للبتات أم مطابقة لغوية متساهلة مع حالة الأحرف اللاتينية، وهو ما سيتم تفصيله لاحقاً.

2.2 حالات المخرجات الرياضية والمنطقية لدالة InStr

تُرجع دالة InStr قيماً عددية دقيقة تعكس بصورة قاطعة الحالة المنطقية لعملية البحث والمطابقة، ويمكن تصنيف هذه المخرجات استناداً إلى الشروط الحدودية للمدخلات على النحو التالي:

  • قيمة عددية صحيحة موجبة ($> 0$): تدل دلالة يقينية على العثور على السلسلة الفرعية String2 داخل String1، ويمثل الرقم المعاد رقم المحرف الدقيق الذي تبدأ عنده السلسلة الفرعية بالاعتماد على الترقيم الأحادي (1-based indexing) المعتمد في VBA.
  • القيمة صفر ($0$): تدل على عدم نجاح عملية المطابقة نهائياً؛ ويعني ذلك إما أن السلسلة الفرعية غير موجودة إطلاقاً ضمن النص الحاضن، أو أن قيمة معامل البداية Start كانت أكبر رياضياً من الطول الكلي للسلسلة المستهدفة String1، مما منع المحرك من مسح أي محرف.
  • حالة السلسلة المستهدفة الفارغة: إذا كانت السلسلة String1 عبارة عن سلسلة صفرية الطول (تساوي "" أو vbNullString)، تُرجع الدالة القيمة صفر فوراً وبشكل حتمي، حيث يستحيل منطقياً العثور على أي عنصر ضمن مجموعة خالية.
  • حالة السلسلة الفرعية الفارغة: إذا كانت السلسلة الفرعية String2 فارغة بطول صفري، فإن الدالة تُرجع قيمة المعامل Start ذاتها، نظراً لأن الفراغ متضمن رياضياً عند كل موضع نصي.
  • حالة القيمة المجهولة (Null): إذا احتوى أي من المعاملين String1 أو String2 على قيمة مجهولة حقيقية (Null مشتقة من حقول قواعد البيانات أو متغيرات نوع Variant)، فإن الدالة تُرجع Null تلقائياً وفقاً لقواعد الجبر المنطقي الثلاثي.

نظراً لأن لغة VBA لا تتضمن دالة صريحة ذات عائد منطقي مثل Contains الموجودة في لغات برمجية حديثة كـ C# أو Java، فإن الممارسات البرمجية الرصينة تقتضي تحويل هذا المخرج العددي إلى تعبير شرطي منطقي (Boolean Expression). يتحقق ذلك عن طريق مقارنة ناتج دالة InStr بالصفر؛ فإذا كتب المطور الشرط على الهيئة: If InStr(1, SourceString, SearchString) > 0 Then، فإن الشرط يُقيّم منطقياً إلى True في حال الوجود الفعلي للنص الفرعي، وإلى False في حال انعدامه، مما يجعلها البنية الأكثر شيوعاً واعتماداً في تدفقات التحكم المنطقي للمشاريع المؤسسية.

3. أنماط المقارنة وضبط حساسية حالة الأحرف في VBA

3.1 المقارنة الثنائية مقابل المقارنة النصية (vbBinaryCompare vs vbTextCompare)

تعتمد كيفية تقييم النصوص وتطابقها في VBA بصورة مباشرة على الثابت البرمجي المستخدم في معامل المقارنة Compare، حيث تنقسم عمليات الفحص إلى مستويين متمايزين جوهرياً: المقارنة الثنائية (Binary Compare) والمقارنة النصية (Textual Compare). في نمط المقارنة الثنائية، الممثل برمجياً بالثابت vbBinaryCompare (وقيمته العددية 0)، يتم فحص النصوص بالاستناد الصارم إلى القيم الرقمية للرموز وفق جدول ترميز ASCII وUnicode. وبما أن الحرف اللاتيني الكبير “A” يحمل القيمة الرقمية 65، بينما يحمل الحرف الصغير “a” القيمة الرقمية 97، فإن المحرك الثنائي يعتبرهما محرفين متباينين تماماً؛ وبالتالي يفشل البحث عن “excel” داخل سلسلة تحتوي على “Excel” عند تفعيل هذا النمط.

في المقابل، صُمم نمط المقارنة النصية، الممثل بالثابت البرمجي vbTextCompare (وقيمته العددية 1)، لإجراء مطابقة لغوية غير حساسة لحالة الأحرف (Case-Insensitive). في هذا الوضع، يلجأ مفسر VBA إلى استدعاء جداول المقارنة اللغوية المضمنة في نظام التشغيل بالاعتماد على الإعدادات الإقليمية (Locale ID)، حيث يُعامل الحرفان “A” و”a” ككيان متطابق وظيفياً. ولا يقتصر تأثير هذا النمط على الحروف اللاتينية فحسب، بل يمتد إلى بعض الحالات الخاصة في اللغات الأخرى والتشكيلات الصوتية.

من الضروري جداً إدراك أن السلوك الافتراضي لدالة InStr عند إسقاط معامل المقارنة يخضع مباشرة لتوجيهات الوحدة النمطية، وتحديداً إعلان Option Compare الموجود في السطر الترويسي لملف الكود البرمجي (Module). فإذا احتوت الترويسة على Option Compare Binary (وهو الوضع الافتراضي إذا لم يُحدد خلاف ذلك)، فإن كافة الدوال النصية ستعمل بأسلوب الفحص الثنائي الصارم. أما إذا كُتب Option Compare Text في أعلى الوحدة، فإن جميع عمليات المقارنة الموضعية والدوال النصية ستتحول تلقائياً إلى النمط غير الحساس لحالة الأحرف، ما لم يتم تجاوز ذلك يدوياً بتمرير الثابت صراحة داخل استدعاء الدالة.

3.2 توحيد حالة الأحرف باستخدام دوال التحويل القياسية

على الرغم من مرونة استخدام الثابت vbTextCompare لتجاوز عقبة حساسية الأحرف، يلجأ كبار مهندسي البرمجيات في بيئات VBA في كثير من الأحيان إلى أسلوب معماري بديل يتمثل في تطبيع النصوص يدوياً (Data Normalization) باستخدام دوال التحويل القياسية مثل LCase أو UCase، مصحوبة بالمقارنة الثنائية. يقوم هذا الأسلوب على تحويل كل من السلسلة الحاضنة والسلسلة المبحوث عنها إلى أحرف صغيرة بالكامل (Lower Case) أو أحرف كبيرة بالكامل (Upper Case) قبل إجراء الفحص الموضعي، كما في الصيغة التوضيحية:

InStr(1, LCase(SourceString), LCase(SearchString), vbBinaryCompare)

ينبع تفضيل هذا الأسلوب المنهجي من بعدين رئيسيين: الأداء الحوسبي والاستقرار العابر للبيئات. من ناحية الأداء، يُعد الفحص الثنائي vbBinaryCompare أسرع ميكانيكياً على مستوى دورات المعالج المركزي مقارنة بالفحص اللغوي vbTextCompare؛ وذلك لأن المقارنة الثنائية تنحدر إلى مستوى تعليمات المقارنة المباشرة للبايتات في الذاكرة (Memory Byte-to-Byte Comparison)، في حين يتطلب الفحص اللغوي الرجوع إلى معايير الترتيب الإقليمية والتحقق من أوزان المحارف. وعلى الرغم من أن استدعاء دالتي LCase ينشئ سلاسل نصية مؤقتة في الذاكرة مما يستهلك جزءاً طفيفاً من الموارد، إلا أن تنفيذه على كميات بيانات محددة مقترناً بالمقارنة الثنائية يوفر اتساقاً مطلقاً في النتائج يتفادى أي تقلبات سلوكية قد تفرضها إعدادات اللغة الإقليمية لنظام التشغيل المضيف (Operating System Locale Settings).

4. التطبيق العملي: استخراج وتصفية البيانات في جداول إكسيل

4.1 بناء إجراءات التكرار الحلقي لفحص النطاقات النصية

يمثل التفاعل المباشر مع أوراق عمل ميكروسوفت إكسيل جوهر التطبيقات العملية للغة VBA؛ حيث تظهر الحاجة الملحة لفحص آلاف الخلايا والتحقق من تضمنها لمصطلحات معينة بغرض التصفية، والتجميع، والتصنيف المالي أو التشغيلي. يتطلب البناء المعماري للإجراءات التي تتعامل مع النطاقات استخدام حلقات التكرار مثل For...Next أو Do While للمرور المنظم على عناصر الكائن Range.

يبدأ الإجراء العملي الموثوق بحساب أبعاد النطاق المستهدف بصورة ديناميكية لتفادي الترميز الصلب لأرقام الصفوف (Hard-coding)، وذلك بالاعتماد على خصائص مثل Cells(Rows.Count, "A").End(xlUp).Row لتحديد آخر صف مأهول بالبيانات. ومن ثم، يُخصص مؤشر حلقي (Loop Index) يتحرك صفاً تلو الآخر عبر العمود المراد اختباره، بينما يقوم مؤشر كتابة منفصل بتتبع مواضع تصدير السجلات التي تلبي شرط الاحتواء إلى ورقة عمل أخرى أو نطاق مستقل، كما هو مبين في المعمارية المنطقية لمعالجة مصفوفات الخلايا.

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

4.2 شرح وتحليل كود تصفية أسماء الفرق الرياضية

لتجسيد هذا المفهوم بصورة عملية موسعة، نفترض وجود جدول يحتوي على بيانات مباريات رياضية في ورقة عمل باسم “MatchData”، حيث يتضمن العمود A أسماء المواجهات المكتوبة كنصوص مدمجة (مثل “Arsenal vs Chelsea” أو “Liverpool vs Manchester City”)، والمطلوب استخلاص جميع المباريات التي يشارك فيها فريق محدد وليكن “Arsenal” وترحيل كامل السجل التابع له إلى ورقة عمل جديدة تسمى “FilteredResults”. يتم بناء الكود النموذجي لهذا الإجراء البرمجي استناداً إلى التحليل التركيبي التالي:

يبدأ الإجراء بالإعلان الصارم عن المتغيرات باستخدام التوجيه Option Explicit، فيُخصص متغير lastRow As Long لتحديد نهاية البيانات، ومتغير targetRow As Long لتعقب صف الكتابة الجديد في ورقة النتائج، ومتغيرات كائنات من نوع Worksheet للإشارة الصريحة للمصنفات. تتشكل النواة الصلبة لهذا الكود من البنية الشرطية المتكررة:

If InStr(1, LCase(wsSource.Cells(i, 1).Value), LCase(searchTerm), vbBinaryCompare) <> 0 Then

تجري معالجة هذا السطر عبر مراحل تقييم تتابعية حاسمة: أولاً، تُستخلص القيمة النصية من الخلية الحالية عبر الخاصية .Value، وتُمرر إلى دالة LCase لتحويلها إلى صيغة الأحرف الصغيرة تماماً والتخلص من أي تفاوتات ناتجة عن إدخال الأسماء بحروف كبيرة أو صغيرة. ثانياً، يُحول مصطلح البحث searchTerm إلى صيغة الأحرف الصغيرة بالتوازي. ثالثاً، تبدأ دالة InStr بالمسح انطلاقاً من الموضع الفهرسي رقم 1 بالاعتماد على الفحص الثنائي الصارم للبايتات. رابعاً، يقوم المعامل العلائقي <> 0 باختبار النتيجة؛ فإذا أعادت الدالة أي قيمة موجبة تزيد عن الصفر، يتم استيفاء الشرط، وينتقل تدفق التنفيذ لنسخ محتويات الصف المطابق بالكامل باستخدام التعليمات wsTarget.Rows(targetRow).Value = wsSource.Rows(i).Value، مع زيادة مؤشر الإخراج targetRow = targetRow + 1. إن توثيق هذه الأكواد بالتعليقات التفصيلية يرفع من موثوقيتها ويسمح للفرق الهندسية بتعديل قواعد المطابقة مستقبلاً دون الإخلال بسلامة البنية الأساسية.

5. البحث العكسي وتحديد المواقع باستخدام دالة InStrRev

5.1 المعمارية الوظيفية لدالة InStrRev واختلافها عن InStr

تُعد دالة InStrRev التوأم التناظري لدالة InStr، حيث صُممت خصيصاً للتعامل مع متطلبات البحث العكسي (Reverse Search) عبر مسح السلسلة النصية انطلاقاً من نهايتها والتحرك نحو بدايتها. على الرغم من أن الهدف النهائي يظل محصوراً في إيجاد تطابق لسلسلة فرعية، إلا أن المعمارية التشغيلية لـ InStrRev تختلف في جانبين بنيويين في غاية الأهمية: ترتيب تمرير المعاملات في شفرة الاستدعاء، وطريقة تفسير موقع البداية. تأتي الصيغة التركيبية لدالة InStrRev على النحو التالي:

InStrRev(StringCheck, StringMatch, [Start], [Compare])

يلاحظ المطور المتمرس فوراً أن ترتيب المعاملات النصية الأساسية في هذه الدالة مقلوب مقارنة بدالة InStr؛ فالسلسلة النصية الحاضنة المراد فحصها تُمرر أولاً كمعامل StringCheck، تليها السلسلة الفرعية المبحوث عنها كمعامل StringMatch، في حين كان العكس تماماً هو المتبع في InStr. يُعد هذا التباين مصدراً شائعاً للأخطاء البرمجية للمطورين الذين يخلطون بين التوقيعين البرمجيين (Function Signatures).

أما بالنسبة للمعامل الاختياري Start، فإنه يحمل قيمة افتراضية قدرها -1، والتي تعني لمفسر اللغة: “ابدأ المسح من المحرف الأخير في السلسلة الحاضنة”. وإذا مرر المطور رقماً محدداً، فإن المسح التراجعي يبدأ من ذلك الموضع متجهاً جهة اليسار نحو بداية النص. ولكن السمة الرياضية الجوهرية التي يجب التشديد عليها هي أن القيمة الفهرسية الناتجة عن دالة InStrRev تُحسب دائماً كإزاحة مطلقة من بداية السلسلة النصية (المحرف الأول على اليسار) تماماً مثل دالة InStr، وليس كإزاحة من النهاية. وبناءً على ذلك، تعيد الدالة موقع أول تطابق تصادفه أثناء رحلتها العكسية، والذي يمثل عملياً “آخر ظهور” لتلك الكلمة أو الرمز داخل النص الأصلي.

5.2 التطبيقات العملية للبحث التراجعي في معالجة النصوص

تتجلى القوة الهندسية لدالة InStrRev في المهام التي تتطلب استخلاص معلومات هيكلية تقع في أواخر السلاسل النصية المركبة. ومن أشهر هذه النماذج في بيئات تكنولوجيا المعلومات هو تحليل مسارات الملفات (File Path Parsing) واستخراج امتداداتها؛ فعند التعامل مع مسار نظام ملفات ويندوز مثل:

C:CorporateDataFinanceAnnualReportsQ4_Audit_Report.xlsx

يرغب المطور غالباً في استخراج اسم الملف بمفرده وعزله عن المسار المجلدي الكامل. إذا استُخدمت دالة InStr العادية للبحث عن رمز الشرطة المائلة العكسية (Backslash )، فإنها ستعيد موضع أول فاصل بعد محرك الأقراص مباشرة. لكن بالاعتماد على دالة InStrRev(filePath, "")، فإن الدالة ترجع موقع آخر شرطة مائلة تفصل اسم الملف عن مجلده الحاضن فوراً. وبدمج هذه النتيجة مع دالة الاقتطاع الأيمن Mid أو Right، يتمكن البرنامج من فصل المسار عن اسم الملف بعملية حسابية واحدة لا تتطلب كتابة أي حلقات تكرارية معقدة.

ينطبق الأمر ذاته على عزل الامتدادات عبر البحث العكسي عن نقطة الفصل (.)، والتعامل مع معلمات الروابط التشعبية (URL Parameters). علاوة على ذلك، يمثل التكامل الهجين بين دالتي InStr وInStrRev تقنية مثالية لتقسيم النصوص المحصورة بين وسمين (Delimiters) متباعدين؛ حيث يمكن استخدام الدالة الأولى للوصول إلى موضع وسم الفتح، واستخدام الدالة الثانية لتحديد موقع وسم الإغلاق الأخير، مما يسهل عملية استخلاص النصوص الواقعة في القلب بدقة رياضية متناهية.

6. مطابقة الأنماط كبديل مرن باستخدام معامل Like

6.1 البنية التركيبية لمعامل Like وقواعد بناء الأنماط

يوفر معامل Like في بيئة VBA أداة لغوية متخصصة ومدمجة في صلب النواة التركيبية للغة لإجراء مقارنات نصية مرنة تعتمد على مطابقة الأنماط البدائية (Wildcard Pattern Matching)، محاكياً بذلك بعض قدرات التعبيرات النمطية ولكن بصيغة مبسطة وسهلة الاستيعاب. على خلاف دوال البحث الموضعي التي تُرجع أرقاماً فهرسية، يُعد معامل Like معاملاً منطقياً ثنائياً (Binary Logical Operator) يربط بين تعبيرين نصيين، ويكون ناتجه دائماً قيمة بوليانية صريحة: إما True أو False. تتمثل الصيغة التعبيرية لهذا المعامل في:

result = stringToTest Like pattern

ترتكز مرونة هذا المعامل على مجموعة من الرموز الخاصة التي تُبنى بها قواعد الأنماط النصية، ونوجز هذه الرموز الحاكمة فيما يلي:

  • الرمز النجمي (*): يطابق أي عدد من المحارف المتتالية، بدءاً من صفر من المحارف (سلسلة فارغة) وصولاً إلى أي طول نصي ممكن. فعلى سبيل المثال، النمط "*Tax*" يتحقق من احتواء النص على كلمة “Tax” في أي موضع، سواء كانت في البداية، أو الوسط، أو النهاية.
  • علامة الاستفهام (?): تطابق محرفاً فردياً واحداً بدقة متناهية وفي موقع محدد؛ فالنمط "A?C" يطابق “ABC” و”A1C”، ولكنه يفشل في مطابقة “ABBC” لتجاوزها الطول الفردي المحدد.
  • رمز الهاشتاغ (#): يطابق أي خانة رقمية مفردة تقع حصراً بين المجال [0-9]، وهو مفيد جداً في تدقيق الأرقام التسلسلية والشفرات البريدية.
  • الأقواس المعقوفة ([charlist]): تتيح بناء مجموعات محارف مخصصة؛ حيث يطابق التعبير أي محرف فردي ينتمي إلى القائمة المحصورة داخل القوسين. يمكن تحديد نطاقات رقمية أو أبجدية داخلها مثل [A-Z] أو [0-9].
  • نفي المجموعات ([!charlist]): بإضافة علامة التعجب داخل الأقواس المعقوفة، تنعكس المطابقة لتستهدف أي محرف لا ينتمي للمجموعة المحددة، مما يتيح استبعاد فئات محددة من الرموز.

6.2 مقارنة منهجية بين دالة InStr ومعامل Like

تتطلب الهندسة البرمجية المقارنة الدقيقة بين البدائل التقنية لاختيار الأداة المثلى لكل سيناريو عملي. عند الموازنة بين دالة InStr ومعامل Like، يبرز التباين الأساسي في الغرض الوظيفي: فدالة InStr هي أداة استعلام موضعي وظيفي صُممت للإجابة عن سؤال: “أين تقع السلسلة وما هو فهرسها؟”، في حين يركز معامل Like على الإجابة المنطقية المجردة: “هل يطابق النص ككل هذا النمط البنيوي؟”.

من زاوية الكفاءة الحاسوبية وسرعة التنفيذ، تتفوق دالة InStr بوضوح في سيناريوهات البحث عن سلاسل فرعية ثابتة ومحددة بدقة (Literal Substrings). يُعزى ذلك إلى أن محرك InStr يعمل عبر خوارزمية بحث مباشر منخفضة المستوى تكتفي بالتحقق من تقارب البايتات دون الحاجة إلى معالجة شجرة قرارات أو تتبع حالات متعددة للأنماط. أما معامل Like، فيتطلب تحليلاً نحويّاً إضافياً لقالب النمط (Pattern Parsing) وتخصيص آلة حالات محدودة لمطابقة الرموز النجمية والأقواس، مما يجعله أبطأ نسبياً في استهلاك دورات المعالج عند تكراره ضمن مئات الآلاف من الدورات الحلقية.

ومع ذلك، تبرز القيمة الاستثنائية لمعامل Like عند تعقيد شروط المطابقة؛ فإذا كان المطلوب هو التحقق من أن الخلية تحتوي على كلمة تبدأ بحرف “D” وتتبعها ثلاثة أرقام عشوائية ثم تنتهي بـ “XYZ”، فإن تحقيق هذا الشرط باستخدام دالة InStr يتطلب كتابة أكواد متداخلة ومطولة تستدعي دوال Mid وIsNumeric وغيرها. بينما يُنجز معامل Like نفس التحقق في سطر برمجي وحيد وأنيق: If cell.Value Like "*D###XYZ*" Then. وبذلك تصبح المفاضلة قائمة على توازن هندسي بين الرغبة في الأداء المطلق للبحث الثابت البسيط (حيث تنتصر InStr)، وبين المرونة التعبيرية للأشكال التركيبية المتغيرة (حيث يكتسح معامل Like).

7. التحقق المتقدم وتطابق النصوص عبر التعابير النمطية (VBScript.RegExp)

7.1 تفعيل وتكوين كائن مكتبة التعابير النمطية في بيئة VBA

عندما تصل متطلبات التدقيق والتحقق النصي إلى مستويات عالية من التعقيد، تظهر محدودية الدوال القياسية ومعاملات المطابقة البسيطة، مما يفرض الانتقال إلى استخدام التعابير النمطية Regular Expressions. لا تحتوي بيئة VBA على محرك تعابير نمطية أصيل مضمن في مكتبتها القياسية، ولكنها تستعين بمكتبة النظام الخارجية المتمثلة في مكتبة كائنات بيئة الفيجوال بيسك سكريبت: Microsoft VBScript Regular Expressions 5.5 عبر معمارية الربط الكائني COM.

يمكن تفعيل هذا المحرك المتقدم بإحدى طريقتين هندسيتين:

  • الربط المبكر (Early Binding): يتم فيه إضافة مرجع المكتبة صراحة عبر قائمة الإشارات في شاشة محرر الأكواد (Tools -> References -> Microsoft VBScript Regular Expressions 5.5). يتيح هذا الأسلوب دعماً كاملاً لميزة الإكمال التلقائي (IntelliSense)، وتدقيق الأنواع أثناء الترجمة المبدئية، وتحقيق سرعة تشغيلية أعلى عند إنشاء الكائنات. يُعلن عنه برمجياً عبر: Dim regEx As New RegExp.
  • الربط المتأخر (Late Binding): يتم فيه إنشاء الكائن ديناميكياً في الذاكرة أثناء وقت التشغيل الفعلي للبرنامج دون إلزام المستخدم بتفعيل أي مراجع مسبقة، وذلك باستخدام الدالة: Set regEx = CreateObject("VBScript.RegExp"). يُعد هذا النموذج هو الأفضل والأكثر أماناً عند توزيع قوالب إكسيل المؤسسية بين أجهزة متعددة لضمان عدم حدوث أخطاء فقدان المراجع (Broken References).

عقب تهيئة الكائن في الذاكرة، يتحكم المطور في سلوك المحرك من خلال ضبط أربع خصائص هيكلية جوهرية:

  • Pattern: السلسلة النصية التي تُكتب فيها شفرة التعبير النمطي، وهي التي تحدد القواعد المنطقية الرياضية للمطابقة.
  • IgnoreCase: خاصية منطقية (Boolean)، تُضبط على True لتجاهل حساسية الأحرف الكبيرة والصغيرة، أو False لإلزام المحرك بالتحقق الدقيق.
  • Global: خاصية منطقية تحدد ما إذا كان البحث سيتوقف فور العثور على أول تطابق مفرد (False)، أم سيستمر لمسح السلسلة بالكامل واصطياد كافة مرات الظهور (True).
  • MultiLine: خاصية منطقية تُعدل سلوك محددات البداية والنهاية (^ و $) لتتعامل مع السلاسل التي تحتوي على فواصل أسطر مبرمجة ككتل نصية متعددة بدلاً من سطر واحد مستمر.

7.2 تنفيذ الفحص والاستخراج باستخدام دالتي Test وExecute

يمنح كائن RegExp المطور وسيلتين رئيسيتين للتفاعل مع السلاسل النصية: الدالة المنطقية Test والدالة التنقيبية Execute. تعمل دالة Test بمثابة اختبار فحص سريع وخفيف الأحمال الحوسبية؛ حيث تأخذ السلسلة النصية المراد فحصها كمعامل وحيد وترجع ناتجاً منطقياً سريعاً True إذا كان النمط متضمناً في أي جزء من السلسلة، أو False إذا عجز المحرك عن إيجاده، تماماً كما هو الحال في:

isValid = regEx.Test(sourceText)

أما دالة Execute، فهي الميثود المسؤول عن جلب البيانات وتفكيكها؛ حيث تقوم بعملية مسح شاملة وتعيد كائناً تجميعياً متخصصاً يُعرف بـ MatchCollection. يحتوي هذا الكائن التجميعي على مجموعة من كائنات Match المستقلة، بحيث يمثل كل كائن منها ظهوراً ناجحاً للتطابق. يوفر كائن التطابق الفردي خصائص تحليلية دقيقة مثل Value (النص الفعلي المستخلص)، وFirstIndex (موضع البداية الصفرية للمقطع المطابق داخل النص الأصلي)، وLength (طول المقطع المكتشف).

تتضح القوة التشغيلية للتعابير النمطية في قدرتها الفائقة على معالجة البيانات النصية غير المنمطة، مثل استخراج عناوين البريد الإلكتروني عبر النمط "[w.-]+@[w.-]+.w+"، أو التحقق من أرقام الهواتف المحمولة الدولية، أو فك تشفير البيانات المشفرة والرموز الضريبية (Tax Identification Numbers) من حقول الملاحظات العشوائية. إن هذا المستوى من التحليل يتجاوز بمراحل ما يمكن أن تقدمه الدوال القياسية، مما يجعل التعابير النمطية جزءاً لا يتجزأ من ترسانة المطور في عمليات هندسة البيانات المتقدمة.

8. معالجة الحالات الاستثنائية والوقاية من الأخطاء البرمجية الشائعة

8.1 إدارة القيم الفارغة والبيانات المفقودة (Null وEmpty)

تُعد بيئة VBA بيئة تعامل صارمة مع الأنواع المتعددة للبيانات غير المعرفة، ومن أبرز الأخطاء القاتلة التي تواجه المطورين عند فحص السلاسل النصية حدوث الخطأ البرمجي الشهير: Type Mismatch (Error 13). ينشأ هذا الخطأ في الغالب عند قراءة محتويات خلية في إكسيل تحتوي على خطأ صيغة مسبق (مثل #N/A أو #VALUE!)، أو عند التعامل مع قواعد بيانات علائقية تُرجع قيماً مجهولة حقيقية من النوع Null.

من الناحية النظرية، يقبل معامل السلسلة في دالة InStr تمرير متغيرات نصية صريحة، ولكن إذا كان المتغير المستهدف من نوع Variant ومحمل بقيمة Null، فإن دالة InStr لن تنهار بل ستعيد ناتجاً من نوع Null. المشكلة الكبرى تقع عندما يحاول المطور تقييم هذا الناتج مباشرة ضمن مقارنة شرطية مثل: If InStr(...) > 0 Then؛ ففي الجبر المنطقي لـ VBA، تؤدي مقارنة أي قيمة مع Null إلى إنتاج Null آخر بدلاً من قيمة بوليانية صريحة، مما يعطل بنية الشروط ويؤدي إلى انهيار غير متوقع أو اتخاذ مسارات خاطئة في تنفيذ البرنامج.

للوقاية المنهجية من هذه الاختناقات البرمجية، ينبغي اتباع هندسة الفحص المسبق واستخدام التحويل الآمن للمدخلات. يُنصح دائماً باستخدام الدالة IsNull() والدالة IsEmpty() للتأكد من الحالة الذاكرية للمدخلات قبل الدفع بها إلى دوال البحث. وعلاوة على ذلك، يُستخدم التكنيك الشهير المتمثل في دمج سلسلة نصية فارغة مع القيمة المستخلصة: CStr(cell.Value & "")؛ يضمن هذا الدمج السريع تحويل القيم الصفرية وEmpty بأمان إلى سلسلة نصية بطول صفر دون التسبب في أخطاء توافق الأنواع، مما يحافظ على استمرارية التدفق البرمجي حتى في أسوأ حالات تلوث البيانات.

8.2 معالجة الأخطاء التشغيلية وحالات الفهرسة الشاذة

تتعدد السيناريوهات الشاذة التي قد تقود الدوال النصية إلى الانهيار التشغيلي، ويأتي في مقدمتها التمرير الخاطئ لقيم معامل البداية Start في دالتي InStr وInStrRev. تفرض القواعد المعمارية للدالة أن تكون قيمة هذا المعامل رقماً صحيحاً موجباً أكبر قطيعاً من الصفر ($Start ge 1$). في حال تمرير قيمة سالبة أو صفرية إلى هذا المعامل، يُطلق مفسر VBA فوراً استثناء تشغيلياً برقم Invalid Procedure Call or Argument (Error 5)، وهو خطأ يوقف تنفيذ الإجراء بالكامل إن لم يكن محاطاً ببنية معالجة استثناءات محكمة.

تقتضي أفضل الممارسات البرمجية هندسة مسارات آمنة عبر أوامر On Error GoTo ErrorHandler لضمان التقاط مثل هذه الانحرافات وإعادة تعيين موارد النظام في حال حدوث أي طارئ. وإلى جانب المعاملات الرقمية، تمثل الفراغات المخفية والمحارف غير المرئية أحد أكثر أسباب الفشل الصامت لعمليات البحث النصي؛ حيث تفشل دالة InStr في العثور على كلمة “Sales” إذا كانت السلسلة المستهدفة تحتوي في الواقع على محرف المسافة الصلبة غير المنكسرة (Non-Breaking Space الممثلة برمز ASCII 160)، والتي غالباً ما تتسلل إلى جداول البيانات عند نسخها من صفحات الإنترنت وتطبيقات الويب.

يقضي الحل الهندسي لهذه المعضلة بتأسيس مرحلة تنظيف تمهيدية (Sanitization Phase) للنصوص المستهدفة قبل تطبيق خوارزميات البحث. يشمل ذلك استخدام دالة Trim القياسية لإزالة الفراغات المبتدئة والمنتهية، مصحوبة باستدعاء دالة Replace لتحويل المسافات الخاصة (ASCII 160) إلى مسافات عادية (ASCII 32)، وتطبيق دالة WorksheetFunction.Clean للتخلص من محارف التحكم المنطقية ومحارف فواصل الأسطر غير المرئية، مما يضمن خضوع النصوص لعملية الفحص في بيئة معيارية نظيفة وشفافة.

9. تحسين الأداء البرمجي في معالجة مصفوفات البيانات الضخمة

9.1 تخزين البيانات في مصفوفات الذاكرة وتفادي القراءة المباشرة من الخلايا

عند كتابة أكواد VBA للتعامل مع بيئات الأعمال المؤسسية، يصطدم المطورون في كثير من الأحيان ببطء التنفيذ الشديد عند فحص آلاف الصفوف في جداول البيانات. إن المصدر الأساسي لهذا البطء ليس خوارزمية البحث الموضعي لدالة InStr بحد ذاتها، بل هو التكلفة التشغيلية العالية لعملية العبور بين طبقة بيئة الكود (VBA Engine) وطبقة واجهة تطبيق إكسيل (Excel COM Interface). في كل مرة يستدعي فيها الكود خاصية قراءة خلية مفردة عبر Range("A" & i).Value، تُنشأ إشارة اتصال ثقيلة عبر جسر COM، وعندما تتكرر هذه العملية مئات الآلاف من المرات، يتحول البرنامج إلى عنق زجاجة حوسبي هائل.

يكمن الحل الهندسي الجذري لهذه المشكلة في نقل البيانات دفعة واحدة إلى الذاكرة العشوائية السريعة عبر تقنية مصفوفات الذاكرة (Memory Arrays). يتيح نظام VBA تفريغ محتويات نطاق كامل من الخلايا داخل متغير واحد من نوع Variant في تعليمة واحدة سريعة، كما في الشكل التالي:

Dim dataBuffer As Variant: dataBuffer = Range("A1:A500000").Value

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

9.2 تعطيل محركات التحديث التلقائي أثناء تنفيذ عمليات البحث الكثيفة

بالتوازي مع استخدام مصفوفات الذاكرة، تمتلك بيئة إكسيل مجموعة من المحركات الداخلية النشطة التي تراقب باستمرار كل تعديل يطرأ على ورقة العمل؛ وتشمل هذه المحركات: محرك إعادة رسم الواجهة وتحديث الرؤية، ومحرك إعادة الحساب التلقائي للمعادلات، ومحرك رصد أحداث المصحف والتطبيق. إذا لم يتم تعطيل هذه المحركات أثناء تنفيذ برمجيات البحث المكثفة، فإن إكسيل سيحاول استهلاك موارده في تحديث العناصر المرئية وإعادة جدولة الحسابات مع كل خطوة، مما يرهق المعالج بصورة لا مبرر لها.

تتطلب المعايير المعمارية للمطور المحترف تطويق إجراءات المعالجة الكبرى بكود حماية للأداء، يتكون من ثلاث ركائز تشغيلية:

  • Application.ScreenUpdating = False: تعمل هذه التعليمة على تجميد الرسوميات لواجهة إكسيل وإيقاف إعادة رسم الخلايا والشاشات حتى اكتمال المعالجة بالكامل، مما يوفر جهداً حوسبياً كبيراً كان يُهدر في معالجة واجهة المستخدم الرسومية.
  • Application.Calculation = xlCalculationManual: توقف هذه التعليمة عملية إعادة حساب كافة المعادلات والصيغ الرياضية المتواجدة في المصنف، وتمنع تشغيل الدوال التابعة في كل مرة تتغير فيها خلية واحدة، إلى أن يتم الانتهاء واستعادة الوضع التلقائي.
  • Application.EnableEvents = False: تحجب هذه التعليمة إطلاق الأحداث المبرمجة مسبقاً (مثل Worksheet_Change)، مما يمنع الأكواد الفرعية من مقاطعة مسار البحث الأساسي والدخول في حلقات تنفيذ لا نهائية أو استدعاءات تعسفية.

من الأهمية بمكان الالتزام بتضمين هذه التوجيهات ضمن كتلة Finally أو في قسم معالجة الأخطاء النهائي لضمان إعادة تشغيل هذه المحركات الحيوية ووضعها في حالتها الطبيعية (True و xlCalculationAutomatic) قبل إنهاء الإجراء البرمجي، حتى وإن تعرض البرنامج لخطأ عارض في منتصف المعالجة.

10. تطوير دوال مخصصة (UDF) للتحقق من النصوص واستخدامها في أوراق العمل

10.1 تصميم دالة التحقق المنطقية وتحديد مدخلاتها ومخرجاتها

تُعد الدوال المخصصة التي يطورها المستخدم، والمعروفة برمجياً بـ User-Defined Functions (UDF)، من أقوى ميزات VBA التي تتيح توسيع إمكانيات مكتبة صيغ إكسيل القياسية. على الرغم من أن إكسيل يوفر دوال مثل FIND وSEARCH، إلا أنها تفتقر إلى إرجاع قيم بوليانية مباشرة نقية، وتتطلب في العادة دمجها مع دالة ISNUMBER لتفادي خطأ #VALUE! عند عدم العثور على النص، مما يجعل كتابة الصيغ داخل أوراق العمل أمراً معقداً ومربكاً للمستخدم النهائي.

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


Public Function ContainsString(ByVal SourceText As Variant, ByVal SearchTerm As Variant, Optional ByVal MatchCase As Boolean = False) As Variant
    On Error GoTo ErrorHandler
    If IsNull(SourceText) Or IsNull(SearchTerm) Then
        ContainsString = CVErr(xlErrValue)
        Exit Function
    End If
    Dim sSource As String, sSearch As String
    sSource = CStr(SourceText)
    sSearch = CStr(SearchTerm)
    If Len(sSearch) = 0 Then
        ContainsString = True
        Exit Function
    End If
    Dim compMode As VbCompareMethod
    compMode = IIf(MatchCase, vbBinaryCompare, vbTextCompare)
    ContainsString = (InStr(1, sSource, sSearch, compMode) > 0)
    Exit Function
ErrorHandler:
    ContainsString = CVErr(xlErrValue)
End Function

يُبرز هذا التصميم متانة عالية؛ حيث اعتُمد تمرير المعاملات كـ Variant للسماح بالتعامل مع كافة أنواع المدخلات الواردة من الخلايا، مع تطبيق التحقق المسبق من قيم Null، وتوفير معامل اختياري MatchCase يتيح للمستخدم في ورقة العمل التحكم بحرية في حساسية حالة الأحرف بمرونة فائقة.

10.2 دمج الدوال المخصصة مع صيغ إكسيل المدمجة والتنسيق الشرطي

بمجرد كتابة هذه الدالة وحفظها ضمن المصنف (بصيغة .xlsm أو كملف ملحق .xlam)، تصبح متاحة للاستدعاء الفوري المباشر من قبل المستخدمين غير التقنيين داخل ورقة العمل، كأي دالة مدمجة مثل SUM أو VLOOKUP. يمكن إدخال الصيغة التالية في أي خلية:

=ContainsString(A2, "Approved")

وتتعاظم فائدة هذه الدالة عند دمجها ضمن الصيغ المنطقية المركبة لدوال اتخاذ القرار، مثل دالة IF الرياضية؛ حيث يمكن توجيه النتائج المالية بسهولة بالصيغة:

=IF(ContainsString(B2, "Corporate"), C2 * 0.15, C2 * 0.05)

علاوة على ذلك، يمثل استخدام هذه الدالة ضمن قواعد التنسيق الشرطي (Conditional Formatting) نقلة نوعية في تصميم لوحات التحكم التفاعلية (Dashboards). يمكن للمحلل إنشاء قاعدة تنسيق شرطي تعتمد على صيغة برمجية، وتطبيق الدالة =ContainsString($A1, "Urgent") على النطاق بالكامل؛ وبمجرد احتواء الخلية على الكلمة المستهدفة، يُفعل التنسيق تلقائياً وتُلون الصفوف بلون مغاير لجذب انتباه المستخدم.

فيما يخص كفاءة الاستدعاء، يجب الحذر من تحويل الدالة المخصصة إلى دالة متطايرة (Volatile Function) عبر استدعاء Application.Volatile True دون مبرر تقني ملح. إن ترك الدالة غير متطايرة بحالتها الافتراضية يضمن عدم قيام إكسيل بإعادة تشغيلها إلا إذا طرأ تغيير فعلي على محتوى الخلايا المرجعية الممررة إليها مباشرة (A2 أو B2)، مما يحفظ سرعة استجابة ورقة العمل ويمنع التجميد غير الضروري للنظام.

11. سيناريوهات تطبيقية متقدمة في سياقات الأعمال والتحليل

11.1 الفحص المتعدد: التحقق من وجود أي سلسلة أو كافة السلاسل في النص

في بيئات العمل المعقدة، نادراً ما تقتصر متطلبات الأعمال على فحص كلمة واحدة، بل تتطلب السيناريوهات في كثير من الأحيان التحقق من قائمة من الكلمات المفتاحية بالاستناد إلى القواعد المنطقية المتقدمة مثل منطق الجمع (AND Logic) أو منطق التخيير (OR Logic). لنفترض أن النظام يحتاج إلى التحقق مما إذا كان وصف المعاملة المالية يحتوي على كلمة “Payment” أو كلمة “Deposit” (منطق OR)، أو أنه يجب أن يحتوي على كلتا الكلمتين “Invoice” و “Paid” معاً في نفس الوقت (منطق AND).

يتطلب الحل البرمجي الأنيق لهذه المسألة استخدام دالة Split لتفكيك قائمة من الكلمات المفتاحية المفصولة برمز محدد (مثل الفاصلة) إلى مصفوفة نصوص مستقلة، ثم تمريرها عبر حلقة تكرارية تفحص كل عنصر على حدة. يوضح الجدول البرمجي التالي الفروق الهندسية بين بناء الخوارزميتين:

  • خوارزمية التحقق الجزئي (Any Substring – OR Logic): تبدأ بافتراض النتيجة MatchFound = False، وتقوم بالدوران على مصفوفة الكلمات؛ وبمجرد أن ترجع دالة InStr قيمة أكبر من الصفر لأي كلمة من الكلمات، تُضبط النتيجة فوراً على MatchFound = True ويتم كسر الحلقة التكرارية باستخدام Exit For توفيراً لدورات المعالج (Short-Circuit Evaluation).
  • خوارزمية التحقق الشامل (All Substrings – AND Logic): تبدأ على العكس بافتراض النتيجة AllFound = True، وتفحص الكلمات؛ وبمجرد أن ترجع دالة InStr القيمة صفراً لأي كلمة مفقودة، يتم قلب المتغير إلى AllFound = False مع الخروج الفوري من الحلقة عبر Exit For، نظراً لأن فقدان عنصر واحد يُبطل منطق الجمع بالكامل.

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

11.2 أتمتة تصنيف وتوجيه السجلات بناءً على الكلمات المفتاحية

تتعدى الاستخدامات المتقدمة للتحقق من النصوص مجرد الفحص السلبي الساكن، لتصبح محركاً لتوجيه مسارات العمل التشغيلية (Workflow Automation). يتجسد هذا السيناريو بوضوح في أنظمة خدمة العملاء ومكاتب الدعم الفني، حيث تستقبل المؤسسة آلاف التذاكر والشكاوى اليومية عبر البريد الإلكتروني أو الاستمارات الإلكترونية، ويُطلب من النظام توجيه كل تذكرة إلى القسم المختص (المالي، الفني، المبيعات) بصورة آلية.

يتم بناء هذا النظام الخبير في VBA عبر مصفوفة قواعد (Rule Matrix) ثنائية الأبعاد، تخزن الفئة المستهدفة في عمود والكلمات الدالة المرتبطة بها في عمود مجاور. على سبيل المثال، تُربط الفئة “Technical Support” بكلمات مثل “Error”, “Crash”, “Login”, “Bug”، في حين تُربط الفئة “Billing” بكلمات مثل “Refund”, “Overcharge”, “Invoice”, “Credit Card”. يقوم الإجراء البرمجي بمسح نصوص التذاكر، واحتساب عدد مرات تكرار الكلمات المفتاحية لكل فئة استناداً إلى دالة InStr، ومن ثم تصنيف التذكرة وإسنادها للفئة التي حققت أعلى وزن تكراري (Keyword Weighting Algorithm).

يمتد التطبيق ذاته إلى معالجة كشوف الحسابات البنكية غير المصنفة في الأقسام المحاسبية؛ حيث يقوم الكود بتحليل السلاسل النصية الواردة في حقل البيان (Transaction Description)، والتحقق من احتوائها على أسماء الموردين المعتمدين، ليرحل المبلغ المالي تلقائياً إلى حساب الأستاذ المساعد المقابل، مع توليد تقارير إحصائية فورية تلخص إجمالي المدفوعات لكل مورد وتبرز السجلات الغامضة التي فشلت الخوارزمية في التعرف عليها للتدخل البشري.

12. دليل المقارنة الشاملة وأفضل الممارسات البرمجية

12.1 مقارنة معيارية شاملة بين أدوات فحص النصوص في VBA

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

الأداة البرمجية نوع المخرج الأساسي السرعة النسبية للأداء مرونة مطابقة الأنماط الاستخدام المثالي في البيئات المؤسسية
InStr رقم صحيح (Long) يمثل الفهرس فائقة جداً (الأسرع مطلقاً) منخفضة (تطابق نصي ثابت فقط) البحث عن كلمات محددة بدقة واستخراج المقاطع انطلاقاً من البداية.
InStrRev رقم صحيح (Long) يمثل الفهرس فائقة جداً (مطابقة للعادية) منخفضة (تطابق نصي ثابت فقط) تحليل مسارات الملفات، فك الامتدادات، والبحث عن آخر ظهور للرموز.
معامل Like قيمة منطقية (Boolean) متوسطة إلى سريعة متوسطة (تدعم الرموز البديلة والأقواس) التحقق الهيكلي من النصوص البسيطة بدون الحاجة إلى استخراج المواقع.
VBScript.RegExp كائنات (Matches/Boolean) بطيئة نسبياً (حمل معالجة أعلى) شديدة الارتفاع (أنماط لا نهائية) التحقق المعقد من الصيغ وتدقيق البريد والهواتف واستخراج النصوص المشفرة.

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

12.2 قائمة المعايير الأكاديمية لكتابة أكواد معالجة نصوص متينة ومستدامة

لضمان وصول البرمجيات المكتوبة بلغة VBA إلى أعلى درجات الجودة، والاستقرار، والقابلية للصيانة داخل البيئات المؤسسية الحساسة، ينبغي للمطورين الامتثال الصارم لحزمة من المعايير والممارسات البرمجية الرصينة:

  • التفعيل الحتمي لخيار التوثيق الصارم (Option Explicit): يجب أن يتصدر هذا الإعلان السطر الأول من كل وحدة نمطية برمجية دون استثناء؛ حيث يُلزم المحرر بإعلان كافة المتغيرات المكتوبة ويمنع الأخطاء الكارثية الناجمة عن الأخطاء الإملائية في أسماء السلاسل النصية، والتي تولد متغيرات فارغة في الذاكرة بصمت.
  • اعتماد معايير تسمية منضبطة وذات دلالة: استخدام نمط التسمية الاصطلاحي (Hungarian Notation المعدل) لتوضيح طبيعة البيانات ونطاق المتغير، مثل استخدام البادئة str للسلاسل النصية (strCustomerName)، والبادئة lng للأرقام الفهرسية (lngPositionIndex)، والبادئة b أو is للمتغيرات المنطقية (isFound)، مما يسهل قراءة الكود وفهمه عند التدقيق البرمجي.
  • تأمين المعاملات والمدخلات (Defensive Programming): افتراض أن أي نص وارد من ورقة العمل أو المستخدم هو نص ملوث محتمل؛ وعليه يجب إخضاع كافة المدخلات للفحص المسبق وتطبيق عمليات التنظيف والتحقق من الأطوال عبر Len() قبل تمريرها لأي دالة فحص.
  • العزل المعماري وفصل المهام (Modular Architecture): تجنب كتابة إجراءات ضخمة تتولى قراءة البيانات، والتحقق منها، وطباعتها في نفس الوقت. بدلاً من ذلك، يجب هندسة وحدات مستقلة بحيث تُعزل دوال التحقق من النصوص داخل دوال فرعية مستقلة تُعنى فقط بالمنطق، وتتولى الإجراءات التنفيذية مهام الإدخال والإخراج.
  • التوثيق المعماري وشرح الحالات الاستثنائية: تضمين تعليقات برمجية داخلية وافية تشرح “لماذا” تم اختيار خوارزمية معينة دون غيرها، وما هي المعايير المتبعة للتعامل مع حساسية حالة الأحرف، لضمان استدامة النظام وتيسير عمليات التطوير المستقبلي بواسطة فرق العمل البرمجية الأخرى.

خاتمة

استعرضنا عبر هذا الدليل التقني الموسع الأسس النظرية والممارسات التطبيقية للتحقق من احتواء السلاسل النصية على سلاسل أخرى في لغة Visual Basic for Applications (VBA). بدأت رحلتنا من التكوين الهيكلي الداخلي للسلاسل النصية المتمثل في نموذج BSTR ونظام ترميز UTF-16، وفهمنا كيفية انعكاس هذا التمثيل على كفاءة الذاكرة وطبيعة البحث الخطي والمؤشرات الموضعية. وتناولنا بالتحليل الرياضي والتفكيك البنيوي الشامل دالة InStr ومعاملاتها، مع توضيح الفوارق الجوهرية بين المقارنة الثنائية vbBinaryCompare والمقارنة النصية vbTextCompare، وتطرقنا إلى أهمية توحيد الأحرف وتطبيع النصوص كبديل يضمن الثبات الأدائي والاستقرار عبر بيئات التشغيل المختلفة.

كما حللنا الجوانب الوظيفية للبحث التراجعي باستخدام دالة InStrRev وتطبيقاتها الحيوية في معالجة المسارات والامتدادات، وانتقلنا بعدها إلى مطابقة الأنماط البنيوية المرنة عبر معامل Like، وصولاً إلى المعالجة المتقدمة والتنقيب العميق عن الكيانات المعقدة بالاستعانة بمحرك التعابير النمطية VBScript.RegExp. ولم تقتصر المعالجة على الجوانب النظرية الصرفة، بل امتدت لتشمل الوقاية الاستباقية من أخطاء الانهيار البرمجي مثل تباين الأنواع مع قيم Null والمدخلات الصفرية، وتقديم استراتيجيات تسريع الأداء المعتمدة على نقل البيانات إلى مصفوفات الذاكرة العشوائية وتجميد التحديثات التلقائية لتطبيق إكسيل، وصولاً إلى بناء دوال مخصصة وتطبيق الخوارزميات المنطقية في أتمتة الأعمال وسياقات اتخاذ القرار وتوجيه التذاكر والسجلات المالية.

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

المراجع

تقييم هذا المحتوى

0.0 / 5 0 تقييمات

اقتباس هذا المقال

looti, M. (2026, سبتمبر 12). VBA: كيفية التحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة أخرى. عرب سايكلوجي. https://arabpsychology.com/statistics/vba-check-if-string-contains-another-string/
looti, Mohammed. “VBA: كيفية التحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة أخرى.” عرب سايكلوجي, 12 سبتمبر 2026, https://arabpsychology.com/statistics/vba-check-if-string-contains-another-string/.
looti, Mohammed. “VBA: كيفية التحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة أخرى.” عرب سايكلوجي. سبتمبر 12, 2026. https://arabpsychology.com/statistics/vba-check-if-string-contains-another-string/.