🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA SendKeys dans Excel — syntaxe, codes de touches, et pourquoi tout s'exécute dans le désordre

|

VBA SendKeys dans Excel — syntaxe, codes de touches, et pourquoi tout s'exécute dans le désordre

TL;DR — SendKeys n'appuie sur aucune touche. Il dépose des frappes dans une file, et c'est la fenêtre qui a le focus au moment où elles sont lues qui les reçoit. Deux conséquences expliquent presque toutes les plaintes à son sujet. Les touches envoyées à Excel ne sont lues que lorsque votre macro rend la main, à la fin ou sur un DoEvents : les lignes qui suivent SendKeys s'exécutent donc d'abord. Et les touches envoyées à un autre programme vont à la fenêtre qui a le focus quand elles arrivent, qui n'est pas forcément celle que vous visiez. Des caractères comme + ^ % ~ ( ) sont des codes : un 50% littéral doit s'écrire 50{%}. N'utilisez SendKeys qu'en dernière ligne d'une macro, pour laisser l'interface d'Excel dans un état utile à l'utilisateur. Pour tout le reste, un appel du modèle objet fait le travail directement.

Sub EditNoteCell()
    Range("D2").Select
    SendKeys "{F2}"                 ' derniere ligne : l'utilisateur arrive en mode Modification dans D2
End Sub

Voici le troisième article d'une série consacrée aux macros qu'Excel lance pour vous : depuis une touche de raccourci, depuis l'horloge avec OnTime, et ici, depuis des frappes simulées. L'idée de la série : aucun de ces mécanismes n'appelle quoi que ce soit directement ; chacun dépose une demande dans une file, et la demande est traitée quand Excel est inactif et disponible. Pour SendKeys, la demande est une frappe, et la file est l'entrée clavier de la fenêtre qui se trouve au premier plan.

Ce que vous allez apprendre

  • Le modèle mental : des frappes dans une file, livrées à la fenêtre qui a le focus
  • La syntaxe, les codes de touches, et comment envoyer des caractères spéciaux littéraux
  • Pourquoi SendKeys semble s'exécuter dans le désordre
  • Le focus, la mauvaise fenêtre, et pourquoi SendKeys ne peut pas tourner sans surveillance
  • L'effet de bord sur le Verr Num
  • Les rares tâches pour lesquelles SendKeys convient, et quoi utiliser à la place

Le modèle mental : des frappes dans une file

Quand vous appuyez sur une touche, Windows la place dans la file d'entrée de la fenêtre qui a le focus, et ce programme la lit quand il en a le temps. SendKeys écrit dans cette même file, comme si les touches avaient été tapées.

SendKeys décide donc ce qui est tapé, mais ni quand c'est lu, ni qui le lit :

  • Quand : le programme destinataire lit sa file quand il est libre. Si le destinataire est Excel, Excel est occupé à exécuter votre macro : il lit donc les touches une fois que votre macro a rendu la main.
  • Qui : les touches vont à la fenêtre qui a le focus au moment où elles sont lues, pas à celle que vous aviez en tête en écrivant la ligne.

Gardez ces deux questions à l'esprit, et les comportements étranges deviennent prévisibles.

Syntaxe et codes de touches

Il existe deux formes, avec les mêmes arguments :

SendKeys "^c"                       ' instruction VBA
Application.SendKeys "^c"           ' methode d'Excel
SendKeys "~", True                  ' Wait:=True, attendre que les touches soient traitees

La plupart des touches s'écrivent telles quelles : SendKeys "abc" tape abc. Les modificateurs et les touches nommées utilisent des codes :

Code Touche
^ Ctrl, comme dans ^s pour Ctrl+S
+ Maj, comme dans +{F10} pour Maj+F10
% Alt, comme dans %{DOWN} pour Alt+Bas
~ ou {ENTER} Entrée
{TAB}, {ESC}, {BS}, {DEL} Tab, Échap, Retour arrière, Suppr
{UP}, {DOWN}, {LEFT}, {RIGHT} touches fléchées
{HOME}, {END}, {PGUP}, {PGDN} navigation
{F1} à {F16} touches de fonction
{LEFT 3} une touche répétée 3 fois
+(abc) Maj maintenue pendant qu'on appuie sur a, b et c

Il n'y a pas de code pour la touche Windows ni pour Impr écran, et SendKeys ne sait pas cliquer avec la souris.

