If you are interested in trying to sort out multiply Excel active objects then the below script using GetActiveObjects might help:
Code: Select all
; Lexikos example to get all active objects
for name, obj in GetActiveObjects()
list .= name " -- " ComObjType(obj, "Name") "`n"
MsgBox %list%
; FanaticGuru example of GetExcel class method Xls
Xls := GetExcel.Xls()
for index, Xl in Xls
for Workbook in Xl.Workbooks
MsgBox % Workbook.name "`n" Workbook.Windows(1).Visible
; FanaticGuru example of GetExcel class method Wbs
Wbs := GetExcel.Wbs(,1) ; only visible workbooks
for index, Wb in Wbs
MsgBox % Wb.Name "`n" Wb.Windows(1).Visible
class GetExcel
{
Xls(Needle := "")
{
Xls := {}
for index, obj in GetActiveObjects()
{
try
Name := obj.Application.ActiveWorkbook.Name
catch
continue
if (RegExMatch(index, "(^|\\)" Name "$") and RegExMatch(Name, Needle))
Xls.Push(obj.Application)
}
return Xls
}
Wbs(Needle := "", Visible := "")
{
Wbs := {}
Xls := GetExcel.Xls()
for index, Xl in Xls
for Workbook in Xl.Workbooks
if RegExMatch(Workbook.Name, Needle)
if (Visible = 1 and Workbook.Windows(1).Visible)
Wbs.Push(Workbook)
else if (Visible = 0 and not Workbook.Windows(1).Visible)
Wbs.Push(Workbook)
else if (Visible = "")
Wbs.Push(Workbook)
return Wbs
}
}
; GetActiveObjects v1.0 by Lexikos
; http://ahkscript.org/boards/viewtopic.php?f=6&t=6494
GetActiveObjects(Prefix:="", CaseSensitive:=false) {
objects := {}
DllCall("ole32\CoGetMalloc", "uint", 1, "ptr*", malloc) ; malloc: IMalloc
DllCall("ole32\CreateBindCtx", "uint", 0, "ptr*", bindCtx) ; bindCtx: IBindCtx
DllCall(NumGet(NumGet(bindCtx+0)+8*A_PtrSize), "ptr", bindCtx, "ptr*", rot) ; rot: IRunningObjectTable
DllCall(NumGet(NumGet(rot+0)+9*A_PtrSize), "ptr", rot, "ptr*", enum) ; enum: IEnumMoniker
while DllCall(NumGet(NumGet(enum+0)+3*A_PtrSize), "ptr", enum, "uint", 1, "ptr*", mon, "ptr", 0) = 0 ; mon: IMoniker
{
DllCall(NumGet(NumGet(mon+0)+20*A_PtrSize), "ptr", mon, "ptr", bindCtx, "ptr", 0, "ptr*", pname) ; GetDisplayName
name := StrGet(pname, "UTF-16")
DllCall(NumGet(NumGet(malloc+0)+5*A_PtrSize), "ptr", malloc, "ptr", pname) ; Free
if InStr(name, Prefix, CaseSensitive) = 1 {
DllCall(NumGet(NumGet(rot+0)+6*A_PtrSize), "ptr", rot, "ptr", mon, "ptr*", punk) ; GetObject
; Wrap the pointer as IDispatch if available, otherwise as IUnknown.
if (pdsp := ComObjQuery(punk, "{00020400-0000-0000-C000-000000000046}"))
obj := ComObject(9, pdsp, 1), ObjRelease(punk)
else
obj := ComObject(13, punk, 1)
; Store it in the return array by suffix.
objects[SubStr(name, StrLen(Prefix) + 1)] := obj
}
ObjRelease(mon)
}
ObjRelease(enum)
ObjRelease(rot)
ObjRelease(bindCtx)
ObjRelease(malloc)
return objects
}
For me when I have one normal "Test" workbook open in Excel and run Lexikos code to show all active objects, I can see Excel objects like:
Code: Select all
C:\Program Files (x86)\Microsoft Office\Office14\Library\Analysis\ATPVBAEN.XLAM -- _Workbook
C:\Program Files (x86)\Microsoft Office\Office14\Library\Analysis\FUNCRES.XLAM -- _Workbook
C:\Program Files (x86)\Microsoft Office\Office14\Library\SOLVER\SOLVER.XLAM -- _Workbook
C:\Users\FG\AppData\Roaming\Microsoft\Excel\XLSTART\PERSONAL.XLSB -- _Workbook
C:\Users\FG\Desktop\Test\Test.xlsx -- _Workbook
I am not really interested in those plugin workbooks from Analysis and Solver. Those are Microsoft extensions you can turn on in Excel to give you additional special functions and abilities. I am also not generally interested in that Personal workbook. That is a hidden workbook that contains various default stuff.
So I wrote a GetExcel class that sorts out plugin stuff and does not return them and also allows me the option to show or not show hidden workbooks. I guess I could have made the class have an option to return the plugin stuff but I never foresee a situation where I would need to use COM with those Excel objects.
FG