- PR -

C#でエクセル操作

1
投稿者投稿内容
松の陰
会議室デビュー日: 2005/11/05
投稿数: 11
投稿日時: 2005-11-05 17:22
今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を配列にしたらうまくいかないのです・・・)

ショボい質問だとすれば大変申し訳ありませんが、
どなたかご存知の方がいらっしゃいましたらご教授よろしくお願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-05 18:47
引用:

松の陰さんの書き込み (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 の入門サイト
じゃんぬねっと日誌
松の陰
会議室デビュー日: 2005/11/05
投稿数: 11
投稿日時: 2005-11-05 19:22
じゃんぬねっとさんありがとうございます!
じゃんねっとさんの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
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-05 21:06
引用:

松の陰さんの書き込み (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 の入門サイト
じゃんぬねっと日誌
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-11-05 23:18
引用:

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



ジェネリックスが使えれば、VC のコンパイラ COM サポート機能の1つである _com_ptr_t と同じような「スマートポインタ」を実装できるので、少しはラクになるはずなんですが。。。
松の陰
会議室デビュー日: 2005/11/05
投稿数: 11
投稿日時: 2005-11-05 23:19
ソースの表示までしていただけるとは
本当にご丁寧にありがとうございます。
ただ少し疑問な点もあるのですが、
参照の開放をしないと適切な終了ができないとのことでしたが、
パッと見まったく問題なく起動・終了している気もするのですが。
目に見えないところで問題が起こっているのでしょうか?

また私は下記のHPのソースを参考にしてプログラムを組み立てたのですが、
こちらにあるソースにも参照の開放らしきものがありません。
これは何か特別な処理を施しているのでしょうか?
質問ばかりですいません・・。
http://support.microsoft.com/default.aspx?scid=kb;ja;302096
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-05 23:52
引用:

松の陰さんの書き込み (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 の入門サイト
じゃんぬねっと日誌
松の陰
会議室デビュー日: 2005/11/05
投稿数: 11
投稿日時: 2005-11-06 15:58
度々ご丁寧にありがとうございます。

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

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

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

スキルアップ/キャリアアップ(JOB@IT)