TL;DR —
SendKeysn'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 unDoEvents: les lignes qui suiventSendKeyss'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 : un50%littéral doit s'écrire50{%}. N'utilisezSendKeysqu'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
