- - PR -
[ASP.NET]EXCELが終了しない
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2003-01-20 22:30
初めまして。
ASP.NETより、EXCELファイルを作成するアプリを開発しております。 ご質問なのですが、EXCELオブジェクトを作成し、処理した後で、オブジェクトを 破棄しても、EXCELが終了しません。(タスクマネージャでみると残っている) 以下がソースです。 Dim xl As Object xl = CreateObject("Excel.Application") xl.Workbooks.Add() ・・・Sheetの操作 xl.Application.DisplayAlerts = False xl.ActiveWorkbook.SaveAs(FileName:=wkpath & wkexcelnm) xl.Quit() xl.Application.DisplayAlerts = True xl = Nothing よくわからないまま、最後に GC.Collect() を入れてみましたが、EXCELが終了 しませんでした。ご存じの方がいらっしゃいましたら、ご教授お願いします。 | ||||
|
投稿日時: 2003-01-21 08:57
エクセルを起動したプログラムが終了すると、終了します。これは、CreateObjectで確保したオブジェクトが、CreateObjectを発行した*スレッド*によって参照されているため、ガベージコレクタがガベージではないと判断しているためと思われます。 「やっぱりわからない、GCの動作」を参考にしてみてください。(直接的なタイトルでなくてすみません) | ||||
|
投稿日時: 2003-01-21 10:47
はじめまして。ご回答ありがとうございます。
「やっぱりわからない、GCの動作」を参考にさして頂き、プログラムを修正してみました が、まだ、EXCELが終了しないみたいです。気持ち悪いのは、EXCEL出力処理が終了した後 もしばらく(10秒位)、EXCELのCPU使用率が100%近い値になっています。 先ほど、ご説明をかなり抜粋しましたので、再度、ご説明さして頂きます。 処理概要 ひな形のEXCELファイルのシート、新しいブックをコピーして、値をセットし新しいブッ クを保存する。 Dim xl As Object Dim booknm as String xl = CreateObject("Excel.Application") xl.Workbooks.Add() booknm = xl.ActiveWorkbook.Name With xl .Workbooks.Open(AppPath & "Report.xls") .Windows("Report.xls").Activate() .Sheets("1-1").Select() .Sheets("1-1").Copy(Before:=.Workbooks(booknm).Sheets(1)) .Workbooks("Report.xls").Close(False) .Application.DisplayAlerts = False .ActiveWorkbook.SaveAs(FileName:="C:\TEST.XLS") .ActiveWorkbook.Close(False) .Application.DisplayAlerts = True .Quit() End With xl = Nothing System.GC.Collect() と言う具合に、教えて頂いたスレッドを参考にし、一部書き換えてみましたが、ダメで した、その他に考えられる手段があれば、ご教授頂ければと思います。 | ||||
|
投稿日時: 2003-01-21 11:16
こんにちは。
私も興味があって試してみたのですが 前出の別スレッド「やっぱりわからない、GCの動作」の最後のJittaさんの書き込みにある「スレッド処理クラスの中でNothingにするだけでなく、スレッド処理クラス自身をNothingしてやらなければいけなかったようです。 」を参考にして作るとうまく開放できました。 具体的には次のようしてみたところExcelが終了されるのをタスクマネージャで確認できました。 Public Class Form1 Inherits System.Windows.Forms.Form +Windows フォーム デザイナで生成されたコード Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim MyTest As New TestClass() MyTest.Test("C:\Test.xls") MyTest = Nothing GC.Collect() End Sub End Class Public Class TestClass Public Function Test(ByVal FileName As String) Dim xl As Object = CreateObject("Excel.Application") xl.Workbooks.Add() xl.ActiveWorkbook.SaveAs(FileName) xl.Quit() End Function End Class | ||||
|
投稿日時: 2003-01-21 11:52
たびたび、申し訳ありません。
ご指摘通り、EXCEL出力部分をクラス可して、試してみましたが、ダメでした。 ちなみに、ASP.NETですので、VB.NETとは少々事情が違うみたいです。 EXCELはIUSR_コンピュータ名のユーザーが使用している事になっています。 | ||||
|
投稿日時: 2003-01-21 12:11
おくちnさん
これです。「スレッド処理クラス自身をNothingしてやらなければいけなかったようです」これがキーなのです。 ご提示のソース中、Object型変数xlを定義したクラスがxlへの参照を保持している間は、xlによって間接的に参照されていたエクセルが「参照されている」と判断されるようなのです。自動変数であるにもかかわらず、プロシージャを抜けただけではxlへの参照は削除されないようです。おそらく、キャッシュのようなものではないかと思います。しかし、再度このプロシージャに制御が移り、CreateObjectによってxlの参照先が更新されると、前に参照していたオブジェクトは「解放」されるようです。 rucioさんのソースを元に説明すると、 Dim MyTest As New TestClass() ...新しいTestClassオブジェクトを生成し、MyTestにそれへの参照を設定します。 MyTest.Test("C:\Test.xls") ...TestClass.Testにはいります。 Dim xl As Object = CreateObject("Excel.Application") ...ここでエクセルのオブジェクトが作られ、xlにそれへの参照が設定されます。 ...操作は省略 xl.Quit() ...エクセルを終了します。 End Function ...ここでxlは自動変数のため消滅し、エクセルオブジェクトへの参照もはずれますが、 ...エクセルオブジェクトを作成したTestClassオブジェクトは存続しています。 ...このため、「TestClassオブジェクトが生成する可能性のあるオブジェクト」 ...としてキャッシュされます。 ...Button1_Clickプロシージャに戻って、 MyTest = Nothing ...これで、上で作ったオブジェクトへの参照がはずれ、 ...TestClassオブジェクトが解放される準備ができました。 GC.Collect() ...GCを強制し、TestClassオブジェクトを解放します。 ...このとき、「TestClassオブジェクトが生成する可能性のあるオブジェクト」も不要になり、 ...エクセルオブジェクトも解放されます。 ※注意※ あくまで私見であり、仕様ではありません。 | ||||
|
投稿日時: 2003-01-21 12:40
ご丁寧なご回答、ありがとうございます。
ご指摘通り、処理をしております。 引用さして頂き、こちらで違う部分を修正致しますと。 Public Class Form1 Inherits System.Web.UI.Page ↑WEB Form +Web フォーム デザイナで生成されたコード Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ↑Page_LoadイベントでEXCELファイルを出力 Dim MyTest As New TestClass() MyTest.Test("C:\Test.xls") ***出力したEXCELファイルをリンク(Aタグ)した画面を表示 MyTest = Nothing GC.Collect() End Sub End Class Public Class TestClass Public Function Test(ByVal FileName As String) Dim xl As Object = CreateObject("Excel.Application") xl.Workbooks.Add() xl.ActiveWorkbook.SaveAs(FileName) xl.Quit() End Function End Class となっております。 | ||||
|
投稿日時: 2003-01-21 13:21
ASP.NETでは何か特段の事情があるのかと思い
こちらでもASP.NETで同様にプログラムを組んでみましたが Excelはきちんと終了できています。 プログラムはおくちnさんのものとまったく同様です。 (リンクを生成する個所も書いてみました。) ただし、ローカル環境でIISを動かして実行しました。 サーバー機にはExcelが入っていないので実験できません……。 |