- 締切済み
Worksheetsオブジェクト解放について・・
VB2005からエクセルを操作するプログラムを書いてます。 設計条件として遅延バインディングの制約があります。 以下のコードではプロセスが残ってしまい原因が分かりません。 有識者のご教授をお願いします。 Public Function OpenBook () As Boolean 'エクセルブックを開く関数 Dim exlAppli As Object = Nothing Dim exlBooks As Object = Nothing Dim exlBook As Object = Nothing Dim exlSheets As Object = Nothing Dim exlSheet As Object = Nothing Try exlAppli = CreateObject("Excel.Application") exlAppli.Visible = False exlAppli.DisplayAlerts = False exlBooks = exlAppli.Workbooks exlBook = exlBooks.Add '(新規作成) exlSheets = exlBook.Worksheets For Each exlSheet In exlSheets '処理 ' ・・中略・・ ' 'シート1個づつをオブジェクト解放 Call Me.sub_ReleaseComObject(DirectCast(sht, Object)) Next Catch ex As Exception '例外処理 MessageBox.Show(ex.Message, "サンプル", MessageBoxButtons.OK, MessageBoxIcon.Error) Return False Finally Call Me.sub_ReleaseComObject(DirectCast(exlSheet, Object)) Call Me.sub_ReleaseComObject(DirectCast(exlSheets, Object)) exlBook.Close(False) Call Me.sub_ReleaseComObject(DirectCast(exlBook, Object)) Call Me.sub_ReleaseComObject(DirectCast(exlBooks, Object)) exlAppli.Quit() Call Me.sub_ReleaseComObject(DirectCast(exlAppli, Object)) End Try Return True End Function 事前バインディングなら上記のコードでプロセスは終了します。 ちなみに、勝手な想像ですが、For Each~に何か原因があるのでしょうか。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
試しに、このソースを貼り付けて(sht を exlSheet に修正して)、実行してみましたが、こちらでは正常に終了していますよ。また Next の前の行をコメント化した場合は、プロセスは残ってしまいます。 なお、sub_ReleaseComObject の中では FinalReleaseComObject を利用しました。
>For Each~に何か原因があるのでしょうか その通りですね。exlSheet を逐一 ReleaseComObject してください(sht というのを解放しているようですが)。 あとは中略されている部分にも何か潜んでいる可能性が。。。 ついでですが、全てのオブジェクトは Object 型から派生しているので Object 型にキャストする必要はありません。
補足
回答ありがとう御座います。 >その通りですね。exlSheet を逐一 ReleaseComObject してください(sht というのを解放しているようですが)。 すみません。"sht"は投稿時の誤植です。 正しくは"exlSheet"です。 中略とした部分は原因を特定しやすくするため、あえて何も入れてません。 以下のコードでもプロセスが残ってしまうのです。 For Each exlSheet In exlSheets 'ひとまず何もしないで様子を見るだけ。 Call Me.sub_ReleaseComObject(DirectCast(exlSheet, Object)) Next For Each~では完全なオブジェクト解放は不可能なのでしょうか?
お礼
お礼が遅くなり申し訳ありません。 私なりにいろいろ調べましたら、解放できていないのは WorkSheetsオグジェクト(exlSheets)で、 WorkSheetオブジェクト(exlSheet)ではなかったようです。 参照カウントがどいう順序でインクリメントしていくのか いまいち理解できないですが、今回のコードでは、結果的にexlSheetsの参照カウントが残っていたことが原因でした。 ちなみにFor Each~をFor~Nextに置き換えると、FinalReleaseComObjectを使わずともReleaseComObjectでプロセスは終了します。 (exlSheets、exlSheetともにカウントはゼロになる) FinalReleaseComObjectを使えば手っ取り早く解放は出来ますが、「参照したら解放」という基本プロセスを曖昧にしたままFinalRelease***に逃げるのは悔しいので、もう少し理解が深まるまで勉強したいと思います。 とりあえず確実に解放する方法は分かりましたので、本件は解決済みとさせて頂きます。 ありがとう御座いました。