VBAでのクラスの作り方です。
2019/10/12: 一部文言等、修正しました。
##クラスモジュールを挿入する
こんな感じでクラスモジュールを挿入します。
プロパティウィンドウの「(オブジェクト名)」の欄でクラスの名称を設定します。
これで空のクラスができました。
###メンバ変数を定義する
クラスのメンバ変数を定義してみます。
Option Explicit
' メンバ変数
Public Name As String
Private Age As Long
Private
とつけたものはクラスの外からはアクセスできません。
Public
は外からアクセスできます。
(アクセス修飾子といいます)
###メソッドを作る
メソッドを追加した例です。
Option Explicit
' メンバ変数
Public Name As String
Private Age As Long
Public Mother As Person
' メソッド
Public Sub SayHello()
MsgBox "Hello, I'm " & Name & "!"
End Sub
' 引数付き
Public Sub SayHelloTo(otherPersonName As String)
MsgBox "Hello, " & otherPersonName & "!" & vbNewLine & _
"I'm " & Name & "!"
End Sub
' 戻り値あり(関数)
Public Function GetAge() As Long
GetAge = Age
End Function
' オブジェクトを返す関数(Setをつけること!)
Public Function GetMother() As Person
Set GetMother = Mother
End Function
メンバ変数と同様、頭にPublic
をつけると外からアクセスでき、Private
ではアクセスできません。
オブジェクト型を返す時は Set
をつける必要があります。
###Me
キーワード
Me
はクラスモジュールでは自身のインスタンスを指します。
###InitializeとTerminate
Class_Initialize
はクラスのインスタンスが生成されたときに呼ばれます。引数はつけられません。
Class_Terminate
はクラスのインスタンスが破棄されたときに呼ばれます。
ただし、ガーベージコレクションが動くタイミングは必ずしも分からないので、リソース(ex. DBへの接続など)を解放するメソッドを別に作るのが良いといわれています。
' 初期化処理
Private Sub Class_Initialize()
Name = "Bob"
Age = 30
Set Mother = Nothing
Debug.Print "initalized"
End Sub
' 終了時処理
Private Sub Class_Terminate()
Name = ""
Age = 0
Set Mother = Nothing
' その他、使用しているリソースの解放処理を行う
'
Debug.Print "terminated"
End Sub
これらのメソッドはPrivate
にします。Public
にするとintellisense(コード補完)で見えてしまいます。
###クラスの使い方
クラスの使い方です。
Option Explicit
Sub test1()
' オブジェクト型の変数を宣言
Dim p As Person
' インスタンス生成
Set p = New Person
' 値をセットする
p.Name = "Bob"
' 値を取得してみる
Debug.Print "age: " & p.GetAge()
' メソッド呼び出し
Call p.SayHello
' オブジェクト破棄(スコープから出るとガーベージコレクションによって勝手に破棄されます)
Set p = Nothing
End Sub
###プロパティ プロシージャを使う
先ほどの例ではメンバ変数Name
に外部から直接値を設定していましたが、それだと例えば空文字列ならエラーを出すといった処理ができません。
メンバ変数の設定時や取得時に何か処理をするには、プロパティ プロシージャを使います。
Option Explicit
' メンバ変数
' NameとMotherをPrivateにした
Private Name As String
Private Age As Long
Private Mother As Person
' 初期化処理
Private Sub Class_Initialize()
Name = "Bob"
Age = 30
Set Mother = Nothing
Debug.Print "initalized"
End Sub
' 終了時処理
Private Sub Class_Terminate()
Name = ""
Age = 0
Set Mother = Nothing
' その他、使用しているリソースの解放処理を行う
'
Debug.Print "terminated"
End Sub
' メソッド
Public Sub SayHello()
MsgBox "Hello, I'm " & Name & "!"
End Sub
' 引数付き
Public Function SayHelloTo(otherPersonName As String) As Person
MsgBox "Hello, " & otherPersonName & "!" & vbNewLine & _
"I'm " & Name & "!"
End Function
' プロパティプロシージャ
Property Get MyName() As String
MyName = Name
End Property
Property Let MyName(namae As String)
If namae = "" Then
' 氏名がブランクならエラー
Err.Raise 10000, , "名前がブランクです"
End If
Name = namae
End Property
Property Get MyAge() As Long
' 5歳さばを読んでみる
MyAge = Age - 5
End Property
Property Get MyMother() As Person
Set MyMother = Mother
End Property
Property Set MyMother(haha As Person)
Set Mother = haha
End Property
値を設定するときは、値型ならばLet、オブジェクト型ならばSetを使います。値の取得は、どちらもGetです。
なお、ここでMyAge
はGet
のプロパティ プロシージャしかないので、readonlyプロパティとか言ったりすることもあります。
使い方です。
Option Explicit
Sub test1()
Dim p As Person
' インスタンス生成
Set p = New Person
' 値をセットする
p.MyName = "Bob"
' オブジェクト型をセットする
Dim mom As Person
Set mom = New Person
Set p.MyMother = mom
' 値を取得してみる
Debug.Print "age: " & p.MyAge
' メソッド呼び出し
Call p.SayHello
' オブジェクト破棄(スコープから出るとガーベージコレクションによって勝手に破棄されます)
Set p = Nothing
End Sub
###Nothing
オブジェクト型で変数を宣言した後、初期状態だとNothing
が変数に入っています。(JavaとかでのNullに相当)
Nothing
かどうか検査するには、If p Is Nothing Then ...
のようにIs
を使います。
##関連
クラスの応用編はこちら→https://qiita.com/Kamo123/items/a39c8f3ffdc5e665de98
##参考文献
VBA Developer's Handbook: Edition 2
https://www.google.co.jp/search?q=VBA+Developer's+Handbook%3A+Edition+2&ie=&oe=
VBAについて網羅的に載っている本です。
現在は絶版になっているようですが、google playストアで電子版を買えました。