C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: COMオブジェクトを使用したEXCEL操作で、HRESULT


(過去ログ 10 を表示中)

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■1541 / inTopicNo.1)  COMオブジェクトを使用したEXCEL操作で、HRESULT
  
□投稿者/ ぴんちはちゃんす (1回)-(2007/02/27(Tue) 15:22:11)

分類:[C# (Windows)] 

初めて投稿させて頂きます。

COMオブジェクトを使用して、EXCELを出力している機能で、
OSがXPの場合、正常に動作するのですが、Win2000(SP4)の場合、

HRESULTからの例外です:0x800A03EC。

というエラーが発生します。

使用しているライブラリはMicrosoft Excel 9.0 Object Libraryです。

ソースを下記に添付致します。
宜しくお願い致します。

Excel.Application xlApplication  = null;
Excel.Workbooks xlWorkbooks = null;
Excel._Workbook xlWorkbook = null;
Excel.Sheets xlSheets = null;
Excel._Worksheet xlWorkSheet = null;
Excel.Range xlRange = null;
// Excel作成
try
{
    // 新しいbookを作る
    try
    {
        xlApplication = new Excel.Application();                      // Excelアプリケーション 
        xlApplication.DisplayAlerts = false;

        try
        {
            xlWorkbooks = xlApplication.Workbooks;

            try
            {
                xlWorkbook = null;

                if (rdo_Syain.Checked == true)
                {
                    xlWorkbook = xlWorkbooks.Add(CMArea.NEXTUserFileTemplatePath);
                }
                else if (rdo_Sosiki.Checked == true)
                {
                    xlWorkbook = xlWorkbooks.Add(CMArea.NEXTGroupFileTemplatePath);
                }
                else if (rdo_Yaku.Checked == true)
                {
                    xlWorkbook = xlWorkbooks.Add(CMArea.NEXTPostFileTemplatePath);
                }

                try
                {
                    xlSheets = xlWorkbook.Worksheets;

                    try
                    {
                        xlWorkSheet = (Excel._Worksheet)xlSheets.get_Item(1);
                        xlRange = null;

                        try
                        {
                            // 範囲を獲得
                            long lRowCnt = insData.GetLength(0);
                            long lColCnt = insData.GetLength(1);
                            xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
                            xlRange = xlRange.get_Resize(lRowCnt, lColCnt);

                            // 値を代入
                            xlRange.Value = insData;

                            //保存
                            xlWorkbook.SaveAs(txt_FilePath1.Text,
                                              Excel.XlFileFormat.xlWorkbookNormal,
                                              Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                              Excel.XlSaveAsAccessMode.xlNoChange,
                                              Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                        }
                        finally
                        {
                            if (xlRange != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);          //COM オブジェクト解放
                        }
                    }
                    finally
                    {
                        if (xlWorkSheet != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet);  //COM オブジェクト解放
                    }
                }
                finally
                {
                    if (xlSheets != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets);        //COM オブジェクト解放
                }
            }
            finally
            {
                try
                {
                    xlWorkbook.Close(Missing.Value, Missing.Value, Missing.Value);
                }
                finally
                {
                    if (xlWorkbook != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook);    //COM オブジェクト解放
                }
            }
        }
        finally
        {
            try
            {
                xlWorkbooks.Close();
            }
            finally
            {
                if (xlWorkbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbooks);  //COM オブジェクト解放
            }
        }
    }
    finally
    {
        try
        {
            // Excel を終了する
            xlApplication.Quit();
        }
        finally
        {
            if (xlApplication != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication); //COM オブジェクト解放
        }

    }
    bRtn = true;
}
catch (Exception exc)
{
    MessageBox.Show("Excel作成時にエラーが発生しました。\n\n" + exc.Message
                   , lbl_Title.Text , MessageBoxButtons.OK, MessageBoxIcon.Error);
    bRtn = false;
}

引用返信 編集キー/
■1542 / inTopicNo.2)  Re[1]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Blue (269回)-(2007/02/27(Tue) 15:27:44)
2007/02/27(Tue) 15:32:57 編集(投稿者)

とりあえず、どこでエラーが発生しているのか特定できますか?
また

insData

に関して何も触れられていないようですが、何者なんでしょうか?


>OSがXPの場合、正常に動作するのですが、Win2000(SP4)の場合、
これは同じバージョンのExcelを利用していますか?
引用返信 編集キー/
■1544 / inTopicNo.3)  Re[2]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (2回)-(2007/02/27(Tue) 15:41:24)
早速の返信ありがとうございます。


