1月20日(2009)


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
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。