Excel не будет полностью закрываться после запуска макроса Word VBA - PullRequest
0 голосов
/ 05 марта 2020

В настоящее время я пытаюсь создать макрос, который открывает пользовательскую электронную таблицу Excel, извлекает некоторые данные для использования в текстовом документе и затем закрывает их. Моя проблема в том, что при запуске макроса открываемая мной электронная таблица все еще технически открыта как фоновый процесс в моем диспетчере задач. В другом вопросе о переполнении стека я прочитал, что причина в том, что visual basi c не освободит ссылочный объект из Excel, пока я не закрою Microsoft Word. Однако даже после закрытия Word фоновый процесс Excel все еще идет, и я могу остановить его, только завершив задачу в диспетчере задач. Чтобы уточнить, если я запустил макрос, закрою Word и затем попытаюсь открыть файл Excel, я могу войти, не сказав мне, что это файл только для чтения. Однако, если я не закрываюсь из Word и пытаюсь go войти в электронную таблицу после запуска макроса, он говорит мне, что это файл только для чтения. Ниже приведен код, который я использую, который вызывает эту проблему для меня. Спасибо всем, кто может помочь.

Sub UpdateProposal()

'Declares variables
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim SpreadsheetPath As String
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range
Dim ExcelWasNotRunning As Boolean
Dim ProposalInfoArr(1 To 30) As String

'Skips to ErrorHandler if user cancels out of file dialog
On Error GoTo ErrorHandler

'Display a Dialog Box that allows to select a single file.
'The path for the file picked will be stored in SpreadsheetPath variable
With Application.FileDialog(msoFileDialogFilePicker)

    'Makes sure the user can select only one file
    .AllowMultiSelect = False

    'Filter to just the following types of files to narrow down selection options
    .Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1

    'Show the dialog box
    .Show

    'Stores in SpreadsheetPath variable
    SpreadsheetPath = .SelectedItems.Item(1)

End With

'If Excel is running, get a handle on it; otherwise start a new instance of Excel
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")

If Err Then
   ExcelWasNotRunning = True
   Set xlApp = New Excel.Application
End If

'If you want Excel to be visible, you could add the line: xlApp.Visible = True here; but your code will run faster if you don't make it visible

'Open the workbook
Set xlBook = xlApp.Workbooks.Open(FileName:=SpreadsheetPath)

'''Extracts Data

'Quits out of Excel if it was not running previous to running the macro.
If ExcelWasNotRunning Then
    xlApp.DisplayAlerts = False
    xlApp.Quit
End If


'Make sure you release object references.
Set xlRange = Nothing
Set xlSheet = Nothing
Set xlBook = Nothing
Set xlApp = Nothing

'Ends the macro before the error handler
Exit Sub

'Ends Macro
ErrorHandler:
    MsgBox "The following error occurred: " & Err.Description

End Sub

1 Ответ

1 голос
/ 06 марта 2020

Вы правильно определяете объекты:

Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range

, но вы забыли об неявно используемом объекте Workbooks ... так как большинство ответов, которые вы найдете, делают ... что означает, что это не так " Тебя выпустят. Так что сделайте это так:

Dim SpreadsheetPath As String
Dim xlApp As Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlRange As Excel.Range

SpreadsheetPath = "C:\MyPath\MyFile.xlsx"
Set xlApp = New Excel.Application
' Set xlApp = GetObject(, "Excel.Application") ' or attach to an existing one
Set xlBooks = xlApp.Workbooks
Set xlBook = xlBooks.Open(FileName:=SpreadsheetPath) ' you can use .Add instead if someone else may have it open already
Set xlSheet = xlBook.Worksheets(1)
Set xlRange = xlSheet.Range("A1")

' do stuff with the worksheet/range
xlRange.Value = "foo"

' the order matters 
' just like it does 
' when you create the objects
Set xlRange = Nothing
Set xlSheet = Nothing
xlBook.Close False
Set xlBook = Nothing
Set xlBooks = Nothing
xlApp.Quit
Set xlApp = Nothing

Однако вы можете обнаружить, что он все еще не освобождается, когда вы хотите, но он будет выпущен, когда вы закроете программу, которую используете для ее создания (в ваш случай, MS-Word), как это (предположительно), когда Windows делает свою встроенную сборку мусора.

Примечание: я удалил обработку ошибок только для того, чтобы сохранить ее чистым примером, но Вы можете оставить это в

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...