كيفية حساب المتوسط المرجح في VBA (مع مثال)

دليل أكاديمي شامل يشرح كيفية حساب المتوسط المرجح باستخدام كود VBA في برنامج إكسيل، مع تفكيك المعادلة الرياضية وتحليل مثال تطبيقي خطوة بخطوة.

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

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

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

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

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

1. مدخل نظري ومفاهيمي للمتوسط المرجح وأهميته الإحصائية

1.1 مفهوم المتوسط المرجح والفرق الجوهري بينه وبين المتوسط الحسابي البسيط

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

من هنا ينبثق المفهوم الإحصائي لـ “المتوسط المرجح” (Weighted Average) كأداة رياضية تراعي التباين المتأصل في الأوزان النسبية للبيانات. يُعرّف الوزن النسبي (Weight) بأنه معامل عددي يُسند إلى كل قيمة رصد بهدف إبراز حجم تأثيرها، أو تكرارها، أو درجة الثقة فيها مقارنة ببقية القيم في المجتمع الإحصائي المدروس. إن إدخال الأوزان يُعيد تشكيل توزيع البيانات، مما يجعل النتيجة النهائية تميل نحو القيم ذات الثقل الأكبر، وهو ما يُعبر بدقة متناهية عن الواقع التجريبي أو الاقتصادي للظاهرة محل الدراسة.

إن إغفال الوزن النسبي وتطبيق المتوسط البسيط في بيئات ذات تباين عالٍ يؤدي إلى تشويه إحصائي يُعرف في نظرية القياس بالانحياز التقديري (Estimation Bias). ففي الدراسات الميدانية التي تتضمن عينات غير متجانسة، مثل قياس الاحتياجات المؤسسية أو استقراء الاتجاهات المجتمعية الواسعة كما ناقشها فارمر وزملاؤه (Farmer et al., 2011)، يُعد ترجيح الاستجابات بحسب التوزيع الديموغرافي أو المنهجي شرطاً لا غنى عنه للوصول إلى تقديرات تمثل المجتمع بدقة، وتفادي تضخيم فئات هامشية على حساب الفئات ذات الثقل الحقيقي في التوزيع العام.

1.2 الصياغة الرياضية لمعادلة المتوسط المرجح

تستند الصياغة الرياضية للمتوسط المرجح إلى دمج عمليتي الضرب القياسي والتجميع في بنية كسرية محكمة. فإذا كان لدينا متغير عشوائي أو مجموعة من القيم المرصودة يُرمز لها بالرمز $x_i$ حيث $i in {1, 2, dots, n}$، وكانت كل قيمة مقترنة بوزن عددي مناظر يُرمز له بالرمز $w_i$، فإن الصيغة الرياضية القياسية للمتوسط المرجح ($\bar{x}_w$) تُكتب على النحو الآتي:

$$\bar{x}_w = \frac{\sum_{i=1}^{n} w_i x_i}{\sum_{i=1}^{n} w_i}$$

يتألف هذا الكسر الرياضي من شقين بنيويين يحملان دلالات إحصائية دقيقة؛ حيث يمثل البسط ($\sum_{i=1}^{n} w_i x_i$) المجموع التراكمي لحواصل ضرب كل قيمة فردية في وزنها النسبي المقابل، مستخدماً رمز التجميع الإغريقي (سيغما $\sum$) للإشارة إلى المرور الخوارزمي التتابعي على كافة العناصر وجمع نواتجها. هذا البسط يجسد في الواقع “الكتلة الإجمالية المرجحة” للظاهرة المقاسة. أما المقام ($\sum_{i=1}^{n} w_i$)، فيمثل المجموع الجبري لكافة الأوزان المستخدمة في التحليل، دون إدخال القيم الأصلية في حسابه.

لضمان صحة هذه المعادلة وتفادي الانهيار الرياضي أثناء التطبيق الحسابي، يجب استيفاء شرطين أساسيين: أولهما ألا يكون مجموع الأوزان مساوياً للصفر مطلقاً ($\sum w_i \neq 0$) لتجنب خطأ القسمة على الصفر اللانهائي (Division by Zero)، وثانيهما أن تكون الأوزان قيماً غير سالبة ($w_i ge 0$) في التطبيقات الإحصائية القياسية، لضمان بقاء المتوسط المرجح محصوراً بصورة منطقية ضمن المجال المغلق بين أدنى قيمة وأعلى قيمة من القيم المرصودة ($[\min(x_i), \max(x_i)]$). تعود جذور هذا التأصيل الرياضي الصارم لنظرية التقدير التربيعي وحساب الأخطاء إلى أبحاث كارل فريدريش غاوس في مطلع القرن التاسع عشر، والتي أسست لكيفية ترجيح المشاهدات المتفاوتة في الدقة القياسية.

1.3 تطبيقات المتوسط المرجح في القياسات التحليلية والبيانات الميدانية

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

