TOP

VBA-Урок 13.3. Використання масивів (Arrays) (Вправи)

Щоби попрактикуватись у використанні масивів, ми створимо нашу власну версію макроса, яку ми використовували для демонстрації переваги масивів у швидкості, крок за кроком...


Далі є початкова точка цієї вправи (ви побачите, що набір даних був зменшений до 1000 рядків):

Тут ви можете завантажити Excel файл з прикладом: arrays_exercise.xls

Ціль вправи: процедура повинна обробляти дані в наборі даних за допомогою циклу і порахувати кількість відповідей "ТАК" або "НІ" для кожного року і для кожного номера клієнта (або "ТАК" або "НІ", залежно від вибору користувача) і ввести цю кількість у вказану комірку робочому аркуші.

Завершіть наступний макрос, щоби зберегти дані з робочого аркуша «DS» в масив:

  1. Sub actualize()  
  2.      Dim last_row As Integer  
  3.        
  4.      'Останній рядок набору даних  
  5.      '...  
  6.           
  7.      'Збереження набору даних в динамічному масиві  
  8.      Dim array_db()  
  9.      '...  
  10.           
  11. End Sub  

Ось один з прикладів вирішення:

  1. Sub actualize()  
  2.      Dim last_row As Integer  
  3.        
  4.      'Останній рядок бази даних  
  5.      last_row = Sheets("DS").Range("A1").End(xlDown).Row  
  6.   
  7.      'Збереження набору даних в динамічному масиві  
  8.      Dim array_db()  
  9.      ReDim array_db(last_row - 2, 2)  
  10.        
  11.      For row_number = 2 To last_row  
  12.          array_db(row_number - 2, 0) = Sheets("DS").Range("A" & row_number)  
  13.          array_db(row_number - 2, 1) = Sheets("DS").Range("B" & row_number)  
  14.          array_db(row_number - 2, 2) = Sheets("DS").Range("C" & row_number)  
  15.      Next  
  16. End Sub  

Це в основному повторює те, що ми робили на попередньому уроці...

