Book.SaveAs部分で !COMException はハンドルされませんでした
投稿者 neptune  (社会人)
投稿日時
2009/5/8 07:40:40
私の書いたソースですかね?
今確認してもあのソース自体は問題なく動作してますが。。。
私の環境には
Microsoft Excel 11.0 Object Library
が入ってないものでこれも確認できません。
取りあえず、パスが存在しなければエラーになりますが、この点は問題ないそうですし。
当方、VB2008EEエディションですが、
Microsoft.Office.Interop.Excel 名前空間は
Visual Studio Tools for Office
のサポートですし、申し訳ないが、確認できません。
悪しからず。
今確認してもあのソース自体は問題なく動作してますが。。。
私の環境には
Microsoft Excel 11.0 Object Library
が入ってないものでこれも確認できません。
取りあえず、パスが存在しなければエラーになりますが、この点は問題ないそうですし。
当方、VB2008EEエディションですが、
Microsoft.Office.Interop.Excel 名前空間は
Visual Studio Tools for Office
のサポートですし、申し訳ないが、確認できません。
悪しからず。
投稿者 yamaV1.02β  (社会人)
投稿日時
2009/5/8 09:18:44
neptune さん返信ありがとうございます。
>私の書いたソースですかね?
neptuneさん=サイト作成者 でありましたか。
御大じきじきのご回答ありがとうございます。
ソースはコピペして検証いたしました。
「
当方、VB2008EEエディションですが、
Microsoft.Office.Interop.Excel 名前空間は
Visual Studio Tools for Office
のサポートですし、申し訳ないが、確認できません。
悪しからず。
」
御意
>私の書いたソースですかね?
neptuneさん=サイト作成者 でありましたか。
御大じきじきのご回答ありがとうございます。
ソースはコピペして検証いたしました。
「
当方、VB2008EEエディションですが、
Microsoft.Office.Interop.Excel 名前空間は
Visual Studio Tools for Office
のサポートですし、申し訳ないが、確認できません。
悪しからず。
」
御意
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2009/5/8 11:06:43
>初級講座「第44回 周辺にあるテクノロジ」4.Excelの操作 のコードの途中でエラーになります。
の執筆は rucio(るきお)さんで、
>http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=242
にあるのが、neptune さんの投稿ですね。
> このエラーでは何が起きているのでしょうか。
個人的には、相互運用機能アセンブリと、実際のタイプライブラリバージョンの
不一致では無いかな、と予想しています。
幾つか確認。
まず、エラーが発生するのは、開発環境ですか? 実行環境ですか?
(開発時にエラーが発生しているのか、それとも作成したEXEを配布した先でエラーになるのか)
それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
(あるいは、開発環境のExcelバージョンと、実行環境のExcelバージョンが一致していないとか)
の執筆は rucio(るきお)さんで、
>http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=242
にあるのが、neptune さんの投稿ですね。
> このエラーでは何が起きているのでしょうか。
個人的には、相互運用機能アセンブリと、実際のタイプライブラリバージョンの
不一致では無いかな、と予想しています。
幾つか確認。
まず、エラーが発生するのは、開発環境ですか? 実行環境ですか?
(開発時にエラーが発生しているのか、それとも作成したEXEを配布した先でエラーになるのか)
それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
(あるいは、開発環境のExcelバージョンと、実行環境のExcelバージョンが一致していないとか)
投稿者 yamaV1.02β  (社会人)
投稿日時
2009/5/8 19:39:47
魔界の仮面弁士さん、回答ありがとうございます。
「
>初級講座「第44回 周辺にあるテクノロジ」4.Excelの操作 のコードの途中でエラーになります。
の執筆は rucio(るきお)さんで、
>http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=242
にあるのが、neptune さんの投稿ですね。
」
サイト作成者=rucioさんでありましたか。
勘違いいたしました。ご指摘ありがとうございます。
>まず、エラーが発生するのは、開発環境ですか? 実行環境ですか?
44回までの学習では{開発環境|実行環境}について理解が及んでいるか心もとないのですが、ソリューションエクスプローラを右クリックした「発行(B)...」を実行してできる \bin\Releaceフォルダ内の.exeファイルを実行環境。VB_2008_Expressを立ち上げて操作する環境を開発環境として検証しました。
結果は同様のエラーが発生しました。
「
それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
(あるいは、開発環境のExcelバージョンと、実行環境のExcelバージョンが一致していないとか)
」
!!!ご明察のとおりxl2000 と xl2003をインストールした環境で作業しています。
以下のコードで作成されるブックのバージョンを確認したところxl2000でした。
Dim Excel As New Microsoft.Office.Interop.Excel.Application
Dim Book As Microsoft.Office.Interop.Excel.Workbook
Dim Sheet As Microsoft.Office.Interop.Excel.Worksheet
'▼前処理
Book = Excel.Workbooks.Add '新規ワークブックを作成
Excel.Visible = True
Stop
Debug.Print(Excel.Version)
Sheet = Book.Worksheets(1) '最初のワークシートを選択
・・・
>それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
このご指摘が当たっているようです。
さて、
さて、
しばらく考えましたが、原因はわかったものの、
Dim Excel As New Microsoft.Office.Interop.Excel.Application
の部分で xl2003 が作成されるようにする方法がわかりません。
「複数のバージョンの Excel を同一環境にインストール」をやめるべきでしょうか。
どんなものなのでしょう。
「
>初級講座「第44回 周辺にあるテクノロジ」4.Excelの操作 のコードの途中でエラーになります。
の執筆は rucio(るきお)さんで、
>http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=242
にあるのが、neptune さんの投稿ですね。
」
サイト作成者=rucioさんでありましたか。
勘違いいたしました。ご指摘ありがとうございます。
>まず、エラーが発生するのは、開発環境ですか? 実行環境ですか?
44回までの学習では{開発環境|実行環境}について理解が及んでいるか心もとないのですが、ソリューションエクスプローラを右クリックした「発行(B)...」を実行してできる \bin\Releaceフォルダ内の.exeファイルを実行環境。VB_2008_Expressを立ち上げて操作する環境を開発環境として検証しました。
結果は同様のエラーが発生しました。
「
それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
(あるいは、開発環境のExcelバージョンと、実行環境のExcelバージョンが一致していないとか)
」
!!!ご明察のとおりxl2000 と xl2003をインストールした環境で作業しています。
以下のコードで作成されるブックのバージョンを確認したところxl2000でした。
Dim Excel As New Microsoft.Office.Interop.Excel.Application
Dim Book As Microsoft.Office.Interop.Excel.Workbook
Dim Sheet As Microsoft.Office.Interop.Excel.Worksheet
'▼前処理
Book = Excel.Workbooks.Add '新規ワークブックを作成
Excel.Visible = True
Stop
Debug.Print(Excel.Version)
Sheet = Book.Worksheets(1) '最初のワークシートを選択
・・・
>それから、複数のバージョンの Excel を同一環境にインストールしていませんか?
このご指摘が当たっているようです。
さて、
さて、
しばらく考えましたが、原因はわかったものの、
Dim Excel As New Microsoft.Office.Interop.Excel.Application
の部分で xl2003 が作成されるようにする方法がわかりません。
「複数のバージョンの Excel を同一環境にインストール」をやめるべきでしょうか。
どんなものなのでしょう。
投稿者 (削除されました)  ()
投稿日時
2009/5/8 22:29:00
(削除されました)
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2009/5/8 22:36:33
> 44回までの学習では{開発環境|実行環境}について理解が及んでいるか心もとないのですが
たとえば、作成した EXE を他の人に使ってもらう場合、その人の使う環境と、
yamaV1.02β さんの開発環境とでは、OS あるいはインストールされているソフト等が
異なりますよね(Excelのバージョン等)。
この場合、開発環境とは「yamaV1.02β さんの環境」を指し、
実行環境とは「EXE を実際に起動させる環境」を指しています。
もし、開発した PC のみで実行させるのであれば、開発環境=実行環境 という事になります。
> Dim Excel As New Microsoft.Office.Interop.Excel.Application
> の部分で xl2003 が作成されるようにする方法がわかりません。
一つの環境に複数の Excel バージョンがインストールされていた場合、
それぞれのバージョンを切り替えて呼び出す事はできません。レジストリ登録の都合上、
どうしても後からインストールした方のライブラリの影響力が強くなってしまうためです。
混在環境におけるバージョン指定呼び出しがどうしても必要であれば、Excel をフルパス指定で
起動した上で、そのインスタンスをそれを GetObject 等を通じて取得するという手法がありますが、
基本的にはバージョン混在を避けるべきでしょう。
以下、少し専門的な話になります。
> Microsoft Excel 11.0 Object Libraryに参照設定して
これは、Excel 2003 のライブラリを参照する事になります。
(00020813-0000-0000-C000-000000000046 ; version 1.5)
> 参照を Microsoft Excel 9.0 Object Library に変更してみたところ
こちらは、Excel 2000 のライブラリですね。
(00020813-0000-0000-C000-000000000046 ; version 1.3)
で、ここからが本題。
> Book.SaveAs("C:\VB\Test.xls")
Workbook.SaveAs メソッドの定義は、2003 と 2000 とでは異なります。
Workbook.SaveAs は、Excel のバージョンによって、以下の3種のメソッド定義が存在します。
引数の数、DispId、メソッド名の違いに着目してみてください。
Excel 97, 2000 が持っているのは、[1] のみです。
Excel 2002, 2003, 2007 が持っているのは、[2] と [3] です。
そのため、たとえば Excel 2003 のライブラリを参照設定して、
> Book.SaveAs("C:\VB\Test.xls")
というコードを書き、それを Excel 2000 環境で実行した場合、
メソッドの定義が異なるため、呼び出しが失敗する事になります。
なお、2003 ライブラリで [3] を呼び出すコードや、
2000 ライブラリで [1] を呼びだすコードを書いた場合は、
Excel 2000以下の環境 …… [1] のメソッドが呼び出される。
Excel 2002以上の環境 …… [3] のメソッドが呼び出される。
となり、そのまま動作する可能性があります。
一方、レイトバインド(あるいは CallByName で呼び出した場合)に成功した件についてです。
まず、SaveAs メソッドは、引数がすべて省略可能(Optional)になっています。
レイトバインドでは、実行時にメソッド名からの名前解決が行われますので、
> Book.SaveAs("C:\VB\Test.xls")
というコードを呼び出した場合、
Excel 2000以下の環境 …… [1] のメソッドが呼び出される。
Excel 2002以上の環境 …… [2] のメソッドが呼び出される。
という呼び分けが行われる事になります。
なお、レイトバインドでの呼び出しを行うために、必ずしもすべてを
> Dim Excel As Object
> Excel = CreateObject("Excel.Application")
のように Object で記述する必要はありません。
必要な部分のみをレイトバインドすれば良いのであれば、たとえば
CObj(Book).SaveAs("C:\VB\Test.xls")
あるいは
Dim oBook As Object = Book
oBook.SaveAs("C:\VB\Test.xls")
あるいは、
CallByName(Book, "SaveAs", CallType.Method, "C:\VB\Test.xls")
といった、部分的な記述を行うだけでも効果があります。
----
なお、このような問題は SaveAs に限った事ではありません。Excel のメソッドやプロパティは、
バージョンが異なると引数の数が増加したり、以前は Sub だったメソッドが Function に
変更されるなどの変更が重ねられてきています。
そのため Excel を利用する場合には、Excel のバージョンを一つに絞っておかないと、
思わぬトラブルの元となってしまうことになります。
どうしてもバージョン混在での開発が必要なら、各 Excel バージョンのライブラリの違いを
十分に把握できる環境と知識が必要になります。それができないのであれば、
> 「複数のバージョンの Excel を同一環境にインストール」をやめるべき
だと思いますよ。
たとえば、作成した EXE を他の人に使ってもらう場合、その人の使う環境と、
yamaV1.02β さんの開発環境とでは、OS あるいはインストールされているソフト等が
異なりますよね(Excelのバージョン等)。
この場合、開発環境とは「yamaV1.02β さんの環境」を指し、
実行環境とは「EXE を実際に起動させる環境」を指しています。
もし、開発した PC のみで実行させるのであれば、開発環境=実行環境 という事になります。
> Dim Excel As New Microsoft.Office.Interop.Excel.Application
> の部分で xl2003 が作成されるようにする方法がわかりません。
一つの環境に複数の Excel バージョンがインストールされていた場合、
それぞれのバージョンを切り替えて呼び出す事はできません。レジストリ登録の都合上、
どうしても後からインストールした方のライブラリの影響力が強くなってしまうためです。
混在環境におけるバージョン指定呼び出しがどうしても必要であれば、Excel をフルパス指定で
起動した上で、そのインスタンスをそれを GetObject 等を通じて取得するという手法がありますが、
基本的にはバージョン混在を避けるべきでしょう。
以下、少し専門的な話になります。
> Microsoft Excel 11.0 Object Libraryに参照設定して
これは、Excel 2003 のライブラリを参照する事になります。
(00020813-0000-0000-C000-000000000046 ; version 1.5)
> 参照を Microsoft Excel 9.0 Object Library に変更してみたところ
こちらは、Excel 2000 のライブラリですね。
(00020813-0000-0000-C000-000000000046 ; version 1.3)
で、ここからが本題。
> Book.SaveAs("C:\VB\Test.xls")
Workbook.SaveAs メソッドの定義は、2003 と 2000 とでは異なります。
Workbook.SaveAs は、Excel のバージョンによって、以下の3種のメソッド定義が存在します。
引数の数、DispId、メソッド名の違いに着目してみてください。
'★ SaveAs メソッド[1] '★ SaveAs メソッド[2] '★ SaveAs メソッド[3]
<DispId(&H11C)> _ <DispId(&H785)> _ <DispId(&H11C), EditorBrowsable(Never)> _
Sub SaveAs( Sub SaveAs( Sub _SaveAs(
Filename, Filename, Filename,
FileFormat, FileFormat, FileFormat,
Password, Password, Password,
WriteResPassword, WriteResPassword, WriteResPassword,
ReadOnlyRecommended, ReadOnlyRecommended, ReadOnlyRecommended,
CreateBackup, CreateBackup, CreateBackup,
AccessMode, AccessMode, AccessMode,
ConflictResolution, ConflictResolution, ConflictResolution,
AddToMru, AddToMru, AddToMru,
TextCodepage, TextCodepage, TextCodepage,
TextVisualLayout) TextVisualLayout, TextVisualLayout)
Local)
Excel 97, 2000 が持っているのは、[1] のみです。
Excel 2002, 2003, 2007 が持っているのは、[2] と [3] です。
そのため、たとえば Excel 2003 のライブラリを参照設定して、
> Book.SaveAs("C:\VB\Test.xls")
というコードを書き、それを Excel 2000 環境で実行した場合、
メソッドの定義が異なるため、呼び出しが失敗する事になります。
なお、2003 ライブラリで [3] を呼び出すコードや、
2000 ライブラリで [1] を呼びだすコードを書いた場合は、
Excel 2000以下の環境 …… [1] のメソッドが呼び出される。
Excel 2002以上の環境 …… [3] のメソッドが呼び出される。
となり、そのまま動作する可能性があります。
一方、レイトバインド(あるいは CallByName で呼び出した場合)に成功した件についてです。
まず、SaveAs メソッドは、引数がすべて省略可能(Optional)になっています。
レイトバインドでは、実行時にメソッド名からの名前解決が行われますので、
> Book.SaveAs("C:\VB\Test.xls")
というコードを呼び出した場合、
Excel 2000以下の環境 …… [1] のメソッドが呼び出される。
Excel 2002以上の環境 …… [2] のメソッドが呼び出される。
という呼び分けが行われる事になります。
なお、レイトバインドでの呼び出しを行うために、必ずしもすべてを
> Dim Excel As Object
> Excel = CreateObject("Excel.Application")
のように Object で記述する必要はありません。
必要な部分のみをレイトバインドすれば良いのであれば、たとえば
CObj(Book).SaveAs("C:\VB\Test.xls")
あるいは
Dim oBook As Object = Book
oBook.SaveAs("C:\VB\Test.xls")
あるいは、
CallByName(Book, "SaveAs", CallType.Method, "C:\VB\Test.xls")
といった、部分的な記述を行うだけでも効果があります。
----
なお、このような問題は SaveAs に限った事ではありません。Excel のメソッドやプロパティは、
バージョンが異なると引数の数が増加したり、以前は Sub だったメソッドが Function に
変更されるなどの変更が重ねられてきています。
そのため Excel を利用する場合には、Excel のバージョンを一つに絞っておかないと、
思わぬトラブルの元となってしまうことになります。
どうしてもバージョン混在での開発が必要なら、各 Excel バージョンのライブラリの違いを
十分に把握できる環境と知識が必要になります。それができないのであれば、
> 「複数のバージョンの Excel を同一環境にインストール」をやめるべき
だと思いますよ。
投稿者 yamaV1.02β  (社会人)
投稿日時
2009/5/9 06:07:39
魔界の仮面弁士さん、解説ありがとうございました。
以前よりVBがらみで検索したときに、何度かハンドルをお見かけしておりました。
十分すぎるほど満足な回答をありがとうございます。
スッ、スバラスィ(;´Д`)
以前よりVBがらみで検索したときに、何度かハンドルをお見かけしておりました。
十分すぎるほど満足な回答をありがとうございます。
スッ、スバラスィ(;´Д`)
初級講座「第44回 周辺にあるテクノロジ」4.Excelの操作 のコードの途中でエラーになります。
http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=242
Microsoft Excel 11.0 Object Libraryに参照設定して、コードを実行すると、
「
'▼後処理
Book.SaveAs("C:\VB\Test.xls") '保存
」
の部分で、
「
!COMException はハンドルされませんでした。
サーバーによって例外が返されました。 HRESULT からの例外:0x80010105 (RPC_E_SERVERFAULT)
トラブルシューティングのヒント:
例外のErrorCode プロパティを調べて,COM オブジェクトによって返された HRESULT を判断します。
この例外に関する一般的なヘルプを参照します。
」
エラーが発生しているのは、Book.SaveAs("C:\VB\Test.xls")の箇所のみです。保存先のフォルダは存在しています。保存先を変更してみたてもこのエラーは発生し続けます。
Book.SaveAs("C:\VB\Test.xls")部分をコメントアウトすると、「'Book1'への変更を保存しますか?」とダイアログが表示され、保存したファイルを見るとコートの他の部分の動作は問題なく実行されているようです。
ヘルプを辿ってみましたが、理解がおよばず、先に進めません。
試しに、レイトバインディングにしてみたところ、問題なく動作しました。
'Dim Excel As New Microsoft.Office.Interop.Excel.Application
'Dim Book As Microsoft.Office.Interop.Excel.Workbook
'Dim Sheet As Microsoft.Office.Interop.Excel.Worksheet
↓
Dim Excel As Object
Dim Book As Object
Dim Sheet As Object
Excel = CreateObject("Excel.Application")
また、参照を Microsoft Excel 9.0 Object Library に変更してみたところ、
Dim Excel As New Microsoft.Office.Interop.Excel.Application
Dim Book As Microsoft.Office.Interop.Excel.Workbook
Dim Sheet As Microsoft.Office.Interop.Excel.Worksheet
↑の3行がエラーになったので、
Dim Excel As New Excel.Application
Dim Book As Excel.Workbook
Dim Sheet As Excel.Worksheet
に変更しまして、問題なく最後まで動作しました。
このエラーでは何が起きているのでしょうか。
どんなものでしょう。