Excel.Application Object .Quit 使 EXCEL.EXE 运行

Posted

技术标签:

【中文标题】Excel.Application Object .Quit 使 EXCEL.EXE 运行【英文标题】:Excel.Application Object .Quit leaves EXCEL.EXE running 【发布时间】:2017-02-08 12:25:32 【问题描述】:

我在 Windows 10 上使用 MS Access 2013。

我正在尝试打开磁盘上的 Excel 文件,更改列格式和一些列,保存并退出。 Sub 运行,但在.Quit 命令之后,“EXCEL.EXE”继续运行,随后对该 Sub 的调用将导致运行时错误。 如果我关闭 Access,“EXCEL.EXE”会在任务管理器中消失,但如果我执行“压缩和修复”数据库则不会。

我有另一个 Sub,它在磁盘上打开一个 Excel 文件并将所有列的宽度更改为“自动宽度”,然后关闭,这不会让“EXCEL.EXE”继续运行。

我在 Dims 和 Sets to Nothing、Workbook Closes 等上尝试了不同的线路顺序。 我在这里和其他网站上搜索过。 VBA 的唯一建议是使用类似ThisWorkbook.Saved = True 的东西。我在.Quit 之前和之后都试过了,但没有效果。 除此之外,我只找到 VB.NET 或其他环境的解决方案。

Sub changeXLcolumnFormatting()

Dim XL As Object
Set XL = CreateObject("Excel.Application")
XL.Visible = False
XL.DisplayAlerts = False
XL.Workbooks.Open "C:\Users\640344\Desktop\rawDataTest.XLSX"
Dim sht As Worksheet

With XL
    Set sht = ActiveWorkbook.Worksheets(1)

    Dim rng As Range
    Dim i As Integer, j As Integer

    field_names = Split("datasistema|Data de Registo|Data Registo CMVM", "|")
    sht.Select
    end_of_table = sht.UsedRange.Columns.Count

    For j = 0 To UBound(field_names)
        For i = 1 To end_of_table
            Set rng = sht.Cells(1, i)
            If InStr(rng.Text, field_names(j)) > 0 Then
                sht.Columns(i).NumberFormat = "yyyy-mm-dd  HH:MM:ss"
            End If
        Next i
    Next j
End With

Set rng = Nothing
Set sht = Nothing
XL.ActiveWorkbook.Close (True)

XL.Quit
Set XL = Nothing

End Sub

【问题讨论】:

您确定在启动宏之前没有任何其他Excel 在运行吗? 您可以尝试通过添加Application.Quit 而不是XL.Quit 来看看它是如何工作的。 也尝试在关闭之前明确保存更改的工作簿 将命令 Application.Quit 放在关闭命令之后 @Vityata:是的,在 Access 中运行 Sub 之前,Excel.exe 没有运行,也没有显示在任务管理器中。使用 Application.Quit 退出 MS Access,这是不需要的。不过,这确实使“EXCEL.EXE”从任务管理器中消失,这是有道理的,因为我的 Sub 不正确,因为 Access 没有正确关闭 Excel。 【参考方案1】:

声明并使用特定的 Workbook 对象 - 就像您对 WorksheetRange 所做的那样,如下所示:

    Dim xls     As Excel.Application
    Dim wkb     As Excel.Workbook
    Dim wks     As Excel.Worksheet
    Dim rng     As Range
    
    Set xls = New Excel.Application
    Set wkb = xls.Workbooks.Open("c:\test\workbook1.xlsx")
    Set wks = wkb.Worksheets(1)
    Set rng = wks.Range(<something>)
    
    ' Do stuff.
    wks.Name = "My New Name"
    With rng
         ' Do more.
    End With

    wkb.Close True
    
    Set rng = Nothing
    Set wks = Nothing
    Set wkb = Nothing
    
    xls.Quit
    
    Set xls = Nothing

另外,不要使用 Select,它仅用于可见用途。改为定义范围。


Cinetyk 的编辑:

使用@Gustav 的指示,执行我想要的并解决问题的代码是:

Sub changeXLcolumnFormatting()

Dim XL As Excel.Application
Dim sht As Excel.Worksheet
Dim wkb As Excel.Workbook
Dim rng As Range

Set XL = New Excel.Application
XL.Visible = False
XL.DisplayAlerts = False

