🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Property — Get・Let・Set(クラスのフィールドへのアクセスを制御する)

|

Excel VBA の Property — Get・Let・Set(クラスのフィールドへのアクセスを制御する)

TL;DRProperty は、クラスのフィールドを ゲートに変えます。呼び出し側から見れば emp.Salary = 65000 は素の変数のように 見えますが、その代入の裏であなたのコードが走ります — だから検証したり、計算したり、 書き込みを拒否したりできます。Property Get読み取りのゲート、Property Letを受け取り、Property Setオブジェクトを受け取ります。LetSet の 取り違えがナンバーワンのエラーで、Let をわざと省くのがフィールドを読み取り専用に する方法です。

' --- クラスモジュール(clsEmployee)の内側 ---
Private mSalary As Currency          ' バッキングフィールド、外部からは隠されている

Public Property Get Salary() As Currency   ' 読み取りのゲート
    Salary = mSalary
End Property

Public Property Let Salary(ByVal value As Currency)   ' 値を書き込むゲート
    If value < 0 Then Err.Raise 5, , "Salary cannot be negative"
    mSalary = value                  ' 格納する前に検証する
End Property

' --- 使い方は素のフィールドとまったく同じに読める ---
' emp.Salary = 65000   -> Property Let を実行(検証して格納)
' Debug.Print emp.Salary -> Property Get を実行(mSalary を返す)
' emp.Salary = -100    -> "Salary cannot be negative" を発生させる

クラスモジュールは、データを素の Public 変数として 公開できます — そして、それが正しい判断であることもあります。しかし、クラスが公開 フィールドの詰め合わせよりも堅牢に感じられる理由は Property プロシージャです。各 フィールドに対して外の世界に何を許すかを、あなたが決めるためのフックだからです。

この記事で学べること

  • 考え方の軸 — 生の変数ではなく、フィールドの前のゲート
  • なぜ Property が素の Public 変数に勝るのか
  • Get・Let・Set — そして誰もがつまずく唯一の区別
  • すべてを機能させるバッキングフィールドのパターン
  • 読み取り専用プロパティの作り方(そして、それがなぜ長所なのか)
  • 素の Public 変数こそが正直な選択になる場面

考え方の軸:Property はフィールドの前に立つ「ゲート」

Propertyフィールドの前に立つゲートです。あなたのオブジェクトを使う人に とっては、通常の変数とまったく同じに見えます — emp.Salary = 65000 と書き、 x = emp.Salary と読みます — しかし、そのひとつひとつの接触が、あなたの書いた小さな プロシージャを走らせます。読み取りは Property Get を、書き込みは Property Let (値の場合)または Property Set(オブジェクトの場合)を走らせます。

その間接性こそがすべての要点です。あなたのコードがゲートの中に座っているので、格納 する前に値をチェックしたり、まったく格納しない値を計算したり、あるいは単に書き込みの ゲートを用意せずフィールドを読み取り専用にしたりできます。呼び出し側は知る必要が ありません — どちらにせよ構文は同じだからです。

なぜ Property が素の Public 変数に勝るのか

Public フィールドは、あなたのオブジェクトへまっすぐ通じた穴です。誰でも、いつでも、 何のチェックもなく、何でも書き込めます。emp.Age = -5 は成功します。emp.Id = 999 は、 恒久的であるはずだったアイデンティティを上書きします。ルールを置く場所がありません。 呼び出し側とフィールドの間にコードがないからです。

Property は、その場所を与えてくれます。それが防ぐ失敗は、無言の不正な書き込みです — 負の年齢、あとで計算を吹き飛ばす文字列にセットされた給与、こっそり再割り当てされた 「一意の」ID。Property Let があれば、不正な書き込みは、3 つ先の手続きで謎の間違った 結果として表面化する代わりに、起きたその場で、明快なメッセージとともに捕まえ られます。

Get・Let・Set:誰もがつまずく唯一の区別

プロパティのプロシージャは 3 つあり、そのうち書き込みの 2 つの間の分かれ目が、VBA の 古典的なつまずきの石です。

プロシージャ 方向 受け取る/返す 用途
Property Get 読み取り 値またはオブジェクトを返す どのプロパティの読み取りにも
Property Let 書き込み を受け取る(Long、String、Date、Currency…) 値プロパティの書き込み
Property Set 書き込み オブジェクトを受け取る(Range、クラスのインスタンス…) オブジェクトプロパティの書き込み

ルールは、VBA における通常の代入を支配するのと同じものです。 値は Let、オブジェクトは Set あるプロパティが Range を保持するのに、それに 対して Property Let を書いてしまうと、emp.HomeCell = Range("A1") の代入は失敗 します。オブジェクトの代入には Set が必要なのに — VBA は見つからない Property Set を 探すからです。プロシージャを、フィールドが保持するものの種類に合わせましょう。

Private mRange As Range

Public Property Get HomeCell() As Range
    Set HomeCell = mRange          ' 注意:オブジェクトを返すので Set
End Property

Public Property Set HomeCell(ByVal r As Range)   ' Let ではなく Set — オブジェクトだから
    Set mRange = r
End Property
' 使い方: Set emp.HomeCell = Range("A1")

Property Get の内側でさえ、オブジェクトを返すときは Set HomeCell = ... を使うことに 注目してください。LetSet の区別は、どこであってもデータの種類に従います。

バッキングフィールドのパターン

プロパティはほとんどの場合、隠されたフィールドを包む対で現れます。フィールドは Private で(m の接頭辞は「member(メンバー)」の慣習です)、外の世界はゲートを通して のみそこに届きます。

