TL;DR — Placez
Public gTaxRate As Doubleen tête d'un module standard, au-dessus de toutes les procédures, et chaque procédure du classeur peut la lire et la modifier. C'est la moitié facile. La moitié difficile, c'est qu'une globale ne garde sa valeur que tant que le projet VBA reste chargé, et le projet est réinitialisé plus souvent qu'on ne le croit : une instructionEnd, le bouton Réinitialiser, une erreur non gérée que l'utilisateur termine, une modification dans l'éditeur VBA, la fermeture du classeur. Après une réinitialisation, chaque globale revient à0,""ouNothing, sans le moindre avertissement. Ne lisez donc jamais une globale que vous n'avez pas vérifiée à l'instant : passez par une fonction qui la reconstruit quand elle est vide, et stockez dans le classeur lui-même tout ce qui doit survivre à la session.
' Module1 - tout en haut, au-dessus de toute Sub ou Function
Option Explicit
Public gTaxRate As Double ' visible par tous les modules de ce projet
Sub SetUp()
gTaxRate = 0.19
End Sub
Sub UseIt()
Debug.Print gTaxRate ' 0.19 - jusqu'a la reinitialisation du projet, puis 0
End Sub
Voici le premier volet d'une série de trois sur l'endroit où vit une valeur. Toute variable a une portée — qui peut la voir — et une durée de vie — combien de temps elle se souvient. Une globale est la plus large sur les deux plans : tout le projet, jusqu'à ce que le projet se réinitialise. Une variable Static garde la longue durée de vie mais réduit la portée à une seule procédure. Un paramètre Optional réduit les deux à un seul appel, la valeur étant fournie par l'appelant. Ma règle pour toute la série : choisissez la plus étroite qui fonctionne.
Ce que vous allez apprendre
- Le modèle mental : la portée, c'est qui voit une valeur ; la durée de vie, combien de temps elle dure
- Comment déclarer une globale, et Public, Global ou Dim en tête de module
- Ce qui réinitialise une globale, et pourquoi la valeur disparaît sans erreur
- L'accesseur autoréparant qui rend une réinitialisation inoffensive
- Le
Dimlocal qui masque votre globale en silence, et l'erreur de nom ambigu - Les variables Public dans les modules de feuille, de ThisWorkbook et de UserForm
- Comment conserver une valeur après la fermeture du classeur
Le modèle mental : portée et durée de vie sont deux questions différentes
L'endroit où vous déclarez une variable répond à deux questions à la fois. La portée, c'est qui peut la voir. La durée de vie, c'est combien de temps elle garde sa valeur. VBA connaît trois niveaux :
| Déclarée | Mot-clé | Portée | Durée de vie |
|---|---|---|---|
Dans une Sub ou une Function |
Dim |
cette procédure uniquement | jusqu'à la fin de la procédure |
| En tête d'un module | Dim ou Private |
toutes les procédures de ce module | jusqu'à la réinitialisation du projet |
| En tête d'un module standard | Public (ou Global) |
toutes les procédures du projet | jusqu'à la réinitialisation du projet |
Le guide Dim couvre la première ligne. Cet article porte sur la dernière, et le fait essentiel se trouve dans la dernière colonne : les variables de niveau module et les variables publiques ne vivent pas jusqu'à la fermeture d'Excel, et elles ne meurent pas non plus quand la procédure qui les a définies se termine. Elles vivent exactement aussi longtemps que l'état du projet, et cet état est plus fragile qu'il n'y paraît.
Déclarer une globale : Public, Global, et où placer la ligne
Une globale doit se trouver dans la section Déclarations d'un module standard : après Option Explicit,
avant la première procédure. Placez la même ligne dans une Sub et VBA la refuse, car Public n'est pas
autorisé à l'intérieur d'une procédure.
Option Explicit
Public gUserName As String ' tout le projet
Global gRunCount As Long ' la meme chose, mot-cle plus ancien
Private mCache As Object ' ce module uniquement
Dim mLastRow As Long ' ce module uniquement, lui aussi
Sub Demo()
' Public x As Long ici serait une erreur de compilation
End Sub
Global est l'ancienne graphie de Public. Il ne fonctionne que dans les modules standard et n'apporte rien :
utilisez Public. Au niveau module, Dim et Private veulent dire la même chose ; préférez Private, parce
qu'il dit ce que vous voulez dire. Un préfixe comme g pour les globales et m pour les variables de niveau
module ne coûte rien et évite le bogue d'une section plus loin.
Si la valeur ne change jamais, ce n'est pas du tout une variable. Utilisez
Public Const VAT_RATE As Double = 0.19 qui, comme le montre le guide Const, ne peut
ni dériver ni être réinitialisée.
La règle qui mord : une globale ne vit que tant que le projet vit
Voici l'échec que tout le monde rencontre. Une macro définit gTaxRate au premier clic, un second bouton
l'utilise, et tout fonctionne toute la matinée. Après le déjeuner, le second bouton calcule avec 0. Aucune
erreur n'a été levée. Le projet a été réinitialisé entre-temps, et une réinitialisation remet chaque variable
de niveau module et chaque variable publique à sa valeur vide :
- Une instruction
Ends'exécute quelque part ; le guide End montre qu'elle efface tout l'état d'un coup. - Vous appuyez sur Réinitialiser (le bouton carré) dans l'éditeur VBA, ou choisissez Exécution > Réinitialiser.
- Une erreur d'exécution non gérée apparaît et l'utilisateur clique sur Fin dans la boîte de dialogue.
- Vous modifiez du code dans l'éditeur VBA : changer une déclaration ou ajouter un module peut forcer une recompilation qui réinitialise le projet. En mode arrêt, Excel demande d'abord ; sinon, cela arrive tout simplement.
- Le classeur qui contient le code est fermé.
Ce qui ne la réinitialise pas : la procédure qui a défini la valeur se termine normalement, une erreur
interceptée par votre propre gestionnaire On Error, ou Exit Sub. C'est cette
asymétrie qui fait paraître le bogue aléatoire. Il apparaît le jour où quelqu'un tombe sur une erreur non
gérée, ou sur votre propre machine juste après que vous avez modifié le code.
La solution : accéder à une globale par un accesseur autoréparant
N'essayez pas d'empêcher les réinitialisations : vous ne le pouvez pas. Rendez-les plutôt inoffensives. Gardez
la variable Private et exposez une fonction qui la reconstruit chaque fois qu'elle est vide :
Option Explicit
Private mRates As Object ' Scripting.Dictionary, construit a la demande
Public Function Rates() As Object
If mRates Is Nothing Then
Dim r As Range
Set mRates = CreateObject("Scripting.Dictionary")
For Each r In ThisWorkbook.Worksheets("Rates").Range("A2:A50")
If Len(r.Value) > 0 Then mRates(r.Value) = r.Offset(0, 1).Value
Next r
End If
Set Rates = mRates
End Function
Sub PriceOrder()
Debug.Print Rates()("EUR") ' fonctionne apres n'importe quelle reinitialisation - l'accesseur recharge
End Sub
Chaque appelant interroge Rates() au lieu de lire mRates directement. Si une réinitialisation l'a vidée,
le premier appelant après la réinitialisation paie le coût du rechargement, et personne ne voit de mauvaise
réponse. La même structure fonctionne pour une valeur simple : testez si elle vaut 0 ou "", et rechargez-la
depuis sa source. Le guide Dictionary couvre l'objet de cache lui-même.
Le piège silencieux : un Dim local du même nom
Le deuxième bogue classique ne fait intervenir aucune réinitialisation :
' Module1
Public gTotal As Double
Sub AddSales()
Dim gTotal As Double ' une NOUVELLE variable locale qui masque la globale
gTotal = gTotal + 100 ' ne modifie que la copie locale
End Sub
Sub ShowTotal()
MsgBox gTotal ' toujours 0
End Sub
Un Dim de niveau procédure portant le même nom qu'une globale la masque : dans AddSales, le nom
gTotal désigne la variable locale. VBA l'accepte sans broncher, et
Option Explicit ne peut rien y faire, puisque les deux variables sont
déclarées. La solution, c'est l'habitude de nommage : les globales commencent par g, et vous ne déclarez
jamais avec Dim un nom en g à l'intérieur d'une procédure.
La collision inverse, elle, lève une erreur. Si Module1 et Module2 déclarent tous deux Public Total, un
troisième module qui écrit Total obtient Ambiguous name detected (nom ambigu détecté) à la compilation.
Qualifiez-la en Module1.Total, ou mieux, donnez un seul propriétaire à chaque globale.
Public dans un module de feuille, de ThisWorkbook ou de UserForm
Public en tête d'un module de feuille, de ThisWorkbook ou d'un UserForm ne crée pas une globale. Il crée
une propriété de cet objet : les autres modules doivent donc nommer l'objet pour l'atteindre :
' Dans le module de code de Sheet1
Public Threshold As Double
' Dans Module1
Sub Check()
Sheet1.Threshold = 500 ' qualifie - cela fonctionne
' Threshold = 500 ' Variable not defined (avec Option Explicit)
End Sub
Ces modules sont des modules objet, si bien que certaines choses n'y sont pas autorisées comme membres
Public : les tableaux, les constantes, les chaînes de longueur fixe et les types définis par l'utilisateur
provoquent tous une erreur de compilation. Un UserForm ajoute sa propre durée de vie : UserForm1.SomeValue
est perdu dès que le formulaire est déchargé, ce que le guide UserForm illustre avec
Unload Me contre Me.Hide. Pour une vraie variable à l'échelle du projet, utilisez un module standard.
Conserver une valeur après la fermeture du classeur
Aucune variable ne survit à la fermeture du classeur. Si une valeur doit encore être là la semaine prochaine — la date de la dernière exécution, un choix de l'utilisateur, un compteur —, écrivez-la dans le fichier :
Sub RememberLastRun()
ThisWorkbook.Worksheets("Settings").Range("B2").Value = Now
End Sub
Function LastRun() As Date
LastRun = ThisWorkbook.Worksheets("Settings").Range("B2").Value
End Function
Une feuille de paramètres rendue très masquée, comme dans le guide Hide Sheet, la garde hors de vue. Une plage nommée masquée fonctionne aussi. Dans les deux cas, le fichier est la mémoire et la variable n'en est qu'une copie rapide — la même idée que l'accesseur ci-dessus.
Le jugement : des globales pour les paramètres et les caches, des arguments pour les données
Les globales ne sont pas maléfiques ; elles sont simplement partagées, et un état partagé est difficile à raisonner. N'importe quelle procédure peut modifier une globale : quand elle contient la mauvaise valeur, il faut fouiller tout le projet pour savoir qui l'a écrite. Ma règle : utilisez une globale pour ce que tout le projet lit et que presque rien n'écrit, comme des paramètres chargés une fois et des caches derrière un accesseur. Quand une procédure doit transmettre des données à une autre, passez-les en argument, avec ByVal ou ByRef choisi délibérément. Si une seule procédure doit se souvenir de quelque chose entre deux appels, une variable Static lui donne cette mémoire sans la partager.
Comment ExcelMaster vous aide
Les bogues de variables globales ressemblent rarement à des bogues de variables globales. Ils ressemblent à un bouton qui fonctionnait ce matin et qui calcule maintenant avec zéro, ou à un total qui ne change jamais parce qu'une copie locale a reçu la mise à jour.
ExcelMaster vous laisse décrire
ce que les macros doivent faire, par exemple « charge les taux une fois et utilise-les dans toutes les macros
de tarification ». Il place l'état partagé derrière un accesseur qui survit aux réinitialisations, fait
circuler les données par des arguments, et repère dans le code existant le Dim local qui masque une globale.
Questions fréquentes
Comment déclarer une variable globale en VBA ?
Écrivez Public suivi du nom et du type, par exemple Public gTaxRate As Double, en tête d'un module
standard, avant la première Sub ou Function. Chaque procédure du projet peut alors la lire et la modifier.
La déclarer à l'intérieur d'une procédure provoque une erreur de compilation.
Quelle est la différence entre Public et Global en VBA ?
Aucune qui compte. Global est l'ancien mot-clé et ne fonctionne que dans les modules standard ; Public
fait le même travail et fonctionne aussi dans les modules de classe, de feuille et de UserForm. Utilisez
Public.
Pourquoi ma variable globale VBA perd-elle sa valeur ?
Le projet VBA a été réinitialisé. Une instruction End, le bouton Réinitialiser de l'éditeur, une erreur non
gérée où l'utilisateur clique sur Fin, certaines modifications du code et la fermeture du classeur effacent
toutes les variables de niveau module et toutes les variables publiques. Accédez à la valeur par une fonction
qui la recharge quand elle est vide.
Comment conserver la valeur d'une variable après la fermeture du classeur ?
Stockez-la dans le classeur, pas dans une variable : une cellule d'une feuille de paramètres masquée, un nom
défini masqué ou une propriété du document. Relisez-la à l'ouverture du classeur, par exemple dans
l'événement Workbook_Open.
Un UserForm peut-il utiliser une variable globale ?
Oui. Déclarez la variable Public dans un module standard, et le code du formulaire peut la lire et la
modifier. Une variable Public déclarée dans le propre module du UserForm appartient au formulaire et est
perdue quand le formulaire est déchargé.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 01/10/2026.
Guides associés : VBA Static Variable · VBA Optional Parameter · VBA Dim · VBA Const · VBA End · VBA ByRef contre ByVal · VBA Dictionary · VBA Option Explicit
