【入門編】オブジェクト変数の初期化忘れを防ぐ:クラスのInitializeイベント活用法 – Excel VBA解析バイブル

スポンサーリンク

こんにちは!マクロの記録から一歩抜け出して、「本格的なVBAの仕組みを作りたい!」と意気込んでいるあなたへ。

VBAを書いていると、避けて通れないのが「オブジェクト変数の初期化忘れ」によるエラー、例えばあの嫌われ者「実行時エラー ’91’: オブジェクト変数または With ブロック変数が設定されていません。」ですよね。

「あ、また `Set` するのを忘れてた……!」と、真っ赤なエラー画面に絶望した経験、ありませんか?

今回は、そんなうっかりミスを構造的に絶滅させる、プログラミングの知恵「クラスのInitialize(イニシャライズ)イベント」を使った極限の防御策を伝授します。ここをクリアすれば、あなたのVBAコードの信頼性はプロの領域へと一気に跳ね上がりますよ。

一緒に優しく、深く、本質を紐解いていきましょう!

1. なぜ「初期化忘れ」は恐ろしいのか?

まずは、私たちが普段やりがちな「危ういコード」の姿を見てみましょう。

標準モジュールで、何かしらのデータを管理する専用の「作業用シート」をオブジェクト変数に格納して操作するシーンを想像してください。

‘ 【危うい標準モジュールの例】
Public wsTarget As Worksheet

Sub DoSomething()
‘ うっかり Set wsTarget = ThisWorkbook.Sheets(“Data”) を書き忘れた!

‘ ここでエラー爆誕!
wsTarget.Range(“A1”).Value = “テスト”
End Sub

このコードを実行すると、`wsTarget` の中身が「空っぽ(Nothing)」のまま操作しようとするため、容赦なくエラー91が飛んきます。

規模が大きくなればなるほど、「どこで変数が初期化されたんだっけ?」と迷子になり、デバッグに膨大な時間を溶かすことになります。これが、変数の初期化を「人間の記憶力」に頼る最大の悪夢です。

2. 救世主「クラスモジュール」と「Initializeイベント」

「じゃあ、人間が覚えておく必要があるなら、VBA側に勝手にやらせればいいじゃない!」

そう気づいた天才たちが辿り着くのが、クラスモジュールです。
クラスの中には、「そのオブジェクトが生まれた瞬間(メモリにロードされた瞬間)に、自動的に1回だけ発動する魔法の儀式」が用意されています。それが `Class_Initialize` イベントです。

図解するなら、このようなイメージです。

[ 新しいクラスのインスタンス化 (New) ]

⚡ 瞬時に発動!【 Class_Initialize 】 ⚡

・内部変数の自動セット
・必要な初期設定の完了

[ 安全に使えるオブジェクトの完成 🎉 ]

人間が `Set obj = New MyClass` と書いた瞬間、VBAが勝手に裏側で `Class_Initialize` を呼び出し、初期設定を完結させてくれます。つまり、「初期化し忘れること自体が不可能になる」という強固な安全地帯が作れるのです。

3. 実践!初期化漏れを防ぐ堅牢なクラスの実装

百聞は一見に如かず。実際に、シートの取得と初期設定を自動化するクラスを作ってみましょう。

手順①:クラスモジュールの作成

VBE(Visual Basic Editor)のメニューから「挿入」>「クラス モジュール」を選択し、プロパティウィンドウで名前を `clsDataHolder` に変更してください。

そこに、以下のコードを貼り付けます。

‘ ==========================================
‘ クラス名: clsDataHolder
‘ 概要: 処理対象のシートを安全に保持するクラス
‘ ==========================================
Option Explicit

‘ 保持するワークシート(カプセル化のためPrivate推奨)
Private m_wsTarget As Worksheet

‘ 【これぞ極意!】オブジェクト生成時に自動実行されるイベント
Private Sub Class_Initialize()
On Error GoTo ErrorHandler

‘ 生成された瞬間に、自動的に特定のシートを紐付ける!
‘ ※もしシートが存在しない場合は、ここで確実にエラーを検知できる
Set m_wsTarget = ThisWorkbook.Sheets(“集計データ”)

Exit Sub
ErrorHandler:
MsgBox “初期化エラー: 必要なシート「集計データ」が見つかりません。”, vbCritical
End Sub

‘ 外部から安全にシートを参照するためのプロパティ(Getのみ提供)
Public Property Get TargetSheet() As Worksheet
Set TargetSheet = m_wsTarget
End Property

手順②:標準モジュールからの呼び出し

次に、標準モジュールからこのクラスを使ってみましょう。

‘ ==========================================
‘ 標準モジュール
‘ ==========================================
Option Explicit

Sub Main_Process()
‘ クラスを実体化(Newした瞬間、自動的にClass_Initializeが走る!)
Dim dataHolder As clsDataHolder
Set dataHolder = New clsDataHolder

‘ この時点で、m_wsTargetには必ずシートがセットされている(あるいはエラーで止まっている)
‘ だから、安心してメソッドやプロパティを叩ける!

Dim ws As Worksheet
Set ws = dataHolder.TargetSheet

ws.Range(“A1”).Value = “初期化成功の証です!”
MsgBox “処理が安全に完了しました。”, vbInformation

‘ ※おまけ:もし「集計データ」シートがなければ、
‘ Newした瞬間にメッセージボックスが出て止まるため、後続の訳のわからないエラーを防げます。
End Sub

4. この設計パターンがもたらす圧倒的なメリット

この書き方を身につけると、あなたのVBAライフは劇的に変わります。

1. 「うっかり忘れ」が構造的に発生しない
`New` キーワードを使うだけで、必要なセットアップが裏で自動完了するため、プログラマーが「セットしたっけ?」と悩む時間がゼロになります。
2. エラーの発生源が明確になる
もし初期設定(シートの存在確認や、外部APIの接続準備など)に失敗した場合、エラーが起きるのは「メインの複雑な処理中」ではなく、「クラスが生まれた瞬間(`Initialize`)」になります。これにより、バグの特定が秒速で終わるようになります。
3. コードの意図が美しく伝わる
「このクラスを使うなら、最初にこういう状態になっているべきだ」という設計思想がコードの構造自体に組み込まれるため、将来メンテする他の人(あるいは未来の自分)にとっても非常に優しいコードになります。

まとめ:一歩上のエンジニアへ

今回は、クラスの `Initialize` イベントを活用して、オブジェクト変数の初期化忘れを防ぐ極意をお伝えしました。

「マクロの記録」から一歩踏み出し、こうしたオブジェクト指向的なアプローチ(カプセル化やライフサイクルの管理)を取り入れることで、VBAは単なる「自動化スクリプト」から「堅牢な業務システム」へと進化します。

ここをクリアすれば、エラー91に怯える日々とはおさらばです。ぜひ、次のあなたのマクロ開発で試してみてくださいね。
あなたのVBAスキル向上を、心から応援しています!

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