COMによるイベントの検知
ExcelのSheetCalculateイベントを取得した際、どのシートが更新されたかを
知るために色々調べた結果を以下に書き記しておく事にする。
Excel側でイベントが発生した場合、こちらで登録したオブジェクトインターフェースから
Invoke()関数を通じて通知が行われる。
Excel側は発生したイベントの情報を盲目的に
Invoke()関数に流し込んでくる。
SheetCalculateイベントの場合、OLE/COM Object Viewer で確認すると
[id(0x0000061b), helpcontext(0x0001061b)]
void SheetCalculate([in] IDispatch* Sh);
となっている。
- OLE/COM Object Viewerによる確認ルート
- ITypeLib Viewer ⇒ Excel ⇒ CoClasses ⇒ coclass Application ⇒ AppEvent ⇒ Methods
コールされたInvoke()関数の第1引数でDISPID dispIdMemberを受け取る。
この内容は上記のid(0x0000061b)にあたる。
なので、例えばInvoke()内部でこの引数でswitch文を作ることでイベント毎の分岐処理ができる。
次に注目したいのが第5引数のDISPPARAMS* pDispParamsである。
ここには上記のSheetCalculate()に与えている引数が入っている。
ちなみのこのSheetCalculate()に指定される引数は変更があったシートのIDispatchである。
DISPPARAMSは
IntPtr rgvarg
IntPtr rgdispidNamedArgs
int cArg
int cNamedArgs
となっていて、各パラメータについては
- rgvarg
- 引数リスト
- rgdispidNamedArgs
- 名前付き引数リスト
- cArg
- 引数リストに含まれる要素数
- cNamedArgs
- 名前付き引数リストに含まれる要素数
名前付き引数リストは与えた引数の用途的な意味合いがあるっぽい。
例えばSheetCalculate()に関してはDISP_VALUE(OAIdl.h参照)が入っている。
rgvargにはVALIANT型でIDispatchが格納されているため、
VARIANT *sh = reinterpret_cast<VARIANT *>(pDispParams->rgvarg);
sh->pdispVal
という感じで計算されたシートのインターフェースを取得する。
ここで得たインターフェースのアドレスと比較をすることで、
どのシートが計算されたのかを知ることができる。
今回はSheetCalculateに関しての話ではあるが、
どのイベントについても上記の要領で引数を取得すればいい。
最終更新:2009年01月20日 15:23