Préambule :
Il s'agit ici principalement de montrer une des capacités de la Méthode ExecuteExcel4Macro.
La manière de procéder décrite ici, utilisant un "intermédiaire", sera toujours moins efficiente qu'un appel direct (par référence ou par appel dans l'entête d'un module).
Excel offre indirectement cette "possibilité" aux autres langages de programmation (VBS ou JS) pour l'appel des fonctions de l'api windows par exemple.

J'ajoute que cette méthode est également utilisable (avec encore d'autres paramètres) à d'autres fins que celles de l'utilisation de fonctions de dll (lancement d'exécutables, etc ...)

Extrait de l'aide en ligne :
Méthode Application.ExecuteExcel4Macro
Exécute une fonction macro Microsoft Excel 4.0, puis renvoie le résultat de la fonction.
Le type renvoyé dépend de la fonction.

Syntaxe :
expression.ExecuteExcel4Macro(String)
expression : Variable représentant un objet Application.
Paramètres :
String : Obligatoire de type Chaîne (String) : Fonction de langage macro Microsoft Excel 4.0 sans signe égal.
Si String contient des guillemets, vous devez les doubler.
Valeur renvoyée : Variant
La syntaxe utilisée ici :
Application.ExecuteExcel4Macro("CALL(""NomDeLaDll"",""NomDeLaFonction"",""Paramètre"",""Arg1"",""Arg2""...)")

Remarque : les guillemets sont doublés (cf paragraphe de l'aide en ligne)

Les paramètres à passer à cette Méthode sont :
  1. Le nom de la dll,
  2. Le nom de la fonction,
  3. Paramètre : indique le type de valeur de retour de la fonction,
  4. Les arguments à passer à la fonction.

Le plus délicat est la détermination de ce paramètre ("JJJJ", "JJCJ", "CCC", "JCA", "2JN", "2JRJRR#" etc ...).
Mes recherches ne m'ayant pas permis de lire une documentation quant à leur détermination, il nous faut les trouver par essais successifs.

Dans les exemples qui suivent, pour des raisons évidentes (VBA ne le permettant pas), nous n'allons pas créer de dll.
Nous allons donc simplement appeler des fonctions de l'api Windows.

Utilisation simple : Simuler un clic gauche
Pour cela, il nous faut faire appel à la DLL user32 et particulièrement à sa fonction mouse_event.
Cette fonction, normalement utilisée dans VBA, serait déclarée, en entête de module, comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Public Declare Sub mouse_event Lib "user32" _
	(ByVal dwFlags As Long, ByVal dx As Long, _
	ByVal dy As Long, ByVal dwData As Long, ByVal dwExtraInfo As Long)
et appelée par exemple comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
Sub ClicGauche()
    mouse_event 2, 0, 0, 0, 0 'Mouse_Down (Left Button)
    mouse_event 4, 0, 0, 0, 0 'Mouse_Up (Left Button)
End Sub
Le paramètre à passer obligatoirement à cette fonction est : dwFlags As Long.
Il peut prendre les valeurs suivantes :
  • 2 : Bouton gauche down
  • 4 : Bouton gauche up
  • 8 : bouton droit down
  • 16 : bouton droit up
  • 32 : bouton du milieu down
  • 64 : bouton du milieu up


Avec la syntaxe exposée plus haut, nous allons nous créer 4 Sub : Pause, Clic_Gauche, Mouse_Down_Left et Mouse_Up_Left :

La Pause utilise la fonction Sleep de la librairie Kernel32 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Public Sub Pause(MilliSec As Long) 'utilisée par ClicGauche
    ExecuteExcel4Macro ("CALL(""kernel32"",""Sleep"",""JJJJJJ""," & MilliSec & ")")
End Sub
Les Mouse_Down et Up utilisent la fonction mouse_event de la librairie (dll) user32 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
Private Sub Mouse_Down_Left() 'utilisée par ClicGauche
     ExecuteExcel4Macro ("CALL(""User32"",""mouse_event"",""JJJJJJ""," & "2" & ")")
End Sub
Private Sub Mouse_Up_Left() 'utilisée par ClicGauche
    ExecuteExcel4Macro ("CALL(""User32"",""mouse_event"",""JJJJJJ""," & "4" & ")")
End Sub
Et enfin, le code d'appel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
Public Sub Clic_Gauche()
    Mouse_Down_Left
    Pause 25
    Mouse_Up_Left
End Sub
Remarque : nous aurions pu créer des fonctions pour récupérer une erreur éventuelle.

Mais là, vous vous dites que c'est bien plus compliqué pour un résultat moins rapide.
C'est très exactement ce que j'annonçais dans le préambule : on ne fait ici que décrire une capacité d'une méthode moins efficiente.

Appel d'une fonction paramétrée
L'exemple choisi ici sera utilisé dans la dernière partie de cette contribution relative au déplacement d'un UserForm.
Il s'agit de la fonction FindWindow de la dll user32.
Elle sert à obtenir le Handle d'une fenêtre Windows, par exemple de la fenêtre application ou d'un UserForm.

Le code de la fonction paramétrée :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
Public Function FindWindo(ClassName As String, Caption As String) As Long
'FindWindowA
    FindWindo = ExecuteExcel4Macro("CALL(""user32"",""FindWindowA"",""JCC""," & """" & ClassName & """" & ", " & """" & Caption & """)")
End Function
Le code d'appel (à partir d'un bouton d'UserForm par exemple) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Private Sub CommandButton2_Click()
    MsgBox FindWindo("ThunderDFrame", Me.Caption)
End Sub
Remarque : Le nom de la classe est ici obligatoire. La fonction retourne une erreur si vous l'omettez ou le remplacez par vbNullString.
Attention la classe des UserForm est différente selon les versions.

Appel d'une fonction dans une autre fonction :
Même principe que pour une fonction paramétrée, sauf que l'on remplace ici la variable par une fonction.
Pour l'exemple, nous allons retourner la couleur du pixel sous le pointeur de la souris.
Nous utiliserons donc :
  • Pour trouver la position de la souris : La fonction GetMessagePos de la librairie user32
  • Pour trouver la couleur du pixel : La fonction GetPixel de la librairie gdi32
  • Pour créer un contexte : La fonction GetWindowDC de la librairie user32
  • Pour retourner la valeur : la fonction MessageBox de la librairie user32


Détermination des coordonnées X et Y de la position de la souris :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
Private Function GetPosition() 'utilisée par GetX et GetY
    GetPosition = ExecuteExcel4Macro("CALL(""user32"",""GetMessagePos"",""J"")")
End Function
 
Public Function GetX()
    GetX = CLng("&H" & Right(Hex(GetPosition), 4))
End Function
 
Public Function GetY()
    GetY = CLng("&H" & Left(Hex(GetPosition), (Len(Hex(GetPosition)) - 4)))
End Function
Création du "Device Context" et retour de la couleur du pixel (à noter ici l'appel de la fonction GetWindoDC à l'intérieur de GetPixel) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
Public Function GetPixel(X, Y)
    GetPixel = ExecuteExcel4Macro("CALL(""gdi32"",""GetPixel"",""JJJJJJ""," & GetWindoDC & "," & X & "," & Y & ")")
End Function
 
Private Function GetWindoDC() 'utilisée par GetPixel
    GetWindoDC = ExecuteExcel4Macro("CALL(""user32"",""GetWindowDC"",""JJJJJJ"")")
End Function
Génération d'une MsgBox :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Public Function MessageBox(StrMessage As String)
    ExecuteExcel4Macro ("CALL(""user32"", ""MessageBoxA"", ""JJCCJ"", 0," & StrMessage & ",0)")
End Function
Finalement, le code d'appel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Sub Quelle_Couleur()
    MessageBox GetPixel(GetX, GetY)
End Sub
Exemple d'utilisation : Déplacer, avec la souris, un UserForm sans barre de fenêtre
Pour l'exemple, nous avons besoin :
  1. D'un Userform nommé UserForm1,
  2. Sur cet UserForm, un bouton de commande : CommandButton1.


Cet UserForm sera présenté sans barre de fenêtre (cf Sub Masque_Barre) et pourra être déplacé manuellement en maintenant la touche Shift et le clic gauche de la souris enfoncés simultanément (cf Sub DeplaceForm et événement UserForm_MouseDown).

Le code, à placer dans le module de l'UserForm, est :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Option Explicit
 
Private LeHwnD As Long
 
'=================== Evénements
Private Sub CommandButton1_Click()
    Unload Me
End Sub
 
Private Sub UserForm_Initialize()
    Masque_Barre Me.Caption
End Sub
 
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'permet le déplacement de l'Userform par la combinaison Shift + clic gauche
    If Button = 1 And Shift = 1 Then DeplaceForm
End Sub
 
'=================== Procédures
Public Sub Masque_Barre(strCapt As String)
Dim style As Long, index As Long
 
    index = -16
    LeHwnD = FindWindo("ThunderDFrame", strCapt)
    style = GetWindoLong(LeHwnD, index) And Not &HC00000
    SetWindoLong LeHwnD, index, style
    DrawMenuB LeHwnD
End Sub
 
'=================== Utilisations des fonctions de l'api
Public Sub DeplaceForm()
'ReleaseCapture & SendMessageA
'https://www.developpez.net/forums/d1517529/autres-langages/general-visual-basic-6-vbscript/vbscript/vos-contributions-vbscript/hta-deplacer-hta-n-barre-titre-bordures/
    ExecuteExcel4Macro "CALL(""user32"",""ReleaseCapture"",""JJ"")"
    ExecuteExcel4Macro "CALL(""user32"",""SendMessageA"",""JJJJJ"",""" & LeHwnD & """,""" & &HA1 & """,""" & &O2 & """,""0"")"
End Sub
 
Private Function FindWindo(ClassName As String, Caption As String) As Long
'FindWindowA
    FindWindo = ExecuteExcel4Macro("CALL(""user32"",""FindWindowA"",""JCC""," & """" & ClassName & """" & ", " & """" & Caption & """)")
End Function
 
Private Function GetWindoLong(ByVal hwnd As Long, ByVal nIndex As Long) As Long
'GetWindowLongA
    GetWindoLong = ExecuteExcel4Macro("CALL(""user32"",""GetWindowLongA"",""JCA""," & hwnd & ", " & nIndex & ")")
End Function
 
Private Sub SetWindoLong(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long)
'SetWindowLongA
    ExecuteExcel4Macro ("CALL(""user32"",""SetWindowLongA"",""JJJJJ""," & hwnd & ", " & nIndex & ", " & dwNewLong & ")")
End Sub
 
Private Sub DrawMenuB(H As Long)
'DrawMenuBar
    ExecuteExcel4Macro ("CALL(""user32"",""DrawMenuBar"",""JJ"", " & H & ")")
End Sub
Conclusion :
Voyez cette contribution comme la présentation d'une curiosité, d'une possibilité offerte par la Méthode ExecuteExcel4Macro.
Je le répète, il sera toujours préférable d'appeler directement ces fonctions.
Je dois néanmoins vous avouer que je me suis bien amusé dans cet exercice...

Merci à unparia pour la relecture.