【发布时间】:2013-10-07 11:48:39
【问题描述】:
我正在使用以下代码对 excel 文件进行一些复制和粘贴:
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.IO
Imports System.Runtime.InteropServices
Private Sub btnCombine_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCombine.Click
Dim xlAppSource As New Excel.Application
Dim xlAppTarget As New Excel.Application
Dim xlWbSource As Excel.Workbook
Dim xlWbTarget As Excel.Workbook
Dim xlsheetSource As Excel.Worksheet
Dim xlsheetTarget As Excel.Worksheet
Dim xlRangeSource As Excel.Range
Dim xlRangeTarget As Excel.Range
Dim Progress As Integer = 0
pbrProgress.Minimum = 0
pbrProgress.Maximum = amountOfFiles
btnCombine.Enabled = False
btnSelect.Enabled = False
pbrProgress.Visible = True
getSaveLocation()
MakeExcelFile()
'loop through all excel files to get the required data
For i = 0 To amountOfFiles - 1
Dim CurrentFile As String = strFileNames(i)
Dim IntAmountOfRows As Integer = amountOfRows(CurrentFile)
Dim intStartOfEmptyRow As Integer = amountOfRows(SummaryLocation)
xlAppSource.DisplayAlerts = False
xlAppTarget.DisplayAlerts = False
'Set current workbook
xlWbSource = xlAppSource.Workbooks.Open(CurrentFile)
xlWbTarget = xlAppTarget.Workbooks.Open(SummaryLocation)
'set current worksheet
xlsheetSource = xlWbSource.ActiveSheet
xlsheetTarget = xlWbTarget.ActiveSheet
'copy range of data from source to target file
xlRangeSource = xlsheetSource.Range("A2:k" & IntAmountOfRows)
xlRangeSource.Copy()
xlRangeTarget = xlsheetTarget.Range("A" & intStartOfEmptyRow)
xlRangeTarget.PasteSpecial(Excel.XlPasteType.xlPasteValues)
'save summary file before closing
xlsheetTarget.SaveAs(SummaryLocation)
'updating progress bar
Progress = Progress + 1
pbrProgress.Value = Progress
Next
'close excel
xlWbSource.Close(True)
xlWbTarget.Close(True)
xlAppSource.Quit()
xlAppTarget.Quit()
xlAppSource.DisplayAlerts = True
xlAppTarget.DisplayAlerts = True
'Cleanup
Marshal.ReleaseComObject(xlAppSource)
Marshal.ReleaseComObject(xlAppTarget)
Marshal.ReleaseComObject(xlWbSource)
Marshal.ReleaseComObject(xlWbTarget)
Marshal.ReleaseComObject(xlsheetSource)
Marshal.ReleaseComObject(xlsheettarget)
Marshal.ReleaseComObject(xlRangeSource)
Marshal.ReleaseComObject(xlRangeTarget)
xlAppSource = Nothing
xlAppTarget = Nothing
xlWbSource = Nothing
xlWbTarget = Nothing
xlsheetSource = Nothing
xlsheetTarget = Nothing
xlRangeSource = Nothing
xlRangeTarget = Nothing
MsgBox("Samenvoegen compleet")
init()
End Sub
我已经尝试了 SO 上给出的所有解决方案:
- 切勿在一条线上使用 2 个点
- 我尝试过使用 marshall.ReleaseComObject
- 我已尝试将对象设置为“无”
但是,每次我运行应用程序时,都会有 10-20 个 excel 进程仍在运行。
【问题讨论】:
-
您忘记了 tmpSource 和 tmpTarget。实际上,您不需要它们,可以将 xlWbTarget = tmpTarget.Open(SummaryLocation) 替换为 xlWbTarget = xlAppTarget.Workbooks.Open(SummaryLocation)。在对象退出后不确定 DisplayAlerts 的确切点。您也可以取消注释最后一堆 Nothing(至少是 App 对象)。如果你做了所有这些,当你关闭你的应用程序时,就不会有任何正在运行的 Excel 进程。
-
PS:我现在意识到(在阅读下面的评论后)您正在循环内创建/处理 Excel 对象。您不需要这样做(实际上非常不推荐,正是因为与释放 Excel 对象相关的问题);您可以一遍又一遍地使用相同的对象,并且只在关闭应用程序之前释放它们。如果您需要打开不同的 Excel 窗口,请根据需要创建尽可能多的对象。
-
我制作 tmpTarget 的原因是因为在另一个问题上,人们被告知不要在互操作中使用超过 1 个点 (.)
-
我不明白最后的推理,但如果你愿意,你可以随意使用 tmpTarget;虽然你也必须释放它。无论如何,正如我之前的 PS 中所说,您应该更改代码:Excel 对象释放过程应该在最后完成一次,当您不再需要对象时。在循环内部,您应该保留相同的对象,或者创建与不同 Excel 窗口一样多的不同对象(所有这些都应在完成后释放)。
-
如果在完成循环(以及对象的所有操作)之后,您编写对象释放代码(通过考虑所有对象 + 最后的 Nothing)。当您关闭应用程序时,不会有任何正在运行的 Excel 实例。要进行测试,请确保没有来自先前执行的 Excel 对象(启动时没有正在运行的 Excel 进程)。
标签: vb.net visual-studio-2010 excel process