サーチ…
構文
ソースモジュール :
[Public] Event [identifier]([argument_list])
ハンドラモジュール :
Dim|Private|Public WithEvents [identifier] As [type]
備考
イベントは
Public
のみ可能です。クラスモジュールのメンバー(イベントを含む)は、デフォルトでは暗黙的にPublic
ので、修飾子はオプションです。WithEvents
変数は、Private
でもPublic
でもWithEvents
ませんが、Friend
はありません。WithEvents
は変数を宣言するキーワードではなく、変数宣言構文の修飾語キーワードの部分であるため、修飾子は必須です。したがって、アクセス修飾子が存在しない場合は、Dim
キーワードを使用する必要があります。
ソースとハンドラ
イベントとは何ですか?
VBAはイベントドリブンです。ホストアプリケーションまたはホスト文書によって生成されたイベントに応答してVBAコードが実行されます。イベントの理解はVBAを理解する上で基本的です。
APIは多くの場合、さまざまな状態に対応していくつかのイベントを発生させるオブジェクトを公開します。たとえば、 Excel.Application
オブジェクトは、新しいワークブックが作成、オープン、アクティブ化、またはクローズされるたびにイベントを発生させます。またはワークシートが計算されるたびに。またはファイルが保存される直前。または直後。フォーム上のボタンは、ユーザーがクリックするとClick
イベントを発生させ、ユーザーフォーム自体はアクティブ化された直後のイベントと閉じられる直前のイベントを発生させます。
APIの観点からは、イベントは拡張ポイントです。クライアントコードでは、これらのイベントを処理するコードを実装し、これらのイベントが発生するたびにカスタムコードを実行することができます。つまり、ワークシートの選択内容が変更されるたびにカスタムコードを自動的に実行できます。 - ワークシート上で選択が変更されたときに発生するイベントを処理します。
イベントを公開するオブジェクトはイベントソースです。イベントを処理するメソッドはハンドラです。
ハンドラー
VBAドキュメントモジュール( ThisDocument
、 ThisWorkbook
、 Sheet1
など)とUserForm
モジュールは、いくつかのイベントを公開する特別なインターフェイスを実装するクラスモジュールです。これらのインターフェイスは、コードペインの上部にある左側のドロップダウンで参照できます。
右側のドロップダウンでは、左側のドロップダウンで選択されたインターフェイスのメンバーが一覧表示されます。
アイテムが右側のリストで選択されると、VBEは自動的にイベントハンドラスタブを生成します。ハンドラが存在する場合は、そこをナビゲートします。
ModuleスコープのWithEvents
変数は、任意のモジュールで定義できます。
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
それぞれのWithEvents
宣言は、左側のドロップダウンから選択できるようになります。右側のドロップダウンでイベントが選択されると、VBEはWithEvents
オブジェクトの名前とイベント名をアンダースコアで結合したイベントハンドラスタブを生成します。
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
Private Sub Foo_Open()
End Sub
Private Sub Bar_SelectionChange(ByVal Target As Range)
End Sub
少なくとも1つのイベントを公開する型だけがWithEvents
で使用でき、 WithEvents
宣言にはNew
キーワードでその場で参照を割り当てることができません。このコードは違法です:
Private WithEvents Foo As New Workbook 'illegal
オブジェクト参照はSet
明示的にSet
必要があります。クラスモジュールでは、 Class_Initialize
ハンドラの中で、そのクラスのインスタンスが存在する限り、そのオブジェクトのイベントをクラスが処理するため、そのための良い場所がよくあります。
ソース
任意のクラスモジュール(またはドキュメントモジュール、またはユーザーフォーム)は、イベントソースになります。 Event
キーワードを使用して、 Event
のシグネチャをモジュールの宣言セクションで定義します。
Public Event SomethingHappened(ByVal something As String)
イベントの署名によって、イベントの発生方法と、イベントハンドラの外観が決まります。
イベントは、定義されているクラス内でのみ発生させることができます。クライアントコードではイベントを処理できます。イベントはRaiseEvent
キーワードで生成されます。イベントの引数はその時点で提供されます:
Public Sub DoSomething()
RaiseEvent SomethingHappened("hello")
End Sub
SomethingHappened
イベントを処理するコードがなければ、 DoSomething
プロシージャを実行するとイベントは発生しますが、何も起こりません。イベントソースがSomething
という名前のクラスの上記のコードであると仮定すると、 ThisWorkbook
このコードは、 test.DoSomething
が呼び出されるたびに "hello"というメッセージボックスを表示します。
Private WithEvents test As Something
Private Sub Workbook_Open()
Set test = New Something
test.DoSomething
End Sub
Private Sub test_SomethingHappened(ByVal bar As String)
'this procedure runs whenever 'test' raises the 'SomethingHappened' event
MsgBox bar
End Sub
データをイベントソースに戻す
参照渡しのパラメータの使用
イベントは、呼び出し元に返されることを意図したByRef
パラメータを定義することができます。
Public Event BeforeSomething(ByRef cancel As Boolean)
Public Event AfterSomething()
Public Sub DoSomething()
Dim cancel As Boolean
RaiseEvent BeforeSomething(cancel)
If cancel Then Exit Sub
'todo: actually do something
RaiseEvent AfterSomething
End Sub
場合BeforeSomething
イベントは、その設定ハンドラ持っcancel
にパラメータをTrue
、実行はハンドラから戻ったときに、 cancel
となりTrue
とAfterSomething
提起されることはありません。
Private WithEvents foo As Something
Private Sub foo_BeforeSomething(ByRef cancel As Boolean)
cancel = MsgBox("Cancel?", vbYesNo) = vbYes
End Sub
Private Sub foo_AfterSomething()
MsgBox "Didn't cancel!"
End Sub
foo.DoSomething
が実行されるとき、 foo
オブジェクト参照がどこかに割り当てられていると仮定すると、メッセージボックスはキャンセルするかどうかをfoo.DoSomething
メッセージを表示し、 Noが選択されたときだけ2番目のメッセージボックスに "did not cancel"というメッセージが表示されます。
可変オブジェクトの使用
また、可変オブジェクトByVal
コピーを渡し、ハンドラにそのオブジェクトのプロパティを変更させることもできます。呼び出し元は変更されたプロパティ値を読み取り、それに応じて動作することができます。
'class module ReturnBoolean
Option Explicit
Private encapsulated As Boolean
Public Property Get ReturnValue() As Boolean
'Attribute ReturnValue.VB_UserMemId = 0
ReturnValue = encapsulated
End Property
Public Property Let ReturnValue(ByVal value As Boolean)
encapsulated = value
End Property
Variant
型と組み合わせると、これは呼び出し元に値を返すためにむしろ明らかでない方法を作成するために使用できます:
Public Event SomeEvent(ByVal foo As Variant)
Public Sub DoSomething()
Dim result As ReturnBoolean
result = New ReturnBoolean
RaiseEvent SomeEvent(result)
If result Then ' If result.ReturnValue Then
'handler changed the value to True
Else
'handler didn't modify the value
End If
End Sub
ハンドラは次のようになります。
Private Sub source_SomeEvent(ByVal foo As Variant) 'foo is actually a ReturnBoolean object
foo = True 'True is actually assigned to foo.ReturnValue, the class' default member
End Sub