ExcelVBAでクラスモジュールを使い始めると、必ずぶつかるのが「プロパティをどうやって自作するのか」という疑問です。変数をPublicで宣言するだけでも値の出し入れはできますが、それでは「不正な値が入ってきてもチェックできない」「読み取り専用にできない」といった問題が残ります。
この記事では、Property Get・Property Let・Property Setという3つのプロシージャを使って、クラスモジュールに独自のプロパティを作る方法を解説します。入力値のチェックや読み取り専用プロパティの作り方まで、実際に動くコード例を交えて紹介します。
Property Get/Let/Setとは何か
クラスモジュールでは、外部から直接変数を触らせるのではなく、Propertyプロシージャを経由してデータをやり取りするのが基本です。役割は次の3つに分かれています。
- Property Get:プロパティの値を「取得」するときに呼ばれる
- Property Let:プロパティに「値(データ型)」を「設定」するときに呼ばれる
- Property Set:プロパティに「オブジェクト」を「設定」するときに呼ばれる
このように分けることで、値を読み取るときと書き込むときで別々の処理(チェックやログなど)を挟めるようになります。
基本のProperty Get/Letを作る
クラスモジュール「Employee」を例に、名前と給与を管理するプロパティを作ってみます。クラスモジュールの挿入方法は、VBEの「挿入」→「クラスモジュール」から行い、プロパティウィンドウで名前を「Employee」に変更してください。
' クラスモジュール「Employee」
Option Explicit
Private mName As String
Private mSalary As Long
Public Property Get Name() As String
Name = mName
End Property
Public Property Let Name(ByVal NewValue As String)
mName = NewValue
End Property
Public Property Get Salary() As Long
Salary = mSalary
End Property
Public Property Let Salary(ByVal NewValue As Long)
If NewValue < 0 Then
MsgBox "給与にマイナスの値は設定できません。"
Exit Property
End If
mSalary = NewValue
End Property
ポイントは、実体となる変数(mName・mSalary)をPrivateで宣言し、外部からはPropertyプロシージャを通してのみアクセスできるようにしている点です。SalaryのProperty Letでは、マイナスの値が渡されたときに処理を中断するチェックを入れています。こうすることで、不正な値がそのまま代入されるのを防げます。
標準モジュールから呼び出すコードは次の通りです。
Sub TestEmployee()
Dim emp As Employee
Set emp = New Employee
emp.Name = "山田太郎"
emp.Salary = 300000
MsgBox emp.Name & "さんの給与は" & emp.Salary & "円です。"
emp.Salary = -1000 ' チェックに引っかかりMsgBoxが表示される
End Sub
読み取り専用プロパティを作る
Property Letを用意しなければ、そのプロパティは「読み取り専用」になります。たとえば、社員IDのように一度決まったら変更されたくない値は、Property Getだけを定義します。
Private mEmployeeId As String
Public Property Get EmployeeId() As String
EmployeeId = mEmployeeId
End Property
Public Sub Initialize(ByVal NewId As String)
mEmployeeId = NewId
End Sub
この場合、emp.EmployeeId = "E001"のように外部から直接代入しようとするとコンパイルエラーになります。値をセットするにはInitializeのような別のメソッドを用意し、生成時に一度だけ設定する形にすると安全です。
Property Setでオブジェクトを扱う
Property Letは文字列や数値などの「値」を受け取るのに対し、Property SetはRangeやWorksheetといった「オブジェクト」を受け取るときに使います。
Private mTargetRange As Range
Public Property Get TargetRange() As Range
Set TargetRange = mTargetRange
End Property
Public Property Set TargetRange(ByVal NewRange As Range)
Set mTargetRange = NewRange
End Property
呼び出す側では、オブジェクトを代入するためSetキーワードが必要になります。
Sub TestTargetRange()
Dim emp As Employee
Set emp = New Employee
Set emp.TargetRange = Worksheets("Sheet1").Range("A1:A10")
MsgBox emp.TargetRange.Address
End Sub
Property Get側でもTargetRange = mTargetRangeではなくSet TargetRange = mTargetRangeと書く点に注意してください。オブジェクトを返すプロパティは、Get側もSetが必要です。
まとめ
Property Get/Let/Setを使うことで、クラスモジュールに「安全な入り口」を作ることができます。
- Property Get:値・オブジェクトを取得する
- Property Let:値(数値・文字列など)を設定する
- Property Set:オブジェクト(Range・Worksheetなど)を設定する
- Property Letを省略すれば読み取り専用プロパティになる
単にPublic変数を並べるよりも一手間かかりますが、入力値のチェックを挟められる、読み取り専用にできるといったメリットは大きいです。自作クラスを設計する際は、まずどのプロパティが「読み書き両方必要か」「読み取り専用でよいか」を整理してから、Property プロシージャを組み立てていくとスムーズです。


コメント