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

صناعة الدوال الخاصة والتعامل مع الأحداث في مايكروسوفت إكسل VBA


محمد Albittar

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

تعرفنا سابقًا على آلية كتابة الإجراءات باستخدام فيجوال بيسك في درس مدخل إلى البرمجة باستخدام VBA في مايكروسوفت إكسل، ووجدنا أن الإجراء من النوع sub-routine يُنفذ أمرًا أو مجموعةً معينةً من الأوامر، وأن الإجراء من النوع Function يُضيف دوال على برنامج مايكروسوفت إكسل للاستخدام الاعتيادي كما لو أنها من ضمن دوال البرنامج الأساسية.

صناعة الدوال

توجد طريقتان لكتابة الإجراء هما:

إجراء مع وسطاء (معطيات)

وتكون الشيفرة كما يلي:

Function name(arguments) as type
    Code
End Function

حيث إن:

  • name: اسم للدالة التي نصنعها، ويُفضل أن يكون الاسم مُعبرًا عن عمل الدالة.
  • arguments: الوسطاء التي ستعمل الدالة مع محتوياتها.
  • type: نوع المُخرَج للدالة التي نصنعها.
  • Code: مجموعة الشيفرات التي ستُنفذها الدالة.

مثال

لدينا البيانات التالية، ونريد صناعة دالة خاصة تعمل على دمج الاسم الأول مع الأخير للحصول على الاسم الكامل.

001MakingFunction.PNG

لدينا وسيطان هنا، هما: الاسم الأول والاسم الأخير من النوع النصي، لذا نكتب الإجراء بالشكل التالي:

Function FullName(FirstName As String, LastName As String) As String
FullName = FirstName & " " & LastName
End Function

عند العودة إلى برنامج مايكروسوفت إكسل سنجد أن الدالة أُضيفت إلى الدوال الأساسية فيه، وتعمل مثل باقي الدوال الاعتيادية.

002MakingFunction.gif

اقتباس

يمكننا وضع وسيط في الدالة قيمته إما من خلية مرجعية مثل المثال السابق، أو ربما لا نضع له قيمة أبدًا، وعندها يجب أن نضع قبله الكلمة Optional التي تدل على أن هذا الوسيط اختياري، أي يمكن ألّا نُسند له قيمةً.

مثال

لدينا البيانات التالية، ونريد صناعة دالة خاصة تحسب الراتب بعد الزيادة، وذلك وفقًا لتقييم كل موظف.

003MakingFunction.PNG

حيث يتقاضى الموظف زيادةً قدرها 0.2 عندما يكون تقييمه أكثر من 7، وزيادةً قدرها 0.1 عندما يكون تقييمه أكثر من 5 وأقل من 7، وزيادةً أخرى قدرها 0.08 عندما يكون أكثر من 1، وزيادةً قدرها 0.04 إذا لم نُسند خانة التقييم للدالة، وعليه يكون الإجراء كالتالي:

Function NewSalary(Salary As Currency, Optional Rate As Integer) As Currency
 If Rate = 0 Then
NewSalary = Salary + (Salary * 0.04)
ElseIf Rate >= 7 Then
NewSalary = Salary + (Salary * 0.2)
 ElseIf Rate >= 5 Then
NewSalary = Salary + (Salary * 0.1)
ElseIf Rate >= 1 Then
NewSalary = Salary + (Salary * 0.08)
End If
End Function

بتنفيذ الدالة على البيانات السابقة نجد التالي:

004MakingFunction.gif

إجراء بدون وسطاء (معطيات)

وتكتب الشيفرة كما يلي:

Function name() as type
    Code
End Function

حيث إن:

  • name: اسم للدالة التي نصنعها، ويُفضل أن يكون الاسم مُعبرًا عن عمل الدالة.
  • type: نوع المُخرَج للدالة التي نصنعها.
  • Code: مجموعة الشيفرات التي ستُنفذها الدالة.

مثال

لنَعُد إلى المثال السابق، حيث نريد إضافة عمود يحتوي أرقامًا تعريفيةً عشوائيةً للموظف، لذلك نكتب الإجراء التالي:

Function RandCode() As Long
RandCode = Rnd() * 10000
End Function

عند تنفيذ الدالة على البيانات السابقة فسنحصل على النتيجة التالية:

005MakingFunction.gif

التعامل مع الأحداث

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

الصيغة العامة لكتابة الأحداث

Sub Event_Name (variables)
 Our code 
