Reputation: 25
I have searched thru other posts for this topic but can not find a solution. I want to run some VBA code in excel 2016 (on an imac running OS 10.13.5) to open a word document (preferably as Read Only). If an instance of word is already running, I want to close it before proceeding. (It would be nice if word is already running to be asked if I wanted to save the other instance(s) before closing them.) The code I have is
Private Sub CommandButton1_Click()
Dim w As Object
' If word is already open get ahold of the running instance
' Otherwise create a new instance
On Error Resume Next
Set w = GetObject(, "Word.Application")
If w Is Nothing Then Set w = CreateObject("Word.Application")
On Error GoTo 0
' Close all open files and shutdown Word
' Loop through any open documents and close them
Do Until w.Documents.Count = 0
w.Documents(1).Close
Loop
w.Quit False
Set w = Nothing
' Now that all instances of word are closed, open the template
Dim wdApp As Object
Dim wdDoc As Object
Set wdApp = CreateObject("Word.application")
wdApp.Visible = True
wdApp.DisplayAlerts = False
MYPATH = "Volumes/256SSD/""How to do stuff""/""myfile.docx"""
Set wdDoc = wdApp.Documents.Open(FileName:=MYPATH)
End Sub
When I run this with word already open, I get variable results. Sometimes the code runs thru the "do until loop" and seems to close the open word instances then proceeds to the last line and gives a vba runtime error "Application-defined or object-defined error". A word instance has been started and is awaiting input of which file to be opened.
If I immediately run the code again, the "do until loop" is not entered and word come asking for file name input. VBA gives a run time error "Automation error". I can then select a file name from Recent Files and this is opened but the run time error remains and the file selected in MYPATH is not opened.
I would appreciate some help on this.
Upvotes: 1
Views: 3035
Reputation: 55
If you want to close all open word documents and application , just paste the code in module then call this "FindAndCloseAllWordApplications" subroutine from you vba code, i am using windows API from excel VBA
Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Long
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Private Const WM_CLOSE As Long = &H10
Private Const MAX_PATH As Long = 260
Private Function EnumWindowsProc(ByVal hWnd As LongPtr, ByVal lParam As LongPtr) As Long
Dim sClassName As String
Dim sWindowName As String
Dim lRet As Long
sClassName = String$(MAX_PATH, vbNullChar)
lRet = GetClassName(hWnd, sClassName, MAX_PATH)
If lRet > 0 Then
sClassName = Left$(sClassName, lRet)
' Check if the window is a Word application
If InStr(1, sClassName, "OpusApp", vbTextCompare) > 0 Then
sWindowName = String$(MAX_PATH, vbNullChar)
lRet = GetWindowText(hWnd, sWindowName, MAX_PATH)
If lRet > 0 Then
sWindowName = Left$(sWindowName, lRet)
Debug.Print "Found Word Application: " & sWindowName
' Close the Word application window
SendMessage hWnd, WM_CLOSE, 0, 0
End If
End If
End If
EnumWindowsProc = 1
End Function
------------------
Public Sub FindAndCloseAllWordApplications()
EnumWindows AddressOf EnumWindowsProc, 0
End Sub
Upvotes: 0
Reputation: 53136
The first part of your code needs work.
This part could be refactored as
Dim w As Object
On Error Resume Next
Set w = GetObject(, "Word.Application")
On Error GoTo 0
Do Until w Is Nothing
Do Until w.Documents.Count = 0
w.Documents(1).Close SaveChanges:=-2
Loop
w.Quit SaveChanges:=0
Set w = Nothing
On Error Resume Next
Set w = GetObject(, "Word.Application")
On Error GoTo 0
Loop
On Error GoTo 0
Upvotes: 1