A子さん「えっ…Forの中にもう一つFor?
なんか見た目ややこしいし、これ絶対ミスるやつでしょ…?」
結論:ネストは“ループの中でさらにループ”する書き方。
表データの操作などにとても便利ですが、インデントと変数名に注意が必要です。
ネスト(入れ子)とは?
ネストとは、「あるループの中に別のループを入れる構造」のことです。
正式には「ネストされたループ」や「入れ子構造のループ」と呼びます。VBAを本気で使い込み始めると、必ず遭遇する概念です。私も最初は「ちょっと複雑だな…」と敬遠していましたが、実務レベルの自動化を考えると避けて通れません。
For i = 1 To 3
For j = 1 To 2
Debug.Print "i=" & i & ", j=" & j
Next j
Next i
このコードを実行すると、実際の動きは以下のようになります。
・iが1のとき、jは1から2まで全て実行
・iが2のとき、jはまた1から2まで全て実行
・iが3のとき、jはまた1から2まで全て実行
イメージとしては「外側のループが1回進むごとに、内側のループが全部まわる」という形になります。Debug.Printの出力結果は:
i=1, j=1
i=1, j=2
i=2, j=1
i=2, j=2
i=3, j=1
i=3, j=2
この「最初の1まわり中に、内側が複数回実行される」という動きが、ネストの本質です。
なぜネストが必要なのか
単純なループなら「For i = 1 To 10」で十分です。でも実務だと、「複数の列それぞれに対して、複数の行の処理をする」みたいな場面がごろごろあります。
例えば、Excelの表は本来「2次元」のデータ構造です。データは「行」と「列」の両方で配置されます。これを自動化処理するには、「行をループ」かつ「列もループ」する必要があります。その時に登場するのがネストです。
ネストなしでこれを実現しようとすると、複雑な計算式や条件分岐が増えて、かえってコードが読みづらくなる。だからネストは「2次元データを処理する標準的な書き方」として確立されているわけです。
典型的なネストの使い方:表を処理する
✅ 例:2行3列のセルに連番を入力する
Dim i As Integer, j As Integer
Dim num As Integer
num = 1
For i = 1 To 2 ' 行
For j = 1 To 3 ' 列
Cells(i, j).Value = num
num = num + 1
Next j
Next i
このコードを実行すると、以下のように連番がセルに入ります。
| A | B | C |
|---|---|---|
| 1 | 2 | 3 |
| 4 | 5 | 6 |
処理の流れを詳しく追ってみます。
i=1のとき:
j=1 → Cells(1,1)に1を入力 → numが2に増加
j=2 → Cells(1,2)に2を入力 → numが3に増加
j=3 → Cells(1,3)に3を入力 → numが4に増加
次のiへ
i=2のとき:
j=1 → Cells(2,1)に4を入力 → numが5に増加
j=2 → Cells(2,2)に5を入力 → numが6に増加
j=3 → Cells(2,3)に6を入力 → numが7に増加
終了
このように「行を1行ずつ進みながら、各行の中で列を1列ずつ進む」という2次元的な処理ができます。これがネストの最大の利点です。
実務での活用例
ネストの威力を実感するため、現実的なシナリオをいくつか紹介します。
📊 例1:複数の行をまとめて処理する
営業報告書が100行あり、各行に対して「売上」「原価」「利益」の3列を計算して、別シートに出力する。
この場合、外側のループで「100行をスキャン」し、内側のループで「3列の計算」をします。ネストなしでこれをやろうとすると、300個の計算式を手書きするハメになります。ネストなら10行で完了。
📋 例2:複数ファイルの複数シートを処理する
フォルダに10個のExcelファイルがあり、各ファイルに5個のシートがあり、それぞれのシートの特定セルを集計する。
この場合、「ファイルをループ」しながら「シートもループ」する3重ネストになることも。それでも書き方さえ正しければ、人間が100回手作業するより遥かに短時間で完了します。
🎯 例3:条件付きで複数セルを検索・更新する
A列の顧客ID「1001」に対応するB~E列の全データを更新する。複数の顧客がいるので「全行をスキャン」しながら「条件に合う列を処理」します。
このように、ネストは単なる「表に数字を入れる」だけじゃなく、実務の自動化で毎日活躍する書き方です。
よくあるミスと防ぎ方
ここではよくあるミスとその防ぎ方について紹介します。
❌ ミス1:インデントしないと可読性が地獄に…
For i = 1 To 3 For j = 1 To 3 Cells(i, j).Value = "○" Next j Next i



