目次
はじめに
ユーザーフォームに同じようなチェックボックスを10個配置し、「どれか一つでもクリックされたら、対応するシートのセルに状態を書き込む」という処理を実装したい場合、CheckBox1_Click()
, CheckBox2_Click()
… と10個のイベントプロシージャを書くのは非効率で、メンテナンスも大変です。
VBAのクラスモジュールという機能を使えば、これらのイベント処理をたった一つの共通コードに集約できます。これにより、コードの重複をなくし、劇的に見通しを良くすることが可能です。
この記事では、少し上級者向けのテクニックになりますが、クラスモジュールを使って複数のチェックボックスのイベント処理を共通化する、スマートでパワフルな方法をステップ・バイ・ステップで解説します。
実装手順の全体像
実装は、以下の2つのステップで行います。
- クラスモジュールの作成: チェックボックスのイベントを「監視」するための設計図(クラス)を作成します。
- ユーザーフォームのコードを記述: フォームが初期化される際に、チェックボックスの数だけクラスの「実体(インスタンス)」を作成し、各チェックボックスと紐付けます。
ステップ1: クラスモジュールを作成する
まず、チェックボックスのイベントを検知するためのクラスを作成します。
- VBEで「挿入」→「クラスモジュール」を選択します。
- 表示されたクラスモジュールのプロパティウィンドウで、
(Name)
をCheckboxEventHandler
に変更します。 - 以下のコードを貼り付けます。
クラスモジュール: CheckboxEventHandler
のコード
' --- このクラスが監視するコントロールを宣言 ---
' WithEventsキーワードが、イベントを検知できるようにするおまじない
Public WithEvents TargetCheckBox As MSForms.CheckBox
' --- 紐付けられたセルを記憶するための変数を宣言 ---
Public LinkedCell As Range
' --- 監視対象のチェックボックスでクリックイベントが発生したときに実行される ---
Private Sub TargetCheckBox_Click()
' チェックボックスの状態(True/False)を、紐付けられたセルに書き込む
If Not LinkedCell Is Nothing Then
LinkedCell.Value = TargetCheckBox.Value
End If
End Sub
コードの解説
Public WithEvents TargetCheckBox As MSForms.CheckBox
:WithEvents
キーワードが、このクラスの核心です。これにより、TargetCheckBox
という変数に代入されたチェックボックスのイベント(_Click
など)を、このクラス内で検知できるようになります。Private Sub TargetCheckBox_Click()
:WithEvents
で宣言した変数名TargetCheckBox
を使って、イベントプロシージャを記述します。ここに書かれたコードが、このクラスに紐付けられた全てのチェックボックスで共通して実行される処理となります。
ステップ2: ユーザーフォームのコードを記述する
次に、ユーザーフォーム側で、先ほど作成したクラス CheckboxEventHandler
を利用するコードを記述します。
ユーザーフォームのコード
' --- 作成したクラスのインスタンスを格納するためのコレクション変数を宣言 ---
' この変数をモジュールレベルで宣言することで、フォームが閉じられるまでインスタンスを保持する
Private CheckBoxHandlers As Collection
' フォームが初期化されるときに実行されるイベント
Private Sub UserForm_Initialize()
Dim i As Long
Dim handler As CheckboxEventHandler
' コレクションを初期化
Set CheckBoxHandlers = New Collection
' --- 3つのチェックボックスに対して、イベントハンドラをセットアップ ---
For i = 1 To 3
' 1. 新しいイベントハンドラ(クラスのインスタンス)を作成
Set handler = New CheckboxEventHandler
' 2. 監視対象のチェックボックスをハンドラの変数にセット
Set handler.TargetCheckBox = Me.Controls("TaskCheckBox" & i)
' 3. 紐付けたいセルをハンドラの変数にセット
Set handler.LinkedCell = ThisWorkbook.Worksheets("Sheet1").Cells(i, "B")
' 4. 作成したハンドラをコレクションに追加して、インスタンスが消えないように保持
CheckBoxHandlers.Add handler
Next i
End Sub
実行前の準備
Sheet1
という名前のワークシートを用意しておきます。- ユーザーフォームを作成し、チェックボックスを3つ配置します。
- それぞれの
(Name)
プロパティをTaskCheckBox1
,TaskCheckBox2
,TaskCheckBox3
に変更します。
コードの解説
Private CheckBoxHandlers As Collection
: 作成したクラスのインスタンスを格納しておくための変数です。これをUserForm_Initialize
の中で宣言すると、プロシージャが終わった瞬間にインスタンスが破棄されてイベントが検知できなくなるため、必ずモジュールの先頭で宣言します。Set handler = New CheckboxEventHandler
: ステップ1で作成した設計図CheckboxEventHandler
から、新しい実体(インスタンス)を作成しています。Set handler.TargetCheckBox = ...
: 作成したインスタンスのTargetCheckBox
変数に、フォーム上の実際のチェックボックスコントロールを代入しています。これで、両者が紐付けられます。CheckBoxHandlers.Add handler
: 作成したインスタンスをコレクションに追加しています。これにより、インスタンスがメモリ上に保持され続け、イベントの監視が継続されます。
まとめ
今回は、クラスモジュールを利用して、複数のコントロールのイベント処理を共通化するという、高度で非常に強力なテクニックをご紹介しました。
- クラスモジュールでイベントを処理する共通のコードを記述する。
WithEvents
キーワードで、コントロールのイベントを補足できるようにする。- ユーザーフォーム側では、コントロールの数だけクラスのインスタンスを作成し、それぞれを紐付ける。
最初は少し難しく感じるかもしれませんが、この構造を一度マスターすれば、大量のコントロールを扱うような複雑なフォームでも、驚くほどシンプルで管理しやすいコードを書くことができるようになります。