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 对象 - 就像您对 Worksheet 和 Range 所做的那样,如下所示:
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 运行的主要内容,如果未能解决你的问题,请参考以下文章
QT操作Excel(通过QAxObject使用了OLE,前提是本地安装了Excel)