HOME > 即効テクニック > Excel VBA > その他関連のテクニック > Ifのネストを避けるには(いろいろな記述方法と実行速度)

Ifのネストを避けるには(いろいろな記述方法と実行速度)|Excel VBA

その他関連のテクニック

Ifのネストを避けるには(いろいろな記述方法と実行速度)

(Excel 97/2000/2002/2003/2007/2010)

If文で判断する条件が複雑になると、ネストの中でネストして、またそのネストの中でネストして・・・と、大量のネストが発生してしまいますが、複数のIfのネストは色々な記述方法で書き変えることが可能です。

■Ifのネストを様々な方法で書きかえる

例えば、次のような条件分岐があるとします。
●サンプル1●

Sub Sample1()
    Dim myData As Integer
    myData = Range("B1").Value
    
    If myData <> 0 Then
        If myData <> 25 Then
            If myData <> 50 Then
                If myData <> 75 Then
                    If myData <> 100 Then
                        MsgBox "セルB1は「0, 25, 50, 75」ではありません"
                    End If
                End If
            End If
        End If
    End If

End Sub

これは、Select Caseステートメントを使って、シンプルに書きかえる事ができます。
●サンプル2●

Sub Sample2()
    Dim myData As Integer
    myData = Range("B1").Value

    Select Case myData
        Case 0, 25, 50, 75, 100
        Case Else
            MsgBox "セルB1は「0, 25, 50, 75」ではありません"
    End Select
        
End Sub

もしくは、次のサンプル3のように書きかえることもできます。
●サンプル3●

Sub Sample3()
    Dim myData As Integer
    myData = Range("B1").Value
    
    If myData <> 0 And _
       myData <> 25 And _
       myData <> 50 And _
       myData <> 75 And _
       myData <> 100 Then
        MsgBox "セルB1は「0, 25, 50, 75」ではありません"
    End If

End Sub

さらに、Do...Loopと組み合わせてサンプル4のように書きかえることもできます。
●サンプル4●

Sub Sample4()
    Dim myData As Integer, i As Long
    myData = Range("B1").Value
    
    Do
        If myData = 0 Then Exit Do
        If myData = 25 Then Exit Do
        If myData = 50 Then Exit Do
        If myData = 75 Then Exit Do
        If myData = 100 Then Exit Do
        MsgBox "セルB1は「0, 25, 50, 75」ではありません"
    Loop Until True
    
End Sub

ただし、サンプル3の書きかえには注意が必要です。
Ifのネストをしているサンプル1では、先に書いたIfステートメントの条件式を満たした場合にのみ次のネストの条件式を評価します。つまり、条件式の結果がFalseとなった場合は残りの条件式を評価しません。上の例ではサンプル1、サンプル2、サンプル4は先に記述した条件式がTrueのときに次の式を評価します。

一方、サンプル3のようにAnd演算子で複数の条件式を指定した場合、条件を満たさない式があったとしてもすべての式を評価します。ここが他のサンプルと異なります。
そのため、次のようなコードでは変数Xが0のときにもY/Xの式を評価し、0除算のエラーが発生するので注意が必要です。

    If X <> 0 And _
       Y <> 0 And _
       Y / X > 1 Then
       '処理
    End If

■処理速度について

では、サンプル1〜サンプル4の処理速度はどうでしょうか?
各サンプルの「myData=Range("B1").Value」と「End Sub」の間をFor...Nextループで1000万回繰り返し実行して、その時間を計測します。各サンプルのMsgBox関数の行はコメントアウトします。

セルB1が1(いずれの条件も満たさない)の場合、セルB1 が0(最初の条件を満たす)の場合について計測すると次のような結果になりました。

セルB1の値 サンプル1 サンプル2 サンプル3 サンプル4
1563 546 480 639
0 147 197 485 158

※ 実行環境:Windows7 Home Premium SP1/Intel Core i3 3.2GHz (64bit)/ Excel 2010
サンプル1〜サンプル4を10回実行し、各回の処理時間の平均値を算出。単位はミリ秒。

いずれの条件も満たさない場合はサンプル3が他より少しだけ速く、最初の条件を満たす場合はすべての条件式を評価するサンプル3が遅くなりました。
ただし、これは5つもの条件式を組み合わせ、1000万回も繰り返した結果です。複数の条件のうち何番目で条件を満たすかわからないようなケースでは、差はより小さくなります。

では、値と比較するのに比べて時間のかかる、セルの値を参照するような条件式ではどうでしょうか?
セルA1を0、A2を 25、A3 を50、A4 を75、A5を100とし、サンプル1の条件式を次のように変更します。サンプル2〜サンプル4も同様にセルA1 〜A5 の値が変数myData(セルB1) と一致するかどうかを判断するような条件式に変更して実行します。ただし、上のケースに比べて処理時間が長くなるため、繰り返し回数を1万回にして計測します。

    If myData <> Range("A1").Value Then
        If myData <> Range("A2").Value Then
            If myData <> Range("A3").Value Then
                If myData <> Range("A4").Value Then
                    If myData <> Range("A5").Value Then
                        'なにもしない
                    End If
                End If
            End If
        End If
    End If
セルB1の値 サンプル1 サンプル2 サンプル3 サンプル4
1 416 397 413 409
0 83 81 416 80

※ 実行環境:Windows7 Home Premium SP1/Intel Core i3 3.2GHz (64bit)/ Excel 2010
サンプル1〜サンプル4を10回実行し、各回の処理時間の平均値を算出。単位はミリ秒。

評価に時間がかかる条件式では、最初の条件を満たすケースでサンプル3と他のサンプルとの処理時間の差が大きくなっていることがわかります。

複数の条件を組み合わせる処理には色々な記述方法がありますが、評価対象や条件式、実行回数、可読性などを考慮して選択すると良いでしょう。