As the title says - will find all instances of Excel and list (to the debug window) all workbooks open. Can be very easily extended for other functionality
Code
Option Explicit
Private Declare Function FindWindowEx Lib "User32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Private Declare Function IIDFromString Lib "ole32" _
(ByVal lpsz As Long, ByRef lpiid As GUID) As Long
Private Declare Function AccessibleObjectFromWindow Lib "oleacc" _
(ByVal hWnd As Long, ByVal dwId As Long, ByRef riid As GUID, _
ByRef ppvObject As Object) As Long
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Private Const RETURN_OK As Long = &H0
Private Const IID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}"
Private Const OBJID_NATIVEOM As Long = &HFFFFFFF0
Sub ComplexTest()
Dim iCounter As Long
Dim hWndXL As Long
Dim oXLApp As Object
Dim oWB As Object
Dim oWS As Object
'// First the first Excel Window
hWndXL = FindWindowEx(0&, 0&, "XLMAIN", vbNullString)
'// Got one, at least...?
Do While hWndXL > 0
'// Increment counter
iCounter = iCounter + 1
'// Print Instance & Handle to Debug window
Debug.Print "Instance #" & iCounter & ": "; "Handle: " & hWndXL
'// Get a reference to it
If GetReferenceToXLApp(hWndXL, oXLApp) Then
'// Iterate through the workbook
For Each oWB In oXLApp.Workbooks
'// Print Workbook name to DEBUG window
Debug.Print , oWB.Name
'// It would be easy enough to check for a workbook name
'// and close it here - the name would be passed as a
'// parameter and the procedure changed to a function
'// to return Success, or otherwise, to the calling procedure
'// With oWB
'// .Saved = True
'// .Close
'// End With
'// List worksheets
For Each oWS In oWB.Worksheets
Debug.Print , , oWS.Name
Next
Next
End If
'// Find the next Excel Window
hWndXL = FindWindowEx(0, hWndXL, "XLMAIN", vbNullString)
Loop
End Sub
'// Returns a reference to a specific instance of Excel.
'// The Instance is defined by the Handle (hWndXL) passed
'// by the calling procedure
Function GetReferenceToXLApp(hWndXL As Long, oXLApp As Object) As Boolean
Dim hWinDesk As Long
Dim hWin7 As Long
Dim obj As Object
Dim iID As GUID
'// Rather than explaining, go read
'// http://msdn.microsoft.com/en-us/library/windows/desktop/ms687262(v=vs.85).aspx
Call IIDFromString(StrPtr(IID_IDispatch), iID)
'// We have the XL App (Class name XLMAIN)
'// This window has a child called 'XLDESK' (which I presume to mean 'XL desktop')
'// XLDesk is the container for all XL child windows....
hWinDesk = FindWindowEx(hWndXL, 0&, "XLDESK", vbNullString)
'// EXCEL7 is the class name for a Workbook window (and probably others, as well)
'// This is used to check there is actually a workbook open in this instance.
hWin7 = FindWindowEx(hWinDesk, 0&, "EXCEL7", vbNullString)
'// Deep API... read up on it if interested.
'// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317978(v=vs.85).aspx
If AccessibleObjectFromWindow(hWin7, OBJID_NATIVEOM, iID, obj) = RETURN_OK Then
Set oXLApp = obj.Application
GetReferenceToXLApp = True
End If
End Function
Display More