Редактировать книгу, открытую или закрытую, из Word VBA - PullRequest
1 голос
/ 07 февраля 2020

Я пытаюсь написать макрос в 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, чтобы ее можно было редактировать, или открываю файл, чтобы редактировать его, если он закрыт?

1 Ответ

0 голосов
/ 08 февраля 2020

Согласно документации , 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...