t-hom’s diary

主にVBAネタを扱っているブログです。

VBAの自作クラスでデフォルトプロパティを設定する方法

海外のサイトで、自作のクラスにデフォルトプロパティを設定する方法を発見した。
(リンク先は英語) http://www.cpearson.com/excel/DefaultMember.aspx

デフォルトプロパティとは、クラス名だけで参照できるデフォルトの値のことである。
たとえば、ExcelのRangeオブジェクトのデフォルトプロパティはValueなので、Range("A1").Value = 1と書かなくてもRange("A1") = 1と書くだけでValueプロパティにアクセスできる。

こういったデフォルトプロパティを自作クラスに実装する方法である。

やり方は以下のサンプルのとおり。

例として、Personクラスを作ったとする。

Private p_name As String, p_age As Integer

Property Get Name() As String
    Name = p_name
End Property

Property Let Name(n As String)
    p_name = n
End Property

Property Get Age() As Integer
    Age = p_age
End Property

Property Let Age(A As Integer)
    p_age = A
End Property

これを一度エクスポートしてclsファイルにする。後でインポートするので、Excel側のクラスは一旦解放しておく。
clsファイルをエディタで開くと、なにやら色々とコード以外のことが書かれている。

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "Person"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private p_name As String, p_age As Integer

Property Get Name() As String
    Name = p_name
End Property

Property Let Name(n As String)
    p_name = n
End Property

Property Get Age() As Integer
    Age = p_age
End Property

Property Let Age(A As Integer)
    p_age = A
End Property

エディタで開いた状態で、Get Nameプロパティの中のコードの先頭行に、Attribute Value.VB_UserMemId = 0を追加して保存する。

Property Get Name() As String
    Attribute Value.VB_UserMemId = 0
    Name = p_name
End Property

そして、インポートしなおす。
すると、コード上は先ほど追記したAttribute Value.VB_UserMemID = 0が見当たらない。

しかし、使ってみると、

Sub test()
    Dim A As New Person
    A = "thom"
    A.Age = 20
    Debug.Print A, A.Age
End Sub

これでちゃんと動作する。

ポイントは、Attribute Value.VB_UserMemID = 0は一箇所しか書いてはいけないということ。
※PropertyならGetメソッドだけに書けばLetでも使える。

ただし、ワークシート型変数を返すプロパティで使ってみたところ失敗した。
プリミティブ型じゃないと動かないのかもしれない。

なお、今回紹介したテクニックは以下の書籍(英語)でも紹介されている。

VBA Developer's Handbook

VBA Developer's Handbook

この書籍ではクラスモジュールの使い方などあまり知られていない高度なテクニックが非常に丁寧に解説されており、英語を読める方にはイチオシのバイブルである。

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