تعلمنا في الدرس السابق حول تصميم واجهات إدخال البيانات باستخدام مايكروسوفت إكسل VBA كيفية تصميم واجهة إدخال البيانات وتوزيع الكائنات، وتنسيقها وتجهيزها لعملية البرمجة، وكذا ربطها بخلايا الصفحة التي ستُرحَّل إليها البيانات عند الضغط على زر الإدخال. وفي هذا المقال سنتعرف على كيفية برمجة هذه الواجهت باستخدام مايكروسوفت إكسل VBA.
كتابة الإجراءات الخاصة بالكائنات
لتحرير الشيفرة البرمجية الخاصة بالكائن نضغط على الكائن نقرةً مزدوجةً، لتظهر لدينا النافذة التي نكتب فيها الشيفرات والإجراءات مثل العادة.
مثال
لفهم آلية البرمجة بالتفصيل سنُبرمج الواجهة التي صممناها مسبقًا، ولكن في البداية يجب تجهيز صفحة استقبال البيانات في ملف الإكسل، فتصبح واجهة الإدخال وصفحة الإكسل كالتالي:
والآن سنحرر واجهة كتابة الشيفرات الخاصة بزر الإدخال، ونبدأ بكتابة التعليمات الخاصة بترحيل البيانات إلى صفحة الإكسل، وهنا نلاحظ أن الإجراء الموجود فيها هو إجراء يُنفذ عند النقر على الزر. والآن نُقسّم الشيفرة إلى أجزاء صغيرة ليسهل علينا التفكير في آلية إنشائها، والعمل الفعلي للواجهة هو جمع البيانات التي نُدخلها عبر كائناتها وترحيلها إلى صفحة الإكسل، ووضعها في السطر الأخير، لذا يجب علينا في البداية معرفة كيف يمكننا معرفة رقم السطر الأخير غير الفارغ، ثم نُرحل البيانات للسطر الذي يليه، ولمعرفة رقمه نَعُدّ الأسطر غير الفارغة ضمن الصفحة كالتالي:
-
نُعرّف متغير من النوع
integer
، أو من النوعlong
، ونُخزن فيه عدد الأسطر غير الفارغة كما يلي:
Private Sub btnAdd_Click() Dim LastRow As Long End Sub
-
نكتب الدالة المسؤولة عن عدّ الخلايا غير الفارغة، وهي الدالة
CountA
، ولكن لاستدعائها ضمن الإجراء نكتبها بالشكل التالي:
LastRow = WorksheetFunction.CountA(Sheets("الموظفون").Range("A:A"))
كما نلاحظ تُستدعى الدوال الأساسية في إكسل عن طريق الفيجوال بيسك بأن نضع قبلها التعليمة WorksheetFunction
، لكن هنا عند تحديد المجال يجب أن نُعرّف مساره كاملًا ابتداءً من اسم الصفحة كما في التعليمة السابقة، حيث نضع:
Sheets("الموظفون").Range("A:A")
أي أن المحرر يستدعي الدالة CountA
، ويحدد لها المجال الذي ستحصي الخلايا منه، ويُخزن النتيجة في المتغير LastRow
.
- الآن نربط كل كائن في الواجهة مع الخلية المقابلة له في صفحة الإكسل، وذلك كالتالي:
Sheets("الموظفون").Cells(LastRow + 1, 1).Value = UserForm.txtName.Value
هنا عرّفّنا المسار الذي سنُسند إليه قيمة الكائن، حيث إن التعليمة Cells(value1,value2)
لديها وسيطتان، الأولى تُعبر عن رقم السطر والثانية تُعبّر عن رقم العمود، ولدينا هنا رقم السطر هو عبارة عن متغير LastRow
الذي يَعُد الخلايا غير الفارغة ونضيف له القيمة 1 لنحصل على موقع أول سطر فارغ بعد البيانات؛ أما UserForm.Name.Value
، فتُعبر عن القيمة المُدخلة عن طريق الواجهة.
يجب أن لا ننسى أن نتعامل هنا عن طريق الاسم البرمجي، وبنفس الطريقة نُسند باقي الكائنات إلّا الكائنات من النوع OptionButton
، وهنا لدينا عدّة قيم للكائن، حيث يجب أن نفحص الكائن هل هو نشط أم لا، وذلك حتى نعوّض قيمة الكائن النشط منها في الخلية الخاصة به، وتكون التعليمات كالتالي:
If UserForm.OptMale = True Then Sheets("الموظفون").Cells(LastRow + 1, 3).Value = "Male" Else Sheets("الموظفون").Cells(LastRow + 1, 3).Value = "Female" End If
أما التعليمات الخاصة ببقية الكائنات فهي كالتالي:
Sheets("الموظفون").Cells(LastRow + 1, 2).Value = UserForm.JobStatus.Value Sheets("الموظفون").Cells(LastRow + 1, 5).Value = UserForm.PhoneNumber.Value Sheets("الموظفون").Cells(LastRow + 1, 6).Value = UserForm.Rate.Value Sheets("الموظفون").Cells(LastRow + 1, 4).Value = UserForm.Salary.Value
- نلاحظ أن البيانات تبقى موجودةً في الكائنات بعد الإرسال، لذا لا بد من كتابة تعليمات تعمل على تفريغ الكائنات بعد ترحيلها، ولإجراء ذلك نُسند قِيَمًا فارغةً للكائنات بعد عمليات الترحيل، وتكون التعليمات كالتالي:
UserForm.txtName.Value = "" UserForm.OptMale = False UserForm.OptFemale = False UserForm.JobStatus.Value = "" UserForm.PhoneNumber.Value = "" UserForm.Rate.Value = "" UserForm.Salary.Value = ""
نلاحظ أن العمليات تعمل على أكمل وجه والواجهة تعمل بطريقة جيدة، ولكن لو ضغطنا على زر الإدخال بدون ملء الكائنات بالبيانات، فسنلاحظ أنه سيملأ صفحة الإكسل بسطرٍ فارغ، وذلك يُعَد خطأً برمجيًا كبيرًا.
- نكتب شروط إدخال للتغلب على الحالة السابقة، لذا نفحص ببساطة جميع الكائنات قبل ترحيل البيانات، فإذا وُجد كائن فارغ فسنوجه المستخدم إلى تعبئته وعدم تركه فارغًا عن طريق رسالة نصية، والتعليمات الخاصة بهذا الجزء من الإجراء كالتالي:
If UserForm.txtName.Value = "" Or (UserForm.OptMale = False And UserForm.OptFemale = False) Or_ UserForm.JobStatus.Value = "" Or UserForm.PhoneNumber.Value = "" Or_ UserForm.JobRate.Value = "" Or UserForm.Salary.Value = "" Then_ MsgBox "يُرجى إتمام البيانات"
اقتباسيكون أحد الكائنين
OptFemale
وOptMale
حاملًا دائمًا للقيمةTrue
والبقيةFalse
، لذلك لا يمكننا فحصها ضمن الشرط مع التعبير المنطقيOR
، بل نفحص جميع قيم الكائن من النوعOption Button
، فإذا كانت جميعهاFalse
وبقية الكائنات أو أحدها فارغة، فعندها نُظهر رسالة الخطأ للمستخدم؛ أما إذا كانت إحدى القيم كائناتها بالقيمةTrue
بينما تحمل جميع الكائنات بيانات، فستُنفذ عملية الترحيل بدون أخطاء.
يصبح الإجراء كاملًا بالشكل التالي:
Private Sub btnAdd_Click() Dim LastRow As Long LastRow = WorksheetFunction.CountA(Sheets("الموظفين").Range("A:A")) If UserForm.txtName.Value = "" Or UserForm.JobStatus.Value = "" Or (UserForm.OptMale = False And UserForm.OptFemale = False) Or UserForm.PhoneNumber.Value = "" Or UserForm.Rate.Value = "" Or UserForm.Salary.Value = "" Then MsgBox "يُرجى إتمام البيانات" Else Sheets("الموظفون").Cells(LastRow + 1, 1).Value = UserForm.txtName.Value Sheets("الموظفون").Cells(LastRow + 1, 2).Value = UserForm.JobStatus.Value If UserForm.OptMale = True Then Sheets("الموظفون").Cells(LastRow + 1, 3).Value = "Male" Else Sheets("الموظفون").Cells(LastRow + 1, 3).Value = "Female" End If Sheets("الموظفون").Cells(LastRow + 1, 5).Value = UserForm.PhoneNumber.Value Sheets("الموظفون").Cells(LastRow + 1, 6).Value = UserForm.Rate.Value Sheets("الموظفون").Cells(LastRow + 1, 4).Value = UserForm.Salary.Value UserForm.txtName.Value = "" UserForm.OptMale = False UserForm.OptFemale = False UserForm.JobStatus.Value = "" UserForm.PhoneNumber.Value = "" UserForm.Rate.Value = "" UserForm.Salary.Value = "" End If End Sub
-
لتطوير العمل أكثر يمكننا إضافة زر جديد على الواجهة السابقة، وعمله هو حذف البيانات التي أدخلناها للكائنات ولم نُرحلها إلى صفحة الإكسل بعد (أي لم نضغط على زر الإدخال)، ويؤدي فقط الجزء الأخير من الإجراء السابق الخاص بتفريغ الكائنات بعد الإرسال، لذا نُضيف زرًا جديدًا نُسميه حذف البيانات، ونضع له الاسم البرمجي
BtnDelete
، ويكون الإجراء الخاص به كالتالي:
Private Sub BtnDelete_Click() UserForm.txtName.Value = "" UserForm.OptMale = False UserForm.OptFemale = False UserForm.JobStatus.Value = "" UserForm.PhoneNumber.Value = "" UserForm.Rate.Value = "" UserForm.Salary.Value = "" End Sub
تعامل واجهات الإدخال مع الأحداث
يمكننا توظيف الأحداث في التعامل مع واجهاتنا لتطوير عمل البرنامج، حيث يمكن التعامل مع الواجهة في الحدث كما تُعامل الدوال والتعليمات في الأحداث كما تعلمنا في درس صناعة الدوال الخاصة والتعامل مع الأحداث في مايكروسوفت إكسل VBA، ولا بد من تطبيق ذلك عمليًا لتوضيح الفكرة أكثر.
مثال
باستخدام الواجهة السابقة نريد تنفيذ إجراء يعمل على إظهار نافذة إدخال البيانات فقط وإخفاء برنامج الإكسل عند فتح الملف، ولإنجاز ذلك نفتح المحرر الخاص بملف العمل، ونختار من أحداثه الحدث الذي يُنفِّذ الأوامر عند فتح الملف، ونضع فيه التعليمات التالية:
Private Sub Workbook_Open() Application.Visible = False UserForm.Show End Sub
حيث يُخفي الأمر Application.Visible = False
ملف الإكسل، ويُظهر الأمر UserForm.Show
واجهة الإدخال عند فتح الملف، ويُشغلها.
نلاحظ أن الإجراء السابق يؤدي المطلوب، ولكن لدينا هنا خلل بسيط، وهو عند إغلاق واجهة الإدخال، حيث يبقى برنامج الإكسل مفتوحًا ويعمل في الخلفية، ولكنه مخفي.
لذا يجب أن نُجهّز حدثًا جديدًا يعمل على حفظ البيانات وإغلاق ملف الإكسل عند إغلاق واجهة إدخال البيانات السابقة، أي أن الحدث خاص بواجهة الإدخال، لذا نكتب التالي:
Private Sub UserForm_Terminate() ActiveWorkbook.Save Application.Quit End Sub
حيث إن:
- UserForm_Terminate: هو حدث يُنفّذ عند إغلاق الواجهة.
- ActiveWorkbook.Save: هو أمر يحفظ ملفات العمل النشطة، وبما أن ملف العمل مرتبط مُسبقًا بالواجهة، فإن الأمر سيُنفذ عليه حتى لو وجدت العديد من ملفات العمل مفتوحةً، لأنه بمجرد النقر ضمن الواجهة يصبح الملف المرتبط بها هو الملف النشط.
- Application.Quit: أمر إغلاق ملف العمل.
لكن يجب الانتباه أنه بمجرد تشغيل هذا الإجراء، فلن نستطيع عرض البيانات من صفحة الإكسل، لذا يجب إضافة إجراء يعمل على فتح البيانات في صفحة الإكسل، ويُنفذ عن طريق زر في الواجهة نفسها.
نضيف زرًا جديدًا يُنفذ الإجراء السابق، ونسميه عرض البيانات، ونسميه اسمًا برمجيًا مثل BtnShowData
، ونكتب الإجراء المناسب لهذه العملية كالتالي:
Private Sub BtnShowData_Click() Application.Visible = True Sheets("الموظفون").Activate UserForm.Hide End Sub
خاتمة
إن تصميم وبرمجة الواجهات من أجمل المزايا في برمجة الإكسل، حيث يزيد العمل عن طريق الواجهات من دقة البيانات المُدخلة، كما يقلل التعامل مع البيانات -عن طريق واجهات تفاعلية- من عمليات التشتت، وكلما تعمقنا أكثر في تطوير برمجياتنا على إكسل، زاد إنتاجنا وكفاءتنا في تقديم البيانات الدقيقة بالسرعة المطلوبة، لأن برمجة الواجهات تضيف شروطًا كثيرةً على العمل، مما يجعل المستخدم أقل عرضةً للوقوع في أخطاء إدخال البيانات بالطريقة التقليدية.
اقرأ أيضًا
- استخدام أدوات مايكروسوفت إكسل لتنسيق الخلايا عن طريق الشيفرات VBA
- استخدام الشيفرات لتنفيذ العمليات الأساسية في مايكروسوفت إكسل VBA
- التفاعل مع المستخدم في مايكروسوفت إكسل باستخدام VBA
- الحلقات التكرارية في مايكروسوفت إكسل باستخدام VBA
- العمليات الشرطية في مايكروسوفت إكسل باستخدام VBA
- مدخل إلى البرمجة باستخدام VBA في مايكروسوفت إكسل
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.