COM操作について (EXCEL 異なるバージョン バインディング)

タグの編集
投稿者 mn  (社会人) 投稿日時 2012/6/11 14:12:18
こんにちは。

現在EXCEL2000を事前バインディングし操作しています。
内容はEXCELを起動、BOOK作成、Datatableの内容をセルに貼り付ける、セルの書式設定をするなどです。
実行環境はEXCEL2000、2003、2007で動作しています。

なぜ異なるバージョンでの動作が可能なのでしょうか。
調べてみると実行時環境のEXCELのバージョンが不明、統一されていない、開発環境と異なるなどの場合は、事前でなく遅延バインディングを利用するという記事をいくつか見受けられました。
ほかにMSDNからPIAやIAなどの記事も見つけられましたが、あまりよく理解できませんでした。

今はインテリセンスも使えて、異なるバージョンで動作できるいい環境なので、重大な問題などなければこのままの環境にしておきたいと思っています。

これについてもう少し詳しく掲載されているところなどありました教えていただけますか。





投稿者 魔界の仮面弁士  (社会人) 投稿日時 2012/6/11 18:39:21
> 今はインテリセンスも使えて、異なるバージョンで動作できるいい環境なので、
インストールの順序は厳守せねばなりませんが、実行環境と使う分には構いません。
http://www.atmarkit.co.jp/fwin2k/win2ktips/847office/office.html

しかし開発環境として用意するのであれば、VMWare や VirtualPC などの
仮想環境を利用するなどして、個別に用意することを検討してみてください。

Office 導入によって、OLE API や Internet Explorer 関連のライブラリが
一緒にインストールされることがあります。また、.NET のような
完全なる side-by-side 実行とはならないため、一部の COM コンポーネントの
レジストリ設定やタイプライブラリ情報も、後から入れたバージョンで
上書きされてしまうことになります。

そのためクリーンインストール環境とは、厳密には異なる動作となりえます。


【4. 複数バージョンが混在インストールしている場合の動作について】
http://blogs.msdn.com/b/office_client_development_support_blog/archive/2012/05/23/offica.aspx
》 複数バージョンの Office が単一マシンに混在している環境の場合、
》 Office としても制限付きで動作することをサポート技術情報にてお伝えしております。
》 しかし、これはあくまで標準機能の説明であり、カスタム コード等の実装内容につきましては、
》 残念ながら動作保障はできません。これまでのお問い合わせ内容からも、旧バージョンの DLL が
》 誤って呼び出されるなど、様々な予期せぬ動作が報告されております。
》 もし、お客様環境にてテストいただき正常動作しない場合につきましては、
》 旧バージョンをアンインストールいただき、新バージョンを修復インストールして
》 いただくなどの措置をお願いすることになります。



> これについてもう少し詳しく掲載されているところなどありました教えていただけますか。
参考までに、事前バインディングおよび実行時バインディングの動作に関する資料を載せておきます。
(旧VB向けの資料なので、COM 相互運用機能の部分に関することは書かれていませんけれども)
http://support.microsoft.com/kb/245115/ja



> なぜ異なるバージョンでの動作が可能なのでしょうか。
既に御存知とは思いますが、Excel のライブラリは、バージョンアップに伴い、
 ・今まで Sub だったメソッドが、Function に変更される
 ・引数無しだったメソッドに、省略可能な引数が追加される
 ・省略可能な引数が追加される
 ・列挙型に新しいメンバーが追加される
 ・新しいメソッド、新しいオブジェクトが追加される
といった違いが生じます。


しかし VBA にとっては、Sub が Function になったり、あるいは
省略可能な引数が末尾に追加されても、プログラムコードには
差異が生じません。そのためExcelバージョンが、開発環境よりも
実行環境の方が高い場合、この差異はある程度無視できます。


> 現在EXCEL2000を事前バインディングし操作しています

参照設定しているのが PIA だった場合には、アセンブリの
バインディング リダイレクトが働くため、実行環境にも PIA が
配置されている限り、ほとんどの場合は正常に動作します。
http://msdn.microsoft.com/ja-jp/library/15s06t57.aspx

