none
アプリからのExcel出力に於いて、Excel 2007 ではエラーとなり動作しない。 RRS feed

  • 質問

  • いつもお世話になります。
    解決の糸口が見つからず、質問させて頂きます。

    参照にMicrosoft Excel 11.0 Object Library を追加して、アプリケーションの
    中からエクセルシート(*.xls)を出力しています。

    皆様に色々と教えて頂きなから手元の開発環境では一通り意図した通りに出力できる
    ようになったのですが、他の環境で少々問題が出てきました。
    手元の環境は、OS:Windows7 OR Windows XP + Excel2003 です。

    実行ファイルを OS:Windows XP + Excel2007 の環境で動かして Excel File を

    book.SaveAs(filePath, XlFileFormat.xlExcel9795, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                        XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                       
    で、保存する段階で ex.Message に「HRESULT からの例外、0x800A03EC」が
    帰ってきます。

    このエラーに関する記述を調べると沢山見つかるのですが、知識不足のため何れも
    解決に繋がるヒントに到達できません。

    Excel2003 でOKで Excel2007 にすると「HRESULT からの例外、0x800A03EC」が出る
    場合は、ここを確認すべき・・・ 見たいな事を教えていただけないかなと投稿させて
    頂きました。

    どの辺りから手を付けて良いのか見当が付かず、困っています。
    皆さん、どうかよろしくお願いいたします。

    2010年8月17日 14:29

回答

  • book.SaveAs(filePath, XlFileFormat.xlExcel9795, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                        XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    すごく残念なのですが、xlExcel9795がなぜかExcel 2007ではつかえなくて、かわりにxlExcel8などを指定します。
    しかし、こちらは、2007よりも前のバージョンじゃ使えないため、バージョンによって振り分ける必要があります。
    困ったもんですorz

    XlFileFormat Enumeration [Excel 2007 Developer Reference]
    http://msdn.microsoft.com/en-us/library/bb241279(v=office.12).aspx
    *下部コメントをご覧ください。

    2010年8月17日 15:41
  • Chuki さん、早速のアドバイス有難うございます。

    まず、私の環境でソースを書き直してみようと試みたのですが、教えて頂いた
    【xlExcel8】がインテリセンスに表示されません。

    ご存じのとおり、Office 2007がインストールされたマシンでは、Microsoft Excel 11.0 Object Libraryと指定してもOffice 2007が上がってきます。
    そのため、引数も各バージョンに合わせたものにする必要があります。基本的には、同じなのですが、割り当て表の中にあったりなかったりするものがあります。
    また、xlExcel9795のように、12の表には載っているのに実際には動かなかったりするものもあります。
    ところで、インテリセンスは11.0の割り当て表に従って作られているので、12用の値は出てきません

    ですので、バージョンによってxlExcel9795などではなく、適宜必要な数字43(=xlExcel9795)を直接渡してください。先ほどは、2007用の割り当て表をリンクしましたので、今度は2003用の割り当て表をつけます。

    Microsoft Excel Constants [Excel 2003 VBA Language Reference]
    http://msdn.microsoft.com/en-us/library/aa221100(office.11).aspx

    手なりのテスト。VS 2005+Office 2003+ Excel 11.0 Object Libraryの組み合わせで作った以下のルーチンが、Office 2007/2010で動作することを確認しました。
    #手なりなので、あんまり異常系とかを考慮していないただのサンプルです。(VB.NETで作成、C#じゃなくてごめんなさいm(_ _)m、ご参考になれば幸いです。)

    Public Class Form1
     Dim objExcel As Excel.Application
     Dim objBooks As Excel.Workbooks
     Dim objBook As Excel.Workbook
    
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     If IsNothing(objExcel) Then
      objExcel = CreateObject("Excel.Application")
      objBooks = objExcel.Workbooks
      objBook = objBooks.Open("c:\test12.xls")
      If CInt(Mid(objExcel.Version, 1, InStr(objExcel.Version, ".") - 1)) > 11 Then
      objBook.SaveAs("c:\temp\test111.xls", 56)'Excel ver.12(2007)以降
      Else
      objBook.SaveAs("c:\temp\test111.xls", 43)'Excel ver.11(2003)以前
    
      End If
     End If
     End Sub
    
     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
     If Not IsNothing(objBook) Then
      objBook.Close()
      ReleaseComObject(objBook)
      objBook = Nothing
      ReleaseComObject(objBooks)
      objBooks = Nothing
      ReleaseComObject(objExcel)
      objExcel = Nothing
     End If
     End Sub
    End Class
    

     

    2010年8月17日 17:58
  •  <p>>ちなみに、「56」に変えたものを Excel2003 の環境で実行すると、これまでとは逆に</p><p>そうですね、この番号はExcel 2003には定義されていないので0x800A03ECが発生します。</p><p>43がExcel 2007に定義されていないためエラーが出るのと同じです。</p>
    
    If CInt(Mid(objExcel.Version, 1, InStr(objExcel.Version, ".") - 1)) > 11 Then
     objBook.SaveAs("c:\temp\test111.xls", 56)'Excel ver.12(2007)以降
     Else
     objBook.SaveAs("c:\temp\test111.xls", 43)'Excel ver.11(2003)以前
    
    

    ベタなVBで申し分かりません。Excel.Applicationオブジェクトから、.よりも前の値を見てバージョン番号を取得し、11(Excel 2003)以前であれば43、12(Office 2007)以上であれば、56を使って保存しています。
    バージョンによって、43と56は排他的になってしまっています。

    ちなみに、Office 2007側は、すでに同盟のファイルが存在して既に開かれているか、アプリが実行しているユーザーに書き込みの権限が割当たっていなかったりしませんか?
    または、Vista以降なのに、Program Files以下などの直接書き込みができないようなエリアに書き込みをしようとしていませんか?
    #特に、Cドライブ直下は、かなりの可能性で書き込めない^^;

    2010年8月18日 5:43
  • > Excel.Applicationオブジェクトから、・・・

    この際、厚かましく質問させて頂きます。

    Excel のバージョンを示す文字列を取り出して、その一部を数値化して判断していると
    言う事でよろしいですね。

    【objExcel.Version】にバージョン番号があるようで、これをC# で取り出す事を試して
    みることにします。

    はい、そうです。"11.0"などとなっています。
    サックリ、Split使った方が楽かもしれませんね^^;

       String verExcel = objExcel.Version;
       String[] ver = verExcel.Split(new Char[]{'.'});
       Debug.WriteLine(ver[0]);
    
    

     

    2010年8月18日 7:16

すべての返信

  • book.SaveAs(filePath, XlFileFormat.xlExcel9795, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                        XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    すごく残念なのですが、xlExcel9795がなぜかExcel 2007ではつかえなくて、かわりにxlExcel8などを指定します。
    しかし、こちらは、2007よりも前のバージョンじゃ使えないため、バージョンによって振り分ける必要があります。
    困ったもんですorz

    XlFileFormat Enumeration [Excel 2007 Developer Reference]
    http://msdn.microsoft.com/en-us/library/bb241279(v=office.12).aspx
    *下部コメントをご覧ください。

    2010年8月17日 15:41
  • Chuki さん、早速のアドバイス有難うございます。

    まず、私の環境でソースを書き直してみようと試みたのですが、教えて頂いた
    【xlExcel8】がインテリセンスに表示されません。

    と言う事で、これまた教えて頂いたURLから関係有りそうな所を探してみました。

    英文で殆ど分からないのですが、Microsoft Excel 12.0 Object Libraryを追加・・
    みたいな事が書いているように見えたので、 これを探しましたが、私の環境では
    関係有りそうなのは、Microsoft Excel 11.0 Object Library と
    Microsoft Excel 5.0オブジェクト ライブラリーのみで 12.0がありません。

    要するに、私の環境ではExcel2007に対応するには不十分なのでしょうか。
    申し遅れましたが、Visual C# Express Edition を使っています。

    その辺りを、もう少しご教授頂けると有り難いのですが、どうか宜しくお願い致し
    ます。

    2010年8月17日 17:16
  • Chuki さん、早速のアドバイス有難うございます。

    まず、私の環境でソースを書き直してみようと試みたのですが、教えて頂いた
    【xlExcel8】がインテリセンスに表示されません。

    ご存じのとおり、Office 2007がインストールされたマシンでは、Microsoft Excel 11.0 Object Libraryと指定してもOffice 2007が上がってきます。
    そのため、引数も各バージョンに合わせたものにする必要があります。基本的には、同じなのですが、割り当て表の中にあったりなかったりするものがあります。
    また、xlExcel9795のように、12の表には載っているのに実際には動かなかったりするものもあります。
    ところで、インテリセンスは11.0の割り当て表に従って作られているので、12用の値は出てきません

    ですので、バージョンによってxlExcel9795などではなく、適宜必要な数字43(=xlExcel9795)を直接渡してください。先ほどは、2007用の割り当て表をリンクしましたので、今度は2003用の割り当て表をつけます。

    Microsoft Excel Constants [Excel 2003 VBA Language Reference]
    http://msdn.microsoft.com/en-us/library/aa221100(office.11).aspx

    手なりのテスト。VS 2005+Office 2003+ Excel 11.0 Object Libraryの組み合わせで作った以下のルーチンが、Office 2007/2010で動作することを確認しました。
    #手なりなので、あんまり異常系とかを考慮していないただのサンプルです。(VB.NETで作成、C#じゃなくてごめんなさいm(_ _)m、ご参考になれば幸いです。)

    Public Class Form1
     Dim objExcel As Excel.Application
     Dim objBooks As Excel.Workbooks
     Dim objBook As Excel.Workbook
    
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     If IsNothing(objExcel) Then
      objExcel = CreateObject("Excel.Application")
      objBooks = objExcel.Workbooks
      objBook = objBooks.Open("c:\test12.xls")
      If CInt(Mid(objExcel.Version, 1, InStr(objExcel.Version, ".") - 1)) > 11 Then
      objBook.SaveAs("c:\temp\test111.xls", 56)'Excel ver.12(2007)以降
      Else
      objBook.SaveAs("c:\temp\test111.xls", 43)'Excel ver.11(2003)以前
    
      End If
     End If
     End Sub
    
     Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
     If Not IsNothing(objBook) Then
      objBook.Close()
      ReleaseComObject(objBook)
      objBook = Nothing
      ReleaseComObject(objBooks)
      objBooks = Nothing
      ReleaseComObject(objExcel)
      objExcel = Nothing
     End If
     End Sub
    End Class
    

     

    2010年8月17日 17:58
  • ↑編集しようとすると画面が崩れるため、別回答で修正させていただきます。
    Office 2003(Ver 11)にあるものではなく、ないものを数字で指定してください。(両方数字でももちろんかまいませんが、インテリセンスがないと面倒ですね^^;)

    (修正前)
    ですので、バージョンによってxlExcel9795などではなく、適宜必要な数字43(=xlExcel9795)を直接渡してください。先ほどは、2007用の割り当て表をリンクしましたので、今度は2003用の割り当て表をつけます。

    (修正後)
    ですので、バージョンによってxlExcel9795などではなく、適宜必要な数字56(=xlExcel8)を直接渡してください。先ほどは、2007用の割り当て表をリンクしましたので、今度は2003用の割り当て表をつけます。

    2010年8月17日 18:11
  • Chuki さん、サンプルまでお示し頂き、ありがとうございます。

    またまた質問で申し訳ありませんが、頂いたサンプルの動きを確認させて下さい。

    ここでは、まず "c:\test12.xls" をオープンし、このファイルのバージョンを確認し
    た後、バージョンによって object FileFormat を「43」もしくは「56」にセットして
    "c:\temp\test111.xls" に保存する。
    だと思いますが、よろしいでしょうか。

    とすると、私の場合、アプリの中で Excelファイルを生成しているため、これを保存
    するのみとなるわけで、

     book.SaveAs(filePath, XlFileFormat.xlExcel9795, Type.Missing,・・・を
     
     book.SaveAs(filePath, 43, Type.Missing,・・・ もしくは
     book.SaveAs(filePath, 56, Type.Missing,・・・
     
    に変えるだけかなと理解し、

     book.SaveAs("c:\\test.xls", 56, Type.Missing,・・・でやってみましたが・・・

    「43」の場合は、Excel2003 の環境でこれまで通り問題なし。

    「56」の場合は、少し様子が変わりましたが、保存は出来ませんでした。
    即ち、ex.Message が「HRESULT からの例外、0x800A03EC」ではなく、以下に変わりました。

    ファイル'C'にアクセスできません。次のいずれかの理由が考えられます。

    ・ファイル名またはパスが存在しません。
    ・ファイルが他のプログラムによって使用されています。
    ・保存しようとしているブロックと同じ名前のブロックが現在開かれています。

    何れも心当たりがありません(3番目は少し気にはなりますが・・)

    【保存】の行で例外が発生しているので、それまでは問題ないと思っているのですが
    何とも言えません。

    ちなみに、「56」に変えたものを Excel2003 の環境で実行すると、これまでとは逆に
    「HRESULT からの例外、0x800A03EC」が発生しました。
    但し、これを無視して処理を続けると、問題なくファイルは出力されるようです。

    どの辺りを攻めればいいのか見当が付きません。
    お付き合い頂けるようでしたら、どうか宜しくお願い致します。

    2010年8月18日 5:12
  •  <p>>ちなみに、「56」に変えたものを Excel2003 の環境で実行すると、これまでとは逆に</p><p>そうですね、この番号はExcel 2003には定義されていないので0x800A03ECが発生します。</p><p>43がExcel 2007に定義されていないためエラーが出るのと同じです。</p>
    
    If CInt(Mid(objExcel.Version, 1, InStr(objExcel.Version, ".") - 1)) > 11 Then
     objBook.SaveAs("c:\temp\test111.xls", 56)'Excel ver.12(2007)以降
     Else
     objBook.SaveAs("c:\temp\test111.xls", 43)'Excel ver.11(2003)以前
    
    

    ベタなVBで申し分かりません。Excel.Applicationオブジェクトから、.よりも前の値を見てバージョン番号を取得し、11(Excel 2003)以前であれば43、12(Office 2007)以上であれば、56を使って保存しています。
    バージョンによって、43と56は排他的になってしまっています。

    ちなみに、Office 2007側は、すでに同盟のファイルが存在して既に開かれているか、アプリが実行しているユーザーに書き込みの権限が割当たっていなかったりしませんか?
    または、Vista以降なのに、Program Files以下などの直接書き込みができないようなエリアに書き込みをしようとしていませんか?
    #特に、Cドライブ直下は、かなりの可能性で書き込めない^^;

    2010年8月18日 5:43
  • Chuki さん、何度も有り難うございます。


    > ・・・Excel 2007に定義されていないためエラーが出るのと同じです。</p>

    この点については、「ナットク」です。
    後は、端末にインストールされている Excel のバージョンに従い、「43」と「56」を
    使い分ければ良いわけですね。


    > ベタなVBで申し分かりません。・・・

    いえいえ、わざわざソースをお示し頂いているのに、十分に読み切れず申し訳ありません。


    > Excel.Applicationオブジェクトから、・・・

    この際、厚かましく質問させて頂きます。

    Excel のバージョンを示す文字列を取り出して、その一部を数値化して判断していると
    言う事でよろしいですね。

    【objExcel.Version】にバージョン番号があるようで、これをC# で取り出す事を試して
    みることにします。


    > ちなみに、Office 2007側は、すでに同盟のファイルが存在して既に開かれているか、・・・
    > ・・・#特に、Cドライブ直下は、かなりの可能性で書き込めない^^;

    ご指摘の通りでした。
    自分のPCは何処でも書き込める(ようにしている?)ため、気がつきませんでした。
    人様のPCでは確かに "c:\test.xls" に限らず、何でも書き込めませんでした。
    フォルダーを作り、そこに書き込むテストを行った所、旨く書き込めました。

    という事で、このスレッドのテーマについては解決しました、有り難うございました。

    2010年8月18日 6:58
  • > Excel.Applicationオブジェクトから、・・・

    この際、厚かましく質問させて頂きます。

    Excel のバージョンを示す文字列を取り出して、その一部を数値化して判断していると
    言う事でよろしいですね。

    【objExcel.Version】にバージョン番号があるようで、これをC# で取り出す事を試して
    みることにします。

    はい、そうです。"11.0"などとなっています。
    サックリ、Split使った方が楽かもしれませんね^^;

       String verExcel = objExcel.Version;
       String[] ver = verExcel.Split(new Char[]{'.'});
       Debug.WriteLine(ver[0]);
    
    

     

    2010年8月18日 7:16
  • Chuki さん、有り難うございました。

    インストール済み Excel のバージョンを確認して旨く書き込めるようになりました。

    お付き合い下さり、本当に有り難うございました。 問題解決です。

    このスレッドは、クローズさせて頂きます。

    2010年8月18日 7:43
  • ご報告ありがとうございます。
    解決に結びついたのでしたら何よりです。

    できれば、クローズの際には後の人の参考になるように、おおつの井上です。さんが回答になったと感じた返信に対して回答ボタンも押して行ってください。

    以上、よろしくお願いします。

    2010年8月18日 7:54
  • Chuki さん、失礼しました。

    先ほど、ふと見ると 【?】のままで、「あれっ」と思った次第です。

    余りに早く解決したうれしさで「参考になった・・・」を投票しただけで、回答のマークを失念していました。

    今後、気をつけます。 有り難うございました。 今後とも、どうぞ宜しくお願い致します。

    2010年8月18日 8:40