適材適所

PowerShellやVBAなどプログラミング系の話多めで

【VBA】For文の抜け方 3選

プログラミングには必須の処理である繰り返し。

繰り返しの処理の中で特定の条件に当てはまった時に繰り返し処理を抜けたいということはよくあります。

VBAにも繰り返し構文がいくつか用意されていますが、その中でFor文(For i = 1 to 10のような)の3つの抜け方について紹介したいと思います。

Exit Forステートメント

基本的な例

基本的にはこれを使えば解決します。

例を見てみましょう。

 
Sub ExitForSample1()
    Dim i As Long
    Debug.Print "Start ExitForSample"
    For i = 1 To 10
        Debug.Print i
        If i = 3 Then
            Debug.Print "Exit Forを実行します。"
            Exit For
        End If
    Next i
    Debug.Print "End ExitForSample"
End Sub

10回の繰り返しのうち、3回目で処理を抜ける例です。

For文の中でExit Forと書くことで強制的にFor文を抜けることができます。

For文がネストされている(複数のFor文の)場合

For文がネストされ、複数のFor文がある場合、Exit Forステートメントだと最も内側のFor文からしか抜けることはできません。

 
Sub ExitForSampleNest()
    Dim i As Long
    Dim j As Long
    Debug.Print "Start ExitForSampleNest"
    For i = 1 To 10
        For j = 1 To 10
            Debug.Print i
            If i = 1 Then
                Debug.Print "Exit Forを実行します。"
                Exit For
            End If
        Next j
        Debug.Print "1つ目のFor終わり"
    Next i
    Debug.Print "End ExitForSampleNest"
End Sub

For文が複数になっていて、全部のForから抜けたいときは次に紹介するGoToステートメントを使うと良いでしょう。

GoToステートメント

悪魔のGoTo?

GoToステートメントは指定したラベルに一気に処理をスキップする命令です。

古いプログラミング言語では多様されていましたが、前後関係ガン無視で、脈絡なく処理が飛びまくることから悪魔のGoToと呼ばれているとかないとか・・・。バグやループの温床になることが多かったのです。

今時の言語では言語仕様上は実装されているものの、その悪魔の挙動のため、事実上は禁じ手となっていることがほとんどです。

しかし最小限、正しく使えばかなり便利なのは間違いありません。

VBAではエラー処理や今回のようなFor文で処理を抜けるときに使われることがあります。

Gotoを使ってFor文から抜ける例になります。

 
Sub GotoSample1()
    Dim i As Long
    Debug.Print "Start GotoSample1"
    For i = 1 To 10
        Debug.Print i
        If i = 3 Then
            Debug.Print "Gotoを実行します。"
            GoTo EXIT_FOR_LABEL
        End If
    Next i
EXIT_FOR_LABEL:
    Debug.Print "End GotoSample1"
End Sub

実行すると、EXIT_FOR_LABELへ処理が一気に飛ぶことがわかります。

ネストされていても関係ない

先ほども書いた通り、前後関係をガン無視でラベルまで処理の流れが飛ぶため、いくらネストされていようが、お構いなしにFor文を抜けることができます。

 
Sub GotoSample2()
    Dim i As Long
    Dim j As Long
    Debug.Print "Start GotoSample2"
    For i = 1 To 10
        For j = 1 To 10
            Debug.Print i
            If i = 3 Then
                Debug.Print "Gotoを実行します。"
                GoTo EXIT_FOR_LABEL
            End If
        Next j
    Next i
EXIT_FOR_LABEL:
    Debug.Print "End GotoSample2"
End Sub

変数をいじる

これは実用性皆無なのですが、For文の仕様を逆手に取ったような方法になります。

For文は変数の値が指定された値より大きく(または小さく)なるまで繰り返し処理を行います。

変数の値が指定された値を超えると処理が終了するので、処理の途中で変数に大きな値を代入してやるとFor文の最初で変数が指定された値を超えたということで処理が終了します。

変数の値が増えていくパターン

 
Sub VariableSample1()
    Dim i As Long
    Debug.Print "Start VariableSample1"
    For i = 1 To 10
        Debug.Print i
        If i = 3 Then
            Debug.Print "変数に最大値より大きい値を代入します"
            i = 11
        End If
    Next i
    Debug.Print "End VariableSample1"
End Sub

変数の値が減っていくパターン

 
Sub VariableSample2()
    Dim i As Long
    Debug.Print "Start VariableSample2"
    For i = 10 To 1 Step -1
        Debug.Print i
        If i = 3 Then
            Debug.Print "変数に最小値より小さい値を代入します"
            i = 0
        End If
    Next i
    Debug.Print "End VariableSample2"
End Sub

注意点

下記のコードを実行してみてください。

変数 i に11が代入された時点では処理は終わらず、Ifの後の処理が実行されていることがわかります。

Sub VariableSample3()
    Dim i As Long
    Debug.Print "Start VariableSample3"
    For i = 1 To 10
        Debug.Print i
        If i = 3 Then
            Debug.Print "変数に最大値より大きい値を代入します"
            i = 11
        End If
        Debug.Print "Ifの後の処理"
    Next i
    Debug.Print "End VariableSample3"
End Sub

つまり、変数 i の値が評価され、処理を終了するか継続するかは、1回の繰り返しが終わったタイミングで決まります。

そのため、繰り返しをせず、処理を中断したいときはこの手法は使えません。

というかそもそも使うことはないとは思いますが・・・。

終わりに

VBAにおけるFor文の抜け方について紹介しました。

VBAももう少しこのあたりの命令が強化されるといいですが、きっともう変わることは絶対にないのでしょうね。

配られたカードの中でできることをやるしかないですね!!

というわけで、ここまでお読みいただき、ありがとうございました。