t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

マクロ作成者が覚えておきたい重要な概念「冪等性(べきとうせい)」について

冪等性(べきとうせい)とは、ある操作を1回行っても複数回行っても結果が同じであることをいう概念である。
言葉の響きは難しいが、これはプログラマーなら何度も遭遇するシチュエーションなので、是非とも覚えておきたい。

たとえばExcelマクロにおいて、以下のコードは冪等ではない。
実行するたびに、オートフィルターのON / OFFが切り替わってしまうからだ。

Sub NotIdempotent()
    Selection.AutoFilter
End Sub

先日業務であるツールを使用する様子を見たが、そのツールで使われていたオートフィルターを設定するコードは冪等ではなかった。
すると、加工するブックは予めオートフィルターを外しておかなければならない。

冪等性に注意を払ってこのコードを作り直すと、以下のようになる。

Sub Idempotent()
    If Not Selection.Parent.AutoFilterMode Then
        Selection.AutoFilter
    End If
End Sub

選択範囲の親(ワークシート)を確認し、フィルターがかかっていたらそれ以上は実行しないという処理である。
ただこの処理でもまだ詰めが甘い。なぜなら、全く意図しない場所にフィルターが掛かっていたとしても、処理済と見做してしまうからだ。

改良したのがこちらのコード。まず狙った位置にオートフィルターをかけ、もし掛かっていなければ外れたと判断してやり直す。

Sub IdempotentFixed()
    Do
        Selection.AutoFilter
    Loop Until Selection.Parent.AutoFilterMode
End Sub

あるいは、最初からフィルターを解除してしまい、それからフィルターを掛ける。

Sub IdempotentFixed2()
    Selection.Parent.AutoFilterMode = False
    Selection.AutoFilter
End Sub

前者はバグにより無限ループを作らないとも限らないので、最初からフィルターを外す後者の方が良いかもしれない。

いずれのコードも冪等性は確保されている。
この冪等性という概念を知っていると、自分のマクロが冪等性を担保しているかという批判的な眼を養うことができ、より安定したコード作成ができるようになると思う。

注意:今回は簡単に紹介する目的でSelectionを使用していますが、実際に組み込むマクロではRangeやWorksheetを特定して使っています。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。