131
187

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

VBAでクラスをつくる

Last updated at Posted at 2017-01-02

VBAでのクラスの作り方です。

2019/10/12: 一部文言等、修正しました。

##クラスモジュールを挿入する
image.png
こんな感じでクラスモジュールを挿入します。

###クラスの名前を付ける
image.png

プロパティウィンドウの「(オブジェクト名)」の欄でクラスの名称を設定します。

これで空のクラスができました。

###メンバ変数を定義する
クラスのメンバ変数を定義してみます。

Person(クラスモジュール)
Option Explicit

' メンバ変数
Public Name As String
Private Age As Long

Privateとつけたものはクラスの外からはアクセスできません。
Publicは外からアクセスできます。
(アクセス修飾子といいます)

###メソッドを作る
メソッドを追加した例です。

Person(クラスモジュール)
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はクラスモジュールでは自身のインスタンスを指します。
image.png

###InitializeとTerminate
Class_Initializeはクラスのインスタンスが生成されたときに呼ばれます。引数はつけられません。
Class_Terminateはクラスのインスタンスが破棄されたときに呼ばれます。
ただし、ガーベージコレクションが動くタイミングは必ずしも分からないので、リソース(ex. DBへの接続など)を解放するメソッドを別に作るのが良いといわれています。

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

これらのメソッドは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

####結果
image.png
image.png

###プロパティ プロシージャを使う
先ほどの例ではメンバ変数Nameに外部から直接値を設定していましたが、それだと例えば空文字列ならエラーを出すといった処理ができません。
メンバ変数の設定時や取得時に何か処理をするには、プロパティ プロシージャを使います。

Person(クラスモジュール)
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です。
なお、ここでMyAgeGetのプロパティ プロシージャしかないので、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

####結果
image.png

image.png

###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ストアで電子版を買えました。

131
187
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
131
187

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?