ループ(繰り返し処理)からの強制脱出


仕事がら、他の人が作成したVBAコードをよく見ます。ひと目で「むむ!この人はできるな」と察するコードもありますが、逆のイメージを感じることも少なくありません。ある程度のスキルに達すると、あとはセンスの問題なのかもしれませんが、そうではなく"知らないために損をしている"ケースもあります。ループ(繰り返し処理)から強制的に脱出するテクニックもそのひとつですね。

たとえば次のコードは、セル範囲A1:A1000の中から「合計」と入力されているセルを探しています。「合計」のセルが見つかったら、そのセルを変数Targetに格納して、その後何らかの処理を行うとします。

Sub Sample()
    Dim i As Long, Target As Range
    For i = 1 To 1000
        If Cells(i, 1) = "合計" Then Set Target = Cells(i, 1)
    Next i
    ''この後Targetに対する処理…
End Sub

「合計」セルが一つしか存在しないのなら、このコードは正常に動作します。しかし、美しくありません。調べる対象はセル範囲A1:A1000です。もし「合計」セルがセルA2にあったらどうでしょう。変数TargetにはセルA2が格納されますので問題ありませんが、すでに「合計」セルが見つかっているにもかかわらず、セルA3:A1000は無駄に調べられることになります。この場合、「合計」セルが見つかった段階でFor Nextステートメントによるループを終了させるべきでしょう。

For NextステートメントやDo Loopステートメントなどによるループから強制的に抜け出るには、Exitステートメントを使います。

Sub Sample2()
    Dim i As Long, Target As Range
    For i = 1 To 1000
        If Cells(i, 1) = "合計" Then
            Set Target = Cells(i, 1)
            Exit For
        End If
    Next i
    ''この後Targetに対する処理…
End Sub

Exitステートメントでループを抜けるには「Exit For」または「Exit Do」と記述します。「Exit For」はFor NextステートメントまたはFor Eachステートメントによるループから脱出し、「Exit Do」はDo Loopステートメントによるループを終了させます。いずれも、それぞれ対応するループ内でしか使用することはできず、実行するとExitステートメントが記述されているループの外側に抜け出ます。

また、Exitステートメントは「Exit Sub」「Exit Function」と書くことで、SubプロシージャやFunctionプロシージャを強制的に終了することもできます。これも覚えておきたいテクニックのひとつです。

Sub Sample2()
    Dim buf As Long
    buf = ActiveCell.Value
    Call myProc(buf)
End Sub
Sub myProc(buf As Long)
    If buf < 1 Then
        MsgBox "1以上の数値を指定してください", vbExclamation
        Exit Sub
    End If
    MsgBox buf * 100
End Sub

上記のサンプルは、Sub Sample2内で変数bufにアクティブセルのデータ(数値と仮定)を格納し、その数値をSub myProcに渡します。Sub myProcでは、受け取った数値を評価して、もし1より小さかったらメッセージを表示して、ただちにプロシージャを終了させます。