VBA - évènement à l'activation d'Excel

Bonjour,

Je souhaite qu'une macro s'exécute quand la fenêtre Excel devient active, par exemple quand je bascule du navigateur à Excel ou de Word à Excel.

Comment faire ?

Merci d'avance.

Daniel

Hello,

Private Sub Workbook_Activate()

End Sub

non ?

Bonjour,

Merci. Non, ça fonctionne quand tu actives un classeur dans Excel. Pas quand tu actives l'application Excel. Ce que je veux obtenir :

1. Firefox actif

2. raccourci Alt+Tab pour activer la fenêtre Excel => exécution de la macro.

Daniel

Bonjour le fil.
Daniel, c'est le serpent qui se mord la queue non ?

Pour qu'une macro fonctionne il faut que le classeur soit activé. Rien ne permet ce que tu veux faire; hormis une application externe en C# par exemple, qui écouterait les évènements Windows, puis si Excel est détectée comme application active, lancer une procédure via « COM ».

Mais ce dois être extérieur à Excel.

Hello,

@danielc ce que vous cherchez à faire n'est pas très net je trouve.

J'ai interrogé l'IA et au bout de moultes relances elle a fini par me donner un code qui a l'air fonctionnel, mais pu***naise faut vraiment insister pour avoir qqchose de fonctionnel.

je copie/colle

Pour intercepter le changement d'application Windows (de n'importe où vers Excel), il faut faire appel aux API Windows (User32.dll) avec la fonction SetWinEventHook ou surveiller le focus de l'application via un timer OnTime.Voici la méthode la plus stable et légère, basée sur une boucle de vérification du focus Windows :

1.Ajouter les déclarations d'API dans un Module standard :Dans PERSONAL.XLSB.Dans l'éditeur VBA (Alt + F11), va dans Insertion > Module (dans PERSONAL.XLSB) et colle ce code

#If VBA7 Then
    Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As LongPtr, lpdwProcessId As Long) As Long
    Private Declare PtrSafe Function GetCurrentProcessId Lib "kernel32" () As Long

#Else
    Private Declare Function GetForegroundWindow Lib "user32" () As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
#End If

Public EstActive As Boolean

Sub DemarrerSurveillance()
    Dim hwndActif As LongPtr
    Dim pidActif As Long

    hwndActif = GetForegroundWindow()
    Call GetWindowThreadProcessId(hwndActif, pidActif)

    ' Vérifie si la fenêtre active appartient au processus Excel
    If pidActif = GetCurrentProcessId() Then
        If Not EstActive Then
            EstActive = True
            ' --- TA MACRO ICI ---
            MsgBox "Excel a repris le focus depuis Windows !"
            ' ---------------------
        End If
    Else
        EstActive = False
    End If

    ' Reboucle toutes les secondes
    Application.OnTime Now + TimeValue("00:00:01"), "DemarrerSurveillance"
End Sub

Sub ArreterSurveillance()
    On Error Resume Next
    Application.OnTime Now + TimeValue("00:00:01"), "DemarrerSurveillance", , False
End Sub

2.Lancer la surveillance au démarrage :Dans ThisWorkbook.Double-clique sur ThisWorkbook (dans PERSONAL.XLSB) et colle :

Private Sub Workbook_Open()
    Call DemarrerSurveillance
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call ArreterSurveillance
End Sub

Comment vérifier :

Déclenche une première fois Workbook_Open (touche F5 dans le code) pour lancer la boucle.

Clique sur Firefox ou une autre application Windows.

Bascule à nouveau sur Excel : le message s'affiche immédiatement.

@Jean-Paul

Je me demandais si une API pouvait détecter que l’application était active (en avant plan) . Couplée avec une macro avec OnTime testant l'état de l’application par exemple. Si ce n'est pas possible, tant pis.

Daniel

bonjour

Moi:

je voulais avoir un évènement dans excel VBa qui ce déclenche a la prise de focus excel alors que même cet événement n'existe pas

DeepSeek :

la prise de focus d'Excel en VBA

Excel VBA n'expose pas d'événement natif pour la prise/perte de focus de l'application. Il faut passer par subclassing : intercepter le message Windows WM_ACTIVATEAPP envoyé à la fenêtre principale d'Excel via l'API SetWindowLongPtr.

1. Module standard (ex : modHook)

```vba

Option Explicit

#If VBA7 Then

Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" _

(ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr

Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _

(ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As Long, _

ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

#End If

Private Const GWL_WNDPROC As Long = -4

Private Const WM_ACTIVATEAPP As Long = &H1C

#If VBA7 Then

Private hWndExcel As LongPtr

Private pPrevWndProc As LongPtr

#End If

Public Sub HookExcelWindow()

hWndExcel = Application.hWnd ' handle de la fenêtre principale Excel

If hWndExcel <> 0 Then

pPrevWndProc = SetWindowLongPtr(hWndExcel, GWL_WNDPROC, AddressOf WndProc)

End If

End Sub

Public Sub UnhookExcelWindow()

If hWndExcel <> 0 And pPrevWndProc <> 0 Then

SetWindowLongPtr hWndExcel, GWL_WNDPROC, pPrevWndProc

hWndExcel = 0

pPrevWndProc = 0

End If

End Sub

' Procédure de rappel : DOIT être dans un module standard (pas ThisWorkbook, pas un UserForm)

Public Function WndProc(ByVal hWnd As LongPtr, ByVal Msg As Long, _

ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

If Msg = WM_ACTIVATEAPP Then

If wParam <> 0 Then

On Error Resume Next

ThisWorkbook.ExcelGotFocus ' ← à personnaliser

On Error GoTo 0

Else

On Error Resume Next

ThisWorkbook.ExcelLostFocus ' ← à personnaliser

On Error GoTo 0

End If

End If

WndProc = CallWindowProc(pPrevWndProc, hWnd, Msg, wParam, lParam)

End Function

```

