création d'une fonction getobject améliorée

patricktoulon

XLDnaute Barbatruc
Bonjour a tous pour une fois c'est moi qui suis collé

alors voila je voudrais créer une fonction getobject
cette fonction existe déjà me direz vous
oui pour un object application elle retourne la première instance de celle ci les autres walouh!!!!
je me suis donc mis dans la tète d'en faire une qui me ramènerait un tableau d'object "application "
on a malgré tout diverses possibilités ou façons de lister les fenêtres ouvertes ou instance d’application entre autre les api Windows voir aussi WMI
ce pendant pour ramener ces éléments a des object application et pouvoir donc les utiliser comme tel c'est une autre affaire
comment pourrais-je faire par exemple avec cette petite sub WMI?
Code:
Sub nb_instances()
Dim strComputer As String, WMIService As Object, TaBlExcel As Object
strComputer = "."
Set WMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set TaBlExcel = WMIService.execquery("select * from win32_process where name='EXCEL.EXE'")
Debug.Print "Nombre d'instances : " & TaBlExcel.Count
Set WMIService = Nothing
Set TaBlExcel = Nothing
End Sub

je voudrais par exemple prendre le classeur(1) de TaBlExcel(1)
MsgBox TaBlExcel(1).Workbooks(1).Name

malheureusement TaBlExcel n'est pas un tableau d'object "application"
si vous avez des idées ou des pistes je suis preneur

merci pour les éventuels retours





 

patricktoulon

XLDnaute Barbatruc
Re

@patricktoulon
Tout le mérite revient à l'auteur du code (voir commentaire dans la PJ)
Moi je n'ai fait qu'ouvrir le tiroir de mes archives ;)

PS: Tu as testé sur un classeur vierge (comme indiqué dans mon précédent message)

Tu trouves aussi deux instances ??

[PS:]

Tu pourras la publier ici, stp?
Que je la range dans un autre tiroir de mes archives ;)


ah ben ca fait plaisir je vois que le sujet intéresse
bon ben voila petite dédicace pour staple 1600
oui je publie ici la fonction
la voila
code complet
comme tu peux le voir j'ai tout regrouper en une je ne sépare pas le test d'accessibilité
je donne même un lien en français montrant un exemple (quand on sais ou chercher c'st plus facile)
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

'*******************************************************************************************
'un exemple ici EN ANGLAIS  de l'utilisation  de l'api AccessibleObjectFromWindow
'lien:https://social.msdn.microsoft.com/Forums/office/en-US/e3e99712-01a7-483e-bf0e-52bb1f94889c/how-to-use-accessibleobjectfromwindow-api-in-vba-to-get-excel-application-object-from-excel?forum=exceldev
'*******************************************************************************************

Function GetAllInstanceExceL()
    Dim x, hWinDesk&, hWin7&, hWndXL&, Tablexcel() As Object, oWB As Object, oWS As Object, obj As Object, iID As GUID, oXLApp As Object
    hWndXL = FindWindowEx(0&, 0&, "XLMAIN", vbNullString)    'trouve le premier handle excel
    Do While hWndXL > 0    'boucle jusqu'a que ""hWndXL"" retourne "0"!!
        x = x + 1    '// Incrementation de la variable x
        hWinDesk = FindWindowEx(hWndXL, 0&, "XLDESK", vbNullString)    'on descend d'un enfant de "XLMAIN"
        hWin7 = FindWindowEx(hWinDesk, 0&, "EXCEL7", vbNullString)    'on descend au petit fils de "XLMAIN"
        'Debug.Print "Instance #" & x & ": "; "Handle: " & hWndXL    '/juste Pour control provisoire affichage dans la fenetre d'execution
        Call IIDFromString(StrPtr(IID_IDispatch), iID)    'construction de "IID" avec le clisd(IID_IDispatch)pour lecture des propriété de la fenetre correspondant au handle
        If AccessibleObjectFromWindow(hWin7, OBJID_NATIVEOM, iID, obj) = RETURN_OK Then ReDim Preserve Tablexcel(1 To x): Set Tablexcel(x) = obj.Application ' test dispo d'assecibilité de la fenetre :"obj" retourne un object
        hWndXL = FindWindowEx(0, hWndXL, "XLMAIN", vbNullString)
        'un exemple ici en francais de l'api AccessibleObjectFromWindow :https://social.msdn.microsoft.com/Forums/office/en-US/e3e99712-01a7-483e-bf0e-52bb1f94889c/how-to-use-accessibleobjectfromwindow-api-in-vba-to-get-excel-application-object-from-excel?forum=exceldev
    Loop
    GetAllInstanceExceL = Tablexcel
End Function

Sub test()
    Dim instances, wb As Workbook, i
    instances = GetAllInstanceExceL
    For i = 1 To UBound(instances)
        For Each wb In instances(i).Workbooks
            Debug.Print "instance : " & i & "  " & wb.Name
        'l'object instances(i) et son ".wb"   peuvent être exploité de toute les manières identiquement à des object instanciés ou nommés en dur dans le code 
       Next
    Next
End Sub
 

eriiic

XLDnaute Barbatruc
Pour les versions supérieures, le résultat affiché n'est pas des plus probant, non ?
Je n'ai pas 2013.
A-priori chaque classeur est dans un processus indépendant, qui apparaissent comme autant d'instances dans la fonction.
Là c'est une question de vocabulaire et de définitions. Peut-être que MS parle d'instance unique un peu par abus de langage, mais visuellement c'est vrai.
Et on pourrait considérer que la fonction à raison vu que les processus sont bien séparés (?)
eric

PS : vous pouvez deviner mes origines normandes ;-)
p’têt ben qu’oui, p’têt ben qu’non
 

