回数を指定して繰り返し(ループ)処理を行う方法を解説します。
For Nextステートメントを使用します。
基本構文
Dim カウンタ変数 As Long For カウンタ変数 = 初期値 To 最終値 ' ここにループしたい処理 Next
サンプルコード
' 同じ処理を10回繰り返し Dim i As Long For i = 1 To 10 MsgBox "テスト" Next
' データを第2行~最終行まで繰り返し Dim ws処理シート As Worksheet Set ws処理シート = ThisWorkbook.Worksheets("○○") Dim 最終行 As Long 最終行 = ws処理シート.Cells(ws処理シート.Rows.Count, 1).End(xlUp).Row Dim R As Long For R = 2 To 最終行 ' 処理例:C列=A列×B列 ws処理シート.Cells(R, 3) = ws処理シート.Cells(R, 1) * ws処理シート.Cells(R, 2) Next
' すべてのシートへ同じ処理 Dim ws処理シート As Worksheet Dim シートNo As Long For シートNo = 1 To ThisWorkbook.Worksheets.Count Set ws処理シート = ThisWorkbook.Worksheets(シートNo) ' 処理例:A1セルの値を読み取り Dim 取得値 As Variant 取得値 = ws処理シート.Range("A1").Value Next
解説
回数を指定して繰り返し処理を行うには、
For Nextステートメント(For文)を使用します。
カウンタ変数を一つ宣言(Dim)して利用するステートメントで、
Nextに到達するとカウンタ変数が1増えて次のループに入ります。
主にサンプルコードで示した3種類の使い方があり、
- 変数を「純粋なカウンタ」として使い、同じ処理を指定回数繰り返し
- 変数を「行番号」として使い、データを1行ずつ順に処理
- 変数を「シート番号」として使い、すべてのシートに同じ処理
このように変数で何をカウントするかで使い分けることが可能です。
使用する変数名について
For文のカウンタ変数に、常に「i」を使用しているコードをたまに見かけますが、
このような書き方はなるべくやめておきましょう。
For i = 2 To 最終行 Cells(i, 3) = Cells(i, 1) * Cells(i, 2) Next
このような書き方をしてしまうと、
- どの変数が何用の変数なのかわかりにくい
- iを使うFor文同士はそのままではコピーして併用できない
- 結果、i・j・kや、i1・i2・i3のように難読化コードを生みやすい
という欠点だらけのコードになってしまいます。
あらかじめ「カウンタ変数が何のカウンタなのかわかるように」しておくと、
コードが読みやすく、コピペ合体やコードの切り貼りに強くなります。
Worksheets(i).Cells(j, k) ' × 読みにくい上にいつもiの行がjになって混乱 Worksheets(シートNo).Cells(R, C) ' ○ 読みやすい上にコピペ合体しやすい
カウンタ変数の名前付けは丁寧に行っておきましょう。
For Nextステートメントで使用できる機能
For文には基本的には上記のコードを利用することになりますが、
さらに複雑な処理を書くために以下の機能を利用可能です。
途中でループを終了する - Exit For
For文を途中で終了する場合は、
Exit Forステートメントを使用します。
Dim i As Long For i = 1 To 10 If i = 5 Then Exit For Next
上記の場合は1~4まで処理した後、
回数が5になったところでFor文が終了されます。
例えば、「途中で空のセルを発見した場合はその時点で終了」
というような処理を実装する際に以下のように使用できます。
Dim R As Long For R = 2 To 最終行 ' A列に空のセルを検知したらループを終了 If ws処理シート.Cells(R, 1) = "" Then Exit For ' 処理例:C列=A列×B列 ws処理シート.Cells(R, 3) = ws処理シート.Cells(R, 1) * ws処理シート.Cells(R, 2) Next
なお、Exit ForはIf文とセットという訳ではなくただの1コードですので、
通常のコードと同様以下どちらの書き方をしてもOKです。
If i = 5 Then Exit For ' または If i = 5 Then Exit For End If
カウンタ変数を1ではなく指定数値ずつ進める - Step
カウンタ変数を2ずつ、3ずつなど指定数値ずつ進める場合は、
最終値の後ろに引数Stepを指定することが出来ます。
' 2・4・6・8・10の順に処理 Dim i As Long For i = 2 To 10 Step 2 Debug.Print i Next
Step 2なら2ずつ、Step 3なら3ずつ進みますので、
飛び飛びのループを実装したい場合に使用してください。
ちなみにStep 0.5と記載すれば一応小数で設定することも可能です。
(もちろん Dim i As Double とカウンタ変数も小数で宣言する必要あり)
カウンタ変数を逆順に進める - Step -1
カウンタ変数を逆順に進める場合は、
Stepにマイナスの数値を指定します。
' 10~1までカウントダウン Dim i As Long For i = 10 To 1 Step -1 Debug.Print i Next
逆順に進める場合は、
初期値を最終値より大きい数値にする必要がある点に注意してください。
For文内でFor文を使用する - ネスト
For文の中に別のFor文を書くことも可能です。
このような構造をFor文のネストと呼びます。
' 3行×3列を順番に処理 Dim R As Long For R = 1 To 3 Dim C As Long For C = 1 To 3 Debug.Print R, C Next Next
特に「すべてのシートのすべての行をループ」する際によく使用されます。
Dim ws処理シート As Worksheet Dim シートNo As Long For シートNo = 1 To ThisWorkbook.Worksheets.Count Set ws処理シート = ThisWorkbook.Worksheets(シートNo) Dim 最終行 As Long 最終行 = ws処理シート.Cells(ws処理シート.Rows.Count, 1).End(xlUp).Row Dim R As Long For R = 2 To 最終行 ' 各シートのデータを1行ずつ処理 Worksheets(シートNo).Cells(R, 1) = "○○" Next Next
前述の通りここでカウンタが被ってしまわないように、
普段からシート番号や行番号を「i」で定義しないようにしてください。
Nextに使用している変数を明記する - Next i
Nextの後ろには対応するカウンタ変数を明記することも可能です。
Dim R As Long For R = 1 To 10 Debug.Print R Next R ' ← ここに変数名を書くことが出来る
書いても書かなくても、Next RとNextの実行結果に違いはありません。
どの変数のNextなのか見やすいというメリットはあるのかもしれませんが、
別にインデントで分かる気はするので私は全く使用しない派です。
気に入ったら使ってみてください。
おまけ:For Nextステートメントの細かい仕様
基本的な使用方法は上記の通りですが、一応細かい仕様だけ触れておきます。
終了後のカウンタ変数の値
For文が最後まで実行された場合、
カウンタ変数にはループ範囲を超えた最初の値が残ります。
Dim i As Long For i = 1 To 10 Debug.Print i Next Debug.Print i ' 11
特にデータをループしている場合は、
Rに最終行が入っているわけではない点にご注意ください。
(最終行+1が入ることになります)
なお、Exit Forで途中終了した場合は終了した時点の値が残ります。
Dim 回数 As Long For 回数 = 1 To 10 If 回数 = 5 Then Exit For Next Debug.Print 回数 ' 5
Stepで最終値を飛び越した場合
Stepを使用した結果、
カウンタ変数が最終値を飛び越えてもエラーにはなりません。
Dim i As Long For i = 1 To 10 Step 4 Debug.Print i ' 1・5・9 Next Debug.Print i ' 13(13のループは実行されていない点に留意)
9の次は13となり、最終値の10を超えた時点でループが終了します。
For文はカウンタ変数が最終値と一致するまでではなく、
最終値を超えるまで繰り返すステートメントです。
最終値をちょうどStepの倍数に調整する必要はありませんのでご安心ください。
途中でカウンタを書き換えた場合
For文の途中でカウンタ変数を書き換えることも可能です。
例えばカウンタを3⇒7にワープさせることも可能です。
Dim i As Long For i = 1 To 10 If i = 3 Then i = 7 Debug.Print i ' 1・2・7・8・9・10 Next
可能は可能ですが、これをやるとコードが著しく難読化され、
どこがどの順番で実行されるかわからない、いわゆるスパゲティコードになります。
この記述は基本は使用せず、どちらかというと
「こう書けてしまうから気を付けないといけない」
という知識として知っておいてください。