1

我正在使用以下代码对 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 进程仍在运行。

4

4 回答 4

3
Option Explicit

Sub Main()

    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit

End Sub

每次都为我工作,并且不会在任务管理器中留下任何 Excel 进程。

注意:如果您的代码在某些时候中断并且您没有正确处理已打开的对象,那么它们只会挂在任务管理器的进程选项卡中。如果您尚未在代码中实现错误处理,请从这里开始。

只是把它当作替代品

Option Explicit

Sub Main()

    On Error GoTo ErrHandler
    Dim xlApp As Excel.Application
    Set xlApp = New Excel.Application

    xlApp.Visible = False
    xlApp.DisplayAlerts = False

    Dim xlWb As Workbook
    Set xlWb = xlApp.Workbooks.Open("C:\...\path")

    Dim xlSht As Worksheet
    Set xlSht = xlWb.Sheets(1)

    xlSht.Range("A1") = "message from " & ThisWorkbook.FullName

    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
    Exit Sub

ErrHandler:
    xlWb.Saved = True
    xlWb.Save
    xlWb.Close

    xlApp.Quit
End Sub
于 2013-10-07T11:56:14.880 回答
0

The Interop Marshal release doesn't always work because Excel XP and lower suck at releasing. I had to use your loop, but replace the Process.Close() and Process.Quit() with Process.Kill(). Works like a charm. Just be careful that you want ALL versions of excel.exe to be killed, because they will.

我用这个:

Workbook.Save()
Workbook.Close()
Application.Quit()

System.Runtime.InteropServices.Marshal.ReleaseComObject(Application)

Worksheet = Nothing
Workbook = Nothing
Application = Nothing

Dim proc As System.Diagnostics.Process

For Each proc In System.Diagnostics.Process.GetProcessesByName("EXCEL")
proc.Kill()
Next
于 2013-10-07T11:56:00.100 回答
0

您可以从 Excel.Application hwnd 获取进程 ID,并使用它来安全地终止进程。

于 2014-06-09T13:34:31.123 回答
0

当您对 Excel 互操作执行任何操作时,它会创建一个新进程。

杀死所有 Excel 进程的问题是您可能会杀死正在使用的进程。您可以使用以下命令终止所有运行了一定时间长度(即从某个时间戳)的进程:

Dim proc As System.Diagnostics.Process
Dim info As ManagementObject
Dim search As New ManagementObjectSearcher("SELECT ProcessId FROM Win32_process WHERE caption = 'Excel'")
For Each info In search.Get()

    'The string will give you the time that the process started
    'You can then subtract that from the current time to see if you want to kill the process
    Dim TheString As String = info.GetText(TextFormat.Mof).ToString

    'Kill the process according to its ID
    proc = System.Diagnostics.Process.GetProcessById(Mid$(TheString, _
                                                    (Len(TheString) - 8), 4))
    proc.CloseMainWindow()
    proc.Refresh()
    If proc.HasExited Then GoTo NoKill
    proc.Kill()
NoKill:
Next

您需要添加:

Imports System.Management

并将“System.Management”的引用添加到您的项目中。

于 2013-10-07T12:43:28.623 回答