وفي مجال القياسات النفسية والتربوية، يبرز المتوسط المرجح في احتساب المعدلات التراكمية للطلاب (GPA)، حيث تُعامل الساعات المعتمدة لكل مساق كأوزان نسبية تحدد مدى تأثير علامة ذلك المساق على المعدل العام. كذلك في تصحيح الاختبارات القياسية، تُوزع الأوزان بحسب معامل صعوبة الأسئلة أو مدى قدرتها على التمييز بين المستويات المعرفية. وتتجلى أهمية ترجيح البيانات أيضاً في نمذجة التكامل الحسي والتحليلات العصبية الحسابية المعقدة، مثلما أوضح أكيربي وزملاؤه (Acerbi et al., 2018) وماغنوتي وزملاؤه (Magnotti et al., 2018) في دراسات الاستدلال السببي، حيث يتم دمج الإشارات الحسية المتباينة من خلال ترجيحها إحصائياً بالاعتماد على دقة وموثوقية كل قناة حسية ومستوى الضجيج المقترن بها.

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

2. البنية البرمجية لبيئة VBA ودورها في العمليات الحسابية

2.1 نظرة عامة على محرر Visual Basic for Applications في بيئة إكسيل

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

تعتمد أتمتة المعادلات الإحصائية عبر VBA على صياغة “إجراءات فرعية” (Subroutines) أو “دوال مخصصة” (User-Defined Functions). يتميز الإجراء الفرعي، المعرف بالكلمة المحجوزة Sub، بقدرته على تنفيذ سلسلة متتابعة من العمليات المعقدة على واجهة البرنامج الممتدة دون الحاجة إلى تدخل يدوي متكرر. إن أتمتة حساب المتوسط المرجح عبر إجراء برمجي يتيح للمحلل معالجة جداول عملاقة تتضمن مئات الآلاف من السجلات، مع إمكانية ربط هذا الإجراء بأزرار تفاعلية داخل ورقة العمل لتحقيق تجربة استخدام سلسة وعالية الكفاءة.

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

2.2 وظيفة كائن دوال ورقة العمل WorksheetFunction في لغة VBA

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

تنبع الميزة الأدائية لاستخدام WorksheetFunction من كفاءة المعالجة اللحظية؛ فعوضاً عن قيام المبرمج بكتابة حلقات تكرارية معقدة (Loops) لقراءة مصفوفات البيانات عنصراً بعنصر وتطبيق الضرب التراكمي يدوياً، يمكن للكود إيكال هذه المهمة الحسابية مباشرة إلى دوال الورقة مثل SumProduct وSum. هذه الدوال مكتوبة ومُحسنة لمعالجة النطاقات الكبيرة في الذاكرة بأدنى استهلاك ممكن لدورات المعالج الدقيق (CPU Cycles)، مما يقلص زمن التنفيذ البرمجي بشكل ملحوظ عند التعامل مع مجموعات البيانات الكبيرة.

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

2.3 آلية التعامل مع النطاقات والخلايا باستخدام كائن Range

يُعد كائن النطاق Range الكائن الجوهري الأكثر استخداماً في تطوير حلول VBA لإكسيل؛ فهو يمثل خلية مفردة، أو صفاً، أو عموداً، أو مصفوفة مستطيلة متصلة أو منفصلة من الخلايا داخل ورقة العمل. تتيح الخاصية البرمجية Range("A1") أو Range("B2:B7") للمطور تحديد الموقع الجغرافي للبيانات الرقمية التي ستدخل في العمليات الحسابية بدقة متناهية، والتعامل مع محتوياتها سواء بالقراءة، أو التعديل، أو التهيئة التنسيقية.

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

عقب إتمام الحساب الرياضي واستخلاص المتوسط المرجح في متغير برمجي، يوفر كائن Range الآلية المباشرة لإسناد هذه القيمة المحسوبة وتخزينها في الخلية المستهدفة داخل ورقة العمل، مثل كتابة Range("E2").Value = .... يؤدي هذا الإسناد إلى تثبيت النتيجة العددية في الورقة إما كقيمة خام نهائية (Constant) أو كصيغة ديناميكية تبعا للمنهجية البرمجية المختارة، مما يضمن عرض المخرجات بصورة واضحة ومهيأة للتقارير والتحليلات اللاحقة.

3. التحليل التفصيلي للصيغة البرمجية المعتمدة لحساب المتوسط المرجح

3.1 تشريح دالة الجمع والضرب المركب WorksheetFunction.SumProduct

تمثل دالة WorksheetFunction.SumProduct الركيزة الرياضية الأولى في بناء البسط الحسابي لمعادلة المتوسط المرجح داخل بيئة VBA. يكمن المسار الرياضي الداخلي لهذه الدالة في أخذ مصفوفتين أو أكثر ذات أبعاد متطابقة، ثم ضرب كل عنصر من عناصر المصفوفة الأولى في العنصر المناظر له تماماً في نفس الموقع من المصفوفة الثانية، وأخيراً جمع كافة النواتج الجزئية المستخلصة لتوليد قيمة عددية واحدة مفردة. هذا المسار يطابق حرفياً المفهوم الرياضي لعملية الضرب القياسي (Dot Product) بين المتجهات في الجبر الخطي.

عند مطابقة هذا السلوك البرمجي مع الصياغة النظرية للمتوسط المرجح، نجد أن SumProduct تمثل الترجمة الخوارزمية المباشرة لرمز التجميع في بسط المعادلة: $\sum_{i=1}^{n} w_i x_i$. فعندما يتم تمرير نطاق القيم ونطاق الأوزان كمعاملين لهذه الدالة عبر الكود، فإنها تقوم لحظياً بحساب $(w_1 \times x_1) + (w_2 \times x_2) + dots + (w_n \times x_n)$ بكفاءة خوارزمية عالية جداً تفوق بكثير كتابة كود تكراري يدوي.

