配列とは、同じ種類のデータを複数個まとめて保存するための変数のことです。静的配列と動的配列があります。
静的配列
静的配列は、配列を宣言するときに要素数を指定する配列です。
数値の場合
以下の例は、静的配列を宣言して要素に値を代入する例です。
Sub Sample1()
'配列を添字1~5で宣言
Dim myArray(1 To 5) As Integer
'For文用のイテレーターを宣言
Dim i As Integer
'myArrayの初期化
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
myArray(5) = 5
'格納されているデータをForループでイミディエイトウィンドウに出力
For i = 1 To 5
Debug.Print myArray(i)
Next i
End Sub
上記の例では、要素数が5の整数型配列を宣言し、各要素に値を代入しています。最後にイミディエイトウィンドウに各配列の要素を出力しています。
上記のコードの動作イメージは以下のとおりです。
上の図のとおり、まず、添字1~5の配列を宣言し、次に宣言した配列に対して1~5数値を添字1~5の配列にそれぞれ数値を代入しています。
文字列の場合
以下の例は、静的配列を宣言して要素に文字列を代入する例です。
Sub Sample2()
'配列を添字1~3で宣言
Dim S(1 To 3) As String
'For文用のイテレーターを宣言
Dim i As Integer
'配列を初期化
S(1) = "佐藤"
S(2) = "山本"
S(3) = "田中"
'格納した文字列をForループでイミディエイトウィンドウに出力
For i = 1 To 3
Debug.Print S(i)
Next i
End Sub
上記の例では、要素数が3の文字列型配列を宣言し、各要素に値を代入しています。最後にイミディエイトウィンドウに各配列の要素を出力しています。
上記のコードの動作イメージは以下のとおりです。
上の図のとおり、まず、添字1~3の配列を宣言し、次に宣言した配列に対してそれぞれの文字列を添字1~3の配列にそれぞれ数値を代入しています。
配列を返す関数(Split関数)
Excel VBAでよく利用されるのが、Split関数です。この関数は配列を返り値として返します。
Sub Sample3()
'Split関数の返り値を格納する変数CとFor文用のイテレーターを宣言
Dim C As Variant, i as Long
'文字列をカンマで分割した結果を変数Cに格納
C = Split("A,B,C", ",")
'Split関数で格納した変数CをForループでイミディエイトウィンドウに出力
For i = 0 To UBound(C)
Debug.Print C(i)
Next i
End Sub
上記の例では、Split関数によって”,”(カンマ)で文字列を分割して各要素に値を代入した配列をValiant型の変数”C”に返しています。最後にイミディエイトウィンドウに各配列の要素を出力しています。
上記のコードの動作イメージは以下のとおりです。
補足として、以下の3点がポイントです。
- Excel VBAでは配列型が存在しないため、配列を受け取る変数は、Variant型で宣言する必要があります。
- Split関数を利用した場合の配列の添字は0から始まることに注意が必要です。
- 文字列の分割数が不明の場合は、配列の上限(UBound関数)を利用すると配列の上限値を自動的に取得することが可能です。
Split関数を利用すると、CSVなどのテキストファイルを取り込んで各々のデータに対して処理を行うことが可能となり、ぜひ習得することをお勧めします。
動的配列
先ほどまでは、配列を宣言するときに、あらかじめ配列の要素数がわかっていることを前提としていました。
一方で、配列宣言時にいくつ値を格納するかわからない場合もあります。たとえば
- あるフォルダの中に存在するすべてのブック名を格納する。
- テキストのデータを検索して条件に合致する行のみ配列に格納する。
上記の場合、変数宣言時には要素数を指定しないで配列を宣言し、マクロの中で必要に応じて要素数を指定することができます。このような配列を動的配列と呼びます。
動的配列の利用方法
以下の例は、動的配列を宣言して要素に値を代入する例です。
Sub Sample4()
'数値格納用のmyArrayとFor文用のイテレーターiを宣言
Dim myArray() As Integer
Dim i As Long
'宣言したmyArrayの大きさを再定義(添字は0~4になる)
ReDim myArray(4)
'myArrayの配列に数値を格納
myArray(0) = 1
myArray(1) = 2
myArray(2) = 3
myArray(3) = 4
myArray(4) = 5
'格納した文字列をForループでイミディエイトウィンドウに出力
For i = 0 To UBound(myArray)
Debug.Print myArray(i)
Next i
End Sub
上記の例では、ReDimステートメントを使用して、要素数が5の整数型配列を宣言しています。
なお、「myArray(4)」は動的配列の要素を「0~4」にしています。
最後にイミディエイトウィンドウに各配列の要素を出力しています。動的配列のため、Split関数と同様に上限値が予めわからないため、UBound関数を利用して上限値(ここでは「4」)を返しています。
動的配列の拡張方法(Preserveキーワード)
動的配列は、状況に応じ要素数の変更を行うことが可能な反面、ReDimステートメントを利用するとこれまで格納していた値が消えてしまうため注意が必要です。
例として以下のマクロがあったとします。
Sub Sample5()
'数値格納用のmyArrayとFor文用のイテレーターiを宣言
Dim myArray() As Integer
Dim i As Long
'配列myArrayの要素数(1~4)の再定義
ReDim myArray(4)
'配列に数値を格納
myArray(0) = 1
myArray(1) = 2
myArray(2) = 3
'配列myArrayの要素数(1~5)を再定義
'※前に格納した1~3の数値は0に初期化される
ReDim myArray(5)
'配列に数値を格納
myArray(3) = 4
myArray(4) = 5
myArray(5) = 6
'配列myArrayをForループでイミディエイトウィンドウに出力する
For i = 0 To UBound(myArray)
Debug.Print myArray(i)
Next i
End Sub
上記のマクロを実行した場合、動作結果は以下のとおりとなります。
イミディエイトウィンドウの実行結果から、「0~2」要素目に入力した「1~3」の値が消去されて「3~5」要素目の「4~6」の値が入力された状態となっています。
今回の「0~2」要素目を消去せず保持したいといったこともあろうかと思います。
その場合、Preserveキーワードを使うことで配列の要素数を変更した後も、前に入力した値を保持することができます。
上記のマクロにPreserveキーワードを利用した例を記載します。
Sub Sample6()
'Forループを利用してイミディエイトウィンドウに配列の内容を出力
Dim myArray() As Integer
Dim i As Long
'配列myArrayの要素数(1~4)の再定義
ReDim myArray(4)
'配列に数値を格納
myArray(0) = 1
myArray(1) = 2
myArray(2) = 3
'配列myArrayの要素数(1~5)を再定義
'※前に格納した1~3の数値は残る
ReDim Preserve myArray(5)
'配列に数値を格納
myArray(3) = 4
myArray(4) = 5
myArray(5) = 6
'配列myArrayをForループでイミディエイトウィンドウに出力する
For i = 0 To UBound(myArray)
Debug.Print myArray(i)
Next i
End Sub
前回のマクロにPreserveキーワードのみを追加したことがわかります。
実行結果は以下のとおりです。
「0~2」要素目に入力した「1~3」の値が保持されていることがわかります。
配列でよく利用する関数
配列を扱ううえで、よく利用する関数を紹介します。
UBound関数
UBound関数は、配列の最大の要素番号を返します。以下の例は、UBoundを使って配列の最大の要素番号を取得する例です。
Sub Sample7()
'数値格納用のmyArrayと配列の最大の要素番号格納用のmaxIndexを宣言
Dim myArray(1 To 5) As Integer
Dim maxIndex As Integer
'myArrayの最大の要素番号をmaxIndexに代入
maxIndex = UBound(myArray)
'イミディエイトウィンドウにmaxIndexの値を出力
Debug.Print maxIndex
End Sub
上記の例では、要素数が5の整数型配列myArray宣言し、UBound関数を使って最大のインデックス番号を変数maxIndexに代入しています。
UBound関数をFor文で利用する
Forループで配列を処理する場合、UBound関数を使用して、配列の要素数を取得することができます。
以下は、Forループを使用して配列の要素を出力する例です。
Sub Sample8()
'数値格納用のmyArrayとFor文用のイテレーターiを宣言
Dim myArray(1 To 5) As Integer
Dim i As Integer
'配列に数値を格納
myArray(1) = 1
myArray(2) = 2
myArray(3) = 3
myArray(4) = 4
myArray(5) = 5
'Forループを利用してイミディエイトウィンドウに配列の内容を出力
For i = 1 To UBound(myArray)'UBound関数で最大の要素番号5を取得
Debug.Print myArray(i)
Next i
End Sub
上記の例では、配列myArrayの要素を出力するために、Forループを使用しています。UBound関数を使用して、配列の要素数を取得し、Forループの終了条件に指定しています。
Forループの中で、配列の各要素を取得するために、myArray(i)という添字を使用しています。i
が1から5まで変化するため、myArray(i)は、myArray(1)からmyArray(5)までの要素を順に取得します。取得した要素は、Debug.Printを使用して、即座に出力されます。
Forループは、配列の要素を処理するために頻繁に使用されます。配列の要素数が不定の場合は、UBound関数を使用して要素数を取得し、Forループの終了条件に指定することで、汎用的なコードを作成することができます。
LBound関数
LBound関数は、配列の最小の要素番号を返します。以下の例は、LBound関数を使って配列の最小の要素番号を取得することができます。
Sub Sample9()
'数値格納用のmyArrayと配列の最大の要素番号格納用のminIndexを宣言
Dim myArray(1 To 5) As Integer
Dim minIndex As Integer
'myArrayの最小の要素番号1を格納する
minIndex = LBound(myArray)
'イミディエイトウインドウにminIndexの値を出力する
Debug.Print minIndex
End Sub
上記の例では、添字1~5の配列を作成し、変数minIndexにLbound関数で最小の要素番号を格納します。その後、変数minIndexの値「1」を表示します。
LBound関数をFor文で利用する
LBound関数を使用することで、配列の範囲をより正確に指定することができます。
以下は、LBound関数を使用して配列の範囲を指定する例です。
Sub Sample10()
'数値格納用のmyArrayとFor文用のイテレーターiを宣言
Dim myArray(0 To 4) As Integer
Dim i As Integer
'配列に数値を格納
myArray(0) = 1
myArray(1) = 2
myArray(2) = 3
myArray(3) = 4
myArray(4) = 5
'Forループを利用してイミディエイトウィンドウに配列の内容を出力
For i = LBound(myArray) To UBound(myArray)'要素番号が不定の場合も処理可能となる
Debug.Print myArray(i)
Next i
End Sub
上記の例では、配列myArrayの範囲を0から4に指定しています。LBound関数を使用して、配列の最小のインデックスを取得し、Forループの開始条件に指定しています。これにより、配列の最初の要素であるmyArray(0)から処理を開始することができます。
Forループの終了条件には、UBound関数を使用して、配列の最大のインデックスを指定しています。配列の最後の要素であるmyArray(4)まで順に処理することができます。
このように、LBound関数を使用することで、配列の範囲を正確に指定し、配列の大きさが変更となった場合も対応できるようになります。
Filter関数
Filter関数は、配列から条件に合致する要素を抽出します。以下は、配列から偶数の要素を取得する例です。
Sub Sample11()
'数値格納用のmyArrayとFor文用のイテレーターiを宣言
Dim myArray(1 To 5) As String
Dim i As Integer
'配列に文字列を格納
myArray(1) = "1"
myArray(2) = "2"
myArray(3) = "23"
myArray(4) = "4"
myArray(5) = "25"
'フィルタした後のデータを格納する変数を宣言
Dim filteredArray As Variant
'"2"が含まれるデータをフィルタした結果("2"と"23"と"25")がFilterdArrayに格納
filteredArray = Filter(myArray, "2", True)
'Forループを利用して、filteredArrayの内容をイミディエイトウィンドウに出力
For i = LBound(filteredArray) To UBound(filteredArray)
Debug.Print filteredArray(i)
Next i
End Sub
上記の例では、Filter関数を使用して、配列myArrayから偶数の要素を取得しています。Filter関数の第1引数には対象となる配列を指定し、第2引数には検索する値(ここでは”2″)を指定します。第3引数には、Trueを指定すると、指定の要素を含む文字列(ここでは”2″と”23″と”25″)が格納されます。
ちなみにFalseを指定するとそれ以外(“1″と”4”)が格納されます。
Array関数
Array関数は、配列を初期化することができます。以下は、配列を初期化を行う例です。
Sub sample12()
'配列を格納する変数Arと配列の要素を格納するresult変数を宣言
Dim Ar As Variant
Dim result As String
'Array関数作られた配列をArに格納
Ar = Array("松", "竹", "梅", "なし")
'Arの要素0の"松"をresultに格納
result = Ar(0)
'resultの内容をイミディエイトウィンドウに出力
Debug.Print result
End Sub
上記の例ではArray関数を利用して配列の初期化を行い、要素0のデータをresultに格納したresult変数の内容を出力します。
Join関数
Join関数は、1次元配列に格納されている文字列を指定の区切り文字で結合することができます。
以下は、格納した文字列をカンマ区切りで結合した例です。
Sub sample13()
'配列を格納する変数Arと配列の要素を格納するresult変数を宣言
Dim Ar As Variant
Dim result As String
'Array関数作られた配列をArに格納
Ar = Array("松", "竹", "梅", "なし")
'Arの要素を","で結合した結果をresultに格納
result = Join(Ar,",")
'resultの内容をイミディエイトウィンドウに出力
Debug.Print result
End Sub
注意点としては、文字列に含まれていない文字列を利用するといった考慮が必要となります。
※含まれていた場合、Sprit関数で元の状態に戻すことができなくなってしまいます。
IsArray関数
IsArray関数を利用すると、関数であるかどうか判別することができます。以下は、配列データであれば、Trueを返す例です。
Sub sample14()
'配列を格納する変数Arと配列判定用の変数resultを宣言
Dim Ar As Variant
Dim result as Boolean
'Array関数作られた配列をArに格納
Ar = Array("松", "竹", "梅", "なし")
'IsArray関数から配列データであるためTrueをresultに格納
result = IsArray(Ar)
'resultの内容をイミディエイトウィンドウに出力
if result then
Debug.Print result'Trueで出力
EndIf
End Sub
例えば、「配列であれば、配列処理を行う。配列でなければ文字列処理を行う」など変数によって処理を制御する用途に利用することができます。
まとめ
以上がExcel VBAで配列を使う方法の説明です。配列は、同じ種類のデータを複数個まとめて処理する場合に非常に便利です。