こんにちは! Excel講師の榊裕次郎です。
この記事は Excel VBA の 講座において、For ~ Next ステートメントのみにフォーカスをあてた質問記録となります。VBAの初歩的な話は抜いて記載していますので、ご了承ください。
制御構造 For Next ステートメント
For ~ Next ステートメントの基本的なプロシージャは以下のとおりです。
Sub example1()
Dim i As Long
For i = 1 To 100
Cells(i, 1).Value = i
Next
End Sub
【実行結果】
※ キャプチャは、4行目~94行目まで非表示にしてます。
Cells(1, 1)で、セルA1を指します。Cells(2,1)でセルA2を指します。
Cells(行・列)なので、上のプロシージャを読み解くと、セルA1に「1」を入力、セルA2に「2」を入力……セルA100に「100」を入力して終了、という内容になります。
変数「i」は、よく繰り返し処理の変数で用いられるため、カウンタ変数と呼びます。変数名で使用される「i」は、カウンタ変数名でよく使われています。
これがExcel VBAでよく用いられる代表的なループ処理です。
【質問1】 変数の初期化は必要ですか?
Sub example2()
Dim i As Long
i = 1
For i = 1 To 100
Cells(i, 1).Value = i
Next
End Sub
この i = 1 は不要です。
ご質問のとおり、変数を初期化してからスタートしたほうが安全な気もしますが、
For i = 1 to 100
の部分で、変数「i」に1から代入してスタート! となっているので、いちいち書く必要はありません。コードはシンプルな方がいいですからね。
【質問2】Next のあとに 変数名は必要? 不要?
Sub example3()
Dim i As Long
For i = 1 To 100
Cells(i, 1).Value = i
Next i
End Sub
Next i の i です。これは省略可能なので、あってもなくても正常に動きます。
ちょっと強引なプロシージャですが、For文をネストして使っているケースを想定してください。
Sub example4()
Dim i As Long
Dim j As Long
For i = 1 To 100
For j = 2 To 3
Cells(i, j).Value = "〇"
Next j
Cells(i, 1).Value = i
Next i
End Sub
セルA1に「1」が入ったら、セルB1とC1に「〇」が入力されるマクロです。こういう場合、Nextのあとにカウンタ変数名があったほうが、どのNextなのかがわかります。
FOM出版のテキストだと「正しくループ処理が行われない可能性がある」という記載があるので、講座ではNextのあとに変数を入力しましょう、と教えていますが、個人的にはNextで完了して……。
いや、実際の開発だと私の場合、ForにForのネストをした成果物はないかも!?
【質問3】繰り返し回数は動的に決めることは可能ですか?
既にA列に87個のデータがあるとしましょう。
Sub example5()
Dim i As Long
Dim Cnt As Long
Cnt = WorksheetFunction.CountA(Columns(1))
For i = 1 To Cnt
Cells(i, 2).Value = "〇"
Next
End Sub
簡単に、Excel VBAであればワークシート関数を使うこともできますので、こんな感じでA列にあるデータ件数の個数を出力することができます。
Cnt の変数には、=COUNTA(A:A) で求めた結果と同じ値が入ります。A列には「87」まで連番が降られていますので、For i = 1 to 87 となるわけですね。
これは一例なので、他にも表の中の最終行を取得して行番号を取得、ということも可能です。講座ではシンプルに説明をするため、i = 1 to 100 みたいに教えています。
ちなみに、Columns(1)はA列を指しますが、
Cnt = WorksheetFunction.CountA(Columns(1))
Cnt = WorksheetFunction.CountA(Columns("A"))
Cnt = WorksheetFunction.CountA(Range("A:A"))
としてもOKです。自分が読みやすいステートメントを使ってください。
【補足】
CellsやColumnsで数字を使う表記は、カウンタ変数(この記事の例でいうと、変数 i のようなやつ)で加算によって変動できます。
Rangeを使うと、A1形式での表記になるので読みやすくなりますが、カウンタ変数が扱いづらくなります。以下、CellsとRangeを比べてみましょう。
Cells(i , 1)
Range("A"& i )
カウンタ変数 i を代入して何かを処理するなら、Cellsのほうが扱いやすいですよね。
と講座で伝えてしまうと、完全主義者の方は勉強ばかりして制作になかなか踏み切らない傾向があるので、コードを書くときに大事なのは、
- まずは処理のゴールに至ること
- そのあとでコードを簡素化できるか検討(リファクタリングといいます)
- 1年後の自分が見ても忘れないか、他の人にこのコードを渡せるか? コメントなどを適宜入れる
という流れがあることを指導しています。
最初はゴールに至れば、コピペコードでも問題ない(とりあえず自分ひとりで使う分には)という考え方をしています。なので、美しさを先に求めず、気楽に、思いのままコーディングしましょう!
【質問4】ループを途中で抜けることは可能ですか?
Exit For を使います。
Sub example6()
Dim i As Long
For i = 1 To 100
Cells(i, 1).Value = i
If i = 78 Then
Exit For
End If
Next
End Sub
繰り返し処理中、もしこの条件だったら~ という流れで停止処理を組み込むことがあります。
If 文の条件式がネストされるので、すこし煩雑に見えてしまうかもしれませんが、変数「i」 が 78 になったら79にループせずにここで処理を抜ける、という意味になります。
まずは、処理を抜けるためには Exif For がある、というところだけ覚えておけばOKです。
まとめ
以上4点アウトプットしました。また今年ご質問があれば追記していきます。
2021年に60人規模でExcel VBAのオンライン社員研修があり、この年もお仕事をいただいたので、あのときもらった質問を整理して、すぐ答えられるよう準備をしておこうと記事にしました。
オンラインでの講座は、気をつけの姿勢を維持したまま話すような教えづらさがあるので、時間があるときにアウトプットしておかないとですね。
所定の回数を繰り返すFor文は、どんなプログラミングでも登場しますからね。私自身も開発業務を通じながらステップアップしていきます!