目次
はじめに
VBAでExcelの大量データを処理する際、セルを1つずつ読み書きしていると非常に時間がかかります。配列を使うと、データをまとめて扱えるため処理速度が劇的に向上します。この記事では、初心者の方が配列の基本を理解できるよう、1次元配列と2次元配列の使い方を段階的に解説していきます。
配列とは
配列は、複数のデータを1つの変数名でまとめて管理できる仕組みです。例えば、5人分の名前を保存したい場合、普通はname1、name2、name3...と5個の変数を用意する必要がありますが、配列を使えばnamesという1つの変数で管理できます。
配列内の各データには番号(インデックス)が付いており、この番号を指定することで特定のデータにアクセスできます。VBAでは、通常0番から始まりますが、設定により1番から始めることも可能です。
1次元配列の基本
【1次元配列の宣言と使い方】
1次元配列は、データを一列に並べて管理する配列です。商品リストや曜日のリストなど、単純なリスト形式のデータに適しています。
Sub Sample1DArray()
Dim fruits(1 To 3) As String
fruits(1) = "りんご"
fruits(2) = "バナナ"
fruits(3) = "みかん"
MsgBox fruits(2) ' 結果: バナナ
End Sub
この例では、fruitsという名前の配列を宣言し、3つの要素(データの入れ物)を用意しています。1 To 3の指定により、インデックスは1から3までとなります。
【配列の要素数を後から決める】
データの数が事前に分からない場合は、動的配列(サイズを後から変更できる配列)が便利です。
Dim items() As String
ReDim items(1 To 10)
ReDimを使うことで、実行時に配列のサイズを決定できます。データ数に応じて柔軟に対応できるため、実務では頻繁に使用します。
【繰り返し処理との組み合わせ】
配列は繰り返し処理と組み合わせることで真価を発揮します。
Sub LoopArray()
Dim numbers(1 To 5) As Long
Dim i As Long
For i = 1 To 5
numbers(i) = i * 10
Next i
For i = 1 To 5
Debug.Print numbers(i)
Next i
End Sub
このコードでは、最初のループで配列に値を格納し、2番目のループで値を出力しています。イミディエイトウィンドウには10、20、30、40、50と表示されます。
2次元配列の基本
【2次元配列の概念】
2次元配列は、表形式のデータを扱う配列です。行と列の2つのインデックスを使ってデータを管理します。Excelのセル範囲をそのまま配列として扱う際によく使用します。
身近な例えで言うと、1次元配列が「下駄箱の1列」だとすれば、2次元配列は「下駄箱全体(行と列がある)」というイメージです。
【2次元配列の宣言と使い方】
Sub Sample2DArray()
Dim scores(1 To 3, 1 To 2) As Long
scores(1, 1) = 80
scores(1, 2) = 75
scores(2, 1) = 90
scores(2, 2) = 85
scores(3, 1) = 70
scores(3, 2) = 95
MsgBox scores(2, 1) ' 結果: 90
End Sub
scores(1 To 3, 1 To 2)は「3行2列の表」を表します。最初の数字が行、2番目の数字が列を示します。例えばscores(2, 1)は「2行目の1列目」のデータにアクセスします。
【Excelのセル範囲を配列に格納する】
2次元配列の最も実用的な使い方は、Excelの複数セルを一気に配列に読み込むことです。
Sub ReadRangeToArray()
Dim data As Variant
data = Range("A1:C5").Value
Debug.Print data(1, 1) ' A1セルの値
Debug.Print data(3, 2) ' B3セルの値
End Sub
Variant型で宣言した変数にRange.Valueを代入すると、自動的に2次元配列として格納されます。このとき、配列のインデックスは自動的に1から始まります。この方法は、セルを1つずつ読むより遥かに高速です。
【2次元配列の繰り返し処理】
2次元配列では、ネストしたループ(ループの中にループを入れる構造)を使って全データを処理できます。
Sub Loop2DArray()
Dim data As Variant
Dim i As Long, j As Long
data = Range("A1:C3").Value
For i = 1 To 3
For j = 1 To 3
Debug.Print "(" & i & "," & j & "): " & data(i, j)
Next j
Next i
End Sub
外側のループが行を、内側のループが列を処理します。iが1のとき、jが1から3まで変化するため、1行目の全列を処理してから2行目に進みます。
1次元配列と2次元配列の使い分け
【1次元配列が適している場面】
1次元配列は、単純なリスト形式のデータに適しています。例えば次のような場面で使用します。
- 商品名や部署名などのマスタデータの一時保存
- 処理対象のシート名リスト
- 計算結果を順番に保存する場合
Dim sheetNames(1 To 3) As String
sheetNames(1) = "売上"
sheetNames(2) = "仕入"
sheetNames(3) = "在庫"
【2次元配列が適している場面】
2次元配列は、表形式のデータ処理に威力を発揮します。
- Excelの複数列×複数行のデータを読み込む
- データベースのような構造(ID、名前、金額など複数項目)を扱う
- 集計表や転記処理で元データと結果データを保持する
' 商品データを配列で管理
Dim products As Variant
products = Range("A2:C10").Value ' 商品名、単価、在庫数
実務では、Excelのセル範囲をそのまま配列に読み込んで処理することが多いため、2次元配列の使用頻度が高くなります。
【配列の次元を調べる方法】
処理の途中で配列が何次元か分からなくなった場合、確認する方法があります。
Dim data As Variant
data = Range("A1:C5").Value
Debug.Print UBound(data, 1) ' 1次元目(行)の最大値
Debug.Print UBound(data, 2) ' 2次元目(列)の最大値
UBound関数の2番目の引数で次元を指定できます。1次元配列の場合、2番目の引数を指定するとエラーになります。
注意点
【インデックスの開始番号】
VBAの配列は、デフォルトでは0から始まります。ただしOption Base 1をモジュールの先頭に記述すると、1から始まるように変更できます。
Option Base 1
Dim values(5) As Long ' 1から5までの5要素
ただし、Excelのセル範囲から読み込んだ配列は、Option Baseの設定に関わらず常に1から始まります。混乱を避けるため、明示的に(1 To 5)と指定する方法が推奨されます。
【配列の初期化】
配列を宣言しただけでは、各要素には何も入っていません(数値型は0、文字列型は空文字列が初期値)。必要に応じて値を代入してから使用する必要があります。
【ReDimでのデータ消失】
ReDimを使って配列のサイズを変更すると、既存のデータは消えてしまいます。データを保持したまま拡張したい場合はReDim Preserveを使用します。
ReDim Preserve items(1 To 20) ' データを保持したまま拡張
ただし、Preserveを使うと処理速度が低下するため、可能であれば最初から十分な大きさを確保しておくのが効率的です。
【2次元配列のPreserve制限】
ReDim Preserveで2次元配列のサイズを変更する場合、最後の次元(列)のみ変更可能で、行数は変更できません。
ReDim Preserve data(1 To 10, 1 To 20) ' OK: 列を拡張
ReDim Preserve data(1 To 20, 1 To 10) ' エラー: 行は変更不可
パフォーマンスのポイント
【配列を使う最大の理由】
配列を使う最大のメリットは処理速度の向上です。セルを1つずつ読み書きする処理と比較してみます。
' セルを1つずつ処理(遅い)
For i = 1 To 1000
Cells(i, 1).Value = Cells(i, 1).Value * 2
Next i
' 配列で一括処理(速い)
Dim data As Variant
data = Range("A1:A1000").Value
For i = 1 To 1000
data(i, 1) = data(i, 1) * 2
Next i
Range("A1:A1000").Value = data
配列を使った処理は、データ量が多いほど速度差が顕著になります。1000行程度のデータで10倍以上、10000行では100倍以上の速度差が出ることもあります。
【画面更新の停止】
配列処理と組み合わせて、画面更新を停止するとさらに高速化できます。
Application.ScreenUpdating = False
' 配列処理
Application.ScreenUpdating = True
処理中の画面のちらつきも防げるため、ユーザー体験の向上にも繋がります。
よくある間違い
【インデックスの範囲外エラー】
配列の要素数を超えるインデックスを指定すると、エラーが発生します。
Dim items(1 To 5) As String
items(6) = "test" ' エラー: インデックスが有効範囲にありません
UBound関数で配列の最大値を確認しながら処理を書くと、このエラーを防げます。
【Variant型以外でのセル範囲読み込み】
Excelのセル範囲を配列に読み込む際、Variant型以外を使うとエラーになります。
Dim data As String
data = Range("A1:A5").Value ' エラー
Variant型は様々なデータ型を柔軟に扱えるため、セル範囲の読み込みには必ずVariant型を使用します。
【1次元と2次元の混同】
1列または1行だけのセル範囲を読み込んでも、結果は2次元配列になります。
Dim data As Variant
data = Range("A1:A5").Value ' 5行1列の2次元配列
Debug.Print data(1) ' エラー: 次元が足りない
Debug.Print data(1, 1) ' OK: 正しいアクセス方法
1列のデータでもdata(i, 1)のように2つのインデックスを指定する必要があります。
まとめ
配列は、VBAで大量のデータを効率的に処理するための重要な機能です。1次元配列はリスト形式のデータに、2次元配列はExcelの表形式データに適しています。特に2次元配列とセル範囲の読み書きを組み合わせることで、処理速度を大幅に向上させることができます。最初は難しく感じるかもしれませんが、小さなコードで試しながら慣れていくのがおすすめです。