Excel VBAの配列とインデックス範囲の基本
不安なまま動かすより、仕組みを一度つかむと一気に楽になります。ここでは、配列の「インデックス範囲」と「実行時エラー」を、初心者でも迷わないように例題つきで説明します。
配列とは何か
- イメージ: 配列は「番号つきの引き出し」。0番、1番、2番…と並んだ小さな入れ物に、同じ種類のデータを並べて入れます。
- インデックス: 引き出しの番号のこと。VBAでは基本的に0から始まります(設定次第で1開始も可能ですが、初心者は0開始で覚えるのが安全)。
宣言とインデックス範囲のルール
- 最大インデックスで宣言:
Dim a(2) As Stringと書くと、使える番号は「0〜2」。つまり3個ぶんの引き出しです。 - 範囲外はエラー:
存在しない番号(例: 3)を使うと、プログラムを実行した時点で「実行時エラー」になります。書いた瞬間(コンパイル時)には気づけないので、動かして初めてエラーに気づくことが多いです。
まずは動かしてみる例題
例題1:正しい範囲で値を入れて取り出す
Sub Example1()
Dim pref(2) As String ' 0~2の3つ分
pref(0) = "東京"
pref(1) = "大阪"
pref(2) = "福岡"
Debug.Print pref(0) ' → 東京
Debug.Print pref(1) ' → 大阪
Debug.Print pref(2) ' → 福岡
End Sub
VB- ポイント:
Dim pref(2)は「3個使える」の意味。0、1、2の3つだけ。
例題2:範囲外でエラーが出る流れ
Sub Example2()
Dim pref(2) As String ' 0~2
pref(0) = "東京"
pref(1) = "大阪"
pref(2) = "福岡"
' 次の行で実行時エラー(添字が範囲外)
pref(3) = "札幌"
End Sub
VB- ここが落とし穴: コードの見た目は正しくても、実行した瞬間に「範囲外アクセス」で止まります。
よくある間違いと対策
- 間違い: 「3つ入れたいから
Dim a(3)だよね?」
→ 対策: VBAは0開始なので、3つならDim a(2)。4つならDim a(3)。 - 間違い: ループで範囲を1つ多く回す
Dim a(2) As Long
Dim i As Long
For i = 0 To 3 ' ← 3まで回すのはダメ(0~2が正しい)
a(i) = i
Next i
VB→ 対策: For i = 0 To UBound(a) のように、配列の「上限」を取り出して使う。
Dim a(2) As Long
Dim i As Long
For i = LBound(a) To UBound(a) ' LBound=0, UBound=2
a(i) = i
Next i
VB安全に書くための基本テクニック
- 要素数に依存しないループを書く
Dim nums(3) As Long ' 0~3の4つ
Dim i As Long
For i = LBound(nums) To UBound(nums)
nums(i) = i * 10
Next i
VB- 範囲チェックを入れる(防御的)
Sub SafeSet(ByRef arr() As String, ByVal idx As Long, ByVal value As String)
If idx < LBound(arr) Or idx > UBound(arr) Then
MsgBox "インデックスが範囲外です: " & idx
Exit Sub
End If
arr(idx) = value
End Sub
VB要素数を後から変える(ReDimの基礎)
- 固定配列:
Dim a(2)のように最初から個数固定。 - 可変配列: まず「配列だけ」宣言し、あとで大きさを決められる。
Sub ExampleReDim()
Dim items() As String ' まだ大きさを決めない
ReDim items(1) ' 0~1(2個)
items(0) = "A"
items(1) = "B"
' もっと必要になったらサイズ変更
ReDim items(3) ' 0~3(4個)に作り直し
' ここで A, B は消える(再作成のため)
End Sub
VB- 値を保持したまま拡張したい:
Preserveを使うReDim Preserve items(3) ' 既存の中身を保持してサイズだけ拡張 - 注意点:
Preserveを使うと「最終次元」しか大きさを変えられません(多次元配列のときの制約)。
使いどころをイメージする例題
例題3:ユーザー入力数に合わせて可変配列に格納
Sub CollectNames()
Dim count As Long
Dim names() As String
Dim i As Long
count = CLng(InputBox("人数を入力してください(例: 3)"))
If count <= 0 Then
MsgBox "1以上の数を入力してください。"
Exit Sub
End If
ReDim names(count - 1) ' 0~(count-1)でcount人分
For i = 0 To UBound(names)
names(i) = InputBox((i + 1) & "人目の名前を入力")
Next i
Debug.Print "人数:", count
For i = LBound(names) To UBound(names)
Debug.Print i, names(i)
Next i
End Sub
VB- ポイント: 入力人数に合わせて配列のサイズを決める。範囲は常に
0~count-1。
まとめ(迷ったらここだけ見返す)
- 配列の基本: 宣言の数字は「最大インデックス」。要素数は「最大インデックス+1」。
- 範囲外は実行時エラー: 書いているときは気づけない。動かして初めて止まる。
- 安全策:
LBoundとUBoundを使ってループ範囲を自動化する。 - 柔軟性: 可変配列は
Dim arr()+ReDim。中身を残すならReDim Preserve。
次の一歩
- Label: 反復処理に慣れる
For、Do Whileと配列の組み合わせを練習。
- Label: エラーを恐れない
- 範囲外に当たったら「学びポイント」。
UBound/LBoundで直せるか確認。
- 範囲外に当たったら「学びポイント」。
- Label: 実践ミニ課題
- 「5教科の点数を配列に入れて平均を出す」プログラムを書いてみる。
- 可変配列で「入力数ぶんの合計と最大値」を出してみる。
