- - PR -
C# Excelのプロパティ>ユーザ設定を扱う方法
投稿者 | 投稿内容 | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-07-13 16:48
次のように実装してみました。
Interop.Application app = new Interop.Application(); Interop.Workbooks activeWorkbooks = app.Workbooks; Interop.Workbook activeWorkbook = activeWorkbooks.Open(@"a.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); Core.DocumentProperties docProps = (Core.DocumentProperties)activeWorkbook.CustomDocumentProperties; そうしますと、実行時、最後のステップで 「型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Microsoft.Office.Core.DocumentProperties' にキャストできません。IID '{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}' が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスがサポートされていません (HRESULT からの例外: 0x80004002 (E_NOINTERFACE))。」 という良く分らないエラーが出てしまったのです。 他にも Tools.Workbook activeWorkbook2 = (Tools.Workbook)activeWorkbook; ということを試みてみましたが、こちらも実行時に 「型 'Microsoft.Office.Interop.Excel.WorkbookClass' の COM オブジェクトをクラス型 'Microsoft.Office.Tools.Excel.Workbook' にキャストできません。COM コンポーネントを表す型のインターフェイスを COM コンポーネントを表さない型にキャストすることはできません。ただし、基になる COM コンポーネントがインターフェイスの IID の QueryInterface 呼び出しをサポートする場合は、インターフェイスにキャストすることができます。」 というエラーが出ました。 何かお分りになりますでしょうか。 [ メッセージ編集済み 編集者: あすか 編集日時 2006-07-13 16:49 ] | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-13 18:02
ごめんなさい、わかりません... (;^-^) 私も今、COM Interop で試してみたのですが、こちらでもキャストができませんでした。 一体全体、実体は何型だというんでしょうね... ただし、VB で遅延バインディングを使用するとできてしまうのです。
うーん、やっぱり型は合っているような気もします。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-13 23:39
ラッパクラスじゃなくて、生のインターフェース型にキャストしてみたら? | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-14 10:05
ええと、これはどういうことなのでしょうか。 私の知識では"生のインターフェース型"が分らないのですが ご面倒でなければ、分りやすく解説していただけないでしょうか。 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-15 05:06
面倒です (^^; 背景を正しく理解するためには OLE/COM の基礎と .NET の型システムに関する知識が必要で、たかだか掲示板の1投稿程度の文書量で「分かりやすく」解説するのは非常に困難です。 技術的な背景や詳細については書籍等を参考にしてもらうとこととして、重要なところをかいつまんで説明すると以下のような感じになります。理解できなかったらごめんなさい。 VSTO の同梱物や tlbimp によって自動生成されたラッパクラスを使っていると忘れがちですが、OLE/COM と .NET では、簡単に言えば動作原理が全く異なります。 Excel.ApplicationClass クラスは典型的なラッパクラスであり、その内部に Excel アプリケーションのインスタンスの OLE/COM ネイティブな参照をカプセルしています。 「ラッパクラスの参照」と「OLE/COM ネイティブな参照」は全くの別物である点が重要です。 さて、ラッパクラスのメソッドには、オブジェクトインスタンスの参照を返すものがあります。 普段あまり深く考える異なることなく
のような構文を利用していると思いますが、HogeWrapper の元ネタとなった OLE/COM レベルでのインターフェース定義(=IHoge::GetHogeHoge())では、GetHogeHoge() メソッドは IHogeHoge または IUnknown/IDispatch を返す設計であったはずです。 何故なら、OLE/COM では、すべてのオブジェクトが実装を義務付けられた IUnknown インターフェースのポインタか、OLE レベルで実装を義務付けられている IDispatch インタフェースのポインタ、または適当なカスタムインターフェースのポインタをオブジェクトインスタンスの参照として使用するからです。 例えば IHoge::GetHogeHoge() の定義が C# 風に表記すると
である時、これを HogeWrapper 生成の際に
のように「翻訳する」のは容易でしょう。 ですが、IHoge::GetHogeHoge() の設計が
のような場合、GetHogeHoge() が返す型は何にするべきでしょうか? 特別なヒントが無い限り、object 型にする他ありません。結果として
となりますが、この時 hogeHoge は .NET の「COM 相互運用機能」で定義された ComObjectClass クラス(=正確な名前を忘れました (^^;)のインスタンスとなります。 ComObjectClass クラスから、HogeHogeClass クラスへのキャストは未定義というか不可能であるため
のようなキャストは実行時エラーになります。(実際、類似の現象が起きていますよね?) ですが、「COM 相互運用機能」は COM レベルで定義されたインターフェースを .NET のインターフェースとして解釈する機能を提供しているため、上記の擬似コードにおける disp は IHogeHoge インターフェース型にはキャストできます。(場合があります)
この場合の「COM から .NET にインポートされたインターフェース型」を「生のインターフェース型」と呼んだのです。 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-15 12:49
そういう意味でしたか... 投稿見合わせていました。 そういう意味であれば、今回はできないですね。 リフレクションでも一応覗き見ましたが、該当するものはなさそうです。 (ひどりさんの説明に少しあるように、System.__ComObject としてしか存在しない) タイプ ライブラリをゴリゴリ書いて何とかするか、 おとなしく、VB の遅延バインドマンセーでしょうかね。 # "面倒です" と言いつつも、思った以上に説明しているひどりさんw _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-16 05:51
MSDN Library を斜め読みした限りでは、Core.DocumentProperties が「生のインターフェース」に一番近いようですね。 これでキャストできないとなると
か、清く正しく? InbokeMember するか、ですね。
元投稿から「頑張っている」雰囲気が伝わってきたので ;-) [ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-07-16 05:54 ] | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-16 09:29
ああ、何で試していたのか書いていなかったのがまずかったですね。 私も、Microsoft.Office.Core にある DocumentProperties が最も近いと思い、
正しくは、InvokeMember ですね? (;^-^) C# で 「遅延バインディング」 を行うには、System.Type.InvokeMember メソッドでしたね。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 |