End sub

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

  • تُكتب الأحداث في محرر الفيجوال بيسك ضمن الأوراق أو ضمن الملف، وليس ضمن model؛ لأن الحدث هو خاص بورقة العمل أو الملف، وبالنقر مرتين على اسم الصفحة أو اسم الملف يفتح المحرر الخاص بالصفحة أو الملف.

006Event.gif

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

007Event.gif

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

008Event.gif

سنتعرف على بعض الأمثلة التي تشرح آلية عمل الأحداث.

مثال 1

نريد إنشاء حدث يُظهر رسالة ترحيب عند فتح صفحة معينة، لذا فأول ما نفعله البحث عن الحدث الذي يُنفذ عند فتح الصفحة، وهو مُعرّف بالاسم SheetActivate، وهذا الحدث يعمل على مستوى الملف، ويكون الإجراء كالتالي:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
 If Sh.Name = "Sheet2" Then
 MsgBox "hello"
 End If
End Sub

حيث إن المتغير sh هو متغير مُعرف في الحدث، يُعبر عن الصفحات كمتغيرات.

009Event.gif

مثال 2

نريد إظهار نفس الرسالة السابقة عند فتح ملف الإكسل. Workbook_Open: هو الحدث الذي يُنفّذ عند فتح ملف الإكسل، ولذلك نكتب الإجراء التالي:

Private Sub Workbook_Open()
MsgBox "welcome back"
End Sub

010Event.gif

مثال 3

نريد كتابة إجراء يُضيف الصفحات الجديدة في نهاية صف الصفحات، ولتنفيذ ذلك علينا تقسيم المراحل لعمل الإجراء ومعرفة الأوامر الضرورية لفعل ذلك:

  • Workbook_NewSheet: هو الحدث الذي يُنفذ عند إضافة صفحة عمل جديدة.
  • يجب في البداية أن نعرف عدد الصفحات في الملف، لذا لنُعرّف المتغير sheet_count، ونُخزن فيه قيمة الأمر الذي يحصي عدد الصفحات، وهو الأمر sheet.count.
  • نكتب الأمر المسؤول عن تحريك الصفحة الجديدة لآخر الصف، وهو الأمر التالي:
object.move after:=sheets("عدد الصفات في الملف")

حيث يُعبّر object هنا عن الصفحة الجديدة، ويُصبح الإجراء كالتالي:

Private Sub Workbook_NewSheet(ByVal Sh As Object)
Dim sheet_count As Integer
sheet_count = Sheet.Count
Sh.Move after:=Sheets("sheet_count")
End Sub

011Event.gif

مثال 4

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

Cells.Interior.ColorIndex = xlNone

حيث تعني القيمة xlNone جعل الخلية بلا لون، وهذه التعليمة تُلغي اللون لكل خلايا الصفحة. الآن نكتب التعليمة الخاصة بجعل خلايا السطر كاملًا تأخذ لونًا موحدًا كالتالي:

EntireRow.Interior.Color = RGB(14, 148, 148)

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Cells.Interior.ColorIndex = xlNone
Target.EntireRow.Interior.Color = RGB(14, 148, 148)
Target.EntireColumn.Interior.Color = RGB(14, 148, 148)
End Sub

011Event.gif

أهم الأحداث المرتبطة بملف العمل

الأحداث المرتبطة بملف العمل كثيرة، ولكن سنذكر أهمها فيما يلي:

  • Workbook_BeforeSave: الحدث قبل إتمام حفظ الملف.
  • Workbook_BeforePrint: الحدث قبل البدء بالطباعة.
  • Workbook_AfterSave: الحدث بعد إتمام حفظ الملف.
  • Workbook_SheetActivate: الحدث عند تنشيط (فتح) الصفحة (ورقة عمل معينة).
  • Workbook_NewSheet: الحدث عند إضافة ورقة عمل جديدة.
  • Workbook_SheetChange: الحدث عند تعديل ورقة عمل.
  • Workbook_BeforeClose: الحدث قبل إغلاق ملف الإكسل.
  • Workbook_Open: الحدث عند فتح ملف الإكسل.

أهم الأحداث المرتبطة بورقة العمل

  • Worksheet_Activate: الحدث عند تنشيط الصفحة.
  • Worksheet_BeforeDelete: الحدث قبل تنفيذ حذف الصفحة.
  • Worksheet_Change: الحدث عند إجراء تغييرات على الصفحة.
  • Worksheet_Deactivate: الحدث عند إلغاء تنشيط الصفحة (الانتقال إلى صفحة أخرى).

خاتمة

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

اقرأ أيضًا


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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...