> とりあえず、どこでエラーが発生しているのか特定できますか?
開発環境がWinXPなので、特定できてはおりませんが、
このソースのどこかでエラーが発生していることは分かっています。
Win2000環境を作成して、エラー箇所を特定してみます。

> また
>
> insData
>
> に関して何も触れられていないようですが、何者なんでしょうか?>

すいません。
引数で、string[,] insData として渡ってきます。


> >OSがXPの場合、正常に動作するのですが、Win2000(SP4)の場合、
> これは同じバージョンのExcelを利用していますか?

同じバージョンです。ちなみに共にEXCEL2000(SP3)を使用しております。

宜しくお願い致します。

引用返信 編集キー/
■1547 / inTopicNo.4)  Re[3]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (3回)-(2007/02/27(Tue) 15:55:09)
エラーの場所が特定できました。

// 範囲を獲得
long lRowCnt = insData.GetLength(0);
long lColCnt = insData.GetLength(1);
xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
→ xlRange = xlRange.get_Resize(lRowCnt, lColCnt);

上記の "→" でエラーが発生していました。
OSに依存するものなのでしょうか?
引用返信 編集キー/
■1549 / inTopicNo.5)  Re[4]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ 未記入 (31回)-(2007/02/27(Tue) 16:00:30)
No1547 (ぴんちはちゃんす さん) に返信
> エラーの場所が特定できました。
>
> // 範囲を獲得
> long lRowCnt = insData.GetLength(0);
> long lColCnt = insData.GetLength(1);
> xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
> → xlRange = xlRange.get_Resize(lRowCnt, lColCnt);
>
> 上記の "→" でエラーが発生していました。
> OSに依存するものなのでしょうか?

そもそもここが、WindowsやOfficeのバージョンがどうであれまずいです。
xlRangeの参照が解放される前に、また突っ込み直しているのはダメです。
引用返信 編集キー/
■1550 / inTopicNo.6)  Re[4]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Blue (270回)-(2007/02/27(Tue) 16:01:16)
No1547 (ぴんちはちゃんす さん) に返信
> エラーの場所が特定できました。
>
> // 範囲を獲得
> long lRowCnt = insData.GetLength(0);
> long lColCnt = insData.GetLength(1);
> xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
> → xlRange = xlRange.get_Resize(lRowCnt, lColCnt);
>
> 上記の "→" でエラーが発生していました。
ちなみに、このときのlRowCnt,lColCntはいくつになっていましたか?


それと、多分この書き方だと、Excelのプロセスが残っちゃうでしょう。
(xlWorkSheet.get_Range("A3", Type.Missing);で取得したものを上書きしちゃっているので
ReleaseComObjectできない)
引用返信 編集キー/
■1552 / inTopicNo.7)  Re[5]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Blue (271回)-(2007/02/27(Tue) 16:03:57)
No1549 (未記入 さん) に返信
>xlRangeの参照が解放される前にまた突っ込み直しているのはダメです。
そういうことなんですね。
やったことないのでそんな動きになるのは知らなかったです。


# 私ならば、なるべく get_Range で済ませるように書くようにする。
# (強引に RC 形式から A1形式に文字列を作る。)
引用返信 編集キー/
■1555 / inTopicNo.8)  Re[6]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ 未記入 (33回)-(2007/02/27(Tue) 16:19:32)
No1552 (Blue さん) に返信
> そういうことなんですね。
> やったことないのでそんな動きになるのは知らなかったです。

環境によっては問題にならないとは思いますけどね。

> # 私ならば、なるべく get_Range で済ませるように書くようにする。
> # (強引に RC 形式から A1形式に文字列を作る。)

私も同じです。get_Resizeは使わない方が良いです。
でも、get_Rangeもあまり推奨できたものじゃないので。
プロパティのRangeを通した方がたぶんいいです。