يشترط لعمل دالة SumProduct بنجاح توافق أبعاد المصفوفات المدخلة كمعاملات؛ فإذا تم تمرير نطاق قيم يتكون من ستة صفوف وعمود واحد، فيجب حتماً أن يتكون نطاق الأوزان من ستة صفوف وعمود واحد أيضاً. إن أي اختلاف في الأبعاد، كأن يتضمن نطاق القيم ستة صفوف ونطاق الأوزان سبعة صفوف، سيؤدي فوراً إلى انهيار العملية البرمجية وصدور خطأ عدم تطابق الأبعاد البرمجي (Error 2015 أو Type Mismatch) من قِبل إكسيل، مما يؤكد ضرورة الحفاظ على التناظر الهيكلي التام للنطاقات.

3.2 دور دالة المجموع WorksheetFunction.Sum كمقام للمعادلة الحسابية

إذا كانت دالة الضرب المركب تشكل بسط المعادلة، فإن دالة المجموع القياسية WorksheetFunction.Sum تشكل مقامها الإحصائي الحاسم. تستقبل هذه الدالة نطاقاً رقمياً واحداً، وتتلخص مهمتها في إجراء جمع جبري تراكمي لكافة القيم العددية المتضمنة داخل ذلك النطاق، وهو ما يحقق حرفياً متطلب الشق الأسفل من معادلة المتوسط المرجح: $\sum_{i=1}^{n} w_i$.

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

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

3.3 تركيب الشيفرة البرمجية الكاملة وتحليل بنية السطر الواحد

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

Range("E2").Value = WorksheetFunction.SumProduct(Range("B2:B7"), Range("C2:C7")) / _
WorksheetFunction.Sum(Range("C2:C7"))

عند التفكيك الأكاديمي لهذا السطر، نلاحظ في الطرف الأيسر تحديد الوجهة النهائية للمخرج الرقمي باستخدام الخاصية Range("E2").Value؛ حيث يتم توجيه معالج VBA لتخزين القيمة المحسوبة مباشرة في الخلية ذات الإحداثيات E2 في ورقة العمل النشطة. أما الطرف الأيمن، فيمثل جوهر العملية الحسابية، حيث يُستدعى البسط عبر دالة SumProduct مطبقة على النطاقين B2:B7 و C2:C7، ثم يُقسم فوراً باستخدام معامل القسمة الرياضي (/) على المقام المحسوب عبر دالة Sum المطبقة على نطاق الأوزان C2:C7.

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

4. إعداد وتجهيز مصفوفة البيانات في جدول إكسيل

4.1 الهيكلة المنطقية لجدول البيانات وتوزيع المتغيرات

تتطلب الإجراءات التحليلية المتقدمة تنظيماً هيكلياً دقيقاً لجداول البيانات، حيث ينبغي أن تتوزع المتغيرات الإحصائية في أعمدة مستقلة ومنفصلة منطقياً، بما يتوافق مع مبادئ “البيانات المنظمة” (Tidy Data). يقتضي التصميم النموذجي لجدول احتساب المتوسط المرجح تخصيص عمود تعريفي للمفردات أو السجلات (مثل أسماء المنتجات أو أسماء الموظفين أو البنود الاختبارية)، يليه عمود مخصص لقيم المتغير التابع المستهدف بالقياس، ثم عمود مجاور للأوزان النسبية أو الكميات المرتبطة بكل قيمة.

في السياقات التجارية والمالية، يُخصص عادة عمود مستقل لمستويات الأسعار (Price) ممثلاً قيم المتغير $x_i$، بينما يُخصص عمود مجاور للكميات المباعة أو أحجام التداول (Amount أو Volume) ليلعب دور الأوزان النسبية $w_i$. هذا الفصل الهيكلي الصارم يمنع التداخل الذهني والحسابي، ويسمح بالرجوع السريع للقيم الأولية ومراجعتها، فضلاً عن تسهيل تحديد النطاقات البرمجية أثناء كتابة الشيفرة في VBA.

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

4.2 تحديد الإحداثيات الدقيقة للنطاقات الرقمية في ورقة العمل

لتطبيق الكود البرمجي بصورة قياسية ودقيقة، يجب تثبيت الإحداثيات المكانية للنطاقات داخل ورقة العمل النشطة. في النموذج العملي المعتمد في هذا الدليل، يتم تخصيص النطاق الجغرافي الواقع بين الصف الثاني والصف السابع في العمود B، أي النطاق B2:B7، لاحتواء مصفوفة قيم المتغير الأساسي، والتي تمثل في دراسة الحالة مستويات الأسعار للمنتجات المباعة.

وبالمقابل التام، يتم تخصيص النطاق الموازي في العمود C، أي النطاق C2:C7، لتخزين مصفوفة الأوزان النسبية المباشرة والمتمثلة في كميات المبيعات المقابلة لكل مستوى سعري. هذا التوازي الصفّي يضمن أن الخلية B2 تقترن وزنياً بالخلية C2، والخلية B3 تقترن بالخلية C3، وهكذا دواليك حتى نهاية النطاق في الصف السابع، وهو ما يحقق التناظر الديكارتي المطلوب لتنفيذ الضرب المتجهي بنجاح.

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

4.3 معايير سلامة البيانات وتجنب الأخطاء الإدخالية

