更新日:、 作成日:

VBA クラスの使い方

はじめに

Excel VBA マクロでクラスの使い方を紹介します。

クラスモジュールのことを一般的に「クラス」と言います。クラスから Worksheet や Range のようなオブジェクトを作成できます。

変数や関数以外にもコンストラクタやプロパティ、イベントなども作成できます。クラスの関数のことを「メソッド」と言ったりもします。VBA ではクラスの継承はできません。

Set 変数名 = New クラス名 のようにして、インスタンス化できます。インスタンス化して初めてクラスを使用できます。

Set 変数名 = Nothing のようにして、インスタンスを破棄できます。

クラスは複雑なので無理に使用する必要はありません。シートや標準モジュールだけでもマクロを作成できます。

クラスとは

オブジェクトを作成するためのデータ型です。その「型」を好きなように作成できます。オブジェクトはすべて参照型になります。

Sheet1 などのシートや、セルを表す Range などもオブジェクトです。

変数や関数といったコード以外にも、コンストラクタやプロパティやイベントなど、クラスの機能があります。

クラス (オブジェクト) の特徴として、インスタンス化すると使用できるようになります。使い終わったら破棄する必要があります。

標準モジュールについては「標準モジュール」をご覧ください。

クラスを追加する

[挿入] から [クラスモジュール] をクリックします。

7

クラスが追加されます。

8

クラスの名前を変更するには、その [クラス] を選択した状態でプロパティウィンドウから [オブジェクト名] を変更します。

9

このクラス名が型名になります。

クラスを定義する

Sheet1 などのシートに対してコードを作成するのと同じように、クラスに変数や関数を定義できます。

' 変数
Public FirstName As String
Public LastName As String

' 関数
Public Function MyName() As String
    MyName = FirstName & LastName
End Function

それ以外にもクラスの機能がいくつもあるので、順に紹介していきます。

クラスを宣言する

Dim 変数名 As クラス名 のように、変数や引数の型としてクラス名を入力します。

Dim c As Class1

実際にクラスを使用するには、インスタンス化する必要があります。

Set 変数名 = New クラス名 のように入力して、その変数に新しいインスタンスを生成します。New がインスタンス化するキーワードです。オブジェクトを代入するには、頭に Set を付ける必要があります。

Dim c As Class1
Set c = New Class1 ' インスタンス化
インスタンス化の動作について詳しくは「値型と参照型の違い」をご覧ください。

クラスの変数.変数名クラスの変数.関数名 のように入力して、そのクラスの変数を参照したり関数呼び出せます。Range などを操作するのと同じです。

' 変数に代入する
c.FirstName = "Tips"
c.LastName = "found"

' 関数を呼び出す
Dim s As String
s = c.MyName
Debug.Print(s) ' Tipsfound
上記の「クラスを定義する」のコードを使用しています。

クラスの変数が不要になったときは、後始末として必ず Nothing を設定します。これでインスタンスが確実に破棄され、メモリが解放されます。

Dim c As Class1
Set c = New Class1

' 処理

Set c = Nothing ' インスタンスが破棄される

後始末

作成したクラスに対して後始末をそこまで気にする必要はありません。ローカル変数なら関数を抜けた時点で自動で Nothing を設定して後始末してくれます。

COM オブジェクトを使用しているときは、必ず後始末します。

CreateObject 関数」を使用してインスタンス化したときは、必ず Nothing を設定する必要があります。忘れるとメモリが解放されなくなるため、不具合が発生します。

オブジェクト変数または With ブロック変数が設定されていません。

インスタンス化する前のクラスの変数の初期値は Nothing です。

インスタンス化していない状態で使用すると「エラー 91 オブジェクト変数または With ブロック変数が設定されていません。」が発生します。

Dim c As Class1 ' Nothing 状態

c.FirstName = "Tips" ' エラー

このエラーは VBA の中でよく発生するので、そのときはインスタンス化されているか確認します。

プライベート オブジェクト モジュールを、パブリック オブジェクト モジュール内で …

クラスの Instancing プロパティに Private と PublicNotCreatable の設定があります。

1

Sheet1 などのシートに、Public な変数や関数の型に指定できるクラスは PublicNotCreatable に設定されている必要があります。

' Sheet1 のコード
Public 変数 As Class1 ' Public 変数のときは Class1 を PublicNotCreatable にする必要がある

Public Sub サブ(引数 As Class1) ' Public 関数のときは Class1 を PublicNotCreatable にする必要がある

End Sub

Private に設定していると「エラー プライベート オブジェクト モジュールを、パブリック オブジェクト モジュール内で、パブリック プロシージャの引数または戻り値、パブリック データ メンバー、またはパブリックのユーザー定義型のフィールドとして、使用することはできません。」が発生します。