Les caractères spéciaux littéraux doivent être entre accolades

Comme + ^ % ~ ( ) sont des codes, on ne peut pas les taper comme du texte. Ceci envoie 50, puis appuie sur Alt :

SendKeys "Discount 50%"             ' faux : % signifie Alt
SendKeys "Discount 50{%}"           ' juste : les accolades le rendent litteral

Les caractères à mettre entre accolades sont + ^ % ~ ( ) { } [ ]. Si le texte provient d'une cellule ou d'une saisie utilisateur, échappez-le dans une fonction plutôt qu'à la main :

Function EscapeKeys(ByVal s As String) As String
    Dim i As Long, ch As String, result As String
    For i = 1 To Len(s)
        ch = Mid$(s, i, 1)
        If InStr("+^%~(){}[]", ch) > 0 Then
            result = result & "{" & ch & "}"
        Else
            result = result & ch
        End If
    Next i
    EscapeKeys = result
End Function

Pourquoi SendKeys semble s'exécuter dans le désordre

C'est la question la plus fréquente : le code qui suit SendKeys s'exécute avant les touches. Un exemple typique :

Sub CopyWithKeys()
    Range("A1:C10").Select
    SendKeys "^c"                   ' mis en file, pas encore lu
    Worksheets("Report").Paste      ' s'execute maintenant : le Presse-papiers est encore vide
End Sub

SendKeys a placé Ctrl+C dans la file d'Excel et a rendu la main aussitôt. Excel lira la file quand il sera libre, et il ne l'est pas : il exécute CopyWithKeys. Paste s'exécute donc en premier, et la copie a lieu après la fin de la macro. Wait:=True n'y change rien, car Excel ne peut pas traiter des touches qui lui sont destinées tant que votre code tourne encore. Un DoEvents après le SendKeys laisse parfois passer les touches, et parfois non, ce qui est pire que jamais.

La règle qui en découle : les touches envoyées à Excel vont sur la dernière ligne de la macro. Rien de ce qui doit se passer après ne doit en dépendre. Et ici, la bonne réponse n'est pas de corriger le minutage, mais d'utiliser le modèle objet, qui s'exécute exactement au moment où la ligne s'exécute :

Range("A1:C10").Copy Destination:=Worksheets("Report").Range("A1")

Le guide copier-coller présente l'ensemble des méthodes de copie.

Le focus décide de qui reçoit les touches

Quand vous envoyez des touches à un autre programme, c'est la seconde question qui prend le dessus : qui a le focus au moment où les touches sont lues ?

Shell "notepad.exe", vbNormalFocus
Application.Wait Now + TimeSerial(0, 0, 1)   ' en esperant que le Bloc-notes soit pret d'ici la
SendKeys "Monthly total: 1250~"

Si le Bloc-notes tarde à s'ouvrir, les touches arrivent dans Excel et se tapent dans une cellule. Si une notification, un e-mail ou une fenêtre de discussion prend le focus pendant cette seconde, le texte part là-bas. Sur un écran verrouillé ou une session à distance réduite, les touches ne vont nulle part. Et Windows bloque les touches envoyées par un programme ordinaire à un programme exécuté en tant qu'administrateur : SendKeys vers une fenêtre élevée ne fait rien, en silence.

D'où une règle absolue pour le travail sans surveillance : SendKeys ne peut pas tourner quand personne ne regarde. Une macro lancée par OnTime ou par le Planificateur de tâches et qui utilise SendKeys finira, tôt ou tard, par taper au mauvais endroit. Pour piloter un autre programme, utilisez son modèle objet via CreateObject, ou lancez-le avec des arguments via Shell.

L'effet de bord sur le Verr Num

Un effet de bord connu de longue date : sur beaucoup de machines Windows, l'instruction VBA SendKeys désactive le Verr Num (Num Lock), et touche parfois au Verr Maj. Les utilisateurs remarquent que leur pavé numérique ne répond plus après avoir lancé votre macro.

Un code qui envoie {NUMLOCK} pour le rétablir ne fait que le basculer de nouveau : il a raison sur certaines machines et tort sur d'autres. Application.SendKeys le provoquerait moins souvent que l'instruction, mais aucun des deux n'est fiable. La vraie correction est la même que pour tout le reste de cette page : envoyer moins de touches. Une macro qui n'utilise SendKeys qu'une fois, en dernière ligne, se fait rarement remarquer pour cela.

