ゆんの業務改善ブログ

①生産性向上 ②業務改善 ③自動化 について情報発信しています。VBAプログラムは本当の初心者から他のアプリケーションを呼び出して使う上級者的な使い方まで幅広いレベルで解説していきます。

VBA 配列を徹底的に解説する (全5回) ③静的配列の初期化と実務的なサンプル

VBAの静的配列の初期化とその具体実務的なサンプルを見て行きます。配列が初期化できると実務的に便利なことが多いです。難しくないので、順番に見て行きましょう。

目次

静的配列の初期化と実務的なサンプルを解説する

配列の初期状態とは

まず始めに、配列の初期状態について確認しておきます。

Sub 配列を作成する()
    
    Dim arr(4) As Variant
    
End Sub

もっとも単純な例で確認します。F8で一行ずつ実行してローカルウィンドウを確認します。
f:id:mutable_yun:20190922110318p:plain

値の所を見ると、Empty 値 となっています。””(長さ0の文字列)でも数字の0でもNothingでもありません。Emptyという「空の状態」という状態を表す特殊な値が入っていることが分かりました。

静的配列の初期化を行う

配列を宣言したばかりの状態では各要素はEmpty(空の状態)となっていることが分かりました。矛盾している様に思うかもしれませんが、各要素にEmpty(空の状態)が格納されている、と考えると良いでしょう。

静的配列の各要素を初期化する

初期状態でEmptyが格納されていると言うことは、逆にEmptyを格納すれば初期化できることになります。

Sub 静的配列の要素の初期化1()

    Dim arr(4) As Variant
    
    arr(0) = "Good Morning"
    arr(1) = "Hello"
    arr(2) = "Good Afternoon"
    arr(3) = "Good Evening"
    arr(4) = "Good Night"
   
    arr(2) = Empty
    
End Sub

f:id:mutable_yun:20190922111256p:plain
arr(2)にEmptyを設定することにより初期化

静的配列をループで初期化する

静的配列は同じグループの複数パラメータが格納されているのに適した変数の型です。そのため、配列を初期化したいときは、どれかの要素を一つだけ初期化するというより、全部初期化したい場面の方が多いと思います。

たとえばエクセルシートに仕入れ先一覧表があって、一行ごとに仕入れ先情報が格納されている。一行ごとにその仕入れ先情報を配列に格納し、別シートで何らかの作業を行い、その作業が終わったら配列を初期化して、次の行の仕入れ先のデータに移る、と言った具合です。

それでは、静的配列を初期化するにはどうすれば良いのでしょうか。結論としては静的配列そのものをEmptyにする事はできません。実験してみます

Sub 実験_配列そのものをEmptyにできるのか()
    
    Dim arr(4) As Variant
    
    arr(0) = "Good Morning"
    arr(1) = "Hello"
    arr(2) = "Good Afternoon"
    arr(3) = "Good Evening"
    arr(4) = "Good Night"
    
    arr = Empty
    
End Sub

f:id:mutable_yun:20190922112154p:plain
コンパイルエラーが発生した

今回は一行ごとの文法のミスはないので(一行だけ見ればarrは配列とはわからず、Variant型の変数の値をEmptyに設定しようとしただけなのでこの一行だけ見ればエラーではない)コーディング中のエラーは出ませんでしたが、実行前のコンパイルでエラーとなりました。

つまり、実行を押した瞬間にコード全体を見ると配列として宣言した変数arrにEmptyをいれようとしたことがわかったのでコンパイルエラーとなりました。(カッコをつける事が配列である事の宣言でしたね)

今回のエラーはarr = Emptyの部分で発生しました。つまり、arrは配列として宣言してそのものの実態があるのにそれをEmptyにはできない、と言う事です。

考えてみれば私たちがここでやりたいことは、arrの要素をすべてEmptyにしたい、と言う事であって、arrそのものをEmptyにしたわけではありません。そこで、ループを使って、全ての要素をEmptyにします。各要素にEmptyを格納していくイメージでOKです。

正しい初期化のサンプルは下記の通りです。

Sub ループを使って初期化する()
    
    Dim arr(4) As Variant
    Dim i As Long
    
    arr(0) = "Good Morning"
    arr(1) = "Hello"
    arr(2) = "Good Afternoon"
    arr(3) = "Good Evening"
    arr(4) = "Good Night"
    
    For i = 0 To 4
        arr(i) = Empty
    Next i
    
    Stop
    
