Excel的VBA自动化在退出后在内存中保留一个进程

我已经看到了很多这个问题的build议,我已经尝试了所有的,但似乎没有工作。 VBA代码位于非Microsoft产品(SAP Business Objects,这可能是问题)。 我创build一个Excel对象:

Set oExcel = CreateObject("Excel.Application")

从其中一个工作表的第1列加载特定工作簿中的内容,然后closuresExcel。 每一次,它都会在内存中留下一个进程,占用5+ MB的内存。

我试着让oExcel对象可见,所以至less我可以在不使用任务pipe理器的情况下杀死它,但是当我调用Quit时,UI将退出,并且仍然离开该进程。

每次运行代码,都会创build一个新的进程。 所以我试图通过调用重用任何现有的Excel进程

Set m_oExcel = GetObject(, "Excel.Application")

只有创build它,如果这个调用什么都不返回,

这并没有激化这个过程,但是每一个过程每次增长5+ MB,所以基本上是一样的问题。

在每种情况下,closures我打开的工作簿并在退出之前将DisplayAlerts设置为False:

 m_oBook.Close SaveChanges:=False m_oExcel.DisplayAlerts = False m_oExcel.Quit 

这段代码已经被使用了至less五年,但是这个问题在我们转移到Windows 7之前并没有出现。

这是完整的代码,以防万一。 注意,所有Excel对象都是模块级variables(“m_”前缀),每个build议都使用了“one-dot”规则。 我也尝试使用通用对象(即后期绑定),但是这也不能解决问题:

 Private Function GetVariablesFromXLS(ByVal sFile As String) As Boolean On Error GoTo SubError If Dir(sFile) = "" Then MsgBox "File '" & sFile & "' does not exist. " & _ "The Agent and Account lists have not been updated." Else Set m_oExcel = CreateObject("Excel.Application") Set m_oBooks = m_oExcel.Workbooks Set m_oBook = m_oBooks.Open(sFile) ThisDocument.Variables("Agent(s)").Value = DelimitedList("Agents") ThisDocument.Variables("Account(s)").Value = DelimitedList("Accounts") End If GetVariablesFromXLS = True SubExit: On Error GoTo ResumeNext m_oBook.Close SaveChanges:=False Set m_oBook = Nothing Set m_oBooks = Nothing m_oExcel.DisplayAlerts = False m_oExcel.Quit Set m_oExcel = Nothing Exit Function SubError: MsgBox Err.Description GetVariablesFromXLS = False Resume SubExit ResumeNext: MsgBox Err.Description GetVariablesFromXLS = False Resume Next End Function 

大多数情况下会发生这种情况,因为Excel保持打开COM加载项。 尝试使用下面的链接来获取有关删除COM加载项的帮助。

添加或删除加载项

我注意到特别的舒适:

注意这将从内存中删除加载项,但将其名称保留在可用加载项的列表中。 它不会从您的计算机上删除加载项。

Acantud已经回答了这个问题,以回应后续的post: https : //stackoverflow.com/questions/25147242完全限定您对Excel工作簿中对象的引用,以避免在任务pipe理器中创build孤立的进程。 在这种情况下,解决scheme是用m_oBook前缀DelimitedList ,如

 ThisDocument.Variables("Agent(s)").Value = m_oBook.DelimitedList("Agents") 

虽然这不应该发生,但您可以发送excel“WindowClose”消息以强制closures。

你将需要这些API函数

 Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 

它应该看起来像这样:

 // First, get the handle hWindow = FindWindow(vbNullString, "Excel") //Get proccess ID GetWindowThreadProcessId(hWindow, ProcessValueID) //Kill the process ProcessValue = OpenProcess(PROCESS_ALL_ACCESS, CLng(0), ProcessValueID) TerminateProcess(ProcessValue, CLng(0)) CloseHandle ProcessValueID 

只需要使用:

 Private Sub Workbook_BeforeClose(Cancel As Boolean) Excel.Application.Quit End Sub 

添加一个基于David Zemens评论的答案。 为我工作。

 m_oExcel.Quit '<- Still in Task Manager after this line Set m_oExcel = Nothing '<- Gone after this line