TOP

VBA-レッスン 13.3。配列 (Arrays) の使用 (演習)

配列の使用を練習するために、配列の速度上の利点を段階的に示すために使用したマクロの独自バージョンを作成します。


この演習の開始点は次のとおりです (データセットが 1000 行に削減されていることがわかります)。

ここで、Excel サンプル ファイルをダウンロードできます: arrays_exercise.xls

演習の目的: この手順では、ループを使用してデータセット内のデータを処理し、各年および各顧客番号 (ユーザーの選択に応じて YES または NO) について YES または NO の応答の数をカウントし、この数量を入力する必要があります。ワークシートの指定されたセル内。

次のマクロを実行して、「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) のサイズを決定するために、データ セット内の「YES」または「NO」の回答の数を数えます。
  • データ セットから、配列内に「YES」または「NO」の回答が含まれる行のみを保存します (これは、3 列目のデータを保存する必要がないことを意味します)。
  • 解決策の一例を次に示します。

    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」の応答の数を決定します。

     '返信数 YES または NO
     rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
    

    配列は、YES または NO の応答の数に合わせてサイズ変更され、2 列に減りました。

    ReDim array_db(rows_number - 1, 1)
    

    このデータは、3 番目の列がユーザーの選択と一致した場合に配列に格納されます。

     '配列に数値を挿入する
     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
             'A列に値を保存する
             array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
             'B列に値を保存する
             array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
             '1 行が保存されました => 配列内の挿入番号が 1 ずつ増加します
             insert_row = insert_row + 1
         End If
     Next
    

    配列には、関心のあるデータのみが含まれています。

    あとは次のことだけです。

  • 2 つのループを使用して、「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