》グローバル アセンブリ キャッシュに (Office と共に、または PIA の
》再頒布可能パッケージをインストールすることにより)  Office PIA を
》インストールし、登録すると、同時にバインディング リダイレクト アセンブリが
》グローバル アセンブリ キャッシュだけにインストールされます。これらの
》アセンブリにより、実行時にプライマリ相互運用機能アセンブリの正しいバージョンが
》確実に読み込まれます。たとえば、2007 Microsoft Office プライマリ相互運用機能
》アセンブリを参照するソリューションが、同じプライマリ相互運用機能アセンブリの
》Microsoft Office 2010 バージョンがあるコンピューターで実行されると、
》バインディング リダイレクト アセンブリによって、そのプライマリ相互運用機能
》アセンブリの Microsoft Office 2010 バージョンを読み込むように .NET Framework
》ランタイムに指示されます。


しかし PIA ではなく自動生成される IA については、この仕組みは適用されません。
Excel 2000 は PIA が無いため、今回はこちらですね。

そもそも IA は、Visual Studio の Service Pack によって出力形式が異なったり、
下記のような不都合を生じさせることもあるため、Office を操作する場合には、
PIA を使うようにと公式にアナウンスされています。
http://support.microsoft.com/kb/316653/ja

このため、PIA の無い Excel 2000 などは、COM 解放時などに関して、厄介な問題を
抱えてしまう可能性があります。VBScript や VB6 などから呼ぶ分には構いませんが、
.NET からの利用する場合は、十分に注意してください。


それはさておき、リダイレクトされないはずの IA で動作するのは、
参照設定したタイプライブラリには、CLSID、IID、ディスパッチID といった
COM 側の識別子情報が含まれているためです。

たとえば、Workbooks クラスには、
 {000208DB-0000-0000-C000-000000000046}
という UUID が付与されています。
※ MsgBox(GetType(Excel.Workbooks).GUID)

これは Excle 97 でも 2010 でも一緒の値のため、バージョンが変わっても、
変わらず Workbooks という型として扱えるわけです。
※ただし Excle 5.0 では {00020862-0000-0000-C000-000000000046} です。


問題は引数の違いですが、これは
 (1) メソッド名や引数定義で解決する場合(CallByName 、あるいは Object 型へのレイトバインド)
 (2) 参照設定されたタイプライブラリのディスパッチIDで呼び出す場合
のいずれが採用されるかによって、動作が異なります。

たとえば、Workbooks.OpenText メソッドを見てみると、
それぞれのバージョンで、下記のような定義の差異があります。


《Excel 2002, 2003, 2007, 2010》
 (a) "OpenText" メソッド:戻り値なし。引数18個(後続 17個は省略可能)。
 (b) "_OpenText"メソッド:戻り値なし。引数16個(後続 15個は省略可能)。
 (c)"__OpenText"メソッド:戻り値なし。引数14個(後続 13個は省略可能)。

《Excel 2000》
 (b) "OpenText" メソッド:戻り値なし。引数16個(後続 15個は省略可能)。
 (c) "_OpenText"メソッド:戻り値なし。引数14個(後続 13個は省略可能)。

《Excel 97》
 (c)  "OpenText"メソッド:戻り値なし。引数14個(後続 13個は省略可能)。

※ アンダーバーで始まるメソッドには、不可視属性も付与されています。


(1) のレイトバインド実装の場合、同じ名前でシグネチャが異なりますが、
後続引数が Optional であるため、VB にとってはあまり問題となりません。
引数を省略できない C# 3.0 以下にとっては大問題ですけれどね。


(2) のアーリーバインド実装の場合、ディスパッチIDでのアクセスとなります。
上記の一覧の前に a~c のアルファベットを付与していますが、それぞれ
 (a) の DispId は、いずれも &H784
 (b) の DispId は、いずれも &H6EB
 (c) の DispId は、いずれも &H2AB
となっているため、ディスパッチインターフェイス経由での呼び出しであれば、
意図したメソッドが呼び出されることになります。
投稿者 mn  (社会人) 投稿日時 2012/6/12 10:05:09
>そもそも IA は、Visual Studio の Service Pack によって出力形式が異なったり、
>下記のような不都合を生じさせることもあるため、Office を操作する場合には、
>PIA を使うようにと公式にアナウンスされています。
>http://support.microsoft.com/kb/316653/ja

こういう不具合が発生する事があるのですね。
私もIA使用時の不具合などを調べていたのですが、このような具体的な記事までたどり着けませんでした。
こういう不具合に直面しない限り、便利な事前バインディングを使用つづけるかもしれませんね。

大変詳しく返答いただきありがとうございました。