Але зараз нам потрібно змінити наш макрос додаванням наступних дій:

  • Визначити вибір користувача ("ТАК" чи "НІ");
  • Порахувати кількість відповідей "ТАК" чи "НІ" в наборі даних, для того щоби визначити розмір масиву (Redim);
  • Зберігаємо тільки ті рядки з набору даних, що містять відповіді "ТАК" чи "НІ" в масиві (це означає, що не потрібно зберігати дані з третього стовпця).
  • Ось один з прикладів вирішення:

    1. Sub actualize()  
    2.      Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer  
    3.        
    4.      'Останній рядок бази даних  
    5.      last_row = Sheets("DS").Range("A1").End(xlDown).Row  
    6.   
    7.      'Пошук значення (YES чи NO)  
    8.      If Sheets("RES").OptionButton_yes.Value = True Then  
    9.          search_value = "YES"  
    10.      Else  
    11.          search_value = "NO"  
    12.      End If  
    13.        
    14.      'Кількість відповідей YES чи NO  
    15.      rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)  
    16.        
    17.      'Збереження набору даних в масив  
    18.      Dim array_db()  
    19.      ReDim array_db(rows_number - 1, 1)  
    20.   
    21.      insert_row = 0  
    22.        
    23.      For row_number = 2 To last_row  
    24.          value_yes_no = Sheets("DS").Range("C" & row_number)  
    25.            
    26.          If value_yes_no = search_value Then  
    27.              array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)  
    28.              array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)  
    29.              insert_row = insert_row + 1  
    30.          End If  
    31.      Next  
    32. End Sub  

    Пошук вибором користувача визначається на початку процедури наступним кодом:

    1. 'Пошук значення (YES чи NO)  
    2. If Sheets("RES").OptionButton_yes.Value = True Then  
    3.     search_value = "YES"  
    4. Else  
    5.     search_value = "NO"  
    6. End If  

    Ми використаємо функцію CountIF, щоби визначити кількість відповідей "ТАК" чи "НІ":

    1. 'Кількість відповідей YES чи NO  
    2. rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)  

    Розмір масиву був змінений, щоби відповідати кількості відповідей "ТАК" чи "НІ" і зменшити до двох стовпців:

    1. ReDim array_db(rows_number - 1, 1)  

    Тепер ці дані будуть збережені в масиві, коли його третій стовпець відповідає вибору користувача:

    1. 'Вставлення номеру в масив  
    2. insert_row = 0  
    3.   
    4. 'Обробка набору даних  
    5. For row_number = 2 To last_row  
    6.     'Значення стовпця C (YES чи NO)  
    7.     value_yes_no = Sheets("DS").Range("C" & row_number)  
    8.       
    9.     'Якщо значення відповідає вибору користувача, рядок зберігається в масиві  
    10.     If value_yes_no = search_value Then  
    11.         'Збереження значення в стовпець A  
    12.         array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)  
    13.         'Збереження значення в стовпець B  
    14.         array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)  
    15.         'Один рядок був збережений => номер вставлення в масиві збільшується на 1  
    16.         insert_row = insert_row + 1  
    17.     End If  
    18. Next  

    Наш масив містить лише ті дані, які нас цікавлять.

    Все, що ам залишилось зробити, це:

  • Обробити кожен елемент таблиці на робочому аркуші "RES", використовючи 2 цикла (така сама ідея, як і у вправі з шахматною дошкою);
  • Вставити загальну кількість входжень на цьому аркуші для кожного року в розрізі кожного номера клієнта для кожної комірки.
  • Ось один з прикладів вирішення:

    1. 'Кількість відповідей "YES"/"NO"  
    2. For no_years = 2011 To 2026  
    3.     For no_client = 1 To 30  
    4.         counter = 0  
    5.           
    6.         For i = 0 To UBound(array_db)  
    7.             If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then  
    8.                 counter = counter + 1  
    9.             End If  
    10.         Next  
    11.           
    12.         Cells(no_years - 2009, no_client + 1) = counter  
    13.     Next  
    14. Next  

    Вирішенн задачі з коментарями, що пояснюють це в деталях:

    1. 'Цикл для кожного рядка  
    2. For no_years = 2011 To 2026  
    3.   
    4.     'Цикл для кожного стовпця  
    5.     For no_client = 1 To 30  
    6.         'Скидання лічильника  
    7.         counter = 0  
    8.           
    9.         'Обробка масиву  
    10.         For i = 0 To UBound(array_db)  
    11.             'Перевірка, що рядок в таблиці відповідає року та номеру клієнта  
    12.             If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then  
    13.                 'Якщо рік та номер клієнта відповідає, лічильник збільшується на 1  
    14.                 counter = counter + 1  
    15.             End If  
    16.         Next  
    17.           
    18.         'Після обробки масиву, підсумок вводиться у відповідну комірку  
    19.         Cells(no_years - 2009, no_client + 1) = counter  
    20.     Next  
    21. Next  

    І накінець, код усього нашого макроса:

    1. Sub actualize()  
    2.      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  
    3.        
    4.      'Видалення вмісту  
    5.      Range("B2:AE17").ClearContents  
    6.        
    7.      'Останній рядок в наборі даних  
    8.      last_row = Sheets("DS").Range("A1").End(xlDown).Row  
    9.   
    10.      'Пошук значення (YES чи NO)  
    11.      If Sheets("RES").OptionButton_yes.Value = True Then  
    12.          search_value = "YES"  
    13.      Else  
    14.          search_value = "NO"  
    15.      End If  
    16.        
    17.      'Кількість відповідей YES чи NO  
    18.      rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)  
    19.        
    20.      'Збереження значень в масив  
    21.      Dim array_db()  
    22.      ReDim array_db(rows_number - 1, 1)  
    23.   
    24.      insert_row = 0  
    25.        
    26.      For row_number = 2 To last_row  
    27.          value_yes_no = Sheets("DS").Range("C" & row_number)  
    28.            
    29.          If value_yes_no = search_value Then  
    30.              array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)  
    31.              array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)  
    32.              insert_row = insert_row + 1  
    33.          End If  
    34.      Next  
    35.        
    36.      'Підрахунок відповідей YES чи NO  
    37.      For no_years = 2011 To 2026  
    38.          For no_client = 1 To 30  
    39.              counter = 0  
    40.                
    41.              For i = 0 To UBound(array_db)  
    42.                  If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then  
    43.                      counter = counter + 1  
    44.                  End If  
    45.              Next  
    46.              Cells(no_years - 2009, no_client + 1) = counter  
    47.          Next  
    48.      Next  
    49. End Sub  

    Тут ви можете завантажити Excel файл з прикладом: arrays_exercise_completed.xls