اذهب إلى المحتوى

برمجة واجهات إدخال البيانات باستخدام مايكروسوفت إكسل VBA


محمد Albittar

تعلمنا في الدرس السابق حول تصميم واجهات إدخال البيانات باستخدام مايكروسوفت إكسل VBA كيفية تصميم واجهة إدخال البيانات وتوزيع الكائنات، وتنسيقها وتجهيزها لعملية البرمجة، وكذا ربطها بخلايا الصفحة التي ستُرحَّل إليها البيانات عند الضغط على زر الإدخال. وفي هذا المقال سنتعرف على كيفية برمجة هذه الواجهت باستخدام مايكروسوفت إكسل VBA.

كتابة الإجراءات الخاصة بالكائنات

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

مثال

لفهم آلية البرمجة بالتفصيل سنُبرمج الواجهة التي صممناها مسبقًا، ولكن في البداية يجب تجهيز صفحة استقبال البيانات في ملف الإكسل، فتصبح واجهة الإدخال وصفحة الإكسل كالتالي:

001UserForm.PNG

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

  • نُعرّف متغير من النوع 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

002UserFormPrograming.gif

  • نلاحظ أن البيانات تبقى موجودةً في الكائنات بعد الإرسال، لذا لا بد من كتابة تعليمات تعمل على تفريغ الكائنات بعد ترحيلها، ولإجراء ذلك نُسند قِيَمًا فارغةً للكائنات بعد عمليات الترحيل، وتكون التعليمات كالتالي:
UserForm.txtName.Value = ""
UserForm.OptMale = False
UserForm.OptFemale = False
UserForm.JobStatus.Value = ""
UserForm.PhoneNumber.Value = ""
UserForm.Rate.Value = ""
UserForm.Salary.Value = ""

003UserFormPrograming.gif

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

004UserFormPrograming.gif

  • نكتب شروط إدخال للتغلب على الحالة السابقة، لذا نفحص ببساطة جميع الكائنات قبل ترحيل البيانات، فإذا وُجد كائن فارغ فسنوجه المستخدم إلى تعبئته وعدم تركه فارغًا عن طريق رسالة نصية، والتعليمات الخاصة بهذا الجزء من الإجراء كالتالي:
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 بينما تحمل جميع الكائنات بيانات، فستُنفذ عملية الترحيل بدون أخطاء.

005UserFormPrograming.gif

يصبح الإجراء كاملًا بالشكل التالي:

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 واجهة الإدخال عند فتح الملف، ويُشغلها.

006UserFormPrograming.gif

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

007UserFormPrograming.gif

لذا يجب أن نُجهّز حدثًا جديدًا يعمل على حفظ البيانات وإغلاق ملف الإكسل عند إغلاق واجهة إدخال البيانات السابقة، أي أن الحدث خاص بواجهة الإدخال، لذا نكتب التالي:

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

008UserFormPrograming.gif

خاتمة

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

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...