こちらの記事を読んだところ、同じようなChangeイベントプロシージャがコントロールの数だけできてしまうことにお悩みの様子。
kantoku.hatenablog.com
面白そうなので色々調べながらやってみた。
参考にしたページはこちら
3.4.3 共通イベント処理クラス - EXCEL-VBA開発講座
まずEventControlというクラスモジュールを用意した。
コードはこちら
Public WithEvents chk As MSForms.CheckBox Public WithEvents txt As MSForms.TextBox Public Sub セット(ByRef Con As MSForms.Control) Select Case TypeName(Con) Case "CheckBox" Set chk = Con Case "TextBox" Set txt = Con Case Else Err.Raise 1000, "EventControl", "想定外のコントロールです。" End Select End Sub Private Sub chk_Change() Call 共通イベント(chk) End Sub Private Sub txt_Change() Call 共通イベント(txt) End Sub Private Sub 共通イベント(C As MSForms.Control) MsgBox C.Name & "が変更されました。" End Sub
クラスモジュール内でオブジェクト変数の宣言にWithEventsを付けるとイベントを捕捉できるようになる。
MSForms.Control型というのもあったがこちらではイベント捕捉ができないようなので、諦めてtxtとchkの二種類を用意する。このあたり、ちょっとダサい。。
そうすると、chk_Changeとtxt_Changeのイベントで共通イベントが呼び出される。
メインのサンプルフォームはこんな感じで適当に用意した。
そしてフォームのコードはこちら
Dim コントロールコレクション As Collection Private Sub UserForm_Initialize() Set コントロールコレクション = New Collection Dim Con As Control Dim EC As EventControl For Each Con In Me.Controls Select Case TypeName(Con) Case "CheckBox", "TextBox" Set EC = New EventControl EC.セット Con コントロールコレクション.Add EC End Select Next End Sub
コレクションをモジュールレベル変数としている。
フォームのInitialize時に先ほど作ったEventControl型にコントロールをセットしていく。(ただしテキストボックスとチェックボックスのみ)
これを実行すると、どのチェックボックス・テキストボックスを変更してもEventControlクラスの共通イベントが実行される。
やや複雑になってはしまうけれど、クラスを汎用的に設計しておけば再利用できて便利だと思う。