Testé sur : Excel 365 v2509 · Excel 2021 · Excel 2019 · dernière vérification le 07/06/2026
En bref — Un Sub (sous-routine) est un bloc d'actions nommé qui s'exécute quand on l'appelle et ne renvoie rien. La macro que vous lancez depuis la boîte Macros est un Sub. On l'appelle par son nom, avec ou sans le mot-clé Call :
Sub SaluerUtilisateur() ' un Sub : une suite d'actions nommée, sans valeur de retour
MsgBox "Bonjour !"
End Sub
Sub LancerRapport()
SaluerUtilisateur ' on l'appelle — sans Call, sans parenthèses
Call SaluerUtilisateur ' résultat identique, juste l'ancienne écriture Call
End Sub
Mal appeler un Sub mène à « Erreur de compilation : attendu = » ou « attendu : fin d'instruction » — l'erreur de Sub la plus fréquente. Tout ce guide tourne autour du pourquoi.
Le modèle mental : un Sub est un verbe que vous appelez par son nom
Voyez un Sub comme une action nommée — un verbe. MettreEnFormeRapport, ExporterFactures, SupprimerAnciennesLignes. Vous définissez les étapes une fois, vous leur donnez un nom, et dès lors vous lancez ces étapes de n'importe où en disant le nom.
Ce que la plupart des tutoriels taisent : il n'existe pas de type « macro » distinct en VBA. Quand vous enregistrez une macro ou en choisissez une dans Développeur → Macros, vous exécutez en réalité un simple Sub — précisément un Sub public sans argument. « Macro » n'est que le mot convivial qu'Excel montre aux utilisateurs ; dessous, c'est un Sub. Une fois ce déclic fait, tout le projet VBA cesse d'être magique et devient une liste d'actions nommées que vous reliez entre elles.
La seule règle : la façon d'appeler décide des parenthèses
Voici la règle qui explique presque toutes les erreurs de débutant :
' Sans argument — les trois sont valides :
SaluerUtilisateur
Call SaluerUtilisateur
Call SaluerUtilisateur()
' AVEC arguments — seules ces deux écritures sont valides :
EcrireLog "rapport.txt", 3 ' ✅ appel direct : PAS de parenthèses, arguments séparés par des virgules
Call EcrireLog("rapport.txt", 3) ' ✅ avec Call : parenthèses OBLIGATOIRES
EcrireLog("rapport.txt", 3) ' ❌ Erreur de compilation : attendu =
La dernière ligne échoue parce que, sans Call, VBA lit EcrireLog( … ) comme « évalue EcrireLog et utilise sa valeur de retour » — or un Sub n'a pas de valeur de retour, et "rapport.txt", 3 n'est de toute façon pas une expression unique. Les parenthèses appartiennent à Call, pas à l'appel direct. C'est exactement la logique de la règle des parenthèses de MsgBox : les parenthèses n'apparaissent que lorsqu'une valeur est utilisée.
En une phrase : appel direct → pas de parenthèses ; mot-clé Call → parenthèses. Choisissez un style et tenez-vous-y. Le VBA moderne abandonne souvent Call tout court.
Une macro est un Sub public — Private le cache
Que votre Sub apparaisse dans la boîte Macros tient à un seul mot devant lui :
Public Sub ClotureMensuelle() ' visible dans la liste Macros (Alt+F8) — c'est « une macro »
PreparerDonnees ' appelle un assistant que l'utilisateur ne voit jamais
ConstruireSynthese
End Sub
Private Sub PreparerDonnees() ' masqué de la liste Macros — un simple assistant
' ...
End Sub
Public (par défaut pour un Sub simple) signifie « tout le monde peut l'appeler et le montrer à l'utilisateur ». Private signifie « seul le code de ce module l'appelle ». Réservez Private aux petits Subs assistants qui font une étape chacun — la boîte Macros reste propre et le mot signale « ce n'est pas un point d'entrée ». Un Sub qui prend des arguments disparaît aussi automatiquement de la liste, car Excel ne peut pas savoir quoi lui passer.
Faire entrer des données : les arguments
Un Sub devient réutilisable dès qu'il cesse de coder en dur des valeurs et se met à les recevoir :
Sub SurlignerLigne(ligneCible As Long, indiceCouleur As Long)
Rows(ligneCible).Interior.ColorIndex = indiceCouleur
End Sub
Sub MarquerEnRetard()
SurlignerLigne 5, 3 ' ligne 5 en rouge
SurlignerLigne 9, 6 ' ligne 9 en jaune
End Sub
La façon dont ces arguments voyagent — si le Sub appelé peut modifier la variable passée — est un piège qui mérite sa propre page. Le défaut en VBA est ByRef, l'original peut donc être modifié à votre insu. Voir ByRef vs ByVal pour le piège derrière « pourquoi mon compteur a-t-il changé après cet appel ? ».
Les procédures d'événement sont des Subs — et ne peuvent pas être autre chose
Chaque événement de feuille ou de classeur que vous avez écrit est un Sub, sans alternative :
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A:A")) Is Nothing Then
MsgBox "Colonne A modifiée."
End If
End Sub
Excel les appelle quand quelque chose se produit (une cellule change, le classeur s'ouvre) et ne lit aucune valeur de retour — ce ne peuvent donc être que des Subs, jamais des Functions. Cette asymétrie rend la frontière Sub/Function limpide : si l'appelant ne veut pas de réponse, c'est un Sub.
L'avis tranché : un Sub, une tâche
Le chemin le plus rapide vers du VBA impossible à maintenir, c'est le Sub Main() de 300 lignes qui importe, nettoie, calcule, met en forme et envoie — tout d'un trait. Découpez-le en Subs nommés qui font chacun une chose :
Public Sub LancerPipeline()
ImporterDonnees
NettoyerDonnees
ConstruireRapport
EnvoyerRapport
End Sub
Désormais LancerPipeline se lit comme une table des matières, chaque étape se teste seule, et quand l'envoi casse vous réparez EnvoyerRapport sans défiler 250 lignes étrangères. Un nom de Sub est une documentation qui ne peut pas dater — elle s'exécute. C'est l'unique habitude qui sépare le VBA qui survit un an du VBA que personne n'ose plus toucher.
Erreurs fréquentes de Sub (et la correction)
| Symptôme | Cause | Correction |
|---|---|---|
| « attendu = » à l'appel | Parenthèses sur un appel direct : MonSub(a, b) |
Retirer les parenthèses (MonSub a, b) ou ajouter Call : Call MonSub(a, b) |
| Macro absente d'Alt+F8 | Sub Private, ou avec arguments |
Le rendre Public sans argument, ou l'appeler depuis un wrapper sans argument |
| « Nom ambigu détecté » | Deux Subs de même nom dans un module | En renommer un — les noms doivent être uniques par module |
| Le Sub s'exécute mais « rien ne se passe » | Un Sub écrit là où il fallait une valeur de retour | Utiliser une Function quand l'appelant a besoin d'une réponse |
| Argument modifié de façon inattendue | Le ByRef par défaut a laissé le Sub muter la variable |
Déclarer le paramètre ByVal — voir ByRef vs ByVal |
| « Sub ou Function non défini » | Faute de frappe, ou le Sub est dans un autre module/classeur | Vérifier l'orthographe ; qualifier par le module/classeur si besoin |
Quand la macro elle-même est le difficile — décrivez-la, c'est tout
Découper le travail en Subs propres est du bon artisanat, mais cela reste de la plomberie à écrire et à maintenir. Si la logique est « importe ces trois fichiers, rapproche-les sur l'ID de commande, signale les écarts, envoie à la compta », le vrai travail n'est pas le découpage en Subs — c'est le code dedans. ExcelMaster Agent vous laisse dire cela en français courant et écrit tout le pipeline pour vous — sans Sub, sans Call, sans maintenance. Essayer gratuitement →
Guides liés
- VBA Function dans Excel — Valeurs de retour & fonctions personnalisées
- VBA ByRef vs ByVal — Pourquoi votre variable a changé après un appel
- VBA MsgBox dans Excel — Oui/Non, boutons & la règle des parenthèses
- VBA Boucle For dans Excel — 8 exemples concrets
FAQ
Qu'est-ce qu'un Sub en VBA ?
Un Sub (sous-routine) est un bloc de code VBA nommé qui exécute des actions et ne renvoie aucune valeur. On le définit par Sub Nom() … End Sub et on le lance en appelant son nom. Les macros que vous lancez depuis la boîte Macros d'Excel sont des Subs.
Quelle différence entre un Sub et une macro ?
Aucune sur le plan technique. « Macro » est seulement le nom destiné à l'utilisateur d'un Sub public sans argument — le seul type qui apparaît dans la liste Développeur → Macros (Alt+F8). Toute macro est un Sub ; tout Sub n'est pas affiché comme macro.
Comment appeler un Sub en VBA ?
De deux façons équivalentes : écrire le nom seul — MonSub (ou MonSub arg1, arg2 avec arguments, sans parenthèses) — ou utiliser le mot-clé Call — Call MonSub(arg1, arg2) (parenthèses obligatoires). Ne mettez pas de parenthèses sur un appel direct à plusieurs arguments : c'est une erreur de compilation.
Pourquoi MonSub(a, b) provoque-t-il une erreur de compilation ?
Sans le mot-clé Call, VBA interprète les parenthèses comme « utilise la valeur de retour de ce Sub », mais un Sub n'en a pas, et a, b n'est pas une expression unique. Retirez les parenthèses (MonSub a, b) ou ajoutez Call (Call MonSub(a, b)).
Quelle différence entre Sub et Function en VBA ?
Un Sub fait un travail et ne renvoie rien ; une Function fait un travail et renvoie une valeur à l'appelant. Prenez une Function quand l'appelant a besoin d'une réponse (et quand vous voulez l'utiliser comme formule de feuille) ; un Sub pour tout le reste.
Que signifie Private Sub en VBA ?
Private Sub rend la procédure appelable uniquement dans le même module et la masque de la boîte Macros. Réservez-le aux assistants qui ne sont pas destinés à être lancés directement par l'utilisateur. Les procédures d'événement comme Worksheet_Change sont Private Sub pour cette raison.
