WithEvents キーワードを使用して組み込みイベントのイベント プロシージャを作成する
Microsoft Office 2000/Visual Basic プログラマーズ ガイド |
ユーザー フォーム、Access フォームとレポート、ThisDocument、ThisWorkbook、および SheetN オブジェクトなど、一般的にイベント プロシージャを記述する対象のオブジェクトには、すべて関連付けられたクラス モジュールが含まれているという共通点があります。Office 97 および Office 2000 のオブジェクト モデルの中にも組み込みイベントを含むものがありますが、関連付けられたクラス モジュールはありません。たとえば、Excel 2000 で Visual Basic Editor からオブジェクト ブラウザを使用すると、Excel の Application オブジェクトには NewWorkbook、WorkbookOpen、および SheetChange など、メンバとして一覧表示されるイベントがいくつかあることがわかります。イベントを提供するその他の Excel オブジェクトには、Chart、OLEObject、および QueryTable オブジェクトがあります。Word の Application オブジェクトおよび Microsoft PowerPoint® の Application オブジェクトもイベントを提供します。
これらのイベントに対するイベント プロシージャを汎用的なクラス モジュールで作成することができます。既定では、クラス モジュールはオブジェクトに関連付けられていませんが、イベントを含むオブジェクトに対するイベント プロシージャを含めることが可能です。
フォーム モジュールのイベント プロシージャでは、フォームの特定のインスタンスに対してのみイベント プロシージャが存在します。たとえば、UserForm1 と UserForm2 は UserForm 型のオブジェクトの異なるインスタンスです。どちらにも、フォームのロード時に実行される Initialize イベントが含まれています。UserForm1 の Initialize イベント プロシージャは UserForm1 のロード時にのみ実行され、UserForm2 のロード時には実行されません。反対に、UserForm2 の場合は UserForm2 のロード時にのみ実行されます。
同様に、関連付けられたモジュールがないオブジェクトのイベントの場合も、イベントはオブジェクトの特定のインスタンスで発生します。具体的には、ほかのインスタンスに対してではなくイベントに対して応答するように指定したオブジェクトのインスタンスで発生します。
オブジェクトのインスタンスがイベントに応答するように指定するには、クラス モジュールで WithEvents キーワードを使用してその種類のモジュール レベル オブジェクトの変数を宣言します。このキーワードによって、VBA は、そのオブジェクト変数に割り当てられたインスタンスのイベントに応答する指定を認識します。WithEvents キーワードは、イベントをサポートするオブジェクトおよびクラス モジュールでの使用に限られます。
たとえば、クラス モジュールに含まれる次のコードは、Excel.Application 型のプライベート オブジェクト変数がイベントに応答するように宣言します。
Private WithEvents xlApp As Excel.Application
イベントに応答するオブジェクト変数を宣言すると、そのオブジェクト変数はクラス モジュールのコード ウィンドウにある [オブジェクト] ボックスに表示され、イベントがコード ウィンドウの [プロシージャ] ボックスに表示されます。イベント プロシージャ スタブを作成するには、これらのボックスでオブジェクト名およびイベント名を選択します。Visual Basic Editor は、次のようなイベント プロシージャ スタブを挿入します。
Private Sub xlApp_NewWorkbook(ByVal Wb As Excel.Workbook)
End Sub
これで、イベントに関連するオブジェクト変数およびイベント プロシージャを作成しました。ただし、この時点ではオブジェクト変数がポイントする対象は設定されていません。クラス モジュールの Initialize イベント プロシージャでこのオブジェクト変数への参照を割り当てる必要があります。Initialize イベントは、クラスの新しいインスタンスが作成されると直ちに発生します。そのため、ここでオブジェクト変数への参照を割り当てておくと、必要に応じて随時使用できることが確実になります。
この場合、オブジェクト変数がアプリケーションの現在のインスタンスをポイントするように設定します。
Private Sub Class_Initialize()
Set xlApp = Application
End Sub
最後に、Initialize イベントを起動してイベント対応の Application オブジェクト変数をメモリにロードするために、クラスの新しいインスタンスを作成する必要があります。新しい標準モジュールを挿入して、クラスのインスタンスをポイントするプライベート モジュール レベルのオブジェクト変数を宣言します。たとえば、クラスの名前が XLEvents である場合、次のオブジェクト変数を宣言します。
Private p_evtEvents As XLEvents
このオブジェクト変数はイベント対応のオブジェクトおよびイベント プロシージャを含むクラスをポイントするため、プロジェクトを閉じるかリセットするまでメモリに残すために、このオブジェクト変数をモジュール レベルで宣言する必要があります。モジュール レベルでの宣言を行わないと、変数が適用範囲を超えたときにオブジェクトはイベントに応答しません。
次に、標準モジュールにクラスの新しいインスタンスを作成するプロシージャを追加します。
Public Sub InitXLEvents()
Set p_evtEvents = New XLEvents
End Sub
このプロシージャを実行すると、Application オブジェクトのイベント プロシージャに追加したすべてのコードは、対応する Application オブジェクト イベントが発生したときに起動します。
Application オブジェクトをイベント対応にするには、Excel を開くたびに InitXLEvents プロシージャを実行する必要があります。Application オブジェクトに対するイベントすべてを 1 度の定義で実行することはできません。
メモ Excel の Application などのオブジェクトに対して使用可能なイベントのいくつかは、そのアプリケーション内で常時使用できるわけではありません。たとえば、Excel の Application オブジェクトには OpenWorkbook イベントがありますが、InitXLEvents などのプロシージャを実行するにはブックを開く必要があります。InitXLEvents を実行した後で次のブックを開いたときにイベントが発生しますが、最初に開いたブックに対するイベントはトラップできません。
オートメーション (旧 OLE オートメーション) をサポートする COM コンポーネントでは、OpenWorkbook イベントの使用をお勧めします。たとえば、前で説明されているようなクラスおよび標準モジュールを含む Word でアプリケーションを記述することができます。ここで 2 つの変更を行う必要があります。Excel のオブジェクト ライブラリへの参照を設定し、現在のインスタンスを取得するのではなく、New キーワードを使用して Excel の Application オブジェクトの新しいインスタンスを作成します。InitXLEvents プロシージャまたは類似したプロシージャを呼び出してオートメーションから Application オブジェクトの新しいインスタンスを作成すると、Excel はブックを開かずにロードします。ここで、Application オブジェクトはイベント対応であるため、オートメーションでブックを開くと直ちに OpenWorkbook イベントが発生します。