根据文档 https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/getobject-function, GetObject(filename)
如果现有文件已打开,则将拾取该文件;如果文件未打开,则可以选择打开该文件:
当执行此代码时,与该关联的应用程序
启动指定路径名,指定文件中的对象
活性。
如果 Excel 未运行,则默认情况下什么都看不到GetObject(filename)
执行。 Excel 将被打开,文件将被打开并更改。因此,存在一个真正的危险,即 Excel 实例和工作簿将“挂起”在内存中,这可以在 Windows“任务管理器”中看到。重复运行此类代码最终可能会使 Windows 崩溃,因此必须小心在每次迭代时正确清理内容。
由于该问题还规定该文件可能已被用户打开,因此有必要确定这一点以及 Excel 应用程序是否已在运行。
以下代码示例演示了如何完成此操作。假设应用程序和文件都没有打开。然后它测试 Excel 是否已在运行。
Set xlApp = GetObject(, "Excel.Application")
请注意语法上的差异:而不是fileName
有一个逗号,后跟应用程序的名称。这将检查应用程序是否可用;如果不是,则会触发错误。所以,On Error Resume Next
先于GetObject
,这意味着错误将被忽略。
由于忽略错误是危险的,所以下一行Or Error GoTo 0
重新打开错误。
If GetObject
不成功,变量xlApp
无法实例化,其“值”是Nothing
. If Not xlApp Is Nothing
执行如果xlApp
可以被实例化并且布尔值appAlreadyOpen
设置为 true 以便我们知道not代码完成后退出 Excel。它还检查所需的工作簿是否已打开。如果是,xlWb
可以实例化并将 fileAlreadyOpened 设置为 true。
If xlWb
无法实例化,因为 Excel 应用程序未运行或工作簿尚未打开,GetObject(fileName)
被执行。工作簿将在现有 Excel 实例(如果已运行)或新的 Excel 实例中打开。在此代码块的末尾有两行注释:如果新启动的 Excel 应用程序可见并在代码结束时保持打开状态,请取消注释它们。
然后可以编辑工作簿。
最后,事情需要清理。检查布尔值,如果不正确,则关闭工作簿和可能的应用程序。很重要最后两行从内存中释放这些对象。如果代码创建任何其他对象,例如Range
s,这些也应该被释放,按照它们实例化的相反顺序。
Sub GetFileOpenedOrClosed()
Dim xlApp As Object ' Excel.Application
Dim xlWB As Object, wb As Object ' Excel.Workbook
Dim fileName As String
Dim fileAlreadyOpen As Boolean, appAlreadyOpen As Boolean
fileName = "C:\Test\SampleChart.xlsx"
fileAlreadyOpen = False
appAlreadyOpen = False
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
On Error GoTo 0
If Not xlApp Is Nothing Then
appAlreadyOpen = True
For Each wb In xlApp.Workbooks
If wb.FullName = fileName Then
Set xlWB = wb
fileAlreadyOpen = True
Exit For
End If
Next
End If
If xlWB Is Nothing Then
Set xlWB = GetObject(fileName)
Set xlApp = xlWB.Application
xlWB.Windows(1).Visible = True 'So that the window is not hidden when file is opened again
'xlApp.Visible = True
'xlApp.UserControl = True
End If
xlWB.Worksheets(1).Cells(7, 1).value = "some other info"
If Not fileAlreadyOpen Then
xlWB.Save
xlWB.Close
End If
If Not appAlreadyOpen Then
xlApp.Quit
End If
Set xlWB = Nothing
Set xlApp = Nothing
End Sub