End Sub

これで無事に初期化できています。

静的配列を初期化するにはループを使う
ループで初期化した実行結果

LBound関数とUBound関数

今回は静的配列なので一番小さなインデックスと一番大きなインデックスの数値がいくつか分かっています。なので数字で直接ループの範囲を指定しても構いません。

しかし、今後業務の内容が変更になり、配列に格納したいパラメータ(値)の数が変わることも想定して、配列の一番小さいインデックスと一番大きなインデックスを取得する関数を使う方が
好ましいでしょう。

Sub LBoundとUBound関数()
    
    Dim arr(4) As Variant
    
    Debug.Print LBound(arr)
    Debug.Print UBound(arr)
    
End Sub

実行結果

 0 
 4 

LBound関数、UBound関数の使い方は引数にインデックスの最小値や最大値を取得したい配列名を入れるだけです。

本当はもう一つ引数をとることができるのですが、それは多次元配列のところで解説します。今は、単に配列名を引数として渡す、と覚えればOKです。ちなみに引数は「ひきすう」と読みます。プロシジャや関数に渡す入力値のことです。

インデックスの最小値と最大値が取得できたので後はFor~Next文で一つずつEmptyを入れて行きます。

先ほどの、サンプルプロシジャのインデックスの下限と上限をLBound関数とUBound関数で取得します。

 Sub ループで配列の各値を初期化する()
    
    Dim arr(4) As Variant
    
    arr(0) = "Good Morning"
    arr(1) = "Hello"
    arr(2) = "Good Afternoon"
    arr(3) = "Good Evening"
    arr(4) = "Good Night"
    
    Dim i As Long
    
    For i = LBound(arr) To UBound(arr)
        arr(i) = Empty
    Next i
    
End Sub

いつものようにF8で一行ずつ実行していきます。

f:id:mutable_yun:20190922113822p:plain
結果

配列arrの各要素に値が順に格納され、その後、順にEmptyに戻っていく様子が分かります。

実務的なサンプルを作成する

実務で使うサンプルに移ります。

f:id:mutable_yun:20190921184841p:plain
売上データサンプル

今回は上のようなデータをサンプルとして考えます。これは各支店の売上のデータのイメージです。このデータを分析するために、

  1. 一行分のデータを配列に格納する
  2. 何らかの処理を行う
  3. 配列を初期化する
  4. 次の行に移る

これを最終行まで繰り返します。

Sub 実務的サンプル()
    
    '>下準備で必要な変数や定数を用意しておく
    Const 最初の行rw As Long = 2
    Dim 最終行rw As Long
    
    Const 最初の列clm As Long = 1
    Const 最後の列clm As Long = 4
    
    Dim 売上データ行arr(最初の列clm To 最後の列clm) As Variant
    
    Dim i As Long 'ワークシートの最初の行から行方向にカウントアップする
    Dim j As Long '売上データを格納するためのカウントアップ
    '<下準備ここまで
    
    最終行rw = Cells(Rows.Count, 1).End(xlUp).Row
    
    For i = 最初の行rw To 最終行rw '一番大きなループ。行方向にループする
        
        '>配列にデータを格納
        For j = 最初の列clm To 最後の列clm
            売上データ行arr(j) = Cells(i, j)
        Next j
        '<配列にデータを格納
        
        '>メインの作業
        'ここにメインの作業を書く。Callで別に記述したプロシジャを呼び出すのがおすすめ
        '<メインの作業
        
        '>次の行に移る前に配列を初期化する
        For j = 最初の列clm To 最後の列clm
            売上データ行arr(j) = Empty
        Next j
        '<次の行に移る前に配列を初期化する
    Next i
    
End Sub

はい、できました。便利ですね!これからは配列をうまく使ってコードをシンプルにし、ワークシートへの参照回数を減らしていきましょう。ワークシートへの参照回数を減らすことはマクロの高速化にもつながりますよ。

静的配列の初期化と実務的なサンプルまとめ

  • 静的配列は一気には初期化できない
  • 静的配列はループで初期化する
  • 配列のインデックス番号の下限値と上限値はLBound関数とUBound関数を使って取得できる

<関連記事>