درس في الإجراءات الفرعية ( العامة )
بسم الله الرحمن الرحيم
وبه أبدا وأستعين ، وأختم بالصلاة والسلام على خاتم الأنبياء والمرسلين ، أما بعد ..
هذا الدرس المتواضع أحب أن أوضح فيه أمور ربما تخفى على المبتدئين في البرمجة مع العلم أني واحداً منهم ولكني أدلو بدلوي في علم تعلمته وأريد أن يتعلمه الجميع ..
أهداف الدرس:
1- أن يتعرف المبرمج على مفهوم الإجراء الفرعي .
2- أن يتعرف المبرمج على فوائد الإجراءات الفرعية.
3- أن يتعرف المبرمج على أنواع الإجراءات الفرعية.
4- أن يكتب المبرمج إجراءاته الفرعية الخاصة من نوع SubRoutine .
5- أن يكتب المبرمج إجراءاته الفرعية الخاصة من نوع Function.
6- أن نبني مكتبه من الإجراءات الفرعية العامة ، تكون مرجع للمبرمج عند الحاجة .
** أن الإجراءات الفرعية ( العامة ) لا ترتبط بحدث معين ، ولكنها تقوم بمهام عامة مثل إجراء الحسابات أو معالجة البيانات بطريقه معينه يحددها المبرمج.
** ومن أهم الفوائد في كتابة الإجراءات الفرعية هو كتابة كود برمجي سهل في الكتابة والتحديث والصيانة وكذلك عدم تكراره في أماكن أخرى من البرنامج حيث يتم استدعائه كلما تطلب الأمر.
** وتنقسم الإجراءات الفرعية ( العامة ) إلى قسمين :
- روتين فرعي SubRoutine يقوم بمجموعة من العمليات التي يحددها المبرمج ولا يعود يقيمه .
- دالة Function تقوم بمجموعة من العمليات التي يحددها المبرمج وتعود بقيمه يحتاجها المبرمج في مكان أخر
من البرنامج .
** كتابة الإجراءات الفرعية من نوع SubRoutine :
قبل كتابة الروتين الفرعي يجب أن نختار إما أن نجعل هذا الروتين خاص من نوع Private Sub بحيث لا يمكن استدعاؤه إلا من داخل الملف ( Form ) الذي يعيش فيه ، أو مشترك من نوع Public Sub بحيث نتمكن من استخدامه من أي مكان آخر داخل البرنامج . وبعد ذلك يجب أن نختار اسم لهذا الإجراء وأنصح بكتابة أسماء واضحة وغير غامضة ، ثم نكتب مجموعة من العمليات التي نحتاجها وفي نهاية الإجراء نقوم بقفله. وكي يتضح المقال نورد المثال ..
مثال1: لنفرض أنه لدينا مجموعة من أدوات التحكم ولتكن أزرار الأوامر التي يحتاج برنامجنا إلى إيقاف عملها عند نقطه معينه و إعادتها للعمل عند نقطة أخرى ، وذلك في أكثر من موقع في نفس الفورم ، وبدل من كتابة نفس الأوامر في كل مره يمكننا أن نقوم بكتابة إجراء فرعي من نوع روتين فرعي لإيقاف عملها كما يلي ..
Private Sub EnableButton () Btn1.Enabled= True Btn2. Enabled =True Btn3.Enabled =True Btn4.Enabled =True End Sub
وعند الرغبة في تنفيذ هذا الروتين في أي موضع في نفس الفورم نكتب EnableButton فقط .
وبنفس الطريقة نقوم بكتابة إجراء فرعي من نوع روتين فرعي لإعادة تشغيل عملها كما يلي ..
Private Sub DisableButton () Btn1.Enabled= False Btn2. Enabled = False Btn3.Enabled = False Btn4.Enabled = False End Sub
وعند الرغبة في تنفيذ هذا الروتين في أي موضع في نفس الفورم نكتب DisableButton فقط .
*كما يمكننا تمرير البيانات إلى الإجراءات الفرعية وذلك عندما يحتاج هذا الإجراء إلى قيمه معينه ومتغيره، ولكي يتم ذلك يجب أن نذكر عدد المتغيرات وأنواعها عند كتابة رأس الإجراء . وكي يتضح المقال سوف نورد مثال ...
مثال 2: لنفرض أن برنامجنا يحتاج إلى إجراء عملية حسابيه مستخدمين بيانات متغيره ، وذلك في أكثر من موضع في البرنامج وبعد ذلك يقوم بعرض النتيجة في مربع رسالة ، إذا نحن نحتاج إلى إجراء فرعي مشترك من نوع روتين فرعي نمرر له مجموعة من البيانات على حسب طلبات البرنامج ، وذلك كما يلي ...
Public Sub ComputationRate(ByVal Value1 As Single, ByVal Value2 As _ Single, ByVal Value3 As Single) Dim MyValue As Single MyValue = (Value1 + Value2) / Value3 MsgBox(MyValue) End Sub
كما نشاهد لقد كتبنا Public Sub وذلك كي نجعل هذا الإجراء مشترك ، واسم الإجراء ComputationRate والقيمة الأولى Value1 من نوع Single والقيمة الثانية Value2 من نوع Single والقيمة الثالثة Value3 من نوع Single ( ملاحظة أن البرنامج سوف يقوم بكتابة ByVal بشكل تلقائي أمام كل متغير وذلك أنه يوجد لدينا طريقتان من التمرير وهي إما التمرير بالقيمة وهي أن نستخدم ByVal من أجل أن نمرر قيمة المتغير مع حماية المتغير من التعديل ، أو التمرير بالإشارة وهي أن نستخدم ByRef وهي تعني أن المتغيرات التي نمررها يمكن تعديلها في الإجراء الذي نمررها له . ومثل هذا التفصيل لن يفيدنا هنا ) .
وعند الرغبة في تنفيذ هذا الإجراء نكتب اسم الإجراء ونمرر له البيانات كما يلي ..
ComputationRate(6, 4, 2) وعند تشغيل البرنامج وتنفيذ الإجراء يظهر مربع رسالة وفيه نتيجة الإجراء وهو الرقم 5 .
* كما يمكننا أن نمرر الأدوات إلى الإجراءات الفرعية وذلك إن المتغيرات ليست هي النوع الوحيد الذي يمكننا تمريره إلى الإجراءات ، فمن الممكن أن نمرر أدوات التحكم أيضاً ، ولكي نمرر أدوات التحكم إلى الإجراء الفرعي نستخدم عبارة As Object في رأس الإجراء وذلك عند الحاجة لكي نحدد أن القيمة التي نمررها عبارة عن أداة تحكم ، وفي داخل الإجراء نستخدم أمر If Typeof لكي نتعرف على نوع الأداة التي يتم تمريرها إلى الإجراء . وكما يقال بالمثال يتضح المقال .
مثال 3 : هنا نستخدم مثال بسيط والغرض منه توضيح الفكرة فقط ، حيث نعد إجراء فرعي يخبرنا بنوع أداة التحكم التي مررناها للإجراء وذلك في مربع رسالة ..
Private Sub TellMeAbout(ByVal MyObject As Object)
If TypeOf MyObject Is Button Then MsgBox("لقد مررت زر أمر")
If TypeOf MyObject Is TextBox Then MsgBox("لقد مررت مربع نص")
End Subولكي ننفذ الإجراء نكتب TellMeAbout(Button1) كي تظهر لنا رسالة تخبرنا بنوع أداة التحكم المدخلة .
مثال 4 : لنفرض أن لدينا برنامج به الكثير من مربعات النص ونريد أن نفرغها جميعا من البيانات كي نعيد إدخال بيانات جديدة ، بالطبع سوف نقوم بكتابة الكود التالي ..
Text1.Text = "" Text2.Text = "" Text3.Text = "" Text4.Text = "" Text5.Text = "" Text6.Text = "" Text7.Text = "" Text8.Text = "" Text9.Text = "" Text10.Text = "" ....الخ
ولكنا لو استخدمنا إجراءاً فرعياً خاصاً سوف يغنينا عن كتابة كل هذه السطور مهما كان عدد مربعات النص ومهما تطلب تكرار هذه العملية في أجزاء أخرى من النموذج ( الفورم ) ..
ولكنا في هذا المثال لن نحتاج إلى استخدم عبارة As Object في رأس الإجراء ، فلنلقي نظرة للكود التالي ثم نتابع الشرح...
1 Private Sub CLEARDATA() ' هذا الاجرائ يستدعا من داخل الفورم 2 Dim txt As Control 3 For Each txt In Me.Controls 4 If TypeOf txt Is TextBox Then 5 txt.Text = "" 6 End If 7 Next 8 End Sub
في السطر رقم 1عرفنا الإجراء الذي سميناه CLEARDATA على أنه خاص بهذا النموذج ( الفورم ) .
في السطر رقم 2 أعلنا عن متغير أسمناه txt وحددنا أن نوعه Control .
في السطر رقم 3 أنشأنا تكرار باستخدام الأمر For Each لكل أدوات التحكم في النموذج .
في السطر رقم 4 شرطنا على أداة التحكم التي أمسك بها الأمر السابق فيما إذا كانت مربع نص ( طبعاً استخدمنا العبارة TypeOf ) فإنه ينفذ الأمر الموجود في السطر رقم 5.
في السطر رقم 5 طلبنا من البرنامج أن يقوم بتفريغ مربع النص من البيانات .
في السطر رقم 6 قمنا بقفل أمر الشرط السابق ذكره ، علماً أنه يمكننا كتابة مجموعة من الأوامر قبل القفل .
في السطر رقم 7 نطلب من الأمر For الإمساك بأداة التحكم التالية في النموذج وهكذا .
في السطر رقم 8 ننهي الإجراء الفرعي .
ولكي نستدعي الإجراء نكتب CLEARDATA فقط ، في أي جزء من النموذج .
مثال 5 : لنفرض أنه لدينا أكثر من نموذج ( Form ) ، ونريد أن نطيق المثال رقم 4 فماذا نفعل ؟
الأمر بسيط ، وهو أن نعد الإجراء على أنه مشترك ونقوم بتعديل بسيط على الكود كما يلي ..
Public Sub CLEARDATA(ByVal frm As Form) Dim txt As Control For Each txt In frm.Controls If TypeOf txt Is TextBox Or TypeOf txt Is ComboBox Then txt.Text = "" End If Next End Sub
ولكي نستدعي الإجراء نكتب CLEARDATA(Me) فقط ، في أي جزء من البرنامج .
** كتابة الإجراءات الفرعية من نوع Function :
بنفس الأسلوب الذي استخدمناه مع الإجراءات الفرعية من نوع SubRoutine سوف يكون العمل إلا أنه سوف يختلف قليلاً ، حيث أن الدالة Function تختلف في طريقة الإعلان عنها وفي أنها تعود بقيمه كما ذكرنا سابقاً ، وهي تستخدم متغيراً لتحتفظ فيه بالقيمة التي سوف تعود بها الدالة ، مع مراعاة تحديد نوع المتغير...
مثال 6 : لنفرض أننا نريد أن نجري عمليه حسابية ( بسيطة أو معقده على حسب احتياجنا ) لمجموعة من المتغيرات ونريد أن نظهر النتيجة في مربع نص ، ونريد أن نقوم بذلك في أجزاء متعددة من النموذج ، فهل نكتب هذه العملية كلما احتجنا لها ؟
بالطبع إن كتابة إجراء فرعي من نوع Function خير سبيل لذلك ، ولتكن العملية الحسابية كما يلي ..
((Value1 + Value2)* Value3)/2 [Code/] ولندرس الآن كيف سوف يكون الكود الخاص بهذا الإجراء .. [Code] Private Function ComputationRate(ByVal Value1 As Single, ByVal Value2 _ As Single, ByVal Value3 As Single) As Single Dim MyOutCome As Single MyOutCome = ((Value1 + Value2)* Value3)/2 Return MyOutCome End Function
في البداية أعلنا عن الإجراء الفرعي بأنه من النوع خاص وأسمه ComputationRate وأنه من النوع Single ، وقمنا بتحديد عدد المتغيرات التي نحتاجها فيه مع ذكر نوع كل متغير ، وبعد ذلك صرحنا عن متغير من نوع Single وأسميناه MyOutCome لكي نخزن فيه نتيجة العملية الحسابية وهذا ما حدث في السطر الذي يليه ، وقبل أن ننهي الإجراء الفرعي أستخدمنا الكلمه Return لكي نرجع القيمه المخزنه في MyOutCome إلى الإجراء ComputationRate لأنها هي القيمة التي سوف يعود بها هذا الإجراء .
ولنكي نستدعي هذا الإجراء الفرعي ونملئ به مربع النص نكتب ..
Text1.Text = ComputationRate(3, 1, 5)
فيكون الرقم المكتوب في مربع النص هو الرقم 10 .
مثال 7 : لنفرض أنه لدينا مشروع كبير وبه مجموعة من النماذج ، كل نموذج به مجموعة من مربعات النص والقوائم المنسدلة ، وأننا نحتاج في نقطه معينة التأكد من عدم خلو هذه الأدوات المذكورة من البيانات لكي تتم معالجتها ، فهل نكتب على سبيل المثال الكود بهذا الشكل ..
If Text1.Text<>"" Or Text2.Text<>"" Or Text3.Text<>"" Or Text4.Text<>"" Or
Text5.Text<>"" Or Text6.Text<>"" Or Text1.Text<>"" Or ComboBox1.Text<>""
Or ComboBox2.Text<>"" Then
-
--
---
Else
MsgBox("يجب التأكد من أن جميع البيانات مدخلة")
End Ifبالطبع لا إن ذلك مضيعة للوقت والجهد ، ولكن مار أيكم لو كتبنا إجراء فرعي يقوم بالتأكد من عدم خلو هذه الأدوات من البيانات كي يتم معالجتها .
إذا فلندرس الكود التالي وهو عبارة عن إجراء فرعي من نوع Function مشترك ويعود بقيمة إما صائب أو خاطئ ..
1 Public Function NothingNullDATA(ByVal frm As Form) As Boolean 2 Dim txt As Control 3 Dim NothingIsNull As Boolean = True 4 For Each txt In frm.Controls 5 If TypeOf txt Is TextBox Or TypeOf txt Is ComboBox Then 6 If txt.Text = "" Then 7 NothingIsNull = False 8 End If 9 End If 10 Next 11 Return NothingIsNull 12 End Function
في السطر رقم ( 1 ) قمنا بالتصريح عن الإجراء الفرعي الذي أسميناه NothingNullDATA على انه مشترك بين جميع النماذج في البرنامج ، وهو من نوع Function ويعود بقيمة إما صائب أو خاطئ ، وله متغير واحد فقط من نوع Form وهو هنا اسم النموذج الذي نريد أن نطبق هذا الإجراء عليه .
في السطر رقم ( 2 ) قمنا بالتصريح عن متغير أسميناه txt وهو من نوع Control أي أداة تحكم.
في السطر رقم ( 3 ) قمنا بالتصريح عن متغير أسميناه NothingIsNull وهو من نوع Boolean وأعطيناه قيمة صائب كقيمة افتراضية.
في السطر رقم ( 4 ) أنشأنا تكرار باستخدام الأمر For Each لكل أدوات التحكم في النموذج .
في السطر رقم ( 5 ) 4 شرطنا على أداة التحكم التي أمسك بها الأمر السابق فيما إذا كانت مربع نص ( طبعاً استخدمنا العبارة TypeOf ) أو قائمة منسدلة ، فإنه ينفذ الأمر الموجود في السطر رقم 6 .
في السطر رقم ( 6 ) هنا شرطنا على أداة التحكم التي أمسكنا بها كي نختبرها فيما إذا كانت فارغة أو ممتلئة ، فإذا كانت فارغة فإنه سوف ينفذ الأمر الموجود في السطر 7 ، وإلا فإنه سوف يبحث عن أداة تحكم أخرى كي يختبرها من جديد.
في السطر رقم ( 7 ) نجعل قيمة المتغير NothingIsNull تساوي False . بمعنى أنه لا توجد بأداة التحكم الحالية أية بيانات أي أنها فارغة .
في السطر رقم ( 8 ) الخروج من أمر الشرط الثاني.
في السطر رقم ( 9 ) الخروج من أمر الشرط الأول.
في السطر رقم ( 10 ) نطلب من الأمر For الإمساك بأداة التحكم التالية في النموذج وهكذا .
في السطر رقم ( 11 ) استخدمنا ألكلمه Return لكي نرجع القيمة المخزنة في NothingIsNull إلى الإجراء NothingNullDATA لأنها هي القيمة التي سوف يعود بها هذا الإجراء .
في السطر رقم ( 12 ) ننهي الإجراء الفرعي .
ولكي نستدعي الإجراء نكتب NothingNullDATA(Me) فقط ، في أي جزء من البرنامج . وذلك كما يلي لمثالنا هذا ...
If NothingNullDATA(Me) = True Then
-
--
---
Else
MsgBox("يجب التأكد من أن جميع البيانات مدخلة")
End Ifهنا نصل إلى نهاية درسنا الذي لا أريد من ورائه جزاءً ولا شكورا سوى الدعاء لي ولوالدي وأسرتي ، وأرجو أن تسامحوني إن وجدتم أخطاء سواء في الإملاء أو الكود أو المعلومات أو الشرح ، فما كان من خطأ فهو من نفسي والشيطان وسوف نسعى إلى تصحيحه ما استطعنا ذلك ، وما كان من صواب فهو من توفيق الله سبحانه وتعلى .
وأرجوا أن تكون هذه المشاركة مخزن أو مستودع للإجراءات الفرعية ، وأدعو من يرغب من أخواني بالمشاركة في كتابة أجراءته الفرعية العامة أن ينشرها في هذه المشاركة حيث لا يصح أن نكتب أي إجراء فرعي في مشاركه مستقلة ما تلبث أن تختفي بعد فتره وجيزة ويصعب تجميعها من هنا وهناك أو حتى البحث عنها ، وذلك حتى تعم الفائدة للجميع ونكوّن قاعدة بيانات كبيره تكون مرجع لنا جميعاً . والله من وراء القصد ..
وفي الختام ما يسعني إلا أن أشكر الله سبحانه وتعالى على أن أعانني على كتابة هذا الدرس ألذي أرجو أن يتقبله مني ويجعله خالصاً لوجهه الكريم ...
ياسر الشيخ :P