Le parti pris : un dernier recours, pour l'interface d'Excel

SendKeys convient à un seul type de tâche : laisser l'interface d'Excel dans un état utile à l'utilisateur, en dernière ligne d'une macro. Mettre une cellule en mode Modification avec {F2}, ou ouvrir une liste déroulante de filtre avec %{DOWN}, sont des usages raisonnables, parce que l'utilisateur est là et que rien dans votre code ne dépend du résultat.

Pour tout le reste, il existe un appel direct qui s'exécute quand la ligne s'exécute, quelle que soit la disposition du clavier et quelle que soit la fenêtre au premier plan :

Ce pour quoi on envoie des touches À utiliser à la place
^c, ^v pour copier-coller Range.Copy, PasteSpecial
^s pour enregistrer ThisWorkbook.Save
~ pour répondre à une invite d'Excel Application.DisplayAlerts = False
des séquences % pour une commande du ruban Application.CommandBars.ExecuteMso "PasteValues"
ouvrir une boîte de dialogue intégrée Application.Dialogs(xlDialogPrint).Show
taper dans un autre programme son modèle objet via CreateObject

Les séquences de raccourcis comme Alt, H, V, V dépendent en outre de la langue d'Office : les lettres du ruban (les touches d'accès) ne sont pas les mêmes dans un Excel anglais, allemand, espagnol ou français, où l'onglet Accueil ne s'appelle pas Home et ne répond pas à la même lettre. Une séquence SendKeys écrite sur l'un est donc fausse sur l'autre. Les appels de la colonne de droite n'ont pas ce problème : ExecuteMso désigne la commande par un identifiant interne, identique dans toutes les langues. Le guide DisplayAlerts montre comment gérer les invites d'Excel sans appuyer sur la moindre touche.

Comment ExcelMaster aide

Un code SendKeys fonctionne en général sur la machine où il a été écrit, le jour où il a été écrit. Il casse sur une autre disposition de clavier, un PC plus lent, une autre langue d'Office, ou la première fois qu'une notification vole le focus.

ExcelMaster lit la macro, comprend ce que chaque ligne SendKeys essaie de faire, et la remplace par l'appel du modèle objet qui fait le même travail directement : la macro ne dépend plus ni du minutage, ni du focus, ni de la disposition du clavier.

Questions fréquentes

Comment envoyer la touche Entrée avec SendKeys ?

Utilisez SendKeys "~" ou SendKeys "{ENTER}". Le tilde correspond à la touche Entrée principale ; {ENTER} correspond à la touche Entrée du pavé numérique, et les deux fonctionnent dans la plupart des programmes.

Pourquoi SendKeys ne fonctionne-t-il pas dans ma macro ?

En général il fonctionne, mais plus tard que prévu : les touches envoyées à Excel sont lues une fois que votre macro a rendu la main, donc les lignes qui suivent SendKeys s'exécutent d'abord. Les touches envoyées à un autre programme vont à la fenêtre qui a le focus au moment où elles sont lues. Placez SendKeys sur la dernière ligne, ou remplacez-le par un appel du modèle objet.

Pourquoi SendKeys désactive-t-il le Verr Num ?

C'est un effet de bord connu de longue date de l'instruction VBA SendKeys sous Windows. Renvoyer {NUMLOCK} ne fait que le basculer et n'est pas fiable. Utilisez SendKeys le moins possible.

Quelle est la différence entre SendKeys et Application.SendKeys ?

SendKeys est l'instruction VBA et Application.SendKeys la méthode d'Excel. Ils acceptent les mêmes codes de touches et le même argument Wait. Tous deux écrivent dans la file d'entrée de la fenêtre qui a le focus.

Comment envoyer un signe pourcentage ou un signe plus avec SendKeys ?

Mettez-le entre accolades : {%}, {+}, {^}, {~}, {(} et {)}. Sans accolades, ces caractères sont lus comme Alt, Maj, Ctrl, Entrée et des codes de regroupement.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 03/10/2026.

Guides connexes : VBA Shortcut Key · VBA OnTime · VBA Copy Paste · VBA DisplayAlerts · VBA DoEvents · VBA Shell · VBA CreateObject · VBA Wait