2. Dans ThisWorkbook

```vba

Private Sub Workbook_Open()

HookExcelWindow

End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)

UnhookExcelWindow ' ⚠ indispensable, sinon crash Excel à la fermeture

End Sub

' Événement personnalisé appelé par le WndProc

Public Sub ExcelGotFocus()

' Ton code ici, ex :

' ThisWorkbook.Sheets(1).Range("A1").Value = Now

End Sub

Public Sub ExcelLostFocus()

' Optionnel : code quand Excel perd le focus

End Sub

```

Points importants

· Application.hWnd = handle de la fenêtre principale d'Excel. Pas besoin de FindWindow.

· WM_ACTIVATEAPP (&H1C) : wParam = 1 → l'appli prend le focus ; wParam = 0 → elle le perd. C'est bien plus fiable que WM_ACTIVATE, qui se déclenche aussi pour les UserForms internes.

· Le WndProc doit impérativement être dans un module standard (une Function Public), sinon AddressOf échoue.

· Toujours restaurer l'ancienne procédure (UnhookExcelWindow) dans Workbook_BeforeClose. Sinon Excel plante à la fermeture ("Excel a cessé de fonctionner").

· Sauvegarde le projet avant de tester : un crash pendant le hook peut empêcher l'enregistrement.

· Si tu veux tester à chaud sans rouvrir le fichier : mets HookExcelWindow dans un Sub et exécute-le manuellement, puis UnhookExcelWindow avant toute modif.

Hello,

en utilisant un serveur COM C# (sous forme d'une dll) qui surveille Windows avec UI Automation. Il détecte les événements (ouverture/fermeture de fenêtre, changement de focus, etc.), récupère les informations de l'élément et les transmet à VBA.

Du côté VBA : pilote le système de surveillance. Il démarre/arrête l'écoute, reçoit les événements envoyés par C#, et les affiche dans la ListView d'un formulaire.

Voici le code VBA :

module de classe CUIAEvents :

Option Explicit
Private WithEvents mUIA As comServ.UIAElemInfo
Public Sub Initialize(ByVal objUIA As comServ.UIAElemInfo)
    Set mUIA = objUIA
End Sub
Private Sub mUIA_OnUIEvent( _
    ByVal eventType As String, _
    ByVal elementName As String)
    HandleUIEvent eventType, elementName
End Sub
Public Sub StopEvents()
    Set mUIA = Nothing
End Sub

module standard :

Option Explicit

Public gUIA As comServ.UIAElemInfo
Public gUIAEvents As CUIAEvents
'==========================================================
' DÉMARRER
'==========================================================
Public Sub StartUIA()
    On Error GoTo ErrHandler
    Set gUIA = New comServ.UIAElemInfo
    Set gUIAEvents = New CUIAEvents
    gUIAEvents.Initialize gUIA
    'WindowOpened + WindowClosed + FocusChanged
    gUIA.SetEventFilter 67
    gUIA.StartListening
    Debug.Print "UI Automation démarrée."
    Exit Sub
ErrHandler:
    MsgBox "Erreur StartUIA :" & vbCrLf & _
           Err.Number & " - " & Err.Description, vbCritical
End Sub
'==========================================================
' ARRÊTER
'==========================================================
Public Sub StopUIA()
    On Error Resume Next
    If Not gUIA Is Nothing Then gUIA.StopListening
    If Not gUIAEvents Is Nothing Then gUIAEvents.StopEvents
    Set gUIAEvents = Nothing
    Set gUIA = Nothing
    Debug.Print "UI Automation arrêtée."
End Sub
'==========================================================
' RÉCEPTION DES ÉVÉNEMENTS
'==========================================================
Public Sub HandleUIEvent(ByVal eventType As String, _
                         ByVal elementName As String)

    Dim itm As ListItem
    On Error GoTo ErrHandler
    Debug.Print Format(Now, "dd/mm/yyyy hh:nn:ss") & _
                " | " & eventType & " | " & elementName
    If Not IsUserFormLoaded("frmUIA") Then Exit Sub
    With frmUIA.lvEvents
        Set itm = .ListItems.Add(, , _
                    Format(Now, "dd/mm/yyyy hh:nn:ss"))
        itm.SubItems(1) = eventType
        itm.SubItems(2) = elementName
        itm.EnsureVisible
    End With
    Exit Sub
ErrHandler:
    Debug.Print "Erreur HandleUIEvent : " & _
                Err.Number & " - " & Err.Description
End Sub
'==========================================================
' VÉRIFIER SI LE USERFORM EST CHARGÉ
'==========================================================
Public Function IsUserFormLoaded(ByVal FormName As String) As Boolean
    Dim frm As Object
    For Each frm In VBA.UserForms
        If frm.name = FormName Then
            IsUserFormLoaded = True
            Exit Function
        End If
    Next frm
End Function
'==========================================================
' AFFICHER LE FORMULAIRE
'==========================================================
Public Sub AfficherUIA()
    frmUIA.Show vbModeless
End Sub

Voici ce que cela donne :

onfocusxl

Ami calmant, J.P

Bonjour à tous,

Merci pour vos contributions.Je n'ai pas trop de disponibilités aujourd'hui mais je regarde vos solutions dès que possible et je vous fais un retour.

Daniel

Rechercher des sujets similaires à "vba evenement activation"