EXCEL.EXE不会关闭

时间:2016-06-29 12:02:15

标签: excel-vba ms-access access-vba vba excel

是的,我知道这个问题不过是新问题而且我已经研究了很多但到目前为止没有任何帮助。这也是我的第一个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)

其余代码只操纵数组

2 个答案:

答案 0 :(得分:2)

全局变量(模块级别上的Dim)保持其值无限期,对象变量保留其引用。所以像

这样的全局变量
Dim wsSource As Worksheet

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

解决方案:

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

  2. 改为使用局部变量Dim编辑功能级别。必要时将它们作为参数传递给其他功能。这是一种更安全的方式。

答案 1 :(得分:1)

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

  

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

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

谢谢!

@Andre 随意发表您的评论作为答案,我会将其标记为解决方案