「同じ処理を何十回も手作業で繰り返している……」
VBAを使い始めた方なら、一度はこんな場面に出くわしたのではないでしょうか。セルに連番を振ったり、データを1行ずつチェックしたり。手作業だと時間がかかるうえにミスも出やすいですよね。
VBAのFor~Next文を使えば、こうした繰り返し処理をたった数行のコードで自動化できます。この記事では基本構文から実務で使えるパターンまで、まとめて解説していきます。
VBA For~Next文とは?繰り返し処理の基本を理解しよう
For~Next文は、VBAで「決まった回数だけ処理を繰り返す」ための構文です。
たとえば「1行目から100行目まで同じ処理をしたい」とき、100回コードを書く必要はありません。For~Next文を使えば、カウンター変数が自動で増えながら指定した回数だけ処理を実行してくれます。
VBAにはいくつかのループ構文がありますが、For~Next文は繰り返す回数がはっきり決まっているときに一番使いやすい構文です。
VBA For~Next文の基本構文と書き方
基本の書き方
For~Next文の構文はこちらです。
Sub sample()
Dim i As Long
For i = 1 To 10
'--- ここに繰り返したい処理を書く ---
Next i
End Sub
動作の流れをかんたんに整理すると、次のようになります。
- カウンター変数
iに初期値(ここでは1)が入る - 処理を実行する
Next iでiが1つ増えるiが最終値(ここでは10)を超えていなければ、2に戻るiが最終値を超えたらループ終了
カウンター変数の名前は i が定番です。ただし row や count など、分かりやすい名前でもOKですよ。ポイントは数値型(Long型)で宣言することです。
Integer 型は扱える範囲が -32,768 から 32,767 までです。一方 Long 型なら約21億まで対応できます。大きなデータでも安心なので、迷ったら Long を選んでおきましょう。変数の型について詳しく知りたい方は「VBAの変数の使い方」の記事もあわせてどうぞ。
Stepで増減値を変更する
通常、カウンター変数は1ずつ増えていきます。Step を使うと、増減の幅を自由に変えられます。
' 2行おきに処理する(1, 3, 5, 7, 9行目)
Sub sample_step()
Dim i As Long
For i = 1 To 9 Step 2
Cells(i, 1).Interior.Color = RGB(255, 255, 200)
Next i
End Sub
カウントを減らすことも可能です。その場合は初期値を最終値より大きくするのを忘れないでくださいね。
' 10から1に向かってカウントダウン
Sub sample_countdown()
Dim i As Long
For i = 10 To 1 Step -1
Cells(i, 1).Value = i & "番目"
Next i
End Sub
注意点として、Step に 0 を指定すると無限ループになります。エラーにはならず延々と処理が続いてしまいます。うっかり書かないように気をつけましょう。
Exit Forで途中終了する
ループの途中で「もうこれ以上繰り返す必要がない」という場面もありますよね。そんなときは Exit For を使います。
' A列から「合計」というセルを探して、見つけたらループ終了
Sub sample_exit_for()
Dim i As Long
For i = 1 To 1000
If Cells(i, 1).Value = "合計" Then
MsgBox i & "行目に「合計」が見つかりました"
Exit For
End If
Next i
End Sub
大量のデータを処理するとき、目的のデータが見つかった時点でループを抜ければ処理時間を大幅に短縮できます。実務ではかなり重宝するテクニックですよ。
VBA For文の実務パターン5選
ここからは、実際の業務で使えるパターンを紹介していきます。
パターン1: セルに連番を振る
一番シンプルな使い方です。指定した範囲に連番を入力します。
Sub 連番を振る()
Dim i As Long
For i = 1 To 20
Cells(i, 1).Value = i
Next i
End Sub
このコードを実行すると A1 から A20 セルに 1 から 20 の連番が入ります。RangeやCellsの使い方を理解しておくと、セルの指定がもっと柔軟にできるようになりますよ。
パターン2: 条件に合うデータだけ処理する
For文とIf文を組み合わせると、条件に合ったデータだけを処理できます。実務で特に使う場面が多いパターンです。
' B列が「未処理」の行だけC列に「要対応」と入力
Sub 条件付き処理()
Dim i As Long
For i = 2 To 100
If Cells(i, 2).Value = "未処理" Then
Cells(i, 3).Value = "要対応"
End If
Next i
End Sub
条件に合う行だけ色を付けたり、別シートにコピーしたりといった応用もできます。
パターン3: 最終行まで自動でループする
実務では、データの行数が毎回変わることがほとんどです。ループの終了値を固定してしまうと、データが増えたときに処理漏れが起きてしまいます。
そこで、最終行を自動取得してループの終了値に使うのが定番パターンです。
Sub 最終行まで処理()
Dim i As Long
Dim lastRow As Long
'--- A列の最終行を取得 ---
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
'--- 2行目からデータ最終行まで処理 ---
If Cells(i, 1).Value = "" Then
Cells(i, 1).Interior.Color = RGB(255, 200, 200)
End If
Next i
End Sub
Cells(Rows.Count, 1).End(xlUp).Row は「A列の一番下から上に向かって、最初にデータがあるセルの行番号を返す」という意味です。これで毎回データ件数を調べなくて済みますよ。
パターン4: 逆順ループで行を安全に削除する
行の削除処理をFor文で行うとき、上から順に回すと行番号がずれて正しく処理できません。Step -1 で下から上に向かってループするのがポイントです。
Sub 空白行を削除()
Dim i As Long
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = lastRow To 2 Step -1
If Cells(i, 1).Value = "" Then
Rows(i).Delete
End If
Next i
End Sub
上から削除すると、たとえば3行目を消した瞬間に4行目が3行目に繰り上がります。すると次の i = 4 では元の5行目を処理してしまい、旧4行目がスキップされます。逆順ループならこの問題が起きません。
パターン5: 複数シートを一括処理する
ブック内のすべてのシートに同じ処理をかけたい場面もあります。シート数をカウンター変数の終了値に使うことで、For文でも対応できます。
Sub 全シートにヘッダー追加()
Dim i As Long
For i = 1 To Worksheets.Count
Worksheets(i).Range("A1").Value = "No."
Worksheets(i).Range("B1").Value = "名前"
Worksheets(i).Range("C1").Value = "金額"
Next i
End Sub
ただし、シートやセル範囲などの「コレクション」を順番に処理するなら、For Each~Next文のほうがコードがシンプルになります。用途に応じて使い分けてみてください。
For文のネスト(入れ子)で表を一括処理する
For文の中にさらにFor文を入れることをネスト(入れ子)と呼びます。少し複雑に見えますが、やっていることはシンプルです。
外側のFor文が行を、内側のFor文が列を担当するイメージで考えてみてください。
' 5行 x 3列の表すべてに値を入力する
Sub ネストの例()
Dim i As Long
Dim j As Long
For i = 1 To 5 '行のループ
For j = 1 To 3 '列のループ
Cells(i, j).Value = i & "行" & j & "列"
Next j
Next i
End Sub
実行すると、A1 から C5 のセルに「1行1列」「1行2列」……といったテキストが入ります。
ネストを使った実務的な例も見てみましょう。表の中で空白セルを見つけて「未入力」と表示するマクロです。
' 表内の空白セルに「未入力」と表示
Sub 空白チェック()
Dim i As Long
Dim j As Long
For i = 2 To 50 '2行目から50行目まで
For j = 1 To 5 'A列からE列まで
If Cells(i, j).Value = "" Then
Cells(i, j).Value = "未入力"
Cells(i, j).Interior.Color = RGB(255, 200, 200)
End If
Next j
Next i
End Sub
ネストするときのポイントは、外側と内側で別の変数名を使うことです。外側が i なら内側は j、さらにネストするなら k にするのが一般的ですよ。同じ変数名を使うとエラーになるので注意してくださいね。
VBA For文でよくあるエラーと対処法
For文を使っていると遭遇しがちなエラーをまとめました。
| エラー内容 | 原因 | 対処法 |
|---|---|---|
| 処理が終わらない(無限ループ) | Step に 0 を指定している | Step の値を1以上(または-1以下)にする |
| ループが一度も実行されない | 初期値 > 最終値になっている(Step が正の値のとき) | 初期値と最終値の大小関係を確認する |
| 「Next に対応する For がありません」 | For と Next の対応がずれている | ネスト時は内側から順に Next を閉じる |
| 「オーバーフロー」エラー | カウンター変数が Integer 型で範囲超え | 変数を Long 型に変更する |
特に「ループが一度も実行されない」パターンは気づきにくいバグです。Step -1 を使うときに初期値と最終値を逆にし忘れるケースが多いので、気をつけましょう。
For~Next・Do Loop・For Eachの使い分け
VBAには For~Next 以外にもループ構文があります。それぞれの特徴を整理しておくと、場面に応じて最適な構文を選べるようになりますよ。
| 構文 | 向いている場面 | 特徴 |
|---|---|---|
| For~Next | 繰り返す回数が決まっているとき | カウンター変数で回数を制御 |
| Do Loop | 条件を満たすまで(または満たす間)繰り返したいとき | 回数が事前に分からなくてもOK |
| For Each | シートやセル範囲などのコレクションを順番に処理したいとき | オブジェクトを1つずつ取り出せる |
どう選べばいい?3ステップの判断フロー
- 繰り返す回数が決まっている? → Yes なら For~Next
- コレクション(シート・セル範囲・配列)を順番に処理したい? → Yes なら For Each
- 「条件を満たすまで」繰り返したい? → Yes なら Do Loop
たとえば「A列の最終行まで処理したいけど、データ件数が毎回変わる」という場合でも、最終行を取得すれば回数が確定するため For~Next で対応できます。一方、「空白セルが見つかるまで」のように終了条件が行数ではない場合は Do Loop が向いています。
まとめ
この記事では、VBAのFor~Next文について基本から実務パターンまで解説しました。
ポイントをおさらいしておきましょう。
- For~Next文は回数が決まった繰り返し処理に最適
- Step で増減幅を変更、Exit For で途中終了できる
- 最終行の自動取得と組み合わせるのが実務の定番パターン
- 逆順ループ(Step -1)は行削除時に必須のテクニック
- ネストを使えば行と列の二重ループで表全体を処理できる
- Do Loop・For Eachとの使い分けで、より適切なループ構文を選べる
For文はVBAの中でも使用頻度がとても高い構文です。まずはこの記事のサンプルコードをコピーして動かしてみてください。自分で動かしてみると、理解がぐっと深まりますよ。
