reimeのメモ帳

主にExcelVBAとかSQLとか

Enum(列挙体)の裏技【VBA】

皆さんEnum(列挙体)使っていますか?

Long型の定数をまとめて定義できるアレです。基本的な使い方は私が紹介するまでもないと思うので、知らない方はググってください。
今回はググってもあんまり出てこなさそうな、けれども知っていると便利かもしれない技を紹介します。

プロシージャの仮引数に設定してインテリセンス(入力補完)が使える

 前に呟いたことがあるので載せます。
私はよく使うのですが意外と知られていない気がします。

 普通の定数ではなくEnumを使う利点の1つはインテリセンス(入力補完)だと思いますが、プロシージャの仮引数にEnum型の変数を定義することで呼び出すときにもインテリセンスを利用できます。

EnumとFunctionを定義して、

f:id:Reime:20190916213004p:plain

呼び出してやると、

f:id:Reime:20190916212556p:plain

 みたく使えます。

使いどころですが、選択肢が決まっていて引数で分岐させたい場面(例えばデータベースの接続先を指定するとか)で威力を発揮します。
あとこのテクニックはSelect Case文と、とても相性が良いです。EnumはLong型しか定義できない為、Select Case文で文字列などに変換してやります。

難点があるとすれば仮引数のEnum変数にPrivateを設定した場合、他のプロシージャから呼べないという点でしょうか。

f:id:Reime:20190916215608p:plain

f:id:Reime:20190916215642p:plain

Private Enumであってもちゃんとインテリセンスが効くのでいけるかと思いきや、

f:id:Reime:20190916215806p:plain

コンパイルエラーになります。
なのでEnumを引数に設定するときはPublic(既定値)にして、多用するときはバッティングしないような命名にしましょう。

メンバを非表示に出来る

 これもあんまり見たことない気がします。

VBEでF2キーを押すとオブジェクトブラウザが開き、オブジェクトとそのメンバの一覧が表示されますが、実はここに表示されず、インテリセンスにも出てこない隠れたメンバが存在します。

有名どころで言えば、Rangeオブジェクトのデフォルトプロパティである_Defaultプロパティ(※よく勘違いされているけれどもValueプロパティではない)でしょうか。

f:id:Reime:20190916221942p:plain

Range("a1").まで入力しても_Defaultは出てきません。
先頭にアンダースコア(「_」のこと。アンダーバーとも)が付いているメンバーは通常非表示になっています。

f:id:Reime:20190916221127p:plain

しかしオブジェクトブラウザの任意の場所で右クリックをして「非表示のメンバーを表示」にチェックをすると、

f:id:Reime:20190916223144p:plain

この通り、隠れたメンバが表示されます。これが非表示メンバです。

さてこの非表示メンバですが、自作のクラスやプロシージャには実装できません。
しかし、なぜかEnum(列挙体)だけはできます。

f:id:Reime:20190916225009p:plain

↑の[_eLast]みたいに先頭にアンダースコアを付けて括弧で括ることで、

f:id:Reime:20190916225801p:plain

ちゃんと非表示になります。

 

(応用)Enumの要素数を(条件付きで)取得できる

 Enumの特性として、要素の値を省略すると直前のメンバ + 1 (先頭のメンバは0)の値が割り振られます。

f:id:Reime:20190916231607p:plain
言葉にすると難しいですが、要するに連番になります(↑の画像の右も左も同じ値が入ります)。

勘の良い方はお気づきかと思いますが、この[_eLast]の値を取得できればEnumの要素数を算出できます。
たとえば、こんな関数を書くとか。

f:id:Reime:20190916232256p:plain

ポイントは[_eLast]が非表示メンバなので、インテリセンスには表示されず、コーディング時のノイズにならない点です。
項目が増える際には[_eLast]の直前に追加します。

 おわりに

Enumってよくシートの値を配列とかに格納する際に、列番号がマジックナンバーになるのを避ける目的で使われると思います。
ただまぁ、列ってよく増減するんですよね。そんなときにEnumの要素数を算出できるとコードの修正が少なくて済むので便利だよなーって考えていました。