PublicNotCreatable に設定されているクラスの Public 変数や関数についても同様です。

Private に設定されているクラスの中では関係ありません。標準モジュールでも関係ありません。

コンストラクタ

クラスをインスタンス化したときに実行されるコードを「コンストラクタ」と言います。逆にインスタンスが破棄されたときに実行されるコードを「デストラクタ」と言います。

VBA にはそれらに対応したイベントがあります。

コードの左上にある (General) から [Class] を選択します。

3

コードの右上から [Initialize] または [Terminate] を選択します。

上記の Class をクリックした時点で自動で Initialize が選択されます。
4
  • Initialize:コンストラクタ。クラスを New したときに発生します。
  • Terminate:デストラクタ。クラスに Nothing を設定したときに発生します。

Initialize イベントを処理して、インスタンス化した時に変数の初期化などができます。イベントなのでコンストラクタに引数を渡すことはできません。

Terminate イベントを処理して、クラスの中で使用しているオブジェクトなどを解放できます。

' Class1 のコード
Private Sub Class_Initialize() ' Initialize イベント
    FirstName = "苗字"
    LastName = "名前"
End Sub

Private Sub Class_Terminate() ' Terminate イベント
    ' 後始末
End Sub

' 他のコード
Sub 実行()
    Dim c As Class1
    Set c = New Class1 ' Class_Initialize イベントが発生する

    Debug.Print(c.MyName) ' 苗字名前

    Set c = Nothing    ' Class_Terminate イベントが発生する
End Sub

プロパティ

プロパティとは高機能な変数みたいなものです。

プロパティを使用すると、プロパティの値を取得または代入するときに専用の関数を経由します。そこで値が不正でないかチェックしたり、イベントを発生させたりできます。

Private m_プロパティ名 As 型名 のように入力します。プロパティは変数でないため値を保存できません。そのため、値を保存するための変数を宣言します。変数名は何でもいいですが、プロパティの変数だとわかるようにプロパティ名を付けます。

Property Get プロパティ名() As 型名 のように入力します。Get がプロパティを取得するときに実行される関数です。Function 関数と同じように戻り値が取得される値になります。

Property Let プロパティ名(ByVal value As 型名) のように入力します。Let がプロパティに代入するときに実行される関数です。引数 value に設定された値が渡されます。引数名は value 以外でも大丈夫です。

Private m_Name As String

Public Property Get Name() As String
    Name = m_Name
End Property

Public Property Let Name(ByVal value As String)
    m_Name = value
End Property

Property Set プロパティ名(ByVal value As 型名) のように入力します。プロパティの型がシートやクラスなどのオブジェクトのときは、Let の代わりに Set を入力します。

Private m_Name As Class1

Public Property Get Name() As Class1
    Set Name = m_Name
End Property

Public Property Set Name(ByVal value As Class1)
    Set m_Name = value
End Property
Dim c As Class1
Set c = New Class1

c.Name = "名前" ' Property Let Name が呼ばれる

Dim s As String
s = c.Name      ' Property Get Name が呼ばれる
Debug.Print(s) ' 名前

Property Get だけにもできます。Property Get だけにすると読み取り専用プロパティになります。

イベント

シートの Change イベントのように、クラスのプロパティが変更されたときにイベントを発生されられます。

詳しくは「イベント」をご覧ください。

クラスの呼び出し

シートや標準モジュールからクラスの変数やプロパティを参照したり、関数を呼び出すには Public で宣言します。

省略したときのプロパティと関数は Public になります。

その変数を参照するには クラスの変数.変数名 のように入力します。プロパティや関数などについても同様です。

クラス1 のコード

Public パブリック変数 As Integer

Private プライベート変数 As Integer

Public Sub パブリック関数()

End Sub

Sub パブリック関数() ' 省略すると Public になる

End Sub

Private Sub プライベート関数()

End Sub

Sheet1 のコード

Sub 実行()
    Dim c As Class1
    Set c = New Class1

    c.パブリック変数 = 1   ' クラスの変数.変数名で参照する
    c.プライベート変数 = 2 ' エラー、Private は参照できない

    Call c.パブリック関数   ' クラスの変数.関数名で呼び出し
    Call c.プライベート関数 ' エラー、Private は呼び出せない

    Set c = Nothing
End Sub

値型と参照型の違い

オブジェクトは参照型です。それ以外の Integer や String などは値型です。参照型を別の変数に代入したり、関数の引数に渡すときに値型と違いがあります。

詳しくは「値型と参照型の違い」をご覧ください。