これ、どのNextがどのForに対応するのか、一瞬で分かりますか?
正直、読みづらいです。特にネストが3段4段になると、地獄です。
➡ インデント(字下げ)を行いましょう。
For i = 1 To 3
For j = 1 To 3
Cells(i, j).Value = "○"
Next j
Next i
ぐっと読みやすくなりました。VBE(Visual Basic Editor)で [Tab] キーを使えば簡単にインデント可能です。複数行を選択してTab押下すれば、一括インデント。Shift+Tabで戻す。
実務では「インデント無しのコード」は「読みにくい= バグが隠れやすい = 後で修正しにくい」という悪循環になります。最初の数秒のインデント作業が、後々の時間を大きく節約します。
❌ ミス2:変数名の使い回し(本当に危険です)
For i = 1 To 3
For i = 1 To 3 ' ←これ、地味に危険です
Debug.Print "i=" & i
Next i
Next i



あ、外側のiと内側のiが同じ名前だ…何か起きそう。
その直感は正しいです。このコードを実行すると、外側のループが正常に動きません。なぜなら、変数iは「共有」されるからです。
内側のループが「Next i」を実行するたびに、変数iが上書きされます。外側のループのiまで影響を受けるんです。結果、ループが思わぬ回数で抜けたり、無限ループになったりします。
➡ 外側と内側で変数名を分ける(例:iとjなど)
For i = 1 To 3
For j = 1 To 3
Debug.Print "i=" & i & ", j=" & j
Next j
Next i
これなら、各変数が独立しています。外側のiが3回ループしている間、内側のjはそのたびに1から3まで全部ループします。
慣例として、外から順に「i」「j」「k」と命名するのが業界標準です。これに従っていれば、他の人がコードを読む時も「あ、3重ネストだな」と一瞬で把握できます。
❌ ミス3:Next文の対応を間違える
特に3重以上のネストになると、「このNext jはどのFor jに対応するのか?」という間違いが発生します。
For i = 1 To 3
For j = 1 To 3
For k = 1 To 3
Debug.Print i & "," & j & "," & k
Next k
Next j
Next i
正しい形は「最後に開いたForから順番に閉じていく」(後入れ先出し)です。
VBEの「自動インデント機能」を有効にしていれば、自動的に対応が取られます。編集メニューの「自動インデント」をオンにしておくことをお勧めします。
❌ ミス4:ネストの深さをコントロールできていない
理論的には何重でも重ねられるネストですが、3重を超えるとコードの複雑さが爆発的に増えます。
i, j, k, l, m…と変数が増え、「あれ、この変数は何をカウントしてるんだっけ?」という状態になりやすい。
➡ そういう時は、処理を小分けにして「別の関数に分ける」という手があります。
Sub Main()
For i = 1 To 3
ProcessRow i
Next i
End Sub
Sub ProcessRow(rowNum As Integer)
For j = 1 To 3
For k = 1 To 3
Debug.Print rowNum & "," & j & "," & k
Next k
Next j
End Sub
こうすることで「メインルーチンは行だけをループ」し、「各行の詳細処理は関数に委譲」という構造になります。結果、各関数が理解しやすくなり、バグも減ります。
応用:条件付きで内側ループをスキップ
ネストの基本が分かったら、次は「特定の条件でループをスキップする」という応用に進みます。
If と Exit For を組み合わせれば、柔軟な処理が可能です。
For i = 1 To 5
For j = 1 To 5
If j = 3 Then
Exit For ' jが3ならループを抜ける
End If
Debug.Print "i=" & i & ", j=" & j
Next j
Next i
このコードを実行すると、jが3に達した時点で内側のループを抜けて、次のiに移ります。
出力は以下のようになります。
i=1, j=1
i=1, j=2
i=2, j=1
i=2, j=2
i=3, j=1
i=3, j=2
i=4, j=1
i=4, j=2
i=5, j=1
i=5, j=2
各iにおいて、j=3になったら即座に内側ループを抜けているのが分かります。
関連:外側ループも一緒に抜けたい場合
もし「j=3に達したら、外側のiループも一緒に抜けたい」という場合は、フラグを使います。
Dim exitFlag As Boolean
exitFlag = False
For i = 1 To 5
For j = 1 To 5
If j = 3 Then
exitFlag = True
Exit For
End If
Debug.Print "i=" & i & ", j=" & j
Next j
If exitFlag Then
Exit For ' 外側ループも抜ける
End If
Next i
このように「フラグ変数」を使うことで、ネストの外側の層にも情報を伝達できます。
ネストの処理速度について
「ネストは遅くないか?」という質問をよく受けます。
答え:ネスト自体は遅くありません。ただし「ループの回数」が増えるので、回数が多いと遅くなります。
例えば、100行×100列のセルに値を入力する場合、10,000回のループが必要です。そこに「セルの計算」や「別シートへのアクセス」が入ると、さらに遅くなります。
大量データを扱う場合は、以下の工夫が有効です。
⚡ 工夫1:画面更新を止める
Application.ScreenUpdating = False
For i = 1 To 1000
For j = 1 To 100
Cells(i, j).Value = i * j
Next j
Next i
Application.ScreenUpdating = True
ScreenUpdatingをFalseにすると、ループ中の画面描画が止まり、速度が大幅に向上します。
⚡ 工夫2:計算を自動計算から手動計算に切り替える
Application.Calculation = xlManual
For i = 1 To 1000
For j = 1 To 100
Cells(i, j).Value = i * j
Next j
Next i
Application.Calculate
Application.Calculation = xlAutomatic
Excelがループ中に毎回計算をするのを防ぎ、最後にまとめて計算させることで高速化できます。
ネスト vs 配列:どっちを使う?
VBAを続けていると、「Arrayを使った処理」という別の方法に出会います。大量の列データを一度に配列に読み込んで、ループで処理する方法です。
「ネストと配列、どっち使う?」というのは、頻出の質問です。
目安:
・数百行程度、計算が軽い → ネストで十分
・数千行以上、複雑な計算 → 配列の方が高速
・小規模な表操作、わかりやすさ重視 → ネスト
・パフォーマンス重視 → 配列
実務では「最初はネストで書いて、遅かったら配列に変える」というやり方が現実的です。必要になるまで、無理に配列にする必要はありません。
よくあるつまずきポイント
🤔 Q1:ネストが上手くいかない。何が間違ってるのか分からない。
A:Debug.Printを大活用しましょう。ループの各段階で「iとjの値は何か」を出力して、期待と一致するか確認します。
For i = 1 To 3
Debug.Print "i=" & i & " (外側ループ開始)"
For j = 1 To 3
Debug.Print " j=" & j & " (内側実行中)"
Next j
Debug.Print "i=" & i & " (外側ループ終了)"
Next i
イミディエイトウィンドウに出力されるDebug.Printの値を眺めれば、ループがどう動いているかが明確になります。
🤔 Q2:ネストの中で、配列やコレクションにアクセスしたい。
A:完全に可能です。むしろ、セル直接アクセスより高速です。
Dim data As Variant
data = Range("A1:C3").Value
For i = 1 To 3
For j = 1 To 3
Debug.Print data(i, j)
Next j
Next i
Cells(i,j)のような遅いセルアクセスより、配列経由の方がずっと高速です。
🤔 Q3:ネストを途中で抜ける時、全部抜けたいのに内側だけ抜けてしまう。
A:先ほど説明した「フラグ方式」で対応します。または、ネストごと別関数に分割して、関数をExit Subで抜けるのも手です。
実践的な例:成績表を作成する
最後に、ネストを使った実践的な例をご紹介します。
シナリオ:10人の学生の、5科目の成績が入力されている。合計点と平均点を計算して、隣の列に出力したい。
Sub CalculateScores()
Dim i As Integer, j As Integer
Dim sum As Integer
Dim avg As Double
' A列:学生名、B列~F列:5科目の成績
' G列:合計、H列:平均
Application.ScreenUpdating = False
For i = 2 To 11 ' 2行目から11行目(学生データ)
sum = 0
For j = 2 To 6 ' B列から F列(5科目)
sum = sum + Cells(i, j).Value
Next j
avg = sum / 5
Cells(i, 7).Value = sum ' G列に合計
Cells(i, 8).Value = avg ' H列に平均
Next i
Application.ScreenUpdating = True
MsgBox "計算が完了しました"
End Sub
このコードは「外側のループで各学生を処理」し、「内側のループで各学生の5科目を合計」しています。10人 × 5科目 = 50回の処理が自動実行されます。
まとめ:ネストを使いこなすコツ
- ネストは「2次元的な処理」に最強。表データの自動化なら避けられない。
- インデント
- 変数名を分ける
- Next文は「最後に開いたForから順番に」閉じる。
- ネストが3重を超えたら、関数に分割することを検討。
- Debug.Printで各段階の値を確認。何が起きてるか可視化する。
- 大量データの場合は、ScreenUpdatingとCalculationの設定で高速化。



ネストはVBAの「基本の基本」ですが、ここを正確に理解していると、後々の複雑な処理がグッと分かりやすくなります。インデント・変数名・構造の3つを意識するだけで、グンと書きやすくなりますよ。


コメント