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

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

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

Re[4]: (Excel)セルへに文字列セット他について


(過去ログ 89 を表示中)

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

■52887 / inTopicNo.1)  (Excel)セルへに文字列セット他について
  
□投稿者/ kaori (4回)-(2010/08/26(Thu) 16:11:16)

分類:[C#] 

こんにちは、毎日暑い日が続きますが、体調を崩さない様にして
頑張ってくださいね。

今日は
1)指定したエクセルシートをアクティブにする方法
2)エクセルのセルに文字をセットする方法
この2点にについてお伺いさせて下さい。

【質問1】
ソース中程に「ctrlSheet.Activate();」と記述したのですが、
「警告1 メソッド 
'Microsoft.Office.Interop.Excel._Worksheet.Activate()' とメソッド以外の’Microsoft.Office.Interop.Excel.DocEvents_Event.Activate' 間があいまいです。
メソッド グループを使用しています。」と出てしまいます。
なぜ警告が出るのでしょうか?
また、正しい記述はどの様なものでしょうか?


【質問2】
ソース内のセルに文字列を入力する方法について、4パターンを自分なりに考え記述
してみました。
それぞれ、セルに文字はセットされるのですが、Excelアプリケーションの終了と解放を
行っても、プロセスに"EXCEL.EXE"が残ってしまいます。
次の3パターンで文字列をセットしてもプロセスに残らない様にするには
どうすればよいのでしょうか?
・Cellsを使ってRangeを取得した後、文字列をセット
・get_Rangeを使って直接文字列をセット
・Cellsを使って直接文字列をセット


(ソース)
    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    Excel.Application ExcelApp = null;
    Excel.Workbooks ExcelBooks = null;
    Excel.Sheets ExcelSheets = null;
    Excel.Workbook CtrlBook = null;
    Excel.Worksheet ctrlSheet = null;
    Excel.Range ctrlRange = null;

    //★【Excelアプリケーション設定】
    ExcelApp = new Excel.Application();
    ExcelApp.DisplayAlerts = false;
    ExcelApp.Visible = true;
                
    //★【ブック設定】
    ExcelBooks = ExcelApp.Workbooks;
    CtrlBook = ExcelBooks.Open("既存のエクセルファイルのパス",
                0,
                false,
                1,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value,
                Missing.Value
                );
                
    //★【シート設定】
    ExcelSheets = CtrlBook.Worksheets;
    ctrlSheet = ExcelSheets["Default"];

    //[×]シートをアクティブにする
    ctrlSheet.Activate();

    //★【セル操作】
    int Pattern = 1;    // ←パターン(0〜3)に変更して検証してみて下さい
    switch (Pattern)
    {
        case 0:
            //[○]get_Rangeを使ってRangeを取得した後、文字列をセット
            ctrlRange = ctrlSheet.get_Range("A2", Missing.Value);
            ctrlRange.Value = "get_Range";
            break;
        case 1:
            //[×]Cellsを使ってRangeを取得した後、文字列をセット
            ctrlRange = ctrlSheet.Cells[1, 1];
            ctrlRange.Value = "Cells";
            break;
        case 2:
            //[×]get_Rangeを使って直接文字列をセット
            ctrlSheet.get_Range("A4", Missing.Value).Value = "直)Range";
            break;
        case 3:
            //[×]Cellsを使って直接文字列をセット
            ctrlSheet.Cells[3, 1].Value = "直)Cels";
            break;
    }

    //★【レンジの解放】
    if (Pattern == 0 || Pattern == 1)
    {
        Marshal.ReleaseComObject(ctrlRange);
        ctrlRange = null;
    }
                
    //★【シート解放】
    Marshal.ReleaseComObject(ctrlSheet);
    ctrlSheet = null;
    Marshal.ReleaseComObject(ExcelSheets);
    ExcelSheets = null;

    //★【ブックの解放】
    Marshal.ReleaseComObject(CtrlBook);
    CtrlBook = null;
    Marshal.ReleaseComObject(ExcelBooks);
    ExcelBooks = null;

    //★【Excelアプリケーションの解放】
    ExcelApp.Quit();
    Marshal.ReleaseComObject(ExcelApp);
    ExcelApp = null;
    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

引用返信 編集キー/
■52888 / inTopicNo.2)  Re[1]: (Excel)セルへに文字列セット他について
□投稿者/ マサヤ (125回)-(2010/08/26(Thu) 17:29:36)
2010/08/26(Thu) 17:32:17 編集(投稿者)

とりあえず、下記で動かしてみました。
Excel.exeが残るのはOpenした後にCloseしないからでは?
Activeのエラーは同じ名前のクラスがあるから明示してください、ってことだと思います。

using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

Microsoft.Office.Interop.Excel.Application ExcelApp = null;
Workbooks ExcelBooks = null;
_Workbook CtrlBook = null;
_Worksheet ctrlSheet = null;
Microsoft.Office.Interop.Excel.Range ctrlRange = null;

//★【Excelアプリケーション設定】
ExcelApp = new Microsoft.Office.Interop.Excel.Application();
ExcelApp.DisplayAlerts = false;
ExcelApp.Visible = true;

//★【ブック設定】
ExcelBooks = ExcelApp.Workbooks;
CtrlBook = (_Workbook)ExcelBooks.Open(@"フルパス",
0,
false,
1,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing
);
//★【シート設定】[1]のところは[シート名]でもOK
ctrlSheet = (_Worksheet)CtrlBook.Worksheets[1];
//シートをアクティブにする
ctrlSheet.Activate();
//★【セル操作】
ctrlRange = ctrlSheet.get_Range("A2", Type.Missing);
ctrlRange.Value2 = "HOGEMASTER";
//★【レンジの解放】
Marshal.ReleaseComObject(ctrlRange);
ctrlRange = null;
CtrlBook.Close(true, Type.Missing, Type.Missing);
//★【シート解放】
Marshal.ReleaseComObject(ctrlSheet);
ctrlSheet = null;
//★【ブックの解放】
Marshal.ReleaseComObject(CtrlBook);
CtrlBook = null;
Marshal.ReleaseComObject(ExcelBooks);
ExcelBooks = null;
//★【Excelアプリケーションの解放】
ExcelApp.Quit();
Marshal.ReleaseComObject(ExcelApp);
ExcelApp = null;
引用返信 編集キー/
■52893 / inTopicNo.3)  Re[2]: (Excel)セルへに文字列セット他について
□投稿者/ kaori (5回)-(2010/08/26(Thu) 23:16:08)
ソースに下を書き忘れていました。
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Reflection;

> Activeのエラーは同じ名前のクラスがあるから明示してください、ってことだと思います。
★Excel._Worksheet ctrlSheet = null;と記述することで警告が出なくなりました。
ありがとうございました。
「_Worksheet」について勉強が必要です(^^;A


> Excel.exeが残るのはOpenした後にCloseしないからでは?
★「CtrlBook.Close(true, Type.Missing, Type.Missing);」が無くても
パターン0で文字列をセットした場合はプロセスに残ること無く、正常に
終了しております。
パターン1〜3の文字列セット方法をご伝授お願いしますorz
・パターン1:Cellsを使ってRangeを取得した後、文字列をセット
・パターン2:get_Rangeを使って直接文字列をセット
・パターン3:Cellsを使って直接文字列をセット


尚、私の環境ではマサヤさんのソースを走らしたところ、
プロセスに"EXCEL.EXE"が残ってしまいます(ノ_`)
引用返信 編集キー/
■52895 / inTopicNo.4)  Re[3]: (Excel)セルへに文字列セット他について
□投稿者/ じゃんぬねっと (10回)-(2010/08/27(Fri) 03:55:10)
No52893 (kaori さん) に返信
>>Activeのエラーは同じ名前のクラスがあるから明示してください、ってことだと思います。
> ★Excel._Worksheet ctrlSheet = null;と記述することで警告が出なくなりました。
> ありがとうございました。
> 「_Worksheet」について勉強が必要です(^^;A

別に _Worksheet の勉強は必要ありません。
私も互換性のために存在している _Worksheet のことはサッパリわかりませんから。
その警告はその変数が参照される前に、明示的に中身が決まっていない (初期化されていない) 時に発せられる警告です。

>>Excel.exeが残るのはOpenした後にCloseしないからでは?
> ★「CtrlBook.Close(true, Type.Missing, Type.Missing);」が無くても
> パターン0で文字列をセットした場合はプロセスに残ること無く、正常に
> 終了しております。

パターン 1 との違いを見れば、Excel プロセスの居残る原因は明確で、
Excel.Range にあたる中間の参照カウントがデクリメントされていないからですね。

COM オブジェクトの参照カウントを解放する
http://jeanne.wankuma.com/tips/csharp/programming/releasecom.html

# 未だにこの手の質問が定期的にあがってくるのは、チョット悲しいかなぁ。
# 5 年前からミニタコタシーロほど回答しているので、検索でいくらでもヒットしそう...
# http://j.mp/aQ187e
#
# よねKENさんも見飽きている質問なんだろうなぁ...
# http://ap.atmarkit.co.jp/bbs/core/fdotnet/12079
引用返信 編集キー/
■52896 / inTopicNo.5)  Re[4]: (Excel)セルへに文字列セット他について
□投稿者/ kaori (6回)-(2010/08/27(Fri) 07:55:27)
おはようございます。じゃんぬねっとさん(^^)
じゃんぬねっとさんとお話が出来て、とても光栄です(^^)

> その警告はその変数が参照される前に、明示的に中身が決まっていない (初期化されていない) 時に発せられる警告です。

★オリジナルソースの
「Excel.Worksheet ctrlSheet = null;」で初期化し
「ctrlSheet = ExcelSheets["Default"];」で中身を
決めていると解釈しているのですが、違うのですね(^^;A トホホホ・・・
ホント無知で申し訳ないですorz


> パターン 1 との違いを見れば、Excel プロセスの居残る原因は明確で、
> Excel.Range にあたる中間の参照カウントがデクリメントされていないからですね。

★正常終了するパターン0とプロセスが残るパターン1を見比べても
両方同じくセル番地をctrlRangeに格納し最後に両パターンとも
Marshal.ReleaseComObject(ctrlRange);
ctrlRange = null;
において、Excel.Rangeの参照カウントをデクリメントしているつもりなのですが、
これまた、私の勘違いなんですね(ノ_`)

パターン0
 ctrlRange = ctrlSheet.get_Range("A2", Missing.Value);
パターン1
 ctrlRange = ctrlSheet.Cells[1, 1];

> # 未だにこの手の質問が定期的にあがってくるのは、チョット悲しいかなぁ。
> # よねKENさんも見飽きている質問なんだろうなぁ...
★心中お察しいたしますorz
ご紹介頂いた記事はこの質問を発信する前にも一通り目は通しました。
VB6の時も同じ事で苦しみ、多数のHPを徘徊してきました。
言語を乗り換え、C#で同じ事で苦しんで藁をも掴む思いです。
foreachでExcelBooksのWorkbookをCloseする処理を書いてみたり、
ExcelApp.Quit→参照カウントのデクリメントの後にGC.Collect();やら
GC.Collect(2);と記述してみたり、けれどプロセスが消えてくれないのです(ノ_`)
ホント申し訳ない気持ちでいっぱいです。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -