QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

C#でエクセル操作

今C#でエクセル操作で、
次のような命令で複数でのセルにエクセル関数の入力を
試みておりますがうまくいきません。

range = xlSheet.get_Range("A1", Missing.Value);
range = range.get_Resize(1, 3);
string[,] input = new string[1, 3];
input[0,0] = "=POWER(1,2)";
input[0,1] = "=POWER(2,2)";
input[0,2] = "=POWER(3,2)";
range.set_Value(Missing.Value, input );

今の場合セルに「1」「4」「9」と表示されれば成功なのですが
「=POWER(1,2)」「=POWER(2,2)」「=POWER(3,2)」
と関数がそのまま表示されてしまうのです。

(複数のセルでなくひとつのセルならば
/string input = "=POWER(4,2)";
range.set_Value(Missing.Value, input );
/
でうまくいくのですが、変数inputを配列にしたらうまくいかないのです・・・)

ショボい質問だとすれば大変申し訳ありませんが、
どなたかご存知の方がいらっしゃいましたらご教授よろしくお願いします。

質問者:松の陰

回答

松の陰さんの書き込み (2005-11-05 17:22) より:

range = xlSheet.get_Range("A1", Missing.Value);

range = range.get_Resize(1, 3);

最初の range で取った参照はどうやって解放するんでしょうか?
もう解放するタイミングがないと思いますが...
COM は必ず変数に参照を取り、然るべきタイミングで解放しましょう。

  COM オブジェクトを解放する

string[,] input = new string[1, 3];

input[0,0] = "=POWER(1,2)";

input[0,1] = "=POWER(2,2)";

input[0,2] = "=POWER(3,2)";

range.set_Value(Missing.Value, input );

配列での関数使用はできなかったような...

________________C# と VB.NET の入門サイト
<a href="http://blogs.wankuma.com/jeanne/" target="
blank">じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

じゃんぬねっとさんありがとうございます!
じゃんねっとさんのHPもかなり参考にさせていただいており
ご本人様からのレス大変光栄です。

・参照の開放について
そんなものがあるとは知りませんでした。教えてくださってありがとうございます。
HPを参考にさせていただいているといいながら見逃してしまっているとは大変失礼しました。

・配列でのエクセル関数使用について
配列の関数使用はできないですか・・、教えていただいてありがとうございます。
かなり強引ですが次のようなやり方で配列を使わずに処理しました。
(もっとスマートなやり方があったらうれしいのですが)

for(int i = 1;i<4;i++)
{
range = xlSheet.get_Range("A" + i.ToString(), Missing.Value);
string input = "=POWER(" + i.ToString() + ",2)";
range.set_Value(Missing.Value, input );

}(これに参照の開放を加えるつもりです。)

いろいろ教えていただいてありがとうございましたm(_ _)m

投稿者:松の陰

編集 履歴 (0)

松の陰さんの書き込み (2005-11-05 19:22) より:

・参照の開放について

そんなものがあるとは知りませんでした。教えてくださってありがとうございます。

というよりは、解放がされていない場合は適切に終了しません。
プロセスが居残ってしまうこともあります。

・配列でのエクセル関数使用について

配列の関数使用はできないですか・・、教えていただいてありがとうございます。

同じ値でないと計算が実行されない仕様になっています。

かなり強引ですが次のようなやり方で配列を使わずに処理しました。

(もっとスマートなやり方があったらうれしいのですが)

そうなるでしょう。
後ほど閲覧する方のために、解放のタイミングについての例を置いておきます。

