配列って使ってますか?配列は同じ型のデータを大量に扱う場合に一つのかたまりとして扱うことができるので便利ですよね。
その一方で、1つの変数を扱う場合に比べて使い方が複雑になるのも事実です。VBAにおいても例外ではありません。
この記事では、配列について
- 配列の宣言、初期化、再定義
- セルと配列で要素の値を共有する方法
- Uboundで配列の要素数を取得する方法
- ループで配列の要素を操作する方法
- 配列をコピーする方法
- Sortで配列の要素をソートする方法
- Filterで配列の要素を検索する方法
- 要素を追加、削除する方法
- 配列を結合する方法
- 配列同士を比較する方法
- 定数配列について
- 配列を関数の引数に指定する方法
など基本的な内容から、応用的な使い方についても解説していきます。
今回は配列について、使い方をわかりやすく解説します。
配列の宣言、初期化、再定義
配列では同じデータ型の変数をたくさん扱う場合に、一つのかたまりとして扱うことができます。配列内のひとつひとつのデータを要素といいます。
それぞれの要素にはインデックス番号(添字)を指定することでアクセスすることができます。配列を宣言する際に、要素数と次元数が決まっている配列を固定長配列といいます。
これに対して、要素数と次元数が決まっていない配列を可変長配列や動的配列といいます。
配列の宣言、定義
それでは配列を宣言、定義する方法についてみていきましょう。
固定長配列と可変長配列で宣言の方法が少々異なります。固定長変数は配列名のあとに「()」(カッコ)を使って下記のように宣言します。
Dim 配列名(添字の上限値) As データ型名
可変長配列の場合は、宣言時には要素数や次元数は指定しません。
Dim 配列名() As データ型名
Arrayで初期化
配列を初期化する方法には主に2つの方法があります。
Eraseステートメントを使う方法とArray関数を使う方法です。Eraseステートメントの引数には初期化する配列名を指定します。
Erase 配列名
それぞれのデータ型によって初期値が違います。
- 数値配列:0(ゼロ)
- 文字列配列:長さ0(ゼロ)の文字列
- オブジェクト配列:Nothing
- バリアント配列:Empty
それぞれの初期値で全要素が設定されます。Array関数を使う場合は要素の値を別々に指定することができます。
ただし、可変長配列でデータ型はバリアント型に限ります。
Dim 配列名() As Variant 配列名 = Array(要素(0), 要素(1), ・・・)
ReDimで再定義
ReDimステートメントを使って要素数などを再設定したり、再初期化することができます。
ReDim 配列名(添字の上限値, ・・・) As データ型名
ReDimステートメントを使って配列の要素数などを変更した場合、元のデータはすべて消えてしまいますので注意してください!
また、データ型の変更が可能なのは可変長配列の宣言時にバリアント型で宣言した場合だけになります。
Eraseで配列のメモリを解放する方法
先ほどEraseステートメントを使った配列の初期化について説明しました。
Eraseステートメントを使ってメモリを解放することも可能です。
2次元配列(多次元配列)の場合
2次元以上の多次元の配列を宣言する場合は、次元ごとに「,」(カンマ)で区切って「()」に並べます。
Dim 配列名(添字の上限値, 添字の上限値, ・・・) As データ型名
ここでは配列の宣言、初期化、再定義などについてお伝えしてきました。
これらについては、こちらで詳しく解説していますので、ぜひ参考にしてください。
セルと配列で要素の値を共有する方法
Excelシート上のセルとVBAの配列で要素の値を共有する方法についてみていきましょう。
セルの値を要素に代入する方法
セルの範囲の値を配列の要素に一括で代入する方法についてみていきましょう。
Sub macro1() Dim arr As Variant arr = WorksheetFunction.Transpose(Range("A1:B5")) Dim msg As String Dim i As Integer, j As Integer For i = 1 To 5 For j = 1 To 2 msg = msg & arr(j, i) & ", " Next j msg = msg & vbCrLf Next i MsgBox msg End Sub
実行結果:
いくつか注意があります。まず、配列arrの要素の値にアクセスするためのインデックス番号が0からではなく、1から始まっています。
また行と列が入れ替わっているので、WorksheetFunctionオブジェクトのTranspose関数を使って行と列を入れ替えてシートとそろえています。
なお、Transpose関数はワークシート関数でExcelシートのセルに入力する数式で使える関数です。ワークシート関数については、こちらで詳しく解説していますので、ぜひ参考にしてください。
要素の値をセルに格納する方法
今度は逆にVBAの配列の要素の値をセルの範囲に一括で格納する方法についてみていきましょう。
Sub macro2() Dim arr(2, 5) As Variant Dim msg As String Dim i As Integer, j As Integer For i = 0 To 4 For j = 0 To 1 arr(j, i) = i + 1 + 10 * j msg = msg & arr(j, i) & ", " Next j msg = msg & vbCrLf Next i Range("A1:B5") = WorksheetFunction.Transpose(arr) MsgBox msg End Sub
実行結果:
こちらのサンプルコードでは、配列arrの要素の値にアクセスするためのインデックス番号は0から始めています。
また、同じようにWorksheetFunctionオブジェクトのTranspose関数を使って行と列を入れ替えてシートとそろえています。
Uboundで配列の要素数を取得する方法
配列を扱う場合に要素数を知っておくと便利な場合があります。
しかし、VBAでは配列の要素数そのものを取得する関数は用意されていません。
配列の要素数を取得するには、UBound関数とLBound関数を使って、以下の式で計算する必要があります。
要素数 = UBound関数の戻り値 - LBound関数の戻り値 + 1
要素数を取得する方法やUBound関数、LBound関数の使い方については、こちらで詳しく解説しています。
ぜひ参考にしてください。
ループで配列の要素を操作する方法
配列の要素を操作するにはForなどのループを使って各要素にアクセスする必要があります。
Forループで操作する方法
For Nextステートメントを使って配列の要素にアクセスする方法は例えば以下のように記述します。
Dim i As Integer 'インデックス番号の変数を宣言 For i = LBound(arr) To UBound(arr) 'arr(i)を使った処理 Next i
詳しくはこちらで解説していますので、ぜひ参考にしてください。
For Eachで操作する方法
For Eachステートメントを使うとFor Nextステートメントより手短に記述することができます。
For Each Var In arr 'Variant型変数Varの宣言は省略 'arr(i)を使った処理 Next Var
こちらで詳しく解説していますので、ぜひ参考にしてください。
配列をコピーする方法
配列をコピーする場合は配列に格納するのではなく、バリアント型の変数に格納します。
サンプルコードで確認しましょう。
Sub macro3() Dim cities1() As Variant, cities2 As Variant cities1 = Array("東京都", "大阪府", "愛知県", "神奈川県", "広島県") cities2 = cities1 Dim msg As String For Each Var In cities2 msg = msg & Var & ", " Next Var MsgBox msg End Sub
実行結果:
Sortで配列の要素をソートする方法
配列の要素が順に並ぶようにソートしたい場合があります。
VBAの場合は、ExcelのSortメソッドやSortオブジェクトを使うと便利です。
こちらで詳しく解説していますので、ぜひ参考にしてください。
Filterで配列の要素を検索する方法
配列の要素の中から条件に一致する要素が含まれているか検索するには、Filter関数を使います。
Filter関数は以下のように記述します。
Filter(sourcearray,match[,include[,compare]])
「[ ]」内は省略可能です。
引数sourcearrayには、検索される配列を指定します。引数matchには、検索する文字列を指定します。
引数includeは、引数matchが含まれる要素を検索する場合にTrueを指定します。引数compareは、文字列を比較するモードを指定します。
0を指定した場合、テキストモードでの比較で大文字と小文字を区別しません。1を指定した場合、バイナリモードでの比較となり大文字と小文字を区別します。
それではサンプルコードで確認しましょう。
Sub macro4() Dim cities1() As Variant, cities2 As Variant cities1 = Array("東京都", "大阪府", "愛知県", "神奈川県", "広島県") cities2 = Filter(cities1, "県", True) Dim msg As String For Each Var In cities2 msg = msg & Var & ", " Next Var MsgBox msg End Sub
実行結果:
このサンプルコードでは、配列cities1から”県”という文字を含む要素のみを格納した配列をFilter関数を使ってcities2に格納しています。
要素を追加、削除する方法
配列の要素を追加、削除する方法について解説します。
要素を追加する方法
要素を追加する場合は、ReDimステートメントを使います。
ただし、このままではこれまでの要素の値が消去されてしまいます。要素の値を保持したまま配列の要素数を変更したい場合は、ReDim Preserveステートメントを使います。
ReDim Preserveステートメントについては、こちらで詳しく解説していますので、ぜひ参考にしてください。
要素を削除する方法
要素を削除する場合は少し面倒です。
配列にはコレクションのremoveメソッドのように削除するメソッドはありません。
使えるメソッドを駆使して、要素を削除する方法をご紹介します。
Sub macro5() Dim cities() As Variant cities = Array("東京都", "大阪府", "愛知県", "神奈川県", "広島県") '3番目の要素を削除 Dim i As Integer For i = 2 To UBound(cities) - 1 cities(i) = cities(i + 1) Next i ReDim Preserve cities(UBound(cities) - 1) Dim msg As String For Each Var In cities msg = msg & Var & ", " Next Var MsgBox msg End Sub
実行結果:
このサンプルコードでは、配列citiesの3番目の要素を削除しています。
4番目以降の要素を1つインデックス番号の小さい要素に代入し、そしてReDim Preserveステートメントを使って要素数を変更しています。
配列を結合する方法
配列の結合には、1つの配列の要素同士を結合する場合と、複数の配列を連結させる場合などが考えられます。
それぞれの場合についてみていきましょう。
Joinで配列の要素を結合する方法
1つの配列から要素同士を結合する場合、Join関数を使うと便利です。
For Eachステートメントを使って要素に1つずつアクセスして、「&」記号で結合する方法もありますが、要素数が多い場合に「&」記号で結合すると処理に時間がかかる場合があります。
Join関数は全ての要素を順に結合した文字列を返します。要素数が多い場合でも高速で処理することができます。
こちらで詳しく解説していますので、ぜひ参考にしてください。
JoinとSplitで配列を連結する方法
例えば要素数の違う2つの配列を連結する関数はVBAでは用意されていません。
ここではSplit関数とJoin関数を使う方法についてご紹介します。
まず、Join関数を使ってそれぞれの配列の要素を結合します。Join関数は引数を指定しない場合、半角スペースを区切り文字として要素を結合します。
それぞれの配列の要素を結合したら、「&」記号を使って結合しましょう。結合したら、半角スペースを区切り文字としてSplit関数で分割された文字列を配列の各要素に格納します。
これで連結した配列が出来上がります。
サンプルコードで確認しましょう。
Sub macro6() Dim cities1() As Variant, cities2() As Variant, cities3 As Variant cities1 = Array("東京都", "大阪府") cities2 = Array("愛知県", "神奈川県", "広島県") cities3 = Split(Join(cities1) & " " & Join(cities2)) Dim msg As String For Each Var In cities3 msg = msg & Var & ", " Next Var MsgBox msg End Sub
実行結果:
なおSplit関数の使い方については、こちらで詳しく解説していますので、ぜひ参考にしてください。
配列同士を比較する方法
配列同士を比較するには、For Eachステートメントを使って要素に1つずつアクセスして比較する方法もありますが、記述が少々面倒になります。
Join関数を使って要素を結合した文字列を比較すると、記述が短くできます。
サンプルコードで確認しましょう。
Sub macro7() Dim cities1() As Variant, cities2() As Variant cities1 = Array("東京都", "大阪府", "愛知県", "神奈川県", "広島県") cities2 = Array("東京都", "大阪府", "北海道", "神奈川県", "広島県") If Join(cities1) = Join(cities2) Then MsgBox "二つの配列は同じです" Else MsgBox "二つの配列は違います" End If End Sub
実行結果:
定数配列について
VBAではConstステートメントを使って配列の定数を定義してもエラーが発生します。
しかし、定数を1つずつ定義するのも面倒です。
Split関数を使って、定数の文字列を区切り文字で分割して配列へ格納する方法をご紹介します。
Sub macro8() Const str As String = "東京都,大阪府,愛知県,神奈川県,広島県" Dim cities As Variant cities = Split(str, ",") Dim msg As String For Each Var In cities msg = msg & Var & ", " Next Var MsgBox msg End Sub
実行結果:
配列を関数の引数に指定する方法
配列を関数の引数に指定したい場合もあります。
引数に配列を指定する場合には引数名の後に「()」(カッコ)を付けます。なお、引数に配列を指定する場合は全て参照渡しになります。
これは引数に配列を指定する場合、先頭のアドレスを渡しているためで値を渡すようにはなっていないからです。また戻り値に配列を指定する場合には戻り値のデータ型の後に「()」(カッコ)を付けます。
以下のような記述になります。
Function プロシージャ名(配列名() As データ型) As 戻り値のデータ型() プロシージャ名 = 戻り値 End Function
こちらで詳しく解説していますので、ぜひ参考にしてください。
VBAの将来性
このように思っている人は多いでしょう。
VBAの用途はさまざまで、
- VBAのスキルがあれば転職できるのでは?
- 業務効率化のスキルは需要が高そうだから
などが上げられます。確かに、業務効率化はどこの企業も目指していて、需要が高いように見えます。ただ、VBAを扱えることが強みになるかといわれると、すこし疑問があります。
VBAは基本的にエクセル上でしか使用することができません。しかし、最近では社内書式をスプレッドシートで管理している企業も増えており、今後エクセル自体の需要が少なくなってしまう可能性も考えられます。
そうなってしまうと、VBAを習得しても活躍の場が限られてしまいますよね。そう考えると将来的にVBAの需要はあまり高くないといえます。
ではVBAを学んでいる人はどうすればいいのでしょう。VBAの将来性や今後の対策などをこちらの記事でまとめているのでぜひご確認ください。
まとめ
ここでは配列の使い方について説明しました。
配列は同じ型のデータを大量に扱う場合に一つのかたまりとして扱うことができるので便利です。またVBAで用意されている関数を使いこなすことで、様々な応用的な使い方ができることをご理解頂けましたでしょうか?
使いこなすことができるように、この記事を何度も参考にして下さいね!