تعتمد الموثوقية الرياضية لأكواد VBA اعتماداً كلياً على سلامة وجودة البيانات المدخلة في النطاقات المعنية. تبرز أهمية خلو الخلايا المحددة في النطاقين B2:B7 و C2:C7 تماماً من أي محارف نصية، أو رموز غير رقمية، أو مسافات خفية ناتجة عن التصدير الخاطئ من قواعد البيانات؛ حيث تؤدي المدخلات النصية داخل دوال الورقة الرياضية إما إلى نتائج مشوهة أو إلى إطلاق أخطاء تشغيلية فورية من نوع “عدم تطابق النوع” (Type Mismatch Error).

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

علاوة على ذلك، يجب التحقق من استيفاء شرط التساوي العددي لصفوف النطاقين، حيث يُعد التفاوت في أطوال المصفوفات (كأن يحتوي نطاق الأسعار على 6 خلايا بينما يحتوي نطاق الكميات على 5 خلايا فقط) السبب البرمجي الأول لفشل دالة SumProduct في العمل، مما يفرض ضرورة المعاينة المسبقة لانتظام أبعاد البيانات في الجدول.

5. دليل خطوة بخطوة لكتابة وتنفيذ ماكرو حساب المتوسط المرجح

5.1 تفعيل محرر Visual Basic وإدراج وحدة نمطية قياسية (Module)

لبدء كتابة الكود البرمجي المخصص لحساب المتوسط المرجح، يتعين على المستخدم الوصول إلى بيئة التطوير المتكاملة VBE داخل إكسيل. يمكن تحقيق ذلك بأسلوب مباشر عبر الضغط على اختصار لوحة المفاتيح الشهير Alt + F11، أو من خلال الانتقال إلى شريط الأدوات العلوي واختيار علامة التبويب “المطور” (Developer)، ثم النقر فوق أيقونة “Visual Basic”. في حال عدم ظهور شريط المطور، يمكن تفعيله بسهولة عبر خيارات إكسيل وتخصيص الشريط.

بمجرد انفتاح نافذة المحرر، تظهر واجهة إدارة المشروع (Project Explorer) في الجانب الأيسر. لإضافة مساحة عمل برمجية نظيفة، يتجه المستخدم إلى شريط القوائم العلوي وينقر على قائمة “إدراج” (Insert)، ثم يختار “وحدة نمطية” (Module). يؤدي هذا الإجراء إلى فتح صفحة برمجية بيضاء قياسية مستقلة تُعرف باسم Module1، وهي البيئة المعيارية الموصى بها لكتابة الإجراءات العامة المتاحة للاستدعاء من أي مكان داخل المصنف.

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

5.2 كتابة وتوثيق كود الإجراء الإجرائي Sub FindWeightedAverage

في مساحة الوحدة النمطية التي تم إدراجها، يتم البدء في كتابة الإجراء الإجرائي المخصص من خلال صياغة ترويسة الإجراء باستخدام الكلمة المحجوزة Sub متبوعة بالاسم الدلالي المختار، وليكن FindWeightedAverage، ومتبوعاً بقوسين فارغين مشيرين إلى عدم استقبال معاملات خارجية في هذا الإجراء المستقل، مع إنهاء الكتلة البرمجية بعبارة End Sub تلقائياً.

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

Sub FindWeightedAverage()
    ' حساب المتوسط المرجح للأسعار والكميات وإسناد الناتج للخلية E2
    ' البسط: مجموع حواصل ضرب الأسعار في الكميات
    ' المقام: إجمالي مجموع الكميات المباعة
    Range("E2").Value = WorksheetFunction.SumProduct(Range("B2:B7"), Range("C2:C7")) / _
                        WorksheetFunction.Sum(Range("C2:C7"))
End Sub

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

5.3 آليات تشغيل الماكرو وتخزين النتيجة في الخلية المطلوبة

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

أما في بيئات العمل التطبيقية والمؤسسية، فإن أفضل ممارسة تتمثل في تسهيل الوصول للماكرو لغير المتخصصين عبر ربطه بعنصر تحكم تفاعلي داخل ورقة العمل. يمكن للمطور إدراج شكل هندسي أو زر تحكم (Button Form Control) من تبويب المطور، وربطه مباشرة بالماكرو المكتوب عبر النقر بزر الفأرة الأيمن واختيار “تعيين ماكرو” (Assign Macro)، مما يسمح بإعادة حساب المتوسط المرجح بنقرة زر واحدة فور تحديث البيانات.

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

6. دراسة حالة تطبيقية مفصلة: بيانات المبيعات والأسعار

6.1 عرض البيانات الأولية الخاصة بحجم المبيعات ومستويات الأسعار

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

يوضح الجدول الإحصائي التالي تفاصيل العينة التجريبية المعتمدة في هذا التطبيق:

رقم السجل (الصف) المنتج / الصنف السعر الفردي للوحدة بالدولار (Price – B) الكمية المباعة / الوزن (Amount – C)
2 المنتج أ 10 20
3 المنتج ب 14 9
4 المنتج ج 8 11
5 المنتج د 12 8
6 المنتج هـ 15 6
7 المنتج و 5 14

