MENU

【VBA】複数ボタンのクリックイベントをまとめて処理する

下図のようにボタンが10個ばらばらに配置されているユーザーフォームのクリックイベントを取得するにはどうしたらいいでしょうか?

VBAではボタンのクリックイベントはボタン名に"_Click"を付加したプロシージャで拾うことができます。たとえばボタン名が"CommandButton1"のときは次のようなプロシージャをユーザーフォームに記述します。

Private Sub CommandButton1_Click()
   MsgBox "CommandButton1が押されました"
End Sub

10個のコマンドボタンのイベントを取得するには10個のプロシージャを記述する必要があります。各プロシージャから共通の処理へ飛ばすにはコマンドボタンの番号などを引数にしたプロシージャを作ることになります。

Private Sub CommandButton1_Click()
   Call CommonSub(1)
End Sub

Private Sub CommandButton2_Click()
   Call CommonSub(2)
End Sub

Private Sub CommandButton3_Click()
   Call CommonSub(3)
End Sub

'~~~ CommandButton10 までのクリックイベントを記述 ~~~

Private Sub CommonSub(Index As Integer)
   MsgBox "CommandButton" & Index & "が押されました"
End Sub

同じような記述を何度も繰り返すのは冗長です。今回は全体を覆った画像コントロールでイベントを取得する方法を考えてみます。

1.概要

ユーザーフォームに10個のコマンドボタンとそれらを覆う透明なイメージコントロールを配置します。コマンドボタンのクリックイベントはイメージコントロールのマウスダウンイベントに代替させます。

2.ユーザーフォームを作る

まず最初に新規ブックでVBE画面を表示してユーザーフォームを追加し、コマンドボタンを10個配置します(位置は適当に)。
次にイメージコントロールをすべてのコマンドボタンを覆うように配置します。

イメージコントロールは「透明」で枠線を「なし」にします。

プロパティ 値
(オブジェクト名) Image1
BackStyle 0 - fmBackStyleTransparent
BorderStyle 0 - fmBorderStyleNone
Picture (なし)

またコマンドボタンを覆うために表示を最前面にする必要があるので、メニューから [書式]→ [順序]→[最前面へ移動] をクリックします。イメージ(Picture)を指定せず背景(BackStyle)を透明にすると裏に隠れているはずのコマンドボタンが透けて見えます。コマンドボタンをクリックしても前面にあるイメージコントロールがクリックされてコマンドボタンのクリックイベントは発生しません。

3.ユーザーフォームのコード

ユーザーフォームにイメージコントロールのマウスダウンイベントを記述します。

Private Sub Image1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
   With Image1
      X = X + .Left
      Y = Y + .Top
   End With
   Dim Index As Integer
   For Index = 1 To 10
      Dim btn As CommandButton
      Set btn = Controls("CommandButton" & Index)
      With btn
         If X >= .Left And X < .Left + .Width And Y >= .Top And Y < .Top + .Height Then
            .BackColor = &H80000005
            MsgBox "CommandButton" & Index & "が押されました"
         Else
            .BackColor = &H8000000F
         End If
      End With
   Next
End Sub

イメージコントロールにはコマンドボタンのようなクリックイベントはありません。拾うことのできるイベントはマウスダウンかマウスアップということになるのですが、今回はマウスダウンを使いました。

4.プログラムの実行

メニューから [実行]→[Sub/ユーザーフォームの実行] でプログラムが実行できます。

適当なコマンドボタンをクリックするとクリックしたコマンドボタンの背景色が白くなりそのコマンドボタンが押された旨のメッセージが表示されます。

5.最後に

ここで紹介した方法はマウスのみを対象にしています。キーボードでのクリック操作はまったく考慮していませんので悪しからず。コマンドボタンをキーボードでクリックできないようにするときはコマンドボタンのTabStopプロパティをFalseにしてください。
またMouseDownではなくMouseUpで判断するようにすると、マウスダウンで指定したボタンを外してマウスアップすることでキャンセル扱いにすることができます。
VBAは融通が利かないのでVB.Netでは平気で書いていた構文がコンパイルエラーとなってイライラすることが多くあります。配列にVariantしか使えないところなどはVB.Netのジェネリックに慣れた者からするとちょっと気持ちが悪いところです。VBAはもうこれ以上発展の余地はないのでしょうか?

最後まで御覧いただきありがとうございました。