Excel VBAで配列を使う方法をお探しですね。
広告
Excel VBAの配列を完全マスター!宣言から使い方まで丁寧に解説
Excel VBAで大量のセルデータを処理するとき、配列を使えるかどうかで処理速度やコードの読みやすさがガラッと変わります。
ただ、配列には「宣言の書き方がいろいろある」「0から始まる添字って何?」「ReDimってどう使うの?」「要素数はどうやって調べるの?」など、初心者がつまずきやすいポイントがたくさんあるのも事実です。
この記事では、Excel VBAの配列を基礎からしっかり理解できるように、宣言・初期化・動的配列・要素数の取得方法まで、実務でよく迷う部分を中心に解説していきます。
セル範囲をまとめて扱うテクニックも紹介するので、マクロの高速化や保守しやすいコード作りにも役立ちますよ。
1. Excel VBAの配列って何?|普通の変数との違いと使うメリット
Excel VBAの配列とは、複数の値を1つの変数名でまとめて管理できる便利な仕組みです。
普通の変数は「名前」や「金額」のように1つの値だけを入れる箱ですが、配列は同じ種類の箱を番号付きでずらっと並べたものだとイメージするとわかりやすいでしょう。
たとえば、5人分の名前を扱うとき、name1、name2、name3…と変数を増やしていくよりも、names(0)、names(1)、names(2)…のように配列で管理したほうが、ループ処理と組み合わせやすくてスッキリします。
VBAでは、この番号のことを「インデックス」または「添字」と呼び、それぞれのデータを「要素」と呼びます。
配列を使う最大のメリットは、**大量のデータを効率よく処理できる**ことです。
Excel VBAでセルを1つずつ読み書きすると、ExcelシートとVBAの間で何度も何度もやり取りが発生するため、データ量が増えるほど処理がどんどん遅くなってしまいます。
一方で、セル範囲を一度配列に読み込んで、VBAのメモリ上で加工してからまとめてシートへ戻すと、Excelとの通信回数をグッと減らせます。
つまり、配列は単に複数の値をまとめるだけでなく、**Excelマクロを高速化するための重要な考え方**でもあるんです。
VBAの配列には、大きく分けて「**静的配列**」と「**動的配列**」の2種類があります。
静的配列は、宣言するときに要素数を決めてしまう配列で、あとからサイズを変えない場面に向いています。
動的配列は、宣言時には要素数を決めず、処理の途中でReDimを使ってサイズを決める配列です。
実務では、読み込むデータの件数が毎回変わることが多いので、動的配列を使う機会のほうが多くなります。
まずは静的配列で基本の形を理解してから、動的配列に進むと、配列全体の仕組みをスムーズに理解できますよ。
2. 配列の宣言方法|静的配列・動的配列・2次元配列の基本
VBAで配列を使うには、まず**宣言**が必要です。
静的配列は、変数名の後ろに括弧を付けて、その中に最大のインデックス番号を指定します。
たとえば、`Dim names(2) As String` と書くと、names(0)、names(1)、names(2) の3つの要素を持つ文字列配列になります。
ここで注意したいのは、**VBAの配列は通常0から始まる**ため、括弧内の数値は「要素数」ではなく「最後のインデックス番号」だという点です。
3個のデータを入れたいなら、`(3)`ではなく`(2)`を指定するのが基本なんです。
“`vba
Sub StaticArraySample()
Dim names(2) As String
names(0) = “佐藤”
names(1) = “鈴木”
names(2) = “高橋”
MsgBox names(0) & “、” & names(1) & “、” & names(2)
End Sub
“`
動的配列を宣言する場合は、括弧の中に数値を入れません。
`Dim scores() As Long` のように書くことで、サイズ未定の配列として宣言できます。
ただし、この時点ではまだ要素数が確保されていないので、いきなり `scores(0) = 80` のように代入するとエラーになってしまいます。
動的配列を実際に使うには、`ReDim scores(2)` のように**ReDimステートメント**でサイズを決める必要があります。
データ件数があとから決まる処理では、この宣言方法がとても重要です。
“`vba
Sub DynamicArraySample()
Dim scores() As Long
ReDim scores(2)
scores(0) = 80
scores(1) = 95
scores(2) = 72
MsgBox scores(1)
End Sub
“`
Excel VBAでは、表形式のデータを扱う場面が多いので、**2次元配列**もよく使います。
2次元配列は、行と列を持つ配列で、ワークシート上の表に近いイメージです。
宣言するときは、`Dim data(2, 1) As Variant` のように、カンマで区切って各次元の最大インデックスを指定します。
この場合、1次元目は0から2までの3要素、2次元目は0から1までの2要素なので、合計で3行×2列のデータを持てることになります。
セル範囲を一括で読み込む場合も、多くは2次元配列として扱われるので、行と列の指定順に慣れておくことが大切です。
3. 配列の初期化と再定義|Array・Erase・ReDim Preserveの使い方
配列の初期化とは、配列に最初の値を入れたり、既存の値をリセットしたりすることです。
静的配列では、各要素に対して `arr(0) = “A”` のように1つずつ値を代入できます。
一方、複数の値をまとめて設定したいときは、**Array関数**を使うと便利です。
ただし、Array関数の戻り値はVariant型の配列になるので、基本的には `Dim arr As Variant` または `Dim arr() As Variant` として受け取ります。
String型やLong型の配列へ直接Array関数の結果を代入しようとすると、型の不一致が起きる場合があるので注意しましょう。
“`vba
Sub ArrayFunctionSample()
Dim fruits As Variant
fruits = Array(“りんご”, “みかん”, “ぶどう”)
MsgBox fruits(0) & ” / ” & fruits(1) & ” / ” & fruits(2)
End Sub
“`
配列の内容をリセットしたいときは、**Eraseステートメント**を使います。
静的配列にEraseを使うと、数値型なら0、文字列型なら空文字、オブジェクト型ならNothingのように、各要素が初期値に戻ります。
一方、動的配列にEraseを使うと、確保されていた配列そのものが解放されて、未初期化の状態に戻ります。
そのため、Erase後に再び動的配列を使う場合は、あらためてReDimでサイズを指定する必要があります。
「値だけ消える」のか「配列のサイズも消える」のかは、静的配列と動的配列で挙動が違うので、実務では特に意識しておきたいポイントです。
**ReDim**は、動的配列の要素数を決めたり、変更したりするために使います。
ただし、普通のReDimを実行すると、それまで配列に入っていた値は消えてしまいます。
既存の値を残したまま要素数を増やしたい場合は、`ReDim Preserve` を使います。
たとえば、3件のデータが入った配列に1件追加したい場合、現在の最大インデックスをUBoundで取得して、それに1を加えてサイズを広げる方法がよく使われます。
ただし、多次元配列でReDim Preserveを使う場合、**変更できるのは最後の次元だけ**という制約があります。
“`vba
Sub PreserveSample()
Dim arr() As Variant
arr = Array(“A”, “B”, “C”)
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr)) = “D”
MsgBox Join(arr, “,”)
End Sub
“`
ReDim Preserveは便利ですが、ループの中で何度も実行すると処理速度が落ちることがあります。
なぜなら、サイズ変更のたびに配列の再確保やコピーが発生するからです。
大量データを扱う場合は、最初に必要な件数を見積もって配列を確保する、または一時的に大きめに確保して最後に縮めるなどの工夫が有効です。
小規模なマクロでは気にしすぎる必要はありませんが、数万行以上のデータを扱う業務処理では、配列のサイズ変更回数が処理時間に影響することがあります。
4. UBoundで要素数を取得する方法|LBoundとの組み合わせと実務の注意点
VBAには、配列の要素数そのものを直接返す専用関数はありません。
その代わりに、最大インデックス番号を返す**UBound関数**と、最小インデックス番号を返す**LBound関数**を使って要素数を計算します。
基本の式は `要素数 = UBound(配列名) – LBound(配列名) + 1` です。
多くの配列は0から始まるので、`UBound(arr) + 1` でも要素数を求められることがありますが、常に安全とは限りません。
Option Base 1を使っている場合や、`Dim arr(1 To 5)` のように開始番号を明示している場合は、LBoundを使わないと正しい要素数にならないことがあります。
“`vba
Sub CountArraySample()
Dim arr As Variant
Dim count As Long
arr = Array(“東京”, “大阪”, “名古屋”)
count = UBound(arr) – LBound(arr) + 1
MsgBox “要素数は ” & count & ” です。
”
End Sub
“`
配列をループ処理する場合も、固定の数値ではなく**LBoundとUBoundを使う**のが安全です。
たとえば、`For i = 0 To 2` のように書くと、配列の要素数が変わったときに修正漏れが起きやすくなります。
一方で、`For i = LBound(arr) To UBound(arr)` と書けば、配列の開始番号や終了番号に合わせて自動的にループできます。
これは「インデックスが有効範囲にありません」というエラーを防ぐ基本的な書き方です。
配列のサイズが処理によって変わる動的配列では、特にこの書き方を習慣にしておくとバグを減らせます。
“`vba
Sub LoopArraySample()
Dim arr As Variant
Dim i As Long
Dim msg As String
arr = Array(“東京”, “大阪”, “福岡”)
For i = LBound(arr) To UBound(arr)
msg = msg & arr(i) & vbCrLf
Next i
MsgBox msg
End Sub
“`
2次元配列でUBoundを使う場合は、**どの次元の最大インデックスを取得するか**を指定します。
`UBound(data, 1)` は1次元目、つまり行方向の最大インデックスを返し、`UBound(data, 2)` は2次元目、つまり列方向の最大インデックスを返します。
Excelのセル範囲を `Range(“A1:C10”).Value` のようにVariant変数へ読み込むと、通常は**1始まりの2次元配列**になります。
この場合、`data(1, 1)` がA1、`data(1, 2)` がB1に対応します。
Array関数で作った配列は基本的に0始まりですが、セル範囲から読み込んだ配列は1始まりになるので、この違いを理解しておくことが重要です。
“`vba
Sub RangeToArraySample()
Dim data As Variant
Dim r As Long, c As Long
data = Range(“A1:C10”).Value
For r = LBound(data, 1) To UBound(data, 1)
For c = LBound(data, 2) To UBound(data, 2)
Debug.Print data(r, c)
Next c
Next r
End Sub
“`
実務で配列を使うなら、**「一括読込、配列上で処理、一括書込」という流れ**を覚えておくと役立ちます。
たとえば、A列の値を加工してB列へ出力する処理では、セルを1つずつ参照するよりも、A列とB列をまとめて配列に読み込んで、配列内で計算してから一括で戻すほうが断然高速です。
このときも、処理対象の行数を固定値で書くのではなく、UBoundで配列サイズを取得すれば、データ件数が変わっても対応しやすいコードになります。
配列は最初こそ難しく見えますが、**宣言、初期化、ReDim、UBoundの4つ**を押さえておけば、Excel VBAで扱えるデータ量と処理の自由度が大きく広がりますよ。
広告
