Согласно документации , GetObject(filename)
подберет существующий файл, если он уже открыт, или, если необходимо, откроет файл, если он не открыт:
Когда этот код выполняется, приложение, связанное с указанным путем, запускается, и объект в указанном файле активируется.
Если Excel не запущен, по умолчанию ничего не будет видно при GetObject(filename)
выполняется. Будет открыт Excel, файл будет открыт и изменен. Следовательно, существует реальная опасность того, что экземпляр Excel и рабочая книга будут «зависать» в памяти, что можно увидеть в «Диспетчере задач» Windows. Повторный запуск такого кода может в конечном итоге привести к sh 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
, а для логического значения appAlreadyOpen
установлено значение true, поэтому мы знаем, что не выходит из Excel после завершения кода. Он также проверяет, открыта ли необходимая рабочая книга. Если это так, можно создать экземпляр xlWb
, а для fileAlreadyOpened установить значение true.
Если создать экземпляр 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