社内SEの話

日々起きたことの記録用

VBAのIIF関数のバグとその挙動について

↓プログラミングで副業を考えたらこちら↓

はじめに

今回の記事はIIF関数を積極的にすすめるわけではありません。
IIF関数は他のブログでも上がっているように致命的なバグがあり、今もなお改善されていません。
動作検証の記事があまりなかったので、掲載します。

IIF関数の使い方

構文

IIf(expr, truepart, falsepart)
Function CheckIt (TestMe As Integer)
    CheckIt = IIf(TestMe > 1000, "Large", "Small")
End Function

IIf 関数

関数の通りならTestMeの大きさ次第でLargeかSmallがCheckItに格納されるはずです。
実際に実行してみると、ちゃんと条件にあった結果を返します。
例の形であれば問題はありません。

バグ検証

実際の動作をデバッグで確認してみると動きがわかります。

Function CheckIt (TestMe As Integer)
    If TestMe > 1000 Then
        CheckIT = "Large"
    Else
        CheckIt = "Small"
    End If
End Function

通常はこんなコードになります。
実行手順はTestMeの条件を判断して大きければLargeの文へ、小さければSmallの文へ移動するはずです。

Function CheckIt (TestMe As Integer)
    CheckIt = IIf(TestMe > 1000, "Large", "Small")
End Function

しかし実際例のコードでデバックすると
1 TestMeの条件判断
2 Largeの読み込み
3 Smallの読み込み
4 結果を返す
という結果になります。
例のコードは文字列を返しているので大きな影響はありませんでしたが、TruePartとFalsePartの部分を関数に置き換えて見ましょう。

Public Sub macro1()
  Dim TestMe As Integer
  Dim Result As String
  TestMe = 50
  Result = IIf(TestMe < 1000, SampleA, SampleB)
  Debug.Print Result
End Sub

Function SampleA() As String
  Debug.Print "Exec Sample A!"
  SampleA = "A"
End Function

Function SampleB() As String
  Debug.Print "Exec Sample B!"
  SampleB = "B"
End Function

上記のコードで実行した結果は

Exec Sample A!
Exec Sample B!
A

SampleBの関数も実行しています。
しかし結果はAを返しています。
ここから言える事はIIF関数はTruePartやFalsePart両方読んでいる
ただ文字を返すだけの簡単なコードではいいけれど、関数で処理した内容をクラス内で使用する変数に上書きをしてしまうと、後勝ちしてしまい正しい結果になりません。
また0除算回避のために使用する下記の例の場合は

Function CheckIt (TestMe As Integer)
    CheckIt = IIf(TestMe  = 0, 0, 1000/ TestMe )
End Function

必ず0除算でエラー停止します。

検証結果

両方読み込んでいる