يكشف الفحص البصري الأولي لهذه البيانات عن تباين واضح في كميات البيع المقترنة بكل سعر؛ فالمنتج “أ” يباع بسعر 10 دولارات ولكن بكمية ضخمة تبلغ 20 وحدة، في حين أن المنتج “هـ” يباع بسعر مرتفع يبلغ 15 دولاراً لكن بكمية محدودة جداً لا تتجاوز 6 وحدات، بينما المنتج “و” يباع بسعر منخفض قدره 5 دولارات بكمية معتبرة قدرها 14 وحدة. هذا التفاوت يبرز استحالة استخدام المتوسط البسيط لتقييم سعر البيع العام للمؤسسة.

6.2 تنفيذ كود VBA واستخراج القيمة الرقمية النهائية

عند تشغيل الإجراء الماكروبي FindWeightedAverage المطور في القسم السابق على جدول البيانات الموضح أعلاه، تتم المعالجة الحسابية بصورة غير مرئية في غضون ميكروثانية، لتظهر في الخلية المستهدفة E2 القيمة الرقمية الدقيقة الآتية:

9.705882

تحمل هذه القيمة الرقمية دلالة إحصائية وتحليلية بالغة العمق؛ فإذا قمنا باحتساب المتوسط الحسابي البسيط للأسعار الستة بمعزل عن كمياتها: $(10 + 14 + 8 + 12 + 15 + 5) / 6 = 64 / 6 \approx 10.6667$ دولار. نلاحظ فوراً وجود فرق جوهري يزيد عن دولار كامل بين التقديرين.

يُعزى انخفاض المتوسط المرجح (9.705882) مقارنة بالمتوسط البسيط (10.6667) إلى التأثير المباشر للأوزان النسبية؛ فالأسعار المرتفعة مثل 14 و 15 دولاراً اقترنت بكميات بيع منخفضة نسبياً (9 و 6 وحدات على التوالي)، بينما اقترنت الأسعار المنخفضة والمتوسطة مثل 10 و 5 دولارات بكميات بيع مرتفعة بلغت (20 و 14 وحدة على التوالي). إن المتوسط المرجح انحاز طبيعياً نحو مركز الثقل التجاري الحقيقي للمؤسسة، مانحاً الإدارة المالية رقماً دقيقاً وموثوقاً يعبر عن متوسط الإيراد الفعلي المتولد عن كل وحدة مباعة من مستودعاتها.

6.3 المطابقة الحسابية اليدوية للتحقق الأكاديمي من صحة النتيجة

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

  • الصف 2 (المنتج أ): $10 \times 20 = 200$
  • الصف 3 (المنتج ب): $14 \times 9 = 126$
  • الصف 4 (المنتج ج): $8 \times 11 = 88$
  • الصف 5 (المنتج د): $12 \times 8 = 96$
  • الصف 6 (المنتج هـ): $15 \times 6 = 90$
  • الصف 7 (المنتج و): $5 \times 14 = 70$

بجمع هذه النواتج الجزئية نحصل على إجمالي البسط: $200 + 126 + 88 + 96 + 90 + 70 = 670$. تمثل هذه القيمة في الواقع إجمالي الإيرادات المالية المحققة من بيع كافة المنتجات المذكورة.

ننتقل ثانياً إلى احتساب المقام عبر إيجاد المجموع التراكمي للأوزان النسبية (الكميات المباعة):
$\sum w_i = 20 + 9 + 11 + 8 + 6 + 14 = 68$ وحدة مباعة إجمالاً.

أخيراً، نقوم بقسمة إجمالي البسط المحسوب على إجمالي المقام:
$$\bar{x}_w = \frac{670}{68} \approx 9.7058823529…$$

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

7. تطوير الكود البرمجي للتعامل مع النطاقات الديناميكية المتغيرة

7.1 قصور النطاقات الثابتة في قواعد البيانات الكبيرة والمتغيرة

على الرغم من النجاح التام للكود السابق في حل مسألة النطاق المحدد B2:B7، إلا أنه يعاني من قصور هيكلي بارز يتمثل في اعتماده على “النطاقات الثابتة” (Hard-coded Ranges). في البيئات التطبيقية الحقيقية للشركات والمؤسسات البحثية، لا تظل البيانات جامدة؛ بل تتدفق سجلات جديدة باستمرار، مما يعني إضافة صفوف بيانات جديدة تتجاوز الصف السابع، أو ربما حذف صفوف معينة نتيجة التنقيح والفرز الدوري.

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

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

7.2 استخدام خاصية End(xlUp) لتحديد الصف الأخير برمجياً

لتحقيق الديناميكية المطلوبة في بيئة VBA، يُعد الأسلوب الأكثر كفاءة وموثوقية في استقراء حدود الجداول هو استخدام خاصية End(xlUp) المرتبطة بكائن الخلايا Cells. تُحاكي هذه الخاصية برمجياً ما يقوم به المستخدم يدوياً عندما ينزل إلى أدنى خلية ممكنة في ورقة العمل (الصف رقم 1048576) ثم يضغط على اختصار Ctrl + Up Arrow ليقفز المؤشر مباشرة إلى آخر خلية نشطة غير فارغة في ذلك العمود من الأسفل.

يتم تخزين رقم الصف المسترجع في متغير برمجي من نوع عددي صحيح طويل (Long)، ثم يُستخدم هذا المتغير لصياغة كائنات النطاقات dynamically. يُوضح الكود المطور التالي كيفية تنفيذ هذه الآلية بأسلوب برمجي متقدم:

Sub FindWeightedAverageDynamic()
    Dim lastRow As Long
    Dim priceRange As Range
    Dim amountRange As Range
    
    ' تحديد رقم آخر صف يحتوي على بيانات في العمود B
    lastRow = Cells(Rows.Count, "B").End(xlUp).Row
    
    ' التحقق من وجود بيانات كافية تبدأ من الصف الثاني
    If lastRow >= 2 Then
        Set priceRange = Range("B2:B" & lastRow)
        Set amountRange = Range("C2:C" & lastRow)
        
        Range("E2").Value = WorksheetFunction.SumProduct(priceRange, amountRange) / _
                            WorksheetFunction.Sum(amountRange)
    End If
End Sub

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

7.3 بناء دالة مخصصة (User Defined Function – UDF) للمتوسط المرجح

على الرغم من فاعلية الإجراءات الفرعية Sub، إلا أن بيئة إكسيل تتيح مساراً أكثر تكاملاً وسلاسة للمستخدم العادي عبر بناء “دوال مخصصة” (User-Defined Functions – UDF). تتيح هذه الدوال للمحلل استخدام المتوسط المرجح مباشرة داخل شبكة خلايا إكسيل كأي دالة قياسية أخرى مثل SUM أو AVERAGE، مع إمكانية سحبها وتطبيقها عبر الخلايا بحرية مرنة.

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

Public Function WEIGHTED_AVG(ValuesRange As Range, WeightsRange As Range) As Double
    ' التحقق من تكافؤ عدد الخلايا بين النطاقين لتجنب الأخطاء البرمجية
    If ValuesRange.CountLarge <> WeightsRange.CountLarge Then
        WEIGHTED_AVG = CVErr(xlErrRef)
        Exit Function
    End If
    
    ' تنفيذ حساب المتوسط المرجح عبر دوال ورقة العمل
    WEIGHTED_AVG = WorksheetFunction.SumProduct(ValuesRange, WeightsRange) / _
                   WorksheetFunction.Sum(WeightsRange)
End Function

بمجرد حفظ هذا الكود، يستطيع أي مستخدم التوجه إلى أي خلية فارغة في ورقة العمل وكتابة الصيغة: =WEIGHTED_AVG(B2:B7, C2:C7)، لتقوم الدالة بحساب النتيجة وإرجاعها فورياً. تجمع هذه المقاربة بين القوة الرياضية لخوارزميات VBA والواجهة التفاعلية السلسة المألوفة لدى كافة مستخدمي جداول البيانات.

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

8.1 التعامل مع خطأ القسمة على الصفر الناتج عن انعدام مجموع الأوزان

تُعد القسمة على الصفر إحدى أبرز المعضلات الرياضية والبرمجية التي قد تواجه أي خوارزمية لحساب المتوسط المرجح. ففي حال كانت جميع الخلايا في نطاق الأوزان (C2:C7) فارغة، أو كانت محتوية على أصفار فقط، أو كان مجموعها الجبري يساوي صفراً نتيجة وجود أوزان سالبة وموجبة متعادلة، فإن الدالة WorksheetFunction.Sum(Range("C2:C7")) ستُرجع القيمة (0).

عند محاولة VBA قسمة ناتج SumProduct على هذا المقام الصفري، تنهار العملية الحسابية فوراً، ويطلق المحرر استثناءً تشغيلياً حاداً يُعرف بالخطأ رقم 11: “Division by zero” (Run-time error 11). يؤدي هذا الخطأ إلى ظهور نافذة تحذيرية للمستخدم تتضمن خياري الإنهاء وتصحيح الكود (Debug)، مما يتسبب في تجربة استخدام غير احترافية وتوقف كامل للأتمتة المؤسسية.

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

8.2 معالجة عدم تطابق أحجام النطاقات المحددة

يُمثل عدم تطابق أحجام أو أبعاد النطاقات المحددة خطأً هندسياً متكرراً ينجم عادة عن خطأ بشري أثناء إدخال المعاملات أو تحديد الخلايا بالماوس. تشترط دالة SumProduct الرياضية تطابقاً هندسياً مطلقاً في عدد الصفوف والأعمدة بين كافة المصفوفات الممررة إليها. فإذا قام المستخدم مثلاً بتمرير النطاق B2:B7 (ستة صفوف) مع النطاق C2:C8 (سبعة صفوف)، فإن الجبر الخطي يعجز عن إيجاد نظير للعنصر السابع في العمود C.

يؤدي هذا التفاوت إلى إطلاق خطأ تشغيلي من نوع Run-time error 1004: Unable to get the SumProduct property of the WorksheetFunction class. لتوفير حماية برمجية متينة، يجب استقراء أبعاد النطاقات برمجياً قبل استدعاء الدالة الحسابية عبر مقارنة الخصائص الهندسية للكائنات مثل Range.Rows.Count أو Range.CountLarge.

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

8.3 استخدام بنية معالجة الأخطاء الشاملة On Error في VBA

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

تعتمد المنهجية المعيارية على كتابة العبارة On Error GoTo ErrorHandler في مستهل الإجراء البرمجي، بحيث يتم تحويل مسار المعالج فور وقوع أي استثناء إلى قسم مخصص يقع في نهاية الكود تحت وسم ErrorHandler:. يُوضح المثال البرمجي التالي هذا البناء المتكامل والشامل:

Sub RobustWeightedAverage()
    On Error GoTo ErrorHandler
    
    Dim valRange As Range, wtRange As Range
    Dim totalWeight As Double, weightedSum As Double
    
    Set valRange = Range("B2:B7")
    Set wtRange = Range("C2:C7")
    
    ' 1. التحقق من تطابق الأبعاد
    If valRange.CountLarge <> wtRange.CountLarge Then
        MsgBox "خطأ: عدد خلايا القيم لا يتطابق مع عدد خلايا الأوزان.", vbCritical, "خطأ في الأبعاد"
        Exit Sub
    End If
    
    ' 2. التحقق من المقام وتفادي القسمة على الصفر
    totalWeight = WorksheetFunction.Sum(wtRange)
    If totalWeight = 0 Then
        MsgBox "خطأ: مجموع الأوزان يساوي صفراً، لا يمكن إتمام القسمة.", vbExclamation, "مقام صفري"
        Exit Sub
    End If
    
    ' 3. تنفيذ الحساب الآمن
    weightedSum = WorksheetFunction.SumProduct(valRange, wtRange)
    Range("E2").Value = weightedSum / totalWeight
    Exit Sub

ErrorHandler:
    MsgBox "حدث استثناء غير متوقع أثناء المعالجة: " & Err.Description, vbCritical, "خطأ برمجي"
End Sub

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

9. مقارنة كفاءة الأداء بين حلول VBA والأساليب الحسابية البديلة

9.1 المقارنة بين كود VBA وكتابة الصيغة مباشرة داخل خلايا إكسيل

يثور في الأوساط التحليلية نقاش مستمر حول المفاضلة بين أتمتة الحسابات الإحصائية باستخدام كود VBA وبين حقن الصيغة الحسابية القياسية =SUMPRODUCT(B2:B7, C2:C7)/SUM(C2:C7) مباشرة داخل خلايا ورقة العمل. لكل من هذين الأسلوبين مزايا وعيوب تحدد سياق استخدامهما الأمثل.

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

في المقابل، يوفر كود VBA حماية مطلقة للمنطق الحسابي؛ حيث تُحفظ الخوارزمية الرياضية في بيئة VBE المحمية بكلمة مرور بعيداً عن أيدي العابثين، مما يضمن أمان النماذج المؤسسية وسلامة بروتوكولاتها. علاوة على ذلك، في الجداول العملاقة التي تضم ملايين الصيغ المتفاعلة، يمكن أن يؤدي الحساب اللحظي إلى تجميد ملف إكسيل واستهلاك الذاكرة العشوائية بصورة مفرطة، بينما يسمح كود VBA بتنفيذ الحساب “عند الطلب” فقط (On-demand)، مما يوفر موارد المعالجة للجهاز.

9.2 حساب المتوسط المرجح عبر مصفوفات الذاكرة في VBA مقابل دوال الورقة

عندما تتسع مجموعات البيانات لتتجاوز مئات الآلاف من السجلات، يبرز فارق جوهري في كفاءة المعالجة وسرعة التنفيذ بين استخدام دوال الكائن WorksheetFunction وبين قراءة البيانات ونقلها بالكامل إلى مصفوفات داخلية في ذاكرة الوصول العشوائي (VBA Memory Arrays). يعود السبب التقني وراء هذا الفارق إلى ما يُعرف بعبء واجهة COM (Component Object Model Overhead)؛ حيث إن كل استدعاء لدالة ورقة العمل يتطلب تبادل بيانات مكثف بين محرك VBA ومحرك إكسيل الأساسي.

تتمثل المقاربة البرمجية المتقدمة في تفريغ النطاقين B2:B100000 و C2:C100000 في مصفوفتين ثنائيتي الأبعاد في الذاكرة بلمسة واحدة، ثم استخدام حلقة تكرار بسيطة For...Next لتطبيق الضرب التراكمي والجمع في الذاكرة الحسابية المحضة لوحدة المعالجة المركزية، كما يوضح الكود الآتي:

Sub FastArrayWeightedAverage()
    Dim valArr As Variant, wtArr As Variant
    Dim num As Double, den As Double
    Dim i As Long, n As Long
    
    ' قراءة النطاقات بالكامل إلى مصفوفات في الذاكرة
    valArr = Range("B2:B100000").Value
    wtArr = Range("C2:C100000").Value
    n = UBound(valArr, 1)
    
    num = 0#: den = 0#
    For i = 1 To n
        If IsNumeric(valArr(i, 1)) And IsNumeric(wtArr(i, 1)) Then
            num = num + (valArr(i, 1) * wtArr(i, 1))
            den = den + wtArr(i, 1)
        End If
    Next i
    
    If den <> 0 Then Range("E2").Value = num / den
End Sub

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

9.3 حفظ النتيجة كقيمة ثابتة مقابل إدراجها كصيغة تفاعلية

يتيح كود VBA للمطور خيارين منهجيين في كيفية إخراج النتيجة النهائية في الخلية E2. الأسلوب الأول، وهو المعتمد في السطر القياسي المشروح: Range("E2").Value = ...، يقوم بحساب الناتج الحسابي داخل بيئة VBA وتخزين الرقم النهائي المجرد (9.705882) كقيمة ثابتة داخل الخلية. هذا الأسلوب ممتاز لمنع أي بطء مستقبلي في المصنف، ولتجميد النتيجة التاريخية للبيانات في لحظة زمنية معينة دون تأثر بالتغييرات اللاحقة.

