我创建了一个在VB.NET中创建几个Excel电子表格的应用程序
我遇到的问题是我无法让Excel完全退出。
我在隐藏了Excel的VB.NET中创建并填充工作簿,该过程(Microsoft Excel)在任务管理器的后台进程中显示
完成后,我将Excel显示为可见,并且该过程将移至应用程序。
然后当我关闭Excel时,该过程又回到后台进程。
知道我做错了吗?
代码:
Dim oExcel As Excel.Application = Nothing
Dim oWorkbook As Excel.Workbook = Nothing
Dim oWorksheet As Excel.Worksheet = Nothing
Dim oRange As Excel.Range = Nothing
oExcel = CreateObject("Excel.Application")
oExcel.DisplayAlerts = False
oExcel.Visible = False
oWorkbook = oExcel.Workbooks.Add
oWorksheet = oWorkbook.ActiveSheet
'Populate, format, etc.
oWorkbook.SaveAs(Me.txtExportLocation.Text & "\sales.xlsx")
oExcel.Visible = True
oRange = Nothing
oWorksheet = Nothing
oWorkbook = Nothing
ReleaseObject(oExcel)
Public Sub ReleaseObject(ByVal obj As Object)
Dim iValue As Integer = 0
Try
Do
iValue = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While iValue > 0
Catch ex As Exception
RaiseError("", "modGeneral." & "." & System.Reflection.MethodBase.GetCurrentMethod().Name, Err.Number, Err.Description)
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
更新2016年10月31日:
好的,现在我真的很困惑。
使用此代码获取以下建议,我可以通过一个警告让Excel完全退出:
GC.Collect()
GC.WaitForPendingFinalizers()
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorksheet) : oWorksheet = Nothing
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorkbook) : oWorkbook = Nothing
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel) : oExcel = Nothing
但是,我的代码正在创建两个工作簿。除SQL之外,创建每个工作簿的代码是相同的。如果用户勾选chkA,则清理代码不起作用。如果他们检查chkB它确实有效。如果他们同时检查两者,它就不起作用。我在下面列出了完整的代码:
Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
Dim oExcel As Excel.Application = Nothing
Dim oWorkbook As Excel.Workbook = Nothing
Dim oWorksheet As Excel.Worksheet = Nothing
Dim drSystem As SqlClient.SqlDataReader = Nothing
Dim sSQL As String = ""
Dim iRowCount As Integer = 2
Try
If Not Me.chkA.Checked And Not Me.chkB.Checked Then
MsgBox("Select A, B or both before continuing.", vbInformation)
Exit Try
End If
Me.Cursor = Cursors.WaitCursor
Me.lblStatus.Text = "Exporting sales..."
oExcel = CreateObject("Excel.Application")
oExcel.DisplayAlerts = False
oExcel.Visible = False
If Me.chkA.Checked Then
oWorkbook = oExcel.Workbooks.Add
oWorksheet = oWorkbook.ActiveSheet
oWorksheet.Cells(1, 1).Value = "Ship date"
oWorksheet.Cells(1, 2).Value = "Customer"
oWorksheet.Cells(1, 3).Value = "Invoice"
oWorksheet.Cells(1, 4).Value = "Purchase order"
oWorksheet.Cells(1, 5).Value = "Railcar"
oWorksheet.Cells(1, 6).Value = "Weight"
oWorksheet.Cells(1, 7).Value = "Total"
oWorksheet.Cells(1, 8).Value = "Member purchase order"
sSQL = "SELECT FORMAT(i.ship_date, N'MM/dd/yyyy') AS ship_date, "
sSQL += "i.customer_no, "
sSQL += "i.invoice_number, "
sSQL += "i.customer_purchase_order_no, "
sSQL += "r.railcar_number, "
sSQL += "r.weight, "
sSQL += "r.total, "
sSQL += "i.member + N'-' + i.member_purchase_order_no AS member_purchase_order_no "
sSQL += "FROM Invoices i "
sSQL += "JOIN Railcars r "
sSQL += "ON i.invoice_number = r.invoice_number "
sSQL += "WHERE i.ship_date BETWEEN N'" & Format(Me.dtpStartDate.Value, "MM/dd/yyyy") & "' AND N'" & Format(Me.dtpEndDate.Value, "MM/dd/yyyy") & "' AND "
sSQL += "invoice_type = N'A' "
sSQL += "ORDER BY i.customer_no, "
sSQL += "i.ship_date, "
sSQL += "r.railcar_number"
drSystem = modGeneral.drRunSQL(sSQL, CommandType.Text)
Do While drSystem.Read
oWorksheet.Cells(iRowCount, 1).Value = drSystem("ship_date")
oWorksheet.Cells(iRowCount, 2).Value = drSystem("customer_no")
oWorksheet.Cells(iRowCount, 3).Value = drSystem("invoice_number")
oWorksheet.Cells(iRowCount, 4).Value = drSystem("customer_purchase_order_no")
oWorksheet.Cells(iRowCount, 5).Value = drSystem("railcar_number")
oWorksheet.Cells(iRowCount, 6).Value = drSystem("weight")
oWorksheet.Cells(iRowCount, 7).Value = drSystem("total")
oWorksheet.Cells(iRowCount, 8).Value = drSystem("member_purchase_order_no")
iRowCount += 1
Loop
drSystem.Close()
With oWorksheet.Range("A1", "J1")
.Font.Bold = True
.EntireColumn.AutoFit()
End With
oWorksheet.Range("D1").EntireColumn.HorizontalAlignment = Excel.Constants.xlLeft
With oWorksheet.Range("F1")
.EntireColumn.HorizontalAlignment = Excel.Constants.xlRight
.EntireColumn.NumberFormat = "#,##0.00_);(#,##0.00)"
End With
With oWorksheet.Range("G1")
.EntireColumn.HorizontalAlignment = Excel.Constants.xlRight
.EntireColumn.NumberFormat = "#,##0.00_);(#,##0.00)"
End With
oWorkbook.SaveAs(Me.txtExportLocation.Text & "\sales-a.xlsx")
End If
If Me.chkB.Checked Then
iRowCount = 2
oWorkbook = oExcel.Workbooks.Add
oWorksheet = oWorkbook.ActiveSheet
oWorksheet.Cells(1, 1).Value = "Ship date"
oWorksheet.Cells(1, 2).Value = "Customer"
oWorksheet.Cells(1, 3).Value = "Invoice"
oWorksheet.Cells(1, 4).Value = "Purchase order"
oWorksheet.Cells(1, 5).Value = "Railcar"
oWorksheet.Cells(1, 6).Value = "Weight"
oWorksheet.Cells(1, 7).Value = "Total"
oWorksheet.Cells(1, 8).Value = "Member purchase order"
sSQL = "SELECT FORMAT(i.ship_date, N'MM/dd/yyyy') AS ship_date, "
sSQL += "i.customer_no, "
sSQL += "i.invoice_number, "
sSQL += "i.customer_purchase_order_no, "
sSQL += "r.railcar_number, "
sSQL += "r.weight, "
sSQL += "r.total, "
sSQL += "i.member + N'-' + i.member_purchase_order_no AS member_purchase_order_no "
sSQL += "FROM mxInvoices i "
sSQL += "JOIN mxRailcars r "
sSQL += "ON i.invoice_number = r.invoice_number "
sSQL += "WHERE i.ship_date BETWEEN N'" & Format(Me.dtpStartDate.Value, "MM/dd/yyyy") & "' AND N'" & Format(Me.dtpEndDate.Value, "MM/dd/yyyy") & "' AND "
sSQL += "invoice_type = N'B' "
sSQL += "ORDER BY i.customer_no, "
sSQL += "i.ship_date, "
sSQL += "r.railcar_number"
drSystem = modGeneral.drRunSQL(sSQL, CommandType.Text)
Do While drSystem.Read
oWorksheet.Cells(iRowCount, 1).Value = drSystem("ship_date")
oWorksheet.Cells(iRowCount, 2).Value = drSystem("customer_no")
oWorksheet.Cells(iRowCount, 3).Value = drSystem("invoice_number")
oWorksheet.Cells(iRowCount, 4).Value = drSystem("customer_purchase_order_no")
oWorksheet.Cells(iRowCount, 5).Value = drSystem("railcar_number")
oWorksheet.Cells(iRowCount, 6).Value = drSystem("weight")
oWorksheet.Cells(iRowCount, 7).Value = drSystem("total")
oWorksheet.Cells(iRowCount, 8).Value = drSystem("member_purchase_order_no")
iRowCount += 1
Loop
drSystem.Close()
With oWorksheet.Range("A1", "J1")
.Font.Bold = True
.EntireColumn.AutoFit()
End With
oWorksheet.Range("D1").EntireColumn.HorizontalAlignment = Excel.Constants.xlLeft
With oWorksheet.Range("F1")
.EntireColumn.HorizontalAlignment = Excel.Constants.xlRight
.EntireColumn.NumberFormat = "#,##0.00_);(#,##0.00)"
End With
With oWorksheet.Range("G1")
.EntireColumn.HorizontalAlignment = Excel.Constants.xlRight
.EntireColumn.NumberFormat = "#,##0.00_);(#,##0.00)"
End With
oWorkbook.SaveAs(Me.txtExportLocation.Text & "\sales-b.xlsx")
End If
oExcel.Visible = True
GC.Collect()
GC.WaitForPendingFinalizers()
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorksheet) : oWorksheet = Nothing
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorkbook) : oWorkbook = Nothing
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel) : oExcel = Nothing
Catch ex As Exception
RaiseError("", Me.Name & "." & System.Reflection.MethodBase.GetCurrentMethod().Name, Err.Number, Err.Description)
Finally
If Not drSystem Is Nothing Then
If Not drSystem.IsClosed Then drSystem.Close()
End If
End Try
Me.lblStatus.Text = ""
Me.Cursor = Cursors.Default
答案 0 :(得分:2)
使用后需要处理并释放excel对象。
我使用的简单代码,即使在任务管理器中也可以关闭excel:
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
它适用于我的应用程序
答案 1 :(得分:1)
不幸的是,在interop的情况下,将变量设置为空不会释放excel进程句柄...但是如果你明确地释放了你已经实例化的每个excel com对象引用,那么一旦excel被释放,这个进程不应该被挂起由用户关闭。当我运行以下代码并关闭excel时,该进程不再挂起(我遗漏了oRange,因为它仍然设置为空,并释放一个没有引发异常的对象):
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim oExcel As Excel.Application = Nothing
Dim oWorkbook As Excel.Workbook = Nothing
Dim oWorksheet As Excel.Worksheet = Nothing
oExcel = CreateObject("Excel.Application")
oExcel.DisplayAlerts = False
oExcel.Visible = False
oWorkbook = oExcel.Workbooks.Add
oWorksheet = oWorkbook.ActiveSheet
'Populate, format, etc.
'oWorkbook.SaveAs(Me.txtExportLocation.Text & "\sales.xlsx")
oExcel.Visible = True
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorksheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWorkbook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel)
Me.Close()
End Sub
End Class