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 GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
' based on code from StackOverflow here:
' http://stackoverflow.com/questions/2971473/can-vba-reach-across-instances-of-excel
Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, ByRef lpiid As UUID) As Long
Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As Long, ByVal dwId As Long, ByRef riid As UUID, ByRef ppvObject As Object) As Long
Type UUID 'GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Const IID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}"
Const OBJID_NATIVEOM As Long = &HFFFFFFF0
Sub ListXLWorkbooks()
Dim vWorkbooks
vWorkbooks = GetXLWorkbooks
For n = LBound(vWorkbooks) To UBound(vWorkbooks)
MsgBox vWorkbooks(n).Name
Next n
End Sub
Private Function GetXLWorkbooks()
Dim hWndMain As Long
Dim hWndDesk As Long
Dim hWnd As Long
Dim lRet As Long
Dim y As Long
Dim sText As String
Dim oWb As Workbook
Dim oDic As scripting.Dictionary
Dim aWorkbooks()
hWndMain = FindWindowEx(0&, 0&, "XLMAIN", vbNullString)
If hWndMain <> 0 Then
Set oDic = CreateObject("Scripting.Dictionary")
Do
hWndDesk = FindWindowEx(hWndMain, 0&, "XLDESK", vbNullString)
Do While hWndDesk <> 0
hWnd = FindWindowEx(hWndDesk, 0, vbNullString, vbNullString)
Do While hWnd <> 0
sText = String$(100, Chr$(0))
lRet = GetClassName(hWnd, sText, 100)
If Left$(sText, lRet) = "EXCEL7" Then
sText = String$(100, Chr$(0))
lRet = GetWindowText(hWnd, sText, 100)
' add to collection
If lRet > 0 Then oDic.Add CStr(hWnd), GetExcelObjectFromHwnd(hWnd)
End If
hWnd = FindWindowEx(hWndDesk, hWnd, vbNullString, vbNullString)
Loop
hWndDesk = FindWindowEx(hWndMain, hWndDesk, vbNullString, vbNullString)
Loop
hWndMain = FindWindowEx(0&, hWndMain, "XLMAIN", vbNullString)
Loop While hWndMain <> 0
If oDic.Count > 0 Then
ReDim aWorkbooks(1 To oDic.Count)
For y = 1 To oDic.Count
Set aWorkbooks(y) = oDic.Items(y - 1)
Next y
GetXLWorkbooks = aWorkbooks
End If
End If
End Function
Public Function GetExcelObjectFromHwnd(ByVal hWnd As Long) As Excel.Workbook
' requires the handle to a workbook (i.e. EXCEL7 class) window
On Error GoTo MyErrorHandler
Dim iid As UUID
Call IIDFromString(StrPtr(IID_IDispatch), iid)
Dim obj As Object
If AccessibleObjectFromWindow(hWnd, OBJID_NATIVEOM, iid, obj) = 0 Then 'S_OK
Set GetExcelObjectFromHwnd = obj.Parent
End If
Exit Function
MyErrorHandler:
MsgBox "GetExcelObjectFromHwnd" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Function
Bookmarks