أما الأسلوب الثاني، فيتمثل في استخدام الخاصية Range("E2").Formula لحقن صيغة إكسيل الرياضية نفسها داخل الخلية عبر الكود، كما في السطر الآتي:
Range("E2").Formula = "=SUMPRODUCT(B2:B7, C2:C7)/SUM(C2:C7)"

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

10. أفضل الممارسات البرمجية والتوصيات المنهجية لإعادة استخدام الكود

10.1 إلزامية التصريح عن المتغيرات وتطبيق تعليمة Option Explicit

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

تكمن الأهمية الجوهرية لـ Option Explicit في حماية المطور من أخطاء التسمية الإملائية القاتلة؛ فبدونها، إذا كتب المبرمج متغيراً باسم totalWeight ثم أخطأ في سطر لاحق وكتب totlWeight، سيعتبره المحرر متغيراً جديداً تماماً ويسند إليه القيمة الافتراضية صفراً، مما يقود إلى كوارث حسابية وأخطاء قسمة غير مفهومة يصعب تعقبها. مع Option Explicit، سيتوقف المترجم فوراً مشيراً إلى الكلمة الخاطئة، مما يوفر ساعات طويلة من التصحيح العبثي.

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

10.2 توثيق وتعديل الكود البرمجي لتعزيز الشفافية الأكاديمية

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

تسهم هذه الترويسة في تسهيل مهمة الباحثين والمحللين الآخرين عند مراجعة الكود وتدقيقه، بما يتوافق مع مبدأ “إعادة الإنتاج العلمي” (Scientific Reproducibility). وفي سياق القياسات السلوكية والعصبية الدقيقة مثل تلك التي ناقشها كونوفالوف وزملاؤه (Konovalov et al., 2021) ونيبه وزملاؤه (Nebe et al., 2024)، يُعد توثيق بروتوكولات احتساب الدرجات والأوزان الترجيحية بصورة برمجية دقيقة شرطاً أساسياً لضمان مصداقية النماذج وصلاحيتها للتعميم عبر عينات بحثية متباينة.

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

10.3 حفظ ملف العمل بالصيغة البرمجية الملائمة واستنتاجات ختامية

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

لتفادي هذه الكارثة التقنية، يجب دائماً عند حفظ الملف للمرة الأولى التوجه إلى قائمة “حفظ باسم” (Save As) واختيار صيغة “مصنف إكسيل يدعم الماكرو” Excel Macro-Enabled Workbook (*.xlsm)، أو اختيار الصيغة الثنائية المتقدمة Excel Binary Workbook (*.xlsb) والتي تتميز بضغط إضافي لحجم الملف وسرعة فائقة في فتح وحفظ قواعد البيانات الضخمة التي تتضمن أكواد VBA مكثفة.

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

المراجع

Acerbi, L., Dokka, K., Angelaki, D. E., & Ma, W. J. (2018). Bayesian comparison of explicit and implicit causal inference strategies in multisensory heading perception. PLoS Computational Biology, 14(7), e1006110. https://doi.org/10.1371/journal.pcbi.1006110

Alfaifi, A. Y. G. (2015). Building the Arabic Learner Corpus and a System for Arabic Error Annotation (Doctoral dissertation, University of Leeds, The University of Sheffield, University of York). White Rose eTheses Online. https://doi.org/10.13140/rg.2.2.32081.53608

Farmer, C. M., Jaycox, L. H., Marshall, G. N., Vaughan, C., & Wrenn, G. L. (2011). A Needs Assessment of New York State Veterans: Final Report to the New York State Health Foundation. RAND Corporation eBooks. https://doi.org/10.7249/tr920

Konovalov, A., Hill, C., Daunizeau, J. A., & Ruff, C. C. (2021). Dissecting functional contributions of the social brain to strategic behavior. Neuron, 109(20), 3323-3337. https://doi.org/10.1016/j.neuron.2021.07.025

Magnotti, J. F., Smith, K. B., Salinas, M., Mays, J., Zhu, L. L., & Beauchamp, M. S. (2018). A causal inference explanation for enhancement of multisensory integration by co-articulation. Scientific Reports, 8(1), 17923. https://doi.org/10.1038/s41598-018-36772-8

Nebe, S., Kretzschmar, A., Brandt, M. C., & Tobler, P. N. (2024). Characterizing Human Habits in the Lab. Collabra: Psychology, 10(1), 92949. https://doi.org/10.1525/collabra.92949

★

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

5.0 / 5 • 7 تقييمات

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

looti, M. (2026, أكتوبر 20). كيفية حساب المتوسط المرجح في VBA (مع مثال). عرب سايكلوجي. https://arabpsychology.com/statistics/how-to-calculate-weighted-average-in-vba-with-example/
looti, Mohammed. “كيفية حساب المتوسط المرجح في VBA (مع مثال).” عرب سايكلوجي, 20 أكتوبر 2026, https://arabpsychology.com/statistics/how-to-calculate-weighted-average-in-vba-with-example/.
looti, Mohammed. “كيفية حساب المتوسط المرجح في VBA (مع مثال).” عرب سايكلوجي. أكتوبر 20, 2026. https://arabpsychology.com/statistics/how-to-calculate-weighted-average-in-vba-with-example/.