VBA

【VBAで配列を使う:実践編①】

VBAでの配列操作 実践編

エクセルVBAの配列操作をシリーズとして記事にしています。
配列は難しいイメージが強いですが、使いこなすととっても強力なのでぜひ使いこなせる様になってください。

入門編を読まれた方は、基礎は理解できていると思いますが、今回は基礎のおさらいも含めて少しづつ実践的な配列の操作に入っていきたいと思います。

動的1次元配列

配列の入門編では、あまり触れなかったのですが静的(サイズが固定の配列)なものしか扱えなければ、実務での有効活用は難しいです。

動的な配列とは、サイズを自由自在に変化させられる配列のことです。
イメージとしては、静的配列はガッチリした箱なのに対して、動的な配列はジャバラ付きの伸縮自在の入れ物だとイメージすると良いです。

動的な配列の宣言

まずサンプルコードをみてください。

Option Explicit

Sub DynamicArraySample()
    Dim myShtNameArray() As String
    Dim myBookNameArray As Variant
    Dim i As Long

    ReDim myShtNameArray(1 To Worksheets.Count) As String
    For i = 1 To Worksheets.Count
        myShtNameArray(i) = Worksheets(i).Name
    Next

    ReDim myBookNameArray(1 To Workbooks.Count) As String
    For i = 1 To Workbooks.Count
        myBookNameArray(i) = Workbooks(i).Name
    Next
    Stop
End Sub

コードをVBEへ貼り付けて、実際に実行してみてください。
上記サンプルコードでは2つの宣言方法で、配列を宣言しています。
どちらかといえば、バリアント型の宣言の方が柔軟な操作が可能になります。

いずれの方法で宣言した同的配列も要素数を決定する際に、ReDimステートメントを使用します。

なお、ReDimステートメントは何度でも使用でき、何度でもサイズ変更が可能です。

Stopステートメントの箇所で停止しますので、ローカルウィンドウで変数の中身を見ると下記の様に各要素を正しく取得出来ていることが確認できます。

VBEのメニューから、「表示」→「ローカルウィンドウ」で表示できます。

ReDimステートメントは実行する度に配列の要素の保持している値を削除(初期化)します。

値(要素)を保持したままサイズ変更

ReDimステートメントを使用することで、サイズは変更できる様になりましたが、実務で配列を操作する場合、要素の値を保持したままでサイズを動的に変更していきたいことも多いと思います。

VBAには、配列の要素を保持したままサイズ変更するステートメントが用意されています。
Preserveキーワードといいます。

文章での説明よりコード例の方が伝わると思いますので、したのコードを実行してみてください。

Option Explicit

Sub ReDimPreserve_Sample()
    Dim myArray() As String
    Dim myCnt As Long
    Dim myAnswer As Variant
    Do
        Do
            '入力ダイアログボックスを表示
            myAnswer = Application.InputBox("日本一高い山は?","答えを入力")
            'キャンセル時はそのまま終了
            If VarType(myAnswer) = vbBoolean Then Exit Sub
        '未入力の場合、再度入力ダイアログボックスを表示
        Loop While Len(myAnswer) = 0
        '入力された内容を動的配列のサイズを変えて保持
        'Preserveキーワードを使って、それまでの内容を失わない
        myCnt = myCnt + 1
        ReDim Preserve myArray(1 To myCnt) As String
        myArray(myCnt) = myCnt & "回目" & vbTab & myAnswer
    '正解したらループを抜ける
    Loop Until myAnswer = "富士山"
    '結果を表示
    MsgBox Join(myArray, vbCrLf) & vbCrLf & vbCrLf _
        & myCnt & "回目で正解しました。", vbInformation
End Sub

いかがでしょうか?
もしかしたら、知らない関数を使用しているかも知れませんが内容としては、インプットボックスで問題を出して、正解するまで無限ループを回す処理をしています。
その際に、入力内容と、回答を同的配列の要素は残したままサイズを変更して保持しています。
正解した時点で、ループを抜けてメッセージボックスで配列の中身をJoin関数で繋ぎ、表示しています。

多次元配列

多次元配列は入門編でも少し触れました。
想像しやすいもので、エクセルのワークシートそのものが2次元配列になります。
縦と横に値を格納する箱が並んでいるイメージです。

多次元配列の要素数変更

基本的には1次元配列と大きく変わらずに使用できるのですが、ReDimステートメントのPreserveキーワードを使って、内容を保持したまま再割り当てを行う場合には制限があります。

Preserveキーワードを使った場合、最終次元以外は変更ができない。

この制限は上級者の方でも、ついうっかり忘れてしまうので注意してください。

多次元配列への代入

入門編②でもセル範囲を代入するコードを記載していますが、読まれていない方のために、本記事でも類似コードを掲載しておきます。
まず、エクセルを開き図の様な表を作ってください。
※データはなんでも良いです。

Option Explicit

Sub ArraySample()
    Dim myArray() As Variant
    Dim myRng As Range
    'タイトル行を含めたデータ範囲
    With Sheet1.UsedRange
        '変数myRngにタイトル行を除いたデータ範囲の
        'Rangeオブジェクトへの参照を代入
        Set myRng = .Resize(.Rows.Count - 1).Offset(1)
    End With
    myArray = myRng.Value
    Stop
    Set myRng = Nothing
End Sub

ローカルウィンドウはこの様に表示されています。

多次元配列はVBAでは最大60次元まで扱うことができます。
しかし、高次元の配列を使用したコードは可読性に乏しく、メモリの消費も大きいので、実務で使用するのは3次元くらいまでにするのが普通です。

1次元配列と2次元配列をうまく活用できる様に学習することが配列操作をマスターする1番の近道ですので、たくさんのサンプルを作ってみてください!!

おわりに

駆け足で説明してきたので、伝わり難いところもあるかも知れませんが、このシリーズで書きたい事はまだまだ多いので、シリーズを全て読んでもらえれば、配列操作が、完璧にマスターできると思います。