Private mName As String                    ' 隠されたバッキングフィールド

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

Public Property Let Name(ByVal value As String)
    mName = Trim$(value)                    ' 入ってくる途中で正規化する
End Property

これが、カプセル化を現実のものにする形です。データは 1 つの Private 変数の中に住み、 あらゆる読み書きは、あなたが制御するコードを通ります。名前の格納方法をあとで変えても — トリミングする、大文字にする、リストと照合して検証する — 変えるのは 1 つの Property Let であって、すべての呼び出し側ではありません。

読み取り専用プロパティの作り方(そして、それがなぜ長所なのか)

Property Let を省くと、フィールドは外部からは読み取り専用になります。クラスは 内部でバッキングフィールドを設定できますが、呼び出し側は読み取ることしかできません。

Private mId As Long

Public Property Get Id() As Long     ' Get のみ — Let なし
    Id = mId
End Property

Friend Sub AssignId(ByVal newId As Long)   ' クラスが内部で設定する
    mId = newId
End Sub
' emp.Id            -> 動作する(読み取り)
' emp.Id = 42       -> コンパイルエラー:読み取り専用プロパティには代入できません

そのコンパイルエラーは障害ではありません — 保証です。読み取り専用プロパティは、 「この値は一度だけ設定され、二度と編集されない」を表現する方法であり、コンパイラーが あなたのためにそれを強制します。同じ手法は、バッキングフィールドをまったく持たない 計算プロパティも与えてくれます。

Public Property Get FullName() As String
    FullName = mFirst & " " & mLast        ' 導出される、何も格納しない
End Property

素の Public 変数こそが正直な選択になる場面

ここに、良い VBA を、意味も分からず真似た定型コードと分けるものがあります。すべての フィールドに Property が要るわけではありません。 あるフィールドが検証を必要とせず、 計算される必要もなく、自由に読み書きしてかまわないなら、Public 変数はまさにそれを 言い表します — そして、mX を行ったり来たりコピーするだけの素通しの GetLet の 対で包むのは、安全性ではなく雑音を足すだけです。

ですから、Property に手を伸ばすのは、理由があるときです — 検証、読み取り専用の ID、計算される値、Set が必要なオブジェクトフィールド。素の、制約のない値には、 Public 変数が正直で読みやすい選択です。ゲートが必要なときにゲートを足しましょう。 開いたフィールドの周りにゲートを建ててはいけません。

ExcelMaster の活用

プロパティのルールは小さいけれど容赦がありません。値には Let、オブジェクトには Set、読み取り専用には Let を省く、各対の裏には Private のバッキングフィールド。 LetSet の組み合わせを間違えればコンパイルできませんし、カプセル化を間違えれば、 「保護された」はずのフィールドは丸開きです。

ExcelMaster は、 その形全体をあなたのために書きます。オブジェクトを説明すれば — 「給与を負にできず、 読み取り専用の ID と計算されるフルネームを持つ Employee」— Private のバッキング フィールド、検証する Property Let、必要なところにはオブジェクト対応の Property Set、 そして Get のみの読み取り専用プロパティを、すべて正しく対にして生成します。どの キーワードがどの種類のフィールドと組むのかを暗記しなくても、きちんとしたカプセル化が 手に入ります。

よくある質問

VBA の Property とは何ですか?

Property は、フィールドへのアクセスを制御するクラスモジュール内の プロシージャです。Property Get はフィールドが読み取られるときに実行され、 Property Let(値の場合)または Property Set(オブジェクトの場合)は書き込まれる ときに実行されます。呼び出し側には通常の変数のように見えますが — emp.Salary = 65000 — 代入の裏であなたのコードが走るので、検証したり、計算したり、フィールドを読み取り専用に したりできます。

Property Let と Property Set の違いは何ですか?

Property Letを受け取ります — Long、String、Date、Currency など。 Property Setオブジェクトを受け取ります — Range、クラスのインスタンス、あるいは 任意の参照型。これは通常の代入と同じルールです。値は =Let 経由)を、オブジェクトは SetSet 経由)を使います。オブジェクトプロパティに Let を、値に Set を使うと、 コンパイルエラーか実行時エラーになります。

VBA で読み取り専用プロパティを作るには?

Property Get を書き、Property Let(または Set)は書きません。そうすると呼び出し側は 値を読めますが、代入はできません — 書き込もうとすると、コンパイルエラー「読み取り専用 プロパティには代入できません」になります。クラス自体は、なお内部でバッキングフィールドを 変更できます。これは、一度だけ設定される ID 値や、他のフィールドから導出されるフルネームの ような計算プロパティに最適です。

Public 変数ではなく Property を使うのはなぜですか?

Public 変数は、いつでも、何のチェックもなく、どんな値でも書き込めます。Property は、 入力を検証し、値を計算し、フィールドを読み取り専用にし、あるいは呼び出し側に触れずに あとでデータの格納方法を変える場所を与えてくれます。そうした理由があるときは Property を使いましょう。素の制約のない値には、Public 変数の方が単純で、まったくもって 正直です。

VBA で Property Get は何をしますか?

Property Get はプロパティの読み取り側です。コードがそのプロパティを読むたびに 実行され、値を返します(オブジェクトプロパティの場合は Set で返します)。ふつうは 書き込み用の Property Let または Set と対にされ、Private のバッキングフィールドを 包みます — しかし Property Get を単独で置けば、読み取り専用または計算プロパティに なります。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-04.

関連ガイド: VBA Class Module · VBA Type · VBA Dim · VBA Function · VBA ByRef vs ByVal