VB.NET EXCEL
下記のコードで、アプリケーション実行中 EXCELが起動したままになり
アプリケーション終了時に、EXCELも一緒に終了する
という、タスクマネージャーに残るという動作になります。
どこの COM の扱い方がまずかったのでしょうか?
教えてください。お願いします。
※文字数制限で、SQLコネクション周り、SQL系宣言 エラー処理を消しました。
※EXCEL周りに関してはすべてそのままです。
変数に代入している COMオブジェクトをすべて Marshal.FinalReleaseComObject してもEXCELが終了しないので何かしら COMオブジェクトを見落としていると思うのですが どれだかわかりません。
よろしくお願いします
Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices
Public Class Cls_Print_Excel
Public Sub S_Print_Excel()
'エクセルアクセス用
Dim _xslFile As String = "C:\base.xls"
Dim objExcel As Excel.Application = Nothing
Dim objWorkBook As Excel.Workbook = Nothing
Dim objWorkBooks As Excel.Workbooks = Nothing
Dim xlSheet As Excel.Worksheet = Nothing
Dim xlRange As Excel.Range = Nothing
Dim xlPageSetup As Excel.PageSetup = Nothing
Try
objExcel = New Excel.Application
objWorkBooks = objExcel.Workbooks
objWorkBooks.Open(_xslFile)
objWorkBook = objExcel.ActiveWorkbook
xlSheet = DirectCast(objWorkBook.Worksheets(1), Microsoft.Office.Interop.Excel.Worksheet)
rs = cm.ExecuteReader()
I = 3
Do While rs.Read
Dim AA() As String = {"B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"}
Dim K As Integer
For K = 0 To 11
IN_Range(xlSheet, AA(K) & I.ToString, rs(K).ToString)
Next
xlRange = xlSheet.Range("3:3")
xlRange.Copy()
A = A + Marshal.ReleaseComObject(xlRange)
xlRange = xlSheet.Range(I.ToString & ":" & I.ToString)
xlRange.PasteSpecial( _
Paste:=Microsoft.Office.Interop.Excel.XlPasteType.xlPasteFormats, _
Operation:=Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, _
SkipBlanks:=False, Transpose:=False)
A = A + Marshal.ReleaseComObject(xlRange)
xlRange = xlSheet.Range(I.ToString & ":" & I.ToString)
xlRange = xlRange.EntireRow
xlRange.AutoFit()
A = A + Marshal.ReleaseComObject(xlRange)
xlRange = xlSheet.Range(I.ToString & ":" & I.ToString)
N = 5.5
While True
If CType(xlRange.RowHeight, Double) < N Then
Exit While
Else
N += 5.5
End If
End While
xlRange.RowHeight = N '高さを設定
A = A + Marshal.ReleaseComObject(xlRange)
I += 1 'ループカウンタを積む
Loop
xlPageSetup = xlSheet.PageSetup
xlPageSetup.PrintArea = "B2:M" & (I - 1).ToString
A = A + Marshal.ReleaseComObject(xlPageSetup)
S_filename = System.IO.Path.GetDirectoryName(_xslFile) & Format(Now(), "yyyy-MM-dd-HH-mm-ss") & ".xls"
objWorkBook.SaveAs(S_filename)
objWorkBooks.Close()
A = A + Marshal.ReleaseComObject(objWorkBooks)
objExcel.Quit()
A = A + Marshal.ReleaseComObject(objExcel)
Exit Sub
Catch ex As Exception
Finally
End Try
End Sub
Private Sub IN_Range(ByRef wSheet As Microsoft.Office.Interop.Excel.Worksheet, _
ByVal iCell As String, _
ByVal Value As String)
Dim rng As Excel.Range = wSheet.Range(iCell)
rng.Value = Value
Marshal.FinalReleaseComObject(rng)
rng = Nothing
End Sub
End Class
お礼
お礼が遅くなり申し訳ありません。 私なりにいろいろ調べましたら、解放できていないのは WorkSheetsオグジェクト(exlSheets)で、 WorkSheetオブジェクト(exlSheet)ではなかったようです。 参照カウントがどいう順序でインクリメントしていくのか いまいち理解できないですが、今回のコードでは、結果的にexlSheetsの参照カウントが残っていたことが原因でした。 ちなみにFor Each~をFor~Nextに置き換えると、FinalReleaseComObjectを使わずともReleaseComObjectでプロセスは終了します。 (exlSheets、exlSheetともにカウントはゼロになる) FinalReleaseComObjectを使えば手っ取り早く解放は出来ますが、「参照したら解放」という基本プロセスを曖昧にしたままFinalRelease***に逃げるのは悔しいので、もう少し理解が深まるまで勉強したいと思います。 とりあえず確実に解放する方法は分かりましたので、本件は解決済みとさせて頂きます。 ありがとう御座いました。