patricktoulon

XLDnaute Barbatruc
ah je le connais celui la d'eriiiic même si il y a un "i" en plus ;)
un xla activé est forcement accessible par tout les classeurs donc c'est pas une question qui me titille plus que ca
maintenant si il est activé par macro dans un des classeur peut être j'ai pas testé
toujours est il que l'on peut lister les complément activés dans chaque classeurs par macro ,parti de la 3 4 lignes ajouté et tu a tes xla listés dans leur instances on pourrait même lui ajouter un tag dans l'object retourné pour le différencier des workbooks
la difficulté etait de pourvoir retourné des object application , ce qui est fait (merci staple1600)
on pourrais insérer le listage des xla juste avant de shoper le handle next en bas de fonction (si c'est un ".xla" ajouter 1 a x et le conter comme un classeur le name donnera aussi son extention"xla(m)" il sera donc bien identifier et bien typé dans TablexceL
 

Staple1600

XLDnaute Barbatruc
Re

Attends, il faut que j'arrive à récréer le plantage
(C'était dans la macro test sur cette ligne : Debug.Print "instance : " & i & " " & wb.Name)

Sinon sur Excel 2013, ton code produit des infos redondantes
Test simple
J'ouvre Excel, je copie/colle ton code, je lance la macro
instance : 1 Classeur1

J'ajoute un nouveau classeur (CTRL+N), j'efface la fenêtre Exécution et je relance la macro.
instance : 1 Classeur1
instance : 1 Classeur2
instance : 2 Classeur1
instance : 2 Classeur2

Bizarre, non ?
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
Sinon sur Excel 2013, ton code produit des infos redondantes
a bon!???
je n'ai pas modifier grand chose a ton code pourtant
bon apres je sais qu'avec 2013 les handles sont classer un peu différemment de 2007 je l'ai déjà remarqué dans d'autres exercices
un exemple concret en listant les handle du ruban il y en a un en moins par rapport a 2007 je ne sais plus quelle displaybars n'existe plus dans 2013
les deux sont en une en fait il faudrait que je cherche dans mes archives
c'est peu être ca modifier peu être les deux findwindowhex (fils/petit fils)
 

Statistiques des forums

Discussions
312 108
Messages
2 085 375
Membres
102 876
dernier inscrit
BouteilleMan