【実務・中級編】クラスモジュールにおけるProperty Get/Let/Setの使い分けとカプセル化の真髄 – Excel VBA解析バイブル

スポンサーリンク

VBAを「スクリプト」から「エンジニアリング」へ昇華させる:カプセル化の真髄

多くのVBAエンジニアは、コードを書く際に「Public変数」の誘惑に負けてしまいます。`Public UserID As String` と宣言し、どこからでも値を書き換えられる状態にする。一見便利ですが、それは「時限爆弾をコードのあちこちに仕込んでいる」のと同じです。

なぜなら、値が変更された瞬間に何が起きるか、誰も追跡できないからです。

今日のテーマは、VBAにおける「Propertyプロシージャ」を用いたカプセル化です。これをマスターすれば、あなたの書くツールは「散らかったマクロ」から「堅牢な業務システム」へと劇的に進化します。

1. なぜ「Public変数」は悪なのか?

例えば、Excelから外部DBへデータを送るツールを作るとします。`UserID`が正しく設定されていないのに、誤った値のまま更新処理が走ったらどうなるでしょうか?

  • Public変数: どこで、いつ、誰が書き換えたか追跡不可能。バグの原因特定に数時間を要する。
  • Propertyプロシージャ: 書き込みの瞬間にバリデーション(妥当性チェック)を実行できる。不正な値は「門前払い」可能。

VBAにおいて、変数は「隠す」のがプロの流儀です。

2. Property Get/Let/Set の正しい使い分け

クラスモジュール内では、以下の3つの役割を厳格に使い分けます。

  • Property Get: 値を「取得」する。読み取り専用にすることも容易。
  • Property Let: プリミティブ型(String, Long, Double等)の値を「設定」する。
  • Property Set: オブジェクト型(Worksheet, Collection, Dictionary等)の参照を「設定」する。

実践的なクラス設計例:`CUserRecord`

以下は、データの整合性を担保しつつ、外部連携を意識した設計のサンプルです。

‘ クラス名: CUserRecord
Option Explicit

‘ プライベート変数(外部から直接アクセスさせない)
Private pUserID As String
Private pTargetSheet As Worksheet

‘ [Get] 値を返すのみ(読み取り専用にしたい場合はLetを書かなければ良い)
Public Property Get UserID() As String
UserID = pUserID
End Property

‘ [Let] 値の代入時にバリデーションを組み込む
Public Property Let UserID(ByVal Value As String)
If Len(Value) <> 8 Then
Err.Raise vbObjectError + 1001, , “UserIDは8桁である必要があります。”
End If
pUserID = Value
End Property

‘ [Set] オブジェクトの参照をセットする(Setキーワードが必要)
Public Property Set TargetSheet(ByVal Value As Worksheet)
If Value Is Nothing Then
Err.Raise vbObjectError + 1002, , “シートが指定されていません。”
End If
Set pTargetSheet = Value
End Property

3. 現場で「死なない」ための3つの鉄則

① 「不正な状態」を許容しない

`Property Let` の中で、値が入ってきた瞬間にチェックを行ってください。後から「なぜこの値が入ったんだ?」と悩む時間をゼロにできます。

② データベース連携には「遅延初期化」を検討する

もしそのクラスが巨大なデータを扱う場合、インスタンス生成時に全てをロードするのは非効率です。`Property Get` が呼ばれたタイミングで初めてDBに接続する「遅延初期化(Lazy Initialization)」を設計に取り入れてください。

③ 継承がないVBAでの「インターフェース」の活用

VBAには強力な継承機能はありませんが、`Implements`によるインターフェース実装は可能です。複数のクラスに共通のメソッドを強制させたい場合、この設計手法が保守性を飛躍的に高めます。

4. プロダクションコードとしての呼び出し方

実際に利用する際のメインプロシージャです。エラーハンドリングとセットで運用することで、堅牢なツールが完成します。

Sub Main()
Dim user As New CUserRecord

On Error GoTo ErrorHandler

‘ ここでバリデーションが働き、8桁以外ならエラーを飛ばす
user.UserID = “A1234567”

‘ オブジェクトの代入は必ずSet
Set user.TargetSheet = ThisWorkbook.Sheets(“Data”)

MsgBox “設定完了: ” & user.UserID
Exit Sub

ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub

最後に:なぜ「カプセル化」にこだわるのか

あなたが書いたコードを、半年後に別の担当者が触るかもしれません。その時、`Public変数`だらけのコードは「地雷原」ですが、`Property`で守られたクラスは「説明書付きの部品」です。

「変更に対して壊れにくいこと」こそが、VBAエンジニアにとっての最大の価値です。

変数を隠し、ロジックをクラスに閉じ込める。この一見面倒に見える一手間が、あなたの業務を自動化する最強の武器になります。さあ、今すぐコードの `Public` を書き換えることから始めましょう。

タイトルとURLをコピーしました