ExcelマクロVBA技術解説
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)

ExcelマクロVBAの問題点と解決策、エクセルVBAの技術的解説
最終更新日:2019-11-01

VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)


VBAクラスを使う事で、ユーザー定義イベントを作成したり、動的にイベントを割り当てる事が出来ます。
ユーザー独自のイベントを作成したり、フォームに動的に追加したコントロールにイベントを設定することができます。


EventステートメントとRaiseEventステートメントを使う事で、ユーザー定義イベントつまりユーザー独自のイベントを作成できます。
変数宣言にWithEventsキーワードを指定することで、クラスで発生するイベントに応答することができます。

ここでは、ユーザーフォームを使って、極めて単純なイベントを実装しています。
このVBAサンプルは、これで何かができるというものではなく、
クラスのイベントを理解する為に極めて単純化したVBAコードになります。

Eventステートメント

ユーザー定義イベントを宣言します。
[Public] Event プロシージャー名[(引数リスト)]

引数リストは、プロシージャーの引数リストと同様ですが、
イベントに名前付き引数、省略可能な引数、またはParamArray引数を指定することはできません。

モジュールレベルで宣言します。
値を返すようにイベントを宣言することはできません。
イベントが宣言されたら、 RaiseEventステートメントを使用してイベントを発生させます。
イベントは、それが宣言されているモジュール内でしか生成できません。

RaiseEventステートメント

モジュールレベルで宣言したイベントを発生させます。
RaiseEvent イベント名[(引数リスト)]

イベント名は、モジュール内でEventステートメントで宣言されたイベントの名前です。
イベントが発生したモジュール内で、そのイベントが宣言されていない場合は、エラーが発生します。

WithEventsキーワード

WithEventsキーワードは、次の構文で使用します。
Dim ステートメント
Private ステートメント
Public ステートメント
モジュール レベルで使用します。

変数がイベントに対応するためのオブジェクト変数であることを指定するキーワードです。
オブジェクトのモジュールのみで使えます、つまり、標準モジュールでは使用できません。
WithEventsは任意の数の変数に宣言できます。
ただし、WithEventsでは配列は作成できません。
また、キーワードNewとWithEventsは一緒には使用できません。

Private WithEvents xlApp As New Excel.Application

Private WithEvents xlApp As Excel.Application
・・・
Set xlApp = New Excel.Application
このように、WithEventsとNewは分けて使わなければなりません。

標準モジュールと動作概要

ユーザーフォームにボタンが2つだけ存在し、クリックでメッセージボックスを表示します。
たったこれだけですが、
ボタン1とボタン2では全く違った実装となります。

マクロ VBA クラス class event

ボタン1
ユーザーフォームに最初から配置されているボタンです。
クリックすると、3秒後にセッメージボックスが表示されます。

マクロ VBA クラス class event

ボタン2
ユーザーフォームの初期化(Initialize)で動的に追加したボタンです。。
クリックすると、直ぐにセッメージボックスが表示されます。

マクロ VBA クラス class event


起動するプロシージャーは以下になります。



Sub EventTest()
  UserForm1.Show
End Sub

記述場所およびプロシージャー名等、特に何も制限はありません。
UserForm1を表示さえすれば、どのような方法でも構いません。

ユーザーフォーム(UserForm1)

ユーザーフォームのオブジェクト名:UserForm1

マクロ VBA クラス class event

ボタンを1つだけ配置、ボタンのオブジェクト名:btn1

Option Explicit

'ボタン1:イベントに応答するために定義する変数
Private WithEvents mTimer As clsEvent

'ボタン2:動的ボタン対応クラスのインスタンス変数
Private clsEvent As clsEvent

'ボタン1:最初から存在するbtn1のClickイベント
Private Sub btn1_Click()
  Set mTimer = New clsEvent
  Call mTimer.TimerMsg(3)
End Sub

'ボタン1:WithEventsを指定したmTimerのTimerEventイベント
Private Sub mTimer_TimerEvent(ByVal aTime As Long)
  MsgBox aTime & "秒経過しました。"
End Sub

'ボタン2:ユーザーフォームにボタンを追加
Private Sub UserForm_Initialize()
  Set clsEvent = New clsEvent
  Set clsEvent.Button = addButton(Me.btn1.Top + 50, _
                  Me.btn1.Left, _
                  Me.btn1.Height, _
                  Me.btn1.Width, _
                  "ボタン2")
End Sub

'ボタン2:ユーザーフォームにボタンを追加
Private Function addButton(ByVal aTop As Single, _
              ByVal aLeft As Single, _
              ByVal aHeight As Single, _
              ByVal aWidth As Single, _
              ByVal aName As String) As MSForms.CommandButton
  Set addButton = Me.Controls.Add("Forms.CommandButton.1", aName, True)
  With addButton
    .Top = aTop
    .Left = aLeft
    .Height = aHeight
    .Width = aWidth
    .Caption = aName
  End With
End Function

クラス(clsEvent)

クラスのオブジェクト名:clsEvent



Option Explicit

'ボタン1:イベントの宣言、RaiseEventでイベント発生
Public Event TimerEvent(ByVal aTime As Long)

'ボタン2:イベントに応答するために定義する変数
Private WithEvents myButton As MSForms.CommandButton

'ボタン1:指定時間後にTimerEventイベントを発生させる
Public Sub TimerMsg(ByVal aTime As Long)
  Application.Wait Now() + TimeSerial(0, 0, aTime)
  RaiseEvent TimerEvent(aTime)
End Sub

'ボタン2:クラスで扱うボタンの設定/取得
Public Property Get Button() As Control
  Set Button = myButton
End Property
Public Property Set Button(ByVal addBtn As Control)
  Set myButton = addBtn
End Property

'ボタン2:クラスで扱うボタンのClickイベント
Private Sub myButton_Click()
  MsgBox myButton.Caption & "がクリックされました。"
End Sub

クラスを使ったイベントの解説

2つのボタンは全く互いに関係はありません、基本的に独立したボタンです。
(ボタン2を配置する時だけボタン1を使っています。)
本来は、
・EventステートメントとRaiseEventステートメントでの、ユーザー定義イベント
・WithEventsキーワードでの、クラス発生イベントの応答
これらを別々に解説するところなのでしょうが、ここではこの2つを一緒にしたものになります。
クラスを使ったイベントとして、混乱しやすく覚えづらい部分なので、その違いを比較しやすいようにと言う目的があります。

VBAの中でのコメントとして、
ボタン1:
ボタン2:
その変数またはプロシージャーが使われているボタンを指しています。
変数およびプロシージャーは、それぞれのボタンで全く別々のものが使用されています。

ボタン1の動作順
ユーザーフォームに最初から配置されているボタンです。
ユーザーフォームが表示された後にボタン1クリック。

btn1_Clickプロシージャー
TimerMsgプロシージャー
RaiseEvent TimerEvent
ここでEventステートメントで定義されているTimerEventを発生させる
mTimer_TimerEventプロシージャー
WithEventsキーワード定義したmTimerのTimerEventが呼ばれる

マクロ VBA クラス class event

ここでの動作自体は、単にClickイベントでメッセージ表示している事と何も変わりません。
あくので、EventとRaiseEventの使い方のサンプルVBAとしての意味合いだけのものです。


ボタン2の動作順
フォームに動的に追加したコントロールにイベントを設定しています。。
ボタン2は、ユーザーフォームには最初は配置されていないボタンです。
ユーザーフォームが初めて表示(使用)されたとき、

UserForm_Initialize
Set clsEvent = New clsEvent 'クラスのインスタンス
Set clsEvent.Button = addButton(… 'クラスにボタンを登録
addButton

ここで動的にボタンを作成し、クラスにボタンを登録しています。
ユーザーフォームが表示された後にボタン2クリック。

myButton_Click
WithEvents myButton As MSForms.CommandButton
フォーム標準のボタンを割り当てています。
Clickはボタンに標準で存在するイベントです。
プロシージャー名は、
変数名_イベント名

マクロ VBA クラス class event

VBAクラスを使ったイベントの最後に

今回紹介した2つの処理
・EventステートメントとRaiseEventステートメントでの、ユーザー定義イベント
・WithEventsキーワードでの、クラス発生イベントの応答
いずれも頻繁に使うものではないと思います。

したがって、全部を覚えようとすることは無いと思います。
動作の仕組みを理解しておき、実際に使う時に調べながら記述できるようにしておくだけで良いでしょう。



同じテーマ「マクロVBA技術解説」の記事

VBAのクラスとは(Class,Property,Get,Let,Set)
クラスを使って他ブックのイベントを補足する
VBAクラスの作り方:列名の入力支援と列移動対応
VBAクラスの作り方:列名のプロパティを自動作成する
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
クラスとイベントとマルチプロセス並列処理
オートフィルタを退避回復するVBAクラス
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス
コレクション(Collection)の並べ替え(Sort)に対応するクラス
VBAクラスのAttributeについて(既定メンバーとFor Each)
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)


新着記事NEW ・・・新着記事一覧を見る

VBAにおける変数のメモリアドレスについて|VBA技術解説(11月8日)
空文字列の扱い方と処理速度について(""とvbNullString)|VBA技術解説(1月7日)
Errオブジェクトとユーザー定義エラー|VBA入門(11月5日)
シングルクォートの削除とコピー(PrefixCharacter)|VBA技術解説(11月4日)
ユーザー定義型の制限とクラスとの使い分け|VBA技術解説(11月3日)
クリップボードに2次元配列を作成してシートに貼り付ける|VBA技術解説(11月1日)
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)|VBA技術解説(10月31日)
VBAクラスのAttributeについて(既定メンバーとFor Each)|VBA技術解説(10月19日)
VBAの用語について:ステートメントとは|VBA技術解説(10月16日)
VBAのマルチステートメント(複数のステートメントを同じ行に)|VBA技術解説(10月14日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|ExcelマクロVBA入門
4.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
5.変数宣言のDimとデータ型|ExcelマクロVBA入門
6.繰り返し処理(For Next)|ExcelマクロVBA入門
7.マクロって何?VBAって何?|ExcelマクロVBA入門
8.ひらがな⇔カタカナの変換|エクセル基本操作
9.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説
10.セルに文字を入れるとは(Range,Value)|VBA入門



  • >
  • >
  • >
  • VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。




    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