VBA自体はあんまり詳しくないけど。
引用返信 編集キー/
■1559 / inTopicNo.9)  Re[5]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (4回)-(2007/02/27(Tue) 16:30:40)
No1550 (Blue さん) に返信
>>エラーの場所が特定できました。
>>
>> // 範囲を獲得
>> long lRowCnt = insData.GetLength(0);
>> long lColCnt = insData.GetLength(1);
>> xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
>> → xlRange = xlRange.get_Resize(lRowCnt, lColCnt);
>>
>>上記の "→" でエラーが発生していました。
> ちなみに、このときのlRowCnt,lColCntはいくつになっていましたか?

466, 5になっています。

> それと、多分この書き方だと、Excelのプロセスが残っちゃうでしょう。
> (xlWorkSheet.get_Range("A3", Type.Missing);で取得したものを上書きしちゃっているので
> ReleaseComObjectできない)

タスクマネージャーを観察してますけど、プロセスは残ってないように思えます。
書き方がまずいんですね。。。

上書きしないように、
xlRangeと同じ定義をしたxlRangeValを宣言して以下のようにしてみました。

xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
xlRangeVal = xlRange.get_Resize(lRowCnt, lColCnt);

しかし、get_Resizeでエラーになります。
そういう問題じゃないんですかね・・・?
引用返信 編集キー/
■1560 / inTopicNo.10)  Re[5]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (6回)-(2007/02/27(Tue) 16:42:01)
No1559で Blue さんに返信した内容と同じで恐縮ですが、

上書きしないように、
xlRangeと同じ定義をしたxlRangeValを宣言して以下のようにしてみました。

xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
xlRangeVal = xlRange.get_Resize(lRowCnt, lColCnt);

しかし、get_Resizeでエラーになります。
そういう問題じゃないんですかね・・・?

引用返信 編集キー/
■1562 / inTopicNo.11)  Re[6]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Blue (274回)-(2007/02/27(Tue) 16:50:40)
No1560 (ぴんちはちゃんす さん) に返信
> しかし、get_Resizeでエラーになります。
> そういう問題じゃないんですかね・・・?
まさかとは思うけど、結合セルはありませんよね?
引用返信 編集キー/
■1563 / inTopicNo.12)  Re[7]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (7回)-(2007/02/27(Tue) 16:57:12)
No1562 (Blue さん) に返信
> ■No1560 (ぴんちはちゃんす さん) に返信
>>しかし、get_Resizeでエラーになります。
>>そういう問題じゃないんですかね・・・?
> まさかとは思うけど、結合セルはありませんよね?

はい、ありません。
関係ありませんが、WEB徘徊をしていると、
私と同じようにrangeに重複している人たちがたくさんいましたwww。
引用返信 編集キー/
■1565 / inTopicNo.13)  Re[8]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ 未記入 (34回)-(2007/02/27(Tue) 17:00:59)
No1563 (ぴんちはちゃんす さん) に返信
> はい、ありません。
> 関係ありませんが、WEB徘徊をしていると、
> 私と同じようにrangeに重複している人たちがたくさんいましたwww。

いるでしょうね。ここの管理人さんがあれだけ注意を促していてもまだ@ITには湧いてきていますから。
で、resizeは使わない方がいいですよ。Office PIAって使えないメンバもある上に、使えても特定環境化でHRESULTからの例外が帰る場合もあります。
後者の場合は実装の問題でないこともありますゆえ。
引用返信 編集キー/
■1567 / inTopicNo.14)  Re[1]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ よねKEN (8回)-(2007/02/27(Tue) 17:03:20)
よねKEN さんの Web サイト
> // 範囲を獲得
> long lRowCnt = insData.GetLength(0);
> long lColCnt = insData.GetLength(1);
> xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
> xlRange = xlRange.get_Resize(lRowCnt, lColCnt);

はずしているかもしれませんが、lRowCnt, lColCntがlong型なのが気になります。
C#のlong型(8バイト)に対応するExcel VBAの型はないのでどのようにマーシャリングされるのだろうか?
という疑問がふと沸きました。

Resizeプロパティの両引数はVariant型ですが、その中に入るのはExcelVBA上に存在する型だけですから、
8バイト整数はないので、Currency型に解釈されるのか、CDec関数でのみ作成できる十進型と解釈されるのか、
あるいはExcelVBAのLong型(4バイト)として、上位4バイトは闇に葬られるのか?読めません。

xlRange = xlRange.get_Resize((int)lRowCnt, (int)lColCnt);
としてみるとどうでしょうか?

引用返信 編集キー/
■1571 / inTopicNo.15)  Re[2]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ ぴんちはちゃんす (8回)-(2007/02/27(Tue) 17:26:23)
No1567 (よねKEN さん) に返信
>> // 範囲を獲得
>> long lRowCnt = insData.GetLength(0);
>> long lColCnt = insData.GetLength(1);
>> xlRange = xlWorkSheet.get_Range("A3", Type.Missing);
>> xlRange = xlRange.get_Resize(lRowCnt, lColCnt);
>
> はずしているかもしれませんが、lRowCnt, lColCntがlong型なのが気になります。
> C#のlong型(8バイト)に対応するExcel VBAの型はないのでどのようにマーシャリングされるのだろうか?
> という疑問がふと沸きました。
>
> Resizeプロパティの両引数はVariant型ですが、その中に入るのはExcelVBA上に存在する型だけですから、
> 8バイト整数はないので、Currency型に解釈されるのか、CDec関数でのみ作成できる十進型と解釈されるのか、
> あるいはExcelVBAのLong型(4バイト)として、上位4バイトは闇に葬られるのか?読めません。
>
> xlRange = xlRange.get_Resize((int)lRowCnt, (int)lColCnt);
> としてみるとどうでしょうか?

おおっ?!通りました!
ありがとうございました。

最終的には、

// 範囲を獲得
int iRowCnt = insData.GetLength(0);
int iColCnt = insData.GetLength(1);
xlRange = xlWorkSheet.get_Range("A3", Type.Missing).get_Resize(iRowCnt, iColCnt);

と致しました。long型が悪さしていたようですね…。
long → int に変更し、
get_Range、get_Resizeを同時に実行するようにすれば、
プロセス残の心配もなくなるかなと思っております。

ですが、あまりいい実装ではないようなので、
他の実装方法を考えていこうと思います。

皆様、ありがとうございました。


解決済み
引用返信 編集キー/
■1573 / inTopicNo.16)  Re[9]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Blue (276回)-(2007/02/27(Tue) 17:33:36)
2007/02/27(Tue) 17:34:22 編集(投稿者)

>get_Range、get_Resizeを同時に実行するようにすれば、
>プロセス残の心配もなくなるかなと思っております。
これはだめでしょう。

基本的に . が2つ横に並ぶようなのは暗黙的にCOMオブジェクト(?)を取得しているので
別々に分けないといけないことになります。
(暗黙的に取得したものはReleaseComObjectできない)


Resize,Offset,Cellsと便利なものがあるけと、オブジェクトの管理が面倒なので
なるべーく、Rangeで取れるように文字列を変換させる、、、と。
解決済み
引用返信 編集キー/
■1583 / inTopicNo.17)  Re[2]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ 未記入 (36回)-(2007/02/27(Tue) 22:27:41)
No1567 (よねKEN さん) に返信
> はずしているかもしれませんが、lRowCnt, lColCntがlong型なのが気になります。

あー見逃していました。
引用返信 編集キー/
■1626 / inTopicNo.18)  Re[3]: COMオブジェクトを使用したEXCEL操作で、HRESULT
□投稿者/ Atata!! (1回)-(2007/02/28(Wed) 23:21:36)
Atata!!@COM総合研究所です。

> はずしているかもしれませんが、lRowCnt, lColCntがlong型なのが気になります。
> C#のlong型(8バイト)に対応するExcel VBAの型はないのでどのようにマーシャリングされるのだろうか?

誤解が生じるといかんので・・・
Windows2000でも、64ビット整数型を保持するVARIANTのマーシャリングは正常に行われます。

“Windows2000以前ではVariantChangeTypeはVT_I8を処理できない”
ことが、この問題の原因であると私は考えています。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -