VBAの配列で「インデックスが有効範囲にありません」と表示されたら、まずLBoundとUBoundで使える番号の範囲を確認します。配列の数を数える式は `UBound(配列) – LBound(配列) + 1` です。
LBoundは最小番号、UBoundは最大番号を返す
配列は複数の値を番号で管理する仕組みです。最初の番号を下限、最後の番号を上限と呼びます。番号は常に0から始まるとは限りません。
用語解説:添字(インデックス)
配列の何番目の要素かを指定する番号。実際に使える最小・最大の番号は配列によって異なります。
| 式 | 調べられる内容 | 例:Dim scores(2 To 4) |
|---|---|---|
| LBound(scores) | 最小の添字 | 2 |
| UBound(scores) | 最大の添字 | 4 |
| UBound – LBound + 1 | 要素数 | 3 |
`UBound`は「最後の番号」であり、「要素数」ではありません。0始まりでは上限に1を足した値が要素数ですが、2始まりなどではその計算は間違います。
1次元配列で範囲を確認してループする
ExcelでAlt+F11からVBAエディターを開き、標準モジュールへ次のマクロを入力します。実行後はCtrl+Gでイミディエイトウィンドウを表示し、出力を確認します。
Sub CheckBounds()
Dim scores(2 To 4) As Long
Dim i As Long
scores(2) = 10
scores(3) = 20
scores(4) = 30
Debug.Print "下限=" & LBound(scores) ' 2
Debug.Print "上限=" & UBound(scores) ' 4
Debug.Print "要素数=" & UBound(scores) - LBound(scores) + 1 ' 3
For i = LBound(scores) To UBound(scores)
Debug.Print scores(i)
Next i
End Sub
想定出力は、下限2・上限4・要素数3に続いて10、20、30です。`For i = 0 To UBound(scores)`に変えると、この配列では0や1が範囲外になります。
2次元配列なら次元を明示する
表のように行と列がある配列では、LBound/UBoundの第2引数に次元(1は行方向、2は列方向)を渡します。省略すると第1次元を調べます。
Sub CheckTableBounds()
Dim cells(1 To 2, 3 To 5) As Long
Dim rowIndex As Long, colIndex As Long
Debug.Print UBound(cells, 1) - LBound(cells, 1) + 1 ' 行数2
Debug.Print UBound(cells, 2) - LBound(cells, 2) + 1 ' 列数3
For rowIndex = LBound(cells, 1) To UBound(cells, 1)
For colIndex = LBound(cells, 2) To UBound(cells, 2)
cells(rowIndex, colIndex) = rowIndex * 10 + colIndex
Next colIndex
Next rowIndex
Debug.Print cells(2, 5) ' 25
End Sub
Excelのセルから配列へ読み込むときも、配列の次元と実際の下限を確認してください。単一セル取得と複数セル取得では返る値の形が違う場合があります。
添字エラーが出たら確認する順番
- まず、対象の変数が配列で、使用前に適切に初期化されているか確認します。未割り当ての動的配列に対するUBoundはエラーになる場合があります。
- 次に、`Debug.Print LBound(arr), UBound(arr)`で実際の範囲を出します。2次元なら第2引数を明示します。
- `Dim arr(1 To 5)`なら1始まり、`Dim arr(0 To 4)`なら0始まりです。`Option Base`は明示的な`To`指定を上書きしません。
- 要素数と添字を混同しないよう、ループは`LBound`から`UBound`まで回します。
配列が空の場合でもUBoundを呼んでよい?
要素がない、または動的配列の領域が割り当てられていない場合、UBoundがエラーになるケースがあります。既に使用する配列の状態が分かっているかを先に確認し、エラーを無条件に握りつぶさないようにします。
(配列の宣言や初期化の基本については『VBA配列の使い方完全ガイド|高速化の仕組みとエラー対策まで』をご参照ください)
次の学習:配列を安全に扱えるようにする
まずは上の1次元の例を`0 To 2`に変更し、下限・上限・要素数の出力がどう変わるかを確かめましょう。次に、2次元配列で行と列を逆に指定すると何が起きるかを比較すると、実際のエラーが読み解きやすくなります。
(型や値の確認でつまずいた場合については『VBA「実行時エラー13 型が一致しません」5つの原因と防御的プログラミングとは?』をご参照ください)
関数仕様の確認にはMicrosoft Learnの`UBound function`・`LBound function`が役立ちます。この記事のコードはMicrosoftの公式仕様と整合を照合しましたが、Excel VBA実機での実行はまだ行っていません。