# それにしても、COM は try 〜 finally、Missing.Value ばかりでつらいですね。




    private void button1_Click(object sender, System.EventArgs e) {
        // 必要な変数は try の外で宣言する
        Excel.Application xlApp = null;

        // COM オブジェクトの解放を保証するために try 〜 finally を使用する
        try {
            xlApp = new Excel.Application();
            xlApp.DisplayAlerts = false;
            xlApp.Visible = true;

            Excel.Workbooks xlBooks = xlApp.Workbooks;

            try {
                Excel.Workbook xlBook = xlBooks.Add(System.Reflection.Missing.Value);

                try {
                    Excel.Sheets xlSheets = xlBook.Worksheets;

                    try {
                        Excel.Worksheet xlSheet = (Excel.Worksheet)xlSheets[1];

                        try {
                            for (int i = 1; i < 4; i++) {
                                Excel.Range xlRange = xlSheet.get_Range("A" + i.ToString(), System.Reflection.Missing.Value);

                                try {
                                    xlRange.Value2 = "=POWER(" + i.ToString() + ", 2)";
                                } finally {
                                    if (xlRange != null) {
                                        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);
                                    }
                                }
                            }
                        } finally {
                            if (xlSheet != null) {
                                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet);
                            }
                        }
                    } finally {
                        if (xlSheets != null) {
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets);
                        }
                    }
                } finally {
                    if (xlBook != null) {
                        try {
                            //xlBook.Close(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
                        } finally {
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook);
                        }
                    }
                }
            } finally {
                if (xlBooks != null) {
                    try {
                        //xlBooks.Close();
                    } finally {
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks);
                    }
                }
            }
        } finally {
            if (xlApp != null) {
                try {
                    //xlApp.Quit();
                } finally {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
                }
            }
        }
    }

________________C# と VB.NET の入門サイト
<a href="http://blogs.wankuma.com/jeanne/" target="
blank">じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

それにしても、COM は try 〜 finally、Missing.Value ばかりでつらいですね。

ジェネリックスが使えれば、VC のコンパイラ COM サポート機能の1つである _com_ptr_t と同じような「スマートポインタ」を実装できるので、少しはラクになるはずなんですが。。。

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

ソースの表示までしていただけるとは
本当にご丁寧にありがとうございます。
ただ少し疑問な点もあるのですが、
参照の開放をしないと適切な終了ができないとのことでしたが、
パッと見まったく問題なく起動・終了している気もするのですが。
目に見えないところで問題が起こっているのでしょうか?

また私は下記のHPのソースを参考にしてプログラムを組み立てたのですが、
こちらにあるソースにも参照の開放らしきものがありません。
これは何か特別な処理を施しているのでしょうか?
質問ばかりですいません・・。
http://support.microsoft.com/default.aspx?scid=kb;ja;302096

投稿者:松の陰

編集 履歴 (0)

松の陰さんの書き込み (2005-11-05 23:19) より:

参照の開放をしないと適切な終了ができないとのことでしたが、

パッと見まったく問題なく起動・終了している気もするのですが。

目に見えないところで問題が起こっているのでしょうか?

Book と Excel.Application だけでも解放されていれば、プロセス上に居残ることはありません。
だからといってオール OK というわけではありません。

また私は下記のHPのソースを参考にしてプログラムを組み立てたのですが、

こちらにあるソースにも参照の開放らしきものがありません。

必ずしも Microsoft の技術文書が合っているわけではありません。
本人さまが降臨してくださったので、渋木先生の Blog へ案内します。(^^)

  「Visual Basic .NET からオートメーションを使用して、Word で新しい文書を作成する方法」トピックに物申す

ちなみに、

  Visual Studio .NET クライアントで自動化した Office アプリケーションが終了しない

ですら当初、ReleaseComObject による解放の記述がありませんでした。
(確か、GC.Collect で試みようとしていたハズ)

________________C# と VB.NET の入門サイト
<a href="http://blogs.wankuma.com/jeanne/" target="
blank">じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

度々ご丁寧にありがとうございます。

そもそもこの問題は前スレでかなり取り上げられてたようですね(_ _;)
そんなことも知らずに常識知らずな質問をしてしまい大変失礼しました。
また、それでもご丁寧にご教授していただいたこと感謝します。
本当にありがとうございました。

ここでいただいたアドバイスとじゃんぬねっとさんのHP、
さらに過去レス(特に「まっく」さんとのやりとり)を参考にしていけば
非力ながらもなんとかなりそうな気がします。

質問につきあっていただきありがとうございました。

投稿者:松の陰

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。