Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


4284 / 76734 ←次へ | 前へ→

【78074】Re:イベント処理について
発言  かず  - 16/3/27(日) 14:16 -

引用なし
パスワード
   ▼かず さん:
>▼かず さん:
>>▼β さん:

サンプルコードに誤字があったので修正しました。

4.サンプルコードの解説 (井川春樹さんの本から抜粋)

'*************************************************************
' 井川さんのサンプルコードの解説
'*************************************************************
では(1)から順に見ていきましょう。
 まず、1行目でEventステートメントを使ってイベントを宣言しています。このクラスは
Rowslnsertというイベントを発行して、そのイベントプロシージヤは、CancelというBoolean d
の引数を参照渡しで受け取りますよ、といった宣言になります。

CheckRowsInsertメソッドは、この後解説するタイマー処理によって繰り返し実行され、
行が挿入されたタイミングでイベントを発行するメソッドです。

ここで重要なのは、Static変数「myRow」が最終行を表すRangeオブジェクトへの参照を保持していることです。

初めて実行されるときだけは変数「myRow」が「Nothing」なので、その場合には最終行を
表すRange オブジェクトへの参照を格納するだけの処理を行いますが、2回目以降には
いよいよチェックを行います。

このチェックには、On Error Resume Nextステートメントを使って、実行時エラーを
無視するようにしてから、変数「myRow」に参照が格納されているRangeオブジェクトの
何らかのプロパティを取得してみるのが簡単です。

ここではRowプロパティを取得していますが他のプロパティでもかまいません。
このとき、行が挿入されていれば最終行は存在しなくなっているのでエラーが発生します。
ですから、「エラーの発生=行が挿入された」と判断できるわけです。エラーの発生の
有無はErr関数を使って参照を取得できるErrObjectオブジェクトのNumberプロパティ
で判断できます。

エラーが発生していなければNumberプロパティの値が「O」となるからです。
そして、行が挿入されたと判断したらRaiseEventステートメントを使ってRowslnsert
イベントを発行します。引数Cancelには変数[myCancel]を指定し、イペントプロシー
ジヤによって、変数.[myCancel」の値が「True」に変更される(引数Cancelに「True」
が設定される)と、ApplicationオブジェクトのUndoメソッドを使って、行挿入の操作
を元に戻します。

次に(2)のコードをご覧ください。これはタイマープロシージヤと呼ばれるプロシー
ジヤで、この後解説するWin32API関数のSetTimer関数の引数lpTimeerFuncにこのプロ
シージヤのアドレスを指定すると、繰り返し非同期で実行されるようになります。

宣言部については決まり事として覚えておいてください。ここで行っている処理は、
clsRowsInsertEventオブジェクトのCheckRowsInscrtメソッドを実行するといった
ものです。

clsRowsInsertEventオブジェクトへの参照は、?Bのコードで定義している
ThisWorkbookクラスのRowsInsertEventClassプロパティを使って取得します。

最後に(3)のコードの要点をまとめます。
まず、このブックモジュールでclsRowsInsertEventオブジェ列が発行するイベント
をハンドルするために、モジュールレベルのオブジェクト変数
「mvRowsInsertEventClass」を、WithEventsキーワードを付けて
、cIsRowsInsertEvent型で宣言します。

そして、そのclsRowsInsertEventオブジェ列のRowslnsertイペントプロシージャに、
行挿入時に実行する処理を記述します。ここでは、キャンセルするかどうかの
問い合わせのみを行っています。

タイマー処理の開始はブックのOpenイベントプロシージャで、終了はBeforeCloseイベント
ブロシージャで行います。

タイマー処理を開始するのはWin32API関数のSetTimerで、引数HwndとnlDEventには0を、
nElapseにはタイマー処理を実行する問隔(ミリ秒)を、lpTimerFunc にはタイマー
プロシージャのアドレスを指定します。プロシージャのアドレスはAddressOf演算子を
使って取得します。

なお、サンプルではnElapseに「O」を指定していますが、当然ですがOミリ秒ごとに処理
を繰り返すといった非現実的なことは不可能です。このような場合処理できる極めて
微小な時間単位で処理が繰り返されます。

SetTimer関数の戻り値はタイマーIDと呼ばれる識別子で、
KillTimer関数のnIDEventに指定することでタイマー処理を終了できます。
サンプルでは、ブックのBeforeCloseイベントプロシージャの処理に保存確認の
ロジックを内包しているのは、BeforeCloseイペントプロシージャの処理によって
タイマー処理(イベント発行のための監視)を完了してから、Excelの機能によって
保存確認が行われた場合にキャンセルすると、イベントをハンドルできない状態で
開かれたままになるからです。

さて(3)のコードの最後で定義しているRowsInsertEventClassプロパティの内容
はまったく難しいものではありません。モジュールレベル変数
[my RowsInsertE vent Class]が「Nothing」であれば新たにインスタンスを生成
してから、その参照を返すプロパティです。

しかし1つだけ重要なことがあります。
このようにして外部にclsRowsInsertEventオブジェクトヘの参照を返す(公開する)
場合には、clsRowsInsertEventクラスのInstancingがデフォルトのPrivate]のまま
ではいけないからです。

このような場合には、あらかじめ[プロパティ]ウインドウを使ってInstancingを
[PublicNotCreatable]に設定しておきます。

ポイント
タイマー処理中に実行時エラーが発生すると、Excelが即座に落ちてしまいます。
万が一にもそのようなことがないように、絶対に実行時エラーが発生しない処理
でない限り、必ずOn Error Resume Nextステートメントを付けるようにしましょう。
--
11 hits

【78064】イベント処理について かず 16/3/26(土) 11:09 質問[未読]
【78065】Re:イベント処理について かず 16/3/26(土) 11:31 回答[未読]
【78067】Re:イベント処理について β 16/3/26(土) 12:52 発言[未読]
【78072】Re:イベント処理について かず 16/3/27(日) 2:25 回答[未読]
【78073】Re:イベント処理について かず 16/3/27(日) 14:15 質問[未読]
【78074】Re:イベント処理について かず 16/3/27(日) 14:16 発言[未読]

4284 / 76734 ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free