Set wkb = XL.Workbooks.Open("C:\Users\640344\Desktop\rawDataTest.XLSX")
Set sht = wkb.Worksheets(1)

Dim i As Integer, j As Integer

field_names = Split("datasistema|Data de Registo|Data Registo CMVM", "|")
end_of_table = sht.UsedRange.Columns.Count

For j = 0 To UBound(field_names)
    For i = 1 To end_of_table
        Set rng = sht.Cells(1, i)
        If InStr(rng.Text, field_names(j)) > 0 Then
            sht.Columns(i).NumberFormat = "yyyy-mm-dd  HH:MM:ss"
        End If
    Next i
Next j

wkb.Close (True)
Set rng = Nothing
Set sht = Nothing

XL.Quit
Set XL = Nothing

End Sub

【讨论】:

古斯塔夫,做到了。非常感谢。现在,看看您的答案,这是有道理的:明确声明对象使我可以“关闭”并将它们明确设置为空。我正在使用一些隐式定义的变量离开,因此这些变量没有被“关闭”,可能它们在内存中的链接仍然存在。我正在学习VBA,这是一个很好的教训,再次非常感谢。也感谢所有花时间阅读和评论的人。 赞成评论而不是答案,因为它解释了原因而答案没有。如果不解释错误机制,答案是无用的,因为您永远不会知道您是否消除了错误以及是哪一行造成的。 这一行“Set xls = New Excel.Application”不容忽视。通过打开一个新实例,代码可以安全地关闭 Excel,而不会干扰用户可能正在与之交互的其他 Excel 实例。【参考方案2】:

这是一个解决这个问题的好方法——使用with new Excel.Application

Option Compare Database
Option Explicit

Public Sub TestMe()

    Dim wkb     As Object
    Dim wks     As Object

    With New Excel.Application

        Set wkb = .Workbooks.Open("C:\Users\vityata\Desktop\myTest.xlsx")
        Set wks = wkb.Worksheets(1)

        wkb.Close True

        Set wks = Nothing
        Set wkb = Nothing
        .Quit

    End With

End Sub

在 C# 中这是 Using 的标准,在 VBA 中很少有人使用它 - 我从未见过它的生产代码。


Cinetyk 的编辑:

使用 Vityata 的指示,按我的预期工作的代码是:

Option Compare Database
Option Explicit

Public Sub changeXLcolumnFormattingV2()

Dim sht As Object
Dim wkb As Object

With New Excel.Application
    .Visible = False
    .DisplayAlerts = False

    Set wkb = .Workbooks.Open("C:\Users\640344\Desktop\rawDataTESTING.XLSX")
    Set wks = wkb.Worksheets(1)

    field_names = Split("datasistema|Data de Registo|Data Registo CMVM", "|")
    end_of_table = wks.UsedRange.Columns.Count

    For j = 0 To UBound(field_names)
        For i = 1 To end_of_table
            Set rng = wks.Cells(1, i)
            If InStr(rng.Text, field_names(j)) > 0 Then
                wks.Columns(i).NumberFormat = "yyyy-mm-dd  HH:MM:ss"
            End If
        Next i
    Next j

    wkb.Close True

    Set wks = Nothing
    Set wkb = Nothing
    .Quit

End With

End Sub

【讨论】:

欢迎您,@Cinetyk。不幸的是,它并不像在 C# 中那样工作,Using() 会注意完全销毁和释放对象,但它仍然很好。 但是在运行 MS Access 时,excel.exe 在使用该代码后不会保留在后台,所以它对我有用。 @Cinetyk - 因为您在代码中有.Quit。但在最好的情况下,如果 VBA 更好一点,它应该会自行关闭,而不需要 .Quit【参考方案3】:

您的 sht 变量赋值缺少成员访问器运算符“。”在 ActiveWorkbook.Worksheets(1) 前面。需要这样写:Set sht = .ActiveWorkbook.Worksheets(1)。

【讨论】:

以上是关于Excel.Application Object .Quit 使 EXCEL.EXE 运行的主要内容,如果未能解决你的问题,请参考以下文章

Excel.Application class

Excel Application操作指南

Excel.Application使用手册

QT操作Excel(通过QAxObject使用了OLE,前提是本地安装了Excel)

加载类型库/DLL (Microsoft.Office.Interop.Excel.Application) 时出错

Dynamics AX 2012 R2 无法创建类"Excel.Application"的COM对象