我正在尝试在Word中编写宏,以便可以将某些信息保存到计算机其他位置的Excel文件中。因此,我写了这个:
Dim exlApp As Object
Dim exlWbk As Object
Set exlApp = CreateObject("Excel.Application")
Set exlWbk = exlApp.Workbooks.Open(FileName:="D:\database.xlsx")
exlWbk.ActiveSheet.Cells(1, 1).Value = "some info"
exlWbk.Close SaveChanges:=True
Set exlWbk = Nothing
exlApp.Quit
Set exlApp = Nothing
该代码对我来说非常正常,除非用户已打开有问题的Excel文件(database.xlsx)。在这种情况下,运行宏将提示我将新更改保存到我的excel文件的新副本中,这不是我想要的。我希望新的更改包含在当前Excel文件中,而不创建第二个副本。
由于上述代码出现了一些问题,所以我这样写:
Dim exlApp As Object
Dim exlWbk As Object
Set exlApp = CreateObject("Excel.Application")
Set exlWbk = exlApp.GetObject("D:\database.xlsx")
exlWbk.ActiveSheet.Cells(1, 1).Value = "some info"
exlWbk.Save
Set exlWbk = Nothing
exlApp.Quit
Set exlApp = Nothing
但是什么都没有改变。我知道有一些方法可以确定我的Excel文件是否打开,但是问题是,如果我发现该文件是打开的,我不知道如何更改代码。
如何确定工作簿是否已在Excel中打开以便可以对其进行编辑,或者如何在关闭时打开文件进行编辑?
根据documentation,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
将错误重新打开。
如果GetObject
不成功,则无法实例化变量xlApp
,并且其“值”为Nothing
。如果可以实例化If Not xlApp Is Nothing
并将布尔值xlApp
设置为true,则执行appAlreadyOpen
,以便在代码完成后我们知道not退出Excel。它还检查所需的工作簿是否已经打开。如果是,则可以实例化xlWb
并将fileAlreadyOpened设置为true。
如果由于Excel应用程序未运行或工作簿尚未打开而无法实例化xlWb
,则将执行GetObject(fileName)
。将在现有的Excel实例(如果已运行)中或在Excel的新实例中打开工作簿。在此代码块的结尾处,注释了两行:如果新启动的Excel应用程序变得可见并在代码结束时保持打开状态,请取消注释它们。
然后可以编辑工作簿。
最后,需要清理东西。检查布尔值,如果不为true,则关闭工作簿和可能的应用程序。 非常重要是从内存中释放这些对象的最后两行。如果代码创建了任何其他对象,例如Range
,则也应以实例化它们的相反顺序释放它们。
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