TOP

VBA- الدرس 13.3. استخدام المصفوفات (Arrays) (تمارين)

للتدرب على استخدام المصفوفات ، سننشئ نسختنا الخاصة من الماكرو الذي استخدمناه لإظهار ميزة السرعة للمصفوفات ، خطوة بخطوة ...


إليك نقطة البداية لهذا التمرين (ستلاحظ أنه تم تقليل مجموعة البيانات إلى 1000 صف):

هنا يمكنك تنزيل ملف Excel: arrays_exercise.xls

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

أكمل الماكرو التالي لحفظ البيانات من ورقة عمل "DS" في صفيف:

Sub actualize()
     Dim last_row As Integer
     
     'الصف الأخير من مجموعة البيانات
     '...
        
     'حفظ مجموعة من البيانات في مصفوفة ديناميكية
     Dim array_db()
     '...
        
End Sub

إليك أحد الأمثلة على الحل:

Sub actualize()
     Dim last_row As Integer
     
     'السطر الأخير من قاعدة البيانات
     last_row = Sheets("DS").Range("A1").End(xlDown).Row

     'حفظ مجموعة من البيانات في مصفوفة ديناميكية
     Dim array_db()
     ReDim array_db(last_row - 2, 2)
     
     For row_number = 2 To last_row
         array_db(row_number - 2, 0) = Sheets("DS").Range("A" & row_number)
         array_db(row_number - 2, 1) = Sheets("DS").Range("B" & row_number)
         array_db(row_number - 2, 2) = Sheets("DS").Range("C" & row_number)
     Next
End Sub

هذا يكرر بشكل أساسي ما فعلناه في الدرس السابق ...

لكننا الآن بحاجة إلى تعديل الماكرو الخاص بنا عن طريق إضافة الإجراءات التالية:

  • تحديد اختيار المستخدم ("نعم" أو "لا") ؛
  • احسب عدد الإجابات "نعم" أو "لا" في مجموعة البيانات لتحديد حجم المصفوفة (Redim) ؛
  • نحن نحفظ فقط تلك الصفوف من مجموعة البيانات التي تحتوي على الإجابات "نعم" أو "لا" في المصفوفة (وهذا يعني أنه ليست هناك حاجة لحفظ البيانات من العمود الثالث).
  • إليك أحد الأمثلة على الحل:

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer
         
         'السطر الأخير من قاعدة البيانات
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         'قيمة البحث (YES أو NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         'عدد الردود YES أو NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         'حفظ مجموعة بيانات في مصفوفة
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
    End Sub
    

    يتم تحديد البحث حسب اختيار المستخدم في بداية الإجراء من خلال الكود التالي:

     'قيمة البحث (YES أو NO)
     If Sheets("RES").OptionButton_yes.Value = True Then
         search_value = "YES"
     Else
         search_value = "NO"
     End If
    

    سنستخدم وظيفة CountIF لتحديد عدد الردود "نعم" أو "لا":

     'عدد الردود YES أو NO
     rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
    

    تم تغيير حجم المصفوفة لتلائم عدد الاستجابات بنعم أو لا وتم تصغيرها إلى عمودين:

    ReDim array_db(rows_number - 1, 1)
    

    سيتم الآن تخزين هذه البيانات في المصفوفة عندما يتطابق عمودها الثالث مع اختيار المستخدم:

     'إدخال رقم في المصفوفة
     insert_row = 0
    
     'معالجة مجموعة البيانات
     For row_number = 2 To last_row
         'قيمة العمود C (YES أو NO)
         value_yes_no = Sheets("DS").Range("C" & row_number)
         
         'إذا كانت القيمة تطابق اختيار المستخدم ، يتم تخزين السلسلة في المصفوفة
         If value_yes_no = search_value Then
             'حفظ القيمة في العمود أ
             array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
             'حفظ القيمة في العمود B
             array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
             'تم حفظ صف واحد => تمت زيادة رقم الإدراج في المصفوفة بمقدار 1
             insert_row = insert_row + 1
         End If
     Next
    

    تحتوي المصفوفة الخاصة بنا على البيانات التي نهتم بها فقط.

    كل ما تبقى للقيام به هو:

  • قم بمعالجة كل عنصر من عناصر الجدول في ورقة العمل "RES" باستخدام حلقتين (نفس فكرة تمرين رقعة الشطرنج) ؛
  • أدخل العدد الإجمالي للتكرارات في هذه الورقة لكل عام حسب رقم كل عميل لكل خلية.
  • إليك أحد الأمثلة على الحل:

     'عدد الردود "YES" / "NO"
     For no_years = 2011 To 2026
         For no_client = 1 To 30
             counter = 0
             
             For i = 0 To UBound(array_db)
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     counter = counter + 1
                 End If
             Next
             
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    حل المشكلة مع التعليقات التي تشرحها بالتفصيل:

     'حلقة لكل صف
     For no_years = 2011 To 2026
     
         'حلقة لكل عمود
         For no_client = 1 To 30
             'إعادة تعيين العداد
             counter = 0
             
             'معالجة المصفوفة
             For i = 0 To UBound(array_db)
                 'التحقق من أن الصف في الجدول يتوافق مع السنة ورقم العميل
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     'إذا تطابق العام ورقم العميل ، يزيد العداد بمقدار 1
                     counter = counter + 1
                 End If
             Next
             
             'بعد معالجة المصفوفة ، يتم إدخال النتيجة في الخلية المقابلة
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    وأخيرًا ، رمز الماكرو بالكامل:

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer, counter As Integer
         
         'حذف المحتوى
         Range("B2:AE17").ClearContents
         
         'الصف الأخير في مجموعة البيانات
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         'قيمة البحث (YES أو NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         'عدد الردود YES أو NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         'حفظ القيم في المصفوفة
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
         
         'عد الإجابات YES أو NO
         For no_years = 2011 To 2026
             For no_client = 1 To 30
                 counter = 0
                 
                 For i = 0 To UBound(array_db)
                     If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                         counter = counter + 1
                     End If
                 Next
                 Cells(no_years - 2009, no_client + 1) = counter
             Next
         Next
    End Sub
    

    هنا يمكنك تنزيل ملف Excel: arrays_exercise_completed.xls