(Excel No5)「If文のOrに注意」

御存じない方の為に、紹介しておきましょう。
まずは、C言語のコードを見て下さい。

#include
int num;
int count (void);
int count () {
    num++;
    return num;
}
int main(void) {
    num = 0;
    printf ("num1 = %d\n", num);
    if ((count() == 1) || (count() == 2))
        printf("num2 = %d\n", num);
    return 0;
}

この結果は、下記のようになります。
num1 = 0
num2 = 1
では、VBAでの同様のコードを作ってみます。(結果を確認するにはイミディエイトウィンドウを表示します)

Option Explicit
Dim
num As Integer
Function Count() As Integer
    num = num + 1
    Count = num
End Function
Sub
main()
    num = 0
    Debug.Print "num1 = " & num
    If ((Count() = 1) Or (Count() = 2)) Then
        Debug.Print "num2 = " & num
    End If
End Sub

この結果は、下記のようになります。
num1 = 0
num2 = 2

(C言語を知らない方にはピンとこないかもしれませんが)このように同じ内容のコードでも結果が異なってしまいます。
これは、If文で条件式がOr接続されている場合の評価に違いがあることによります。
条件式がOr接続で複数書かれている場合、C言語の場合は最初のCount()==1の条件式が真になった(成立した)ため、そこで条件式の評価が終了してnum2=1の出力が行われます。つまり、2つ目のCount()は実行されません。
ところが、VBAの場合は最初の条件式Count()=1が成り立っても、全部の条件式が評価されるのです。つまり、2つ目のCount()も実行されてしまいます。これは、今に始まったことではなくかなり前から(VBでも)そうなので、VBAの仕様と言えるかもしれません。
通常は特に意識する必要はないと言えますが、上記のように結果が変わってしまう場合や、(あまりよい例とは言えませんが)下記の場合は注意が必要です。

Sub main2()
    Dim buf As Variant
    buf = InputBox("データ?")
    If (CInt(buf) <= 0) Or (Left("abcdef", CInt(buf)) <> "ab") Then
        MsgBox "NG"
    End If
End Sub

buf(数値しか入力されないと仮定)が-1の場合、(CInt(buf) <= 0)が成立するためNGと表示されそうに思いますが、2つ目の条件式も実行されてしまうため、Leftの第2引き数が-1なのでエラーが発生してしまいます。
VBAでは1ステートメントづつ実行されるため、場合によってはこのような現象は見つけにくいものになりますので、覚えておいた方がよいでしょう。
蛇足になりますが、複数の条件をOrで接続している場合、常にすべての条件が評価されているため性能に影響することになります。これが問題になる場合は、複数のIf文に分けるなりして不必要な処理は実行されない様にするとよいでしょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください