【簡単解説】VBA クラスモジュール 1記述と宣言 2021.06.29
クラスとは「新たな階層グループ」のような概念であり、そこに属するメンバーに共通の特性や属性を持たせるといったイメージです。学校で例えるなら、学年とは違う階層である部活や委員会のような感じです。
「VBAの基礎はある程度習得したけど、クラスモジュールは敷居が高く感じる」といった方も多いのではないでしょうか。
ここでは、クラスモジュールの使い方やポイントを備忘録として残します。
内容
●クラスモジュールのメリット
●記述と宣言
・Sub・Function
・変数
・オブジェクト
サンプルファイル
記事に載せてあるコードサンプルのファイル ダウンロード
クラスモジュール
メリット
クラスモジュールのメリットには、次のものが挙げられる。
・SubやFunctionの所属(モジュール)をわかりやすく表記できる
・任意のオブジェクトをグループとして扱える
・オブジェクトに新たなプロパティを追加するようなイメージで扱える
私がよく用いるのは、ユーザーフォームの多数のコントロールを共通のクラスに所属させ、共通のイベントを設定する方法である。
例えば、20のLabelコントロール(Label1~20)を共通のクラスに所属させ、Clickイベントを共有すると、コントロール毎にClickイベントを書かなくてよい。
少し慣れが必要であるが、使えるとメリット大きい。
他のモジュールとの違い
クラスモジュールに記述した変数・サブルーチン・関数等は、そのままでは使用できない。
使用する場合は、クラスのインスタンスを生成し、
・インスタンス.変数
・インスタンス.関数
といった使い方をする。
インスタンスとは設計図をもとにつくられたものである。ここでいう設計図はクラスにあたる。
インスタンス=クラスの複製という認識でよい。
クラスを使用する際は、そのクラスのインスタンスを生成する過程を必ずたどる。
クラスモジュールの挿入
オブジェクトモジュール名の右クリックメニュー → 「挿入」 → 「クラスモジュール」
あるいはメニューバーの「挿入」→「クラスモジュール」
Excelマクロ管理ツール
記述と宣言
SubとFunction
サブルーチン(Sub)や関数(Function)のクラスモジュールでの記述は、標準モジュールと同じでよい。
標準モジュールでそれらを使用する場合は「クラスインスタンス.関数」といった記述になる。
Sub Msg(name As String) MsgBox name & "さん こんにちは。" End Sub
Function Total(n1 As Double, n2 As Double, n3 As Double) As Double Total = n1 + n2 + n3 End Function
Sub Sample1() Dim clsSample1 As Class1 'Class1型のオブジェクト変数を宣言 「Class1」はクラスモジュール名 Set clsSample1 = New Class1 'インスタンスを生成 オブジェクトへの参照を設定 Call clsSample1.Msg("sakae1") MsgBox "合計:" & clsSample1.Total(51, 62.3, 4.7) End Sub
クラスモジュールと標準モジュールの記述に問題なければ、インテリセンスが表示される。
【補足情報】
標準モジュールの宣言は、前述の形で記述されていることが多いが、次の形でも問題ない。
Sub Sample2() Dim clsSample1 As New Class1 'インスタンスを生成 Call clsSample1.Msg("sakae2") MsgBox "合計:" & clsSample1.Total(50, 72.6, 13.4) End Sub
オブジェクト型変数を宣言するときに「New」キーワードを指定すると、オブジェクトのインスタンスが生成される。
その場合は、Setステートメントで改めてオブジェクトへの参照を代入する必要はない。
変数
クラスモジュールのPublic型変数は、どのモジュール・プロシージャでも使用できるが、変数単体では使用できない。「クラスインスタンス.変数」といった形で使用する。
クラスインスタンスの適用範囲を、標準モジュール全体とする場合は、標準モジュールの宣言セクションに記述する。
'宣言セクション Public strAddress As String
'宣言セクション Dim clsAds As New Class2
Sub Sample3() clsAds.strAddress = ActiveCell.Address(False, False) End Sub
Sub Sample4() MsgBox clsAds.strAddress End Sub
上記のSample3を実行するとアクティブセルのアドレスが、Class2クラスのインスタンスであるclsAdsのもつ変数、strAddressに代入され保持される。
Sample4を実行すると保持されているアドレスを確認できる。
クラスモジュールのPrivate型変数は、クラス内でしか使用できない。
そのため次のように、プロパティの取得や設定用として使用することが多い。
'宣言セクション Private strAddress As String
Property Get ActAds() As String '取得用プロパティ ActAds = strAddress End Property
Property Let ActAds(newAddress As String) '設定用プロパティ strAddress = newAddress End Property
'宣言セクション Dim clsAds2 As New Class3
Sub Sample5() clsAds2.ActAds = ActiveCell.Address(False, False) 'プロパティを設定 End Sub
Sub Sample6() MsgBox clsAds2.ActAds 'プロパティを取得 End Sub
上記のSample5を実行すると、アクティブセルのアドレスが、Class3クラスのインスタンスであるclsAds2のもつ、ActAdsプロパティに設定される。
Sample6を実行すると、ActAdsプロパティの値が取得され表示される。
【補足情報】Property(プロパティ)
上記のクラスモジュール記述を例に挙げる。
'宣言セクション Private strAddress As String
Property Get ActAds() As String '取得用プロパティ ActAds = strAddress End Property
Property Let ActAds(newAddress As String) '設定用プロパティ strAddress = newAddress End Property
上記コードを見てわかる通り、Property(プロパティ)の使い方はSubやFunctionと異なる。
Get(取得)とLet(設定)では、共通のプロシージャ名(プロパティ名)を用いる。
プロパティ取得の際は、変数(今回の例ではstrAddress)に保持してある値を渡す形になる。
プロパティ設定の際は、受け取った変数(今回の例ではnewAddress)をクラス内の変数(strAddress)に渡す形になる。
そのような仕組みから、使用する変数とプロパティの型は共通でなければならない。
オブジェクト
次はオブジェクトの場合である。
次のコードは、クラスモジュールでオブジェクトと、オブジェクトのアドレス格納用プロパティを記述し、標準モジュールでそれらを利用しているサンプルである。
アクティブシートの2つのShapeオブジェクトを対象としている。
'宣言セクション Private mySP As Shape Private strAddress As String
'///オブジェクト Public Property Get Shp() As Shape 'オブジェクト取得用プロパティ Set Shp = mySP End Property
Public Property Let Shp(newSP As Shape) 'オブジェクト設定用プロパティ Set mySP = newSP End Property
'/// Property Get SpAds() As String '取得用プロパティ SpAds = strAddress End Property
Property Let SpAds(newAds As String) '設定用プロパティ strAddress = newAds End Property
'宣言セクション Dim objSP(1 To 2) As New Class4
Sub Sample7() objSP(1).Shp = ActiveSheet.Shapes("スマイル 1") objSP(2).Shp = ActiveSheet.Shapes("スマイル 2") objSP(1).SpAds = objSP(1).Shp.TopLeftCell.Address(False, False) objSP(2).SpAds = objSP(2).Shp.TopLeftCell.Address(False, False) End Sub
Sub Sample8() If objSP(1).Shp Is Nothing Then Exit Sub MsgBox objSP(1).SpAds If objSP(2).Shp Is Nothing Then Exit Sub MsgBox objSP(2).SpAds End Sub
Sample7を実行すると、ShapeとそのShapeの位置するセルアドレスが、インスタンスのもつプロパティに設定される。
Sample8を実行すると、インスタンスのプロパティから、アドレスが取得され表示される。
インスタンスのプロパティにオブジェクトを設定する場合、一般的には次のようにSetステートメントを使用することが多い。
Set objSP(1).Shp = ActiveSheet.Shapes("スマイル 1")
しかしサンプルコードを見てわかる通り、「Set」を使用しなくとも構わない。
サンプルコードでは、標準モジュールに「Set」が記述されていないが、クラスモジュールで「Set」するため、問題なく実行できる。
クラスモジュールの記述を見れば、引数の参照渡しのようなイメージであることがわかる。