sts023
06-15-2014, 08:46 AM
Hi guys - as usual I'm going round in circles with this one. Any help would be appreciated.
Background
In Word, when opening a specific document, I want to open a specific Excel spreadsheet (lets call it the DB Workbook), which it is entirely possible that the User is already working in. In Word VBA I can detect this successfully, and when I do, I present the User with an Userform warning them that the DB Workbook is open, and offer them three options, viz - 1. Abandon (i.e. Exit Word), 2. Close and save the DB Workbook, or 3. Close the DB workbook without saving it.
All of this is working, but....
The Problem
I always end up with an instance of Excel with a blank workbook if I choose either of the Save options.
Having tried stepping through my code, it appears that the line
gobjDBWkb.Close SaveChanges:=True
seems to close the Workbook, but leaves the instance of Excel which opened the Workbook still active.
I use the following Sub to identify if any instance of Excel was loaded from the file whose fully qualified address is held in the variable “gstrMastreBalancesDataFull”, defined as
Public gstrMasterBalancesDataFull As String
Other relevant definitions are
Public gobjDBWkb As Workbook
Public Sub GetAllXLWindows()
Dim lngHWnd As Long
Dim lngHWndDesk As Long
Dim lngHWndMain As Long
Dim lngRet As Long
Dim objWkb As Workbook
Dim strClassName As String
Dim strMsg As String
Dim strText As String
gbooXLWasAlreadyOpen = False 'Pessimist!
'*
'** Returns Handle to XLMAIN (Top level
'** reference to Excel).
'*
lngHWndMain = FindWindowEx(0, 0, "XLMAIN", vbNullString)
'*
'** Is Excel running?
'*
If lngHWndMain <> 0 Then 'Yes!
'*
'* Load each instance of Excel
'** into a Collection.
'*
Set gcolWindows = New Collection
Do
'*
'** Find XLDESK (instance of Excel on Desktop).
'*
lngHWndDesk = FindWindowEx(lngHWndMain, 0, "XLDESK", vbNullString)
Do While lngHWndDesk <> 0
'*
'** For each Child of XLDESK....
'*
lngHWnd = FindWindowEx(lngHWndDesk, 0, vbNullString, vbNullString)
Do While lngHWnd <> 0
'*
'** Set up a string of 100 nulls, to be used
'** by GetclassName to return the Class Name.
'** Note, the length of the name is the
'** result of GetClassName
'*
strText = String$(100, Chr$(0))
'*
'** Get the Class Name
'** We're looking for "EXCEL7", which is
'** the Class name for a Workbook.
'*
lngRet = GetClassName(lngHWnd, strText, 100)
strClassName = Left(strText, lngRet)
Select Case strClassName
Case "EXCEL7" 'Excel Workbook
strText = String$(100, Chr$(0))
lngRet = GetWindowText(lngHWnd, strText, 100)
If lngRet > 0 Then
'*
'**Add XLObject to the collection, with a
'** key of the lngHWnd.
'*
gcolWindows.Add funGetXlObjFromHwnd(lngHWnd), CStr(lngHWnd)
End If
Case "EXCEL6" 'Worksheet cell in edit mode.
Case "NUIPANE" '?? (Found by inspection)
End Select
lngHWnd = FindWindowEx(lngHWndDesk, lngHWnd, vbNullString, vbNullString)
Loop 'End of Child loop
lngHWndDesk = FindWindowEx(lngHWndMain, lngHWndDesk, vbNullString, vbNullString)
Loop
'*
'** Get next Windows object
'*
lngHWndMain = FindWindowEx(0&, lngHWndMain, "XLMAIN", vbNullString)
Loop While lngHWndMain <> 0
'*
'** End of Discovery phase.
'*
On Error Resume Next
For lngRet = 1 To gcolWindows.Count
Set objWkb = gcolWindows(lngRet)
If objWkb.Windows(1).Visible And _
Not objWkb.IsAddin And _
objWkb.FullName = gstrMasterBalancesDataFull Then
Set gobjDBWkb = objWkb
gbooXLWasAlreadyOpen = True
End If
Next lngRet 'Examine next Collection item.
End If
End Sub 'GetAllXLWindows
Note that it is also possible that the User may have other unrelated instances of Excel open, so if I were to issue a sort of "Find Excel and shut it down", I'd probably shut every instance down, which I don't want to do.
I've tried
gobjDBWkb.Quit after the Close,
but I just get "Automation error - The Object invoked has disconnected from its clients".
Any ideas? (Please!)
Background
In Word, when opening a specific document, I want to open a specific Excel spreadsheet (lets call it the DB Workbook), which it is entirely possible that the User is already working in. In Word VBA I can detect this successfully, and when I do, I present the User with an Userform warning them that the DB Workbook is open, and offer them three options, viz - 1. Abandon (i.e. Exit Word), 2. Close and save the DB Workbook, or 3. Close the DB workbook without saving it.
All of this is working, but....
The Problem
I always end up with an instance of Excel with a blank workbook if I choose either of the Save options.
Having tried stepping through my code, it appears that the line
gobjDBWkb.Close SaveChanges:=True
seems to close the Workbook, but leaves the instance of Excel which opened the Workbook still active.
I use the following Sub to identify if any instance of Excel was loaded from the file whose fully qualified address is held in the variable “gstrMastreBalancesDataFull”, defined as
Public gstrMasterBalancesDataFull As String
Other relevant definitions are
Public gobjDBWkb As Workbook
Public Sub GetAllXLWindows()
Dim lngHWnd As Long
Dim lngHWndDesk As Long
Dim lngHWndMain As Long
Dim lngRet As Long
Dim objWkb As Workbook
Dim strClassName As String
Dim strMsg As String
Dim strText As String
gbooXLWasAlreadyOpen = False 'Pessimist!
'*
'** Returns Handle to XLMAIN (Top level
'** reference to Excel).
'*
lngHWndMain = FindWindowEx(0, 0, "XLMAIN", vbNullString)
'*
'** Is Excel running?
'*
If lngHWndMain <> 0 Then 'Yes!
'*
'* Load each instance of Excel
'** into a Collection.
'*
Set gcolWindows = New Collection
Do
'*
'** Find XLDESK (instance of Excel on Desktop).
'*
lngHWndDesk = FindWindowEx(lngHWndMain, 0, "XLDESK", vbNullString)
Do While lngHWndDesk <> 0
'*
'** For each Child of XLDESK....
'*
lngHWnd = FindWindowEx(lngHWndDesk, 0, vbNullString, vbNullString)
Do While lngHWnd <> 0
'*
'** Set up a string of 100 nulls, to be used
'** by GetclassName to return the Class Name.
'** Note, the length of the name is the
'** result of GetClassName
'*
strText = String$(100, Chr$(0))
'*
'** Get the Class Name
'** We're looking for "EXCEL7", which is
'** the Class name for a Workbook.
'*
lngRet = GetClassName(lngHWnd, strText, 100)
strClassName = Left(strText, lngRet)
Select Case strClassName
Case "EXCEL7" 'Excel Workbook
strText = String$(100, Chr$(0))
lngRet = GetWindowText(lngHWnd, strText, 100)
If lngRet > 0 Then
'*
'**Add XLObject to the collection, with a
'** key of the lngHWnd.
'*
gcolWindows.Add funGetXlObjFromHwnd(lngHWnd), CStr(lngHWnd)
End If
Case "EXCEL6" 'Worksheet cell in edit mode.
Case "NUIPANE" '?? (Found by inspection)
End Select
lngHWnd = FindWindowEx(lngHWndDesk, lngHWnd, vbNullString, vbNullString)
Loop 'End of Child loop
lngHWndDesk = FindWindowEx(lngHWndMain, lngHWndDesk, vbNullString, vbNullString)
Loop
'*
'** Get next Windows object
'*
lngHWndMain = FindWindowEx(0&, lngHWndMain, "XLMAIN", vbNullString)
Loop While lngHWndMain <> 0
'*
'** End of Discovery phase.
'*
On Error Resume Next
For lngRet = 1 To gcolWindows.Count
Set objWkb = gcolWindows(lngRet)
If objWkb.Windows(1).Visible And _
Not objWkb.IsAddin And _
objWkb.FullName = gstrMasterBalancesDataFull Then
Set gobjDBWkb = objWkb
gbooXLWasAlreadyOpen = True
End If
Next lngRet 'Examine next Collection item.
End If
End Sub 'GetAllXLWindows
Note that it is also possible that the User may have other unrelated instances of Excel open, so if I were to issue a sort of "Find Excel and shut it down", I'd probably shut every instance down, which I don't want to do.
I've tried
gobjDBWkb.Quit after the Close,
but I just get "Automation error - The Object invoked has disconnected from its clients".
Any ideas? (Please!)