【问题标题】:EXCEL.EXE won't closeEXCEL.EXE 不会关闭
【发布时间】:2016-06-29 12:02:14
【问题描述】:

是的,我知道问题不是新问题,我已经研究了很多,但到目前为止没有任何帮助。这也是我的第一篇 stackoverflow 帖子,所以如果我做错了什么,请告诉我。 我想要做的是通过 VBA 代码一次导入多个 Excel 工作表。到目前为止,我的代码正在运行,但我的问题是任务管理器中始终存在一个 EXCEL.EXE 实例,当我想导入多个文件时会导致问题。 我已经尝试了以下线程中提出的解决方案:

Closing Excel.exe process

VB.NET Excel Program Leaves EXCEL.EXE floating after completion

https://social.msdn.microsoft.com/Forums/en-US/908ba72a-3293-4eb9-b80e-fd2e6e78e185/vba-close-excel-problem?forum=accessdev

Remove Excel task from Task manager after running from Access using VBA

这是我的导入代码,我只用了几个星期的 VBA,所以请不要看得太仔细。

Public Function importExcelFiles()


Dim tablename As String
Dim spreadsheetType As String
Dim xlAppl As Excel.Application
Dim xlWB As Excel.Workbook
' **** function imports the excel file and copies data into target table  *********

' choose the file to import
path = OpenFile("Select file for import", "Excel-Files" & Chr$(0) & "*.xls; *.xlsx; *.xlsm", "Excel-Files", CurrentProject.path)

If Not IsNull(path) And Not path = "" And Not path = " " Then

    Set xlAppl = CreateObject("excel.application")
    Set xlWB = xlAppl.Workbooks.Open(path)
    
   
    spreadsheetType = acSpreadsheetTypeExcel9
    
    Call AlternateKKS("KKS_DB", xlAppl, xlWB)
    tablename = "KKS_DB"
    DoCmd.TransferSpreadsheet acImport, spreadsheetType, tablename, path, false, "merged!" 'import to excel'
            

    
    DoCmd.SetWarnings False
    xlAppl.DisplayAlerts = False
    xlWB.Close acSaveNo
    xlAppl.Quit
    
    Set xlWB = Nothing
    Set xlAppl = Nothing

    
End If


End Function 

我注意到当我取消注释 Call AlternateKKS 时它可以工作,所以可能有一些东西阻止 Excel.exe 关闭。 该函数中有相当多的代码,所以在我发布所有这些之前,我想知道我应该寻找什么可能会导致问题。它所做的基本上是将工作表读入一个数组,对数据进行一些修改并将其写回“合并”的工作表上。 我已经确定有一个 xlWB。或 xlAppl。每当我参考工作表时,我不使用 msdn 论坛上提到的 with 语句(剧透中的链接)。

PS:另一方面,我要导入的工作表称为“合并”,但由于某种原因,它只有在我放 !最后(一位同事告诉我这样做)但我们不知道为什么。

编辑:这里是所有直接引用应用程序或工作表的代码

Dim wsSource As Worksheet
Dim wsDestination As Worksheet

Public Function ReadIntoArray(name As String, ByRef xlWB As Excel.Workbook) As Variant


'    Dim ret As String
g_arrayrange = GetLastCell(name, xlWB)

Set wsSource = xlWB.Sheets(name)

Call Sort(wsSource, xlWB)

ReadIntoArray = wsSource.range("A1:" & g_arrayrange).Value


End Function

Sub WriteBackArray(data() As Variant, destination As String, ByRef xlWB As Excel.Workbook)


Set wsDestination = xlWB.Sheets(destination)

wsDestination.UsedRange.ClearContents

wsDestination.range("A1").resize(UBound(data, 1), UBound(data, 2)) = data


End Sub

Function GetLastCell(name As String, ByRef xlWB As Excel.Workbook) As String 'return coordinates of last cell with data'

Dim lrw As Long
Dim lcol As Long
Dim lastCell As String
Dim rng As range
Dim sheet As Worksheet
Dim col As String

Set sheet = xlWB.Sheets(name)
Set rng = xlWB.Sheets(name).Cells
'get last row '

lrw = rng.Find(What:="*", _
                After:=rng.Cells(1), _
                Lookat:=xlPart, _
                LookIn:=xlFormulas, _
                SearchOrder:=xlByRows, _
                SearchDirection:=xlPrevious, _
                MatchCase:=False).row


'get last column'
lcol = rng.Find(What:="*", _
                After:=rng.Cells(1), _
                Lookat:=xlPart, _
                LookIn:=xlFormulas, _
                SearchOrder:=xlByColumns, _
                SearchDirection:=xlPrevious, _
                MatchCase:=False).Column

g_lrw = lrw

'change to string for further use as range'
lastCell = GetCellAsString(lcol, lrw)

GetLastCell = lastCell


End Function

在另一个函数中

source = xlAppl.Transpose(source)

其余代码只操作数组

【问题讨论】:

  • 在您未包含在本文中的代码部分中是否有任何与 Excel 实例相关的代码。如与关闭 Excel 实例有关。你能发布 AlternativeKKS() 的代码
  • 在您的应用程序中查找 anywhere,您可以在其中使用任何 Excel 对象或方法以及 WITH 代码块。这是一个众所周知的问题,除非您的代码显式声明并清除用作 with 块对象的基于自动化的对象变量(With...End With 语法),否则这些对象可能会作为“孤立”com 卡在内存中对象。然后,这将阻止其自动化服务器类的发布(因为组成对象仍然具有非零 COM 引用计数)。这将表现为您观察到的症状:尽管调用了 .Quit,但 Excel 不会关闭。
  • 基于自动化的对象实例都应该这样使用: Dim objTemp as (Object/Excel.range/whatever) set objTemp = (whatever) With ObjTemp 'do stuff here End With set objTemp = Nothing你不应该做的是:使用 objExclApp.worksheets(1).range("myNamedrange") 'do stuff End With :这是一种可以为范围对象留下幻像引用的事情LINK
  • 对于wsSourcewsDestination 之类的变量:您是否删除了它们的Dim 语句?还是它们是全局变量?或者模块没有Option Explicit? (耶!)
  • 那么你必须Set wsSource = Nothing等一旦不再使用,否则他们将无限期地保留他们的参考。局部变量(在必要时作为参数传递给其他函数)在这方面更安全。

标签: excel ms-access vba


【解决方案1】:

全局变量(Dimed 在模块级别)无限期地保持它们的值,对象变量保持它们的引用。所以像

这样的全局变量
Dim wsSource As Worksheet

将保留其对 Excel 对象的引用,从而防止 EXCEL.EXE 关闭。

解决方案:

  1. Set wsSource = Nothing 一旦不再使用。这可能很棘手 - 您必须通过程序逻辑处理所有可能的路径。

  2. 改用局部变量Dimed 在函数级别)。必要时将它们作为参数传递给其他函数。这是一种更安全的方式。

【讨论】:

    【解决方案2】:

    因为似乎没有功能可以让我将安德烈的评论标记为答案:

    然后,一旦不再使用它们,就必须执行 Set wsSource = Nothing 等操作,否则它们将无限期地保留它们的引用。局部变量(在必要时作为参数传递给其他函数)在这方面更安全

    您建议的两个解决方案都有效!设置 wsSource = Nothing 当它是全局的以及重写代码以便 wsSource 和 wsDestination 是局部变量使 EXCEL.EXE 正确关闭。

    谢谢!

    @安德烈 随时发表您的评论作为答案,我会将其标记为解决方案

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      • 2018-10-25
      • 2021-04-17
      • 1970-01-01
      相关资源
      最近更新 更多