3日がかりのその仕事、3分で終わらせる方法教えます!
パソコンスキルの心技体

Iif関数は、条件式の値にかかわらず、「条件式がTrueのときにやる処理」、「条件式がFalseのときにやる処理」の両方をやってしまうので注意

2014年5月6日
  • このエントリーをはてなブックマークに追加
  • follow us in feedly

エクセルマクロ・VBA達人養成塾 小川です。

昨日のブログ

で、「フォーカス・リーディング」の寺田昌嗣さんから依頼されて作ったマクロを公開しました。

その中で、Iif関数の挙動について「?」と思ったことについて書きましたが。

超優秀な元受講生さんからの助言で解決(というか、バグではなかったことが分かった)したので今日はその話題を。

Iif関数は、以下の書式で書きます。

Iif(条件式, 条件式がTrueのときにやる処理, 条件式がFalseのときにやる処理)

関数ですから、Left関数、Mid関数等々と同じように

hensu = Left("なんとかかんとか", 3)

のように、

hensu = Iif(hoge > 3, 5, 7) '[a]

というように書きます。

上記の式であれば、変数hogeの値が3より大きければhensuには5という値が入ります。
上記の式であれば、変数hogeの値が3より小さければhensuには7という値が入ります。

つまり、上記の式であれば、結果として起こることは以下と同じ。

If hoge > 3 Then
    hensu = 5 '[1]
Else
    hensu = 7 '[2]
End If

ところが、Iif関数は、If文と異なり、条件式の値がTrue/Falseどちらに転ぶかにかかわらず、「条件式がTrueのときにやる処理」、「条件式がFalseのときにやる処理」の両方をとにかくやっちゃう、という性質があります。

If 文なら、 [1], [2] のどちらかしか実行されません。
でも、ざっくり言うと、 Iif関数では、[1], [2]の両方をやってしまうわけです。

そのことは、[a]のような式では問題になりませんが、

『「条件式がTrueのときにやる処理」と「条件式がFalseのときにやる処理」のそれぞれ、違うセルを結合する処理が入っている』となると、問題になります。


さて、ここで、変数hogeの値によって、「セルA1~A2」か、「セルA1~B1」かのどちらかだけを結合するマクロを書きたいとします。

そのためのサンプルとして、以下に、OK1, OK2, NG という3つのマクロを書いてみました。
そのうちの2つは、問題なく動きます。そして、1つは、おかしな挙動になります。

以下は問題ありません。このマクロは、変数hogeの値によって、セル範囲A1~A2か、A1~B1の、どちらかしか結合しません。

Sub OK1()
    Dim hoge As Long
    Dim hensu As Long
    hoge = 9
    If hoge > 3 Then
        Range(Range("A1"), Range("A2")).Merge
    Else
        Range(Range("A1"), Range("B1")).Merge
    End If
End Sub

以下も、問題ありません。このマクロも、変数hogeの値によって、セル範囲A1~A2か、A1~B1の、どちらかしか結合しません。

Sub OK2()
    Dim hoge As Long
    Dim hensu As Long
    hoge = 9
    If hoge > 3 Then
        hensu = mg(Range("A1"), Range("A2"))
    Else
        hensu = mg(Range("A1"), Range("B1"))
    End If
End Sub
Function mg(r1 As Range, r2 As Range) As Integer
    Dim r As Range
    Set r = Range(r1, r2)
    Range(r1, r2).MergeCells = True
    mg = r.Count
End Functio

ところがOK2をIifで表現しようとした以下は問題です。
以下の式は、 hoge の値の評価にかかわらず、 mg(Range(“A1”), Range(“A2”)) , mg(Range(“A1”), Range(“B1”)) の両方の処理を実行してしまいます。

Sub NG()
    Dim hoge As Long
    Dim hensu As Long
    hoge = 9
    hensu = IIf(hoge > 3, mg(Range("A1"), Range("A2")), mg(Range("A1"), Range("B1")))
End Sub
Function mg(r1 As Range, r2 As Range) As Integer
    Dim r As Range
    Set r = Range(r1, r2)
    Range(r1, r2).MergeCells = True
    mg = r.Count
End Function

なぜかというと、前述したとおり、Iif関数は、If文と異なり、条件式の値がTrue/Falseどちらに転ぶかにかかわらず、「条件式がTrueのときにやる処理」、「条件式がFalseのときにやる処理」の両方をとにかくやっちゃう、という性質があるからです。

..と、そんな話の延長でした。

僕が当初書いたマクロでは、以下のようにさらに入れ子がいろいろ入っていました。
そのため、ステップイン実行していてもいまいち面倒くさくて、問題の真の理由はつきとめられないままでした(汗

Private Function Neco(r1 As Range, r2 As Range) As Range
    Set Neco = IIf(Rnd() > 0.5, r1, r2)
End Function
Private Function Mg(r1 As Range, r2 As Range) As Range
    Set Mg = Range(r1, r2)
    Range(r1, r2).MergeCells = True
End Function
Private Function IsBk(rT As Range) As Boolean
    IsBk = rT.Interior.Color = vbBlack
End Function
Sub Main()
    Set rRet = IIf( _
                IsBk(rA(1)), _
                Mg(rA(0), rA(1)), _
                Mg(rA(0), rA(2)) _
            )
End Sub

ということで、Iif関数は仕様どおりの挙動でした。
僕のほうが仕様を正確に理解していなかった、ということでした。

キーワード

コメント

コメントを残す

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

最新の記事

人気記事

最新記事

カテゴリ

最新コメント

タグクラウド