Propertyを使って配列定数っぽいものを実現する

列挙体とPropertyを組みあわせて配列定数っぽくする

前回

akashi-keirin.hatenablog.com

のつづき。

Propertyに配列をセットする

Propertyプロシージャ内でArray関数を用いて、Propertyに配列を持たせるようにした。

標準モジュール
Option Explicit
Private hasGot As Boolean
Private CONST_ARRAY_ As Variant
Public Property Get CONST_ARRAY(ByVal i As Long) As Variant
  If Not hasGot Then _
    CONST_ARRAY_ = Array("アホ", "バカ", "カス"): hasGot = True
  CONST_ARRAY = CONST_ARRAY_(i)
End Property

引数付きにするのが良いのかどうかはわからない。

CONST_ARRAYを参照するたびにArray関数が作動するのもちょっとアレだと思ったので、配列取得済みかどうかをフラグ変数hasGotで判定するようにした。

エラー対応皆無なので、当然引数に存在しないインデックスを渡すと即エラーが出る。

配列のインデックス用に列挙体を作る

配列と列挙体は非常に相性が良いと思うので、引数指定用に列挙体を作った。

スト2 標準モジュール
Private Enum Batou
  アホ
  バカ
  カス
End Enum

これで、配列のインデックスを有意味な文字列で指定できるようになった。

使ってみる

次のコードで実験。

リスト3 標準モジュール
Public Sub testConstArray()
  Debug.Print CONST_ARRAY(アホ)
  Debug.Print CONST_ARRAY(バカ)
  Debug.Print CONST_ARRAY(カス)
End Sub

おお、わかりやすい!(笑)

こいつを実行すると、

f:id:akashi_keirin:20180826102108j:plain

わかりやすい結果だ!(笑)

おわりに

一つのブックの中に、同じ様式のたくさんのシートがあって、それぞれに値を転記していくようなときがある。転記先シートが一つだけなら、データ書き込みセルにそれぞれ名前を付ける、という対処法があるが、同じ様式のシートが複数あると、そのやり方では上手くいかない。

かといって、データ書き込みセルのアドレスを定数にしてしまうと、今度は列挙体に同じ名前が使えなくなってしまう。

標準モジュールのPropertyにするのが適切なやり方なのかどうかはわからないが、こうすることで可読性の高いコードが書けるのではないかと思った。

追記

せっかく列挙体を使うのだから、Property Getの引数を列挙体型にしないと意味がないな、と思ったので、コードを修正。

リスト4 標準モジュール
Option Explicit
Private hasGot As Boolean
Private CONST_ARRAY_ As Variant
Private Enum Batou
  アホ
  バカ
  カス
End Enum
Public Property Get CONST_ARRAY(ByVal batou_ As Batou) As Variant
  If Not hasGot Then _
    CONST_ARRAY_ = Array("アホ", "バカ", "カス"): hasGot = True
  CONST_ARRAY = CONST_ARRAY_(batou_)
End Property

Property Getの引数をBatou型にした。投げやりな列挙体名ですまん。

これでコード入力時に

f:id:akashi_keirin:20180826144839j:plain

このようにIntellisenseが働いて超便利。