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

VBA Class Module dans Excel — créez votre propre objet (plan contre instance, et le piège As New)

|

VBA Class Module dans Excel — créez votre propre objet (plan contre instance, et le piège As New)

TL;DR — Un class module est un plan pour votre propre type d'objet. Vous l'écrivez une fois, puis vous créez autant d'instances indépendantes que vous voulez avec New. Deux choses piègent tout le monde : le nom du class module est le nom du type (il n'y a pas de mot-clé Class à l'intérieur), et les objets sont des types référence, si bien que Set b = a fait de a et b deux noms pour la même instance. Préférez le Set x = New clsThing explicite au Dim x As New clsThing, qui cache un piège d'instanciation paresseuse.

' --- Dans un class module nommé  clsEmployee  (renommez-le dans la fenêtre Propriétés) ---
Private mName As String
Private mSalary As Currency

Public Property Get Name() As String:   Name = mName:      End Property
Public Property Let Name(v As String):  mName = v:         End Property
Public Property Get Salary() As Currency: Salary = mSalary: End Property
Public Property Let Salary(v As Currency): mSalary = v:     End Property

Public Function AnnualCost() As Currency   ' le comportement vit avec les données
    AnnualCost = mSalary * 1.3             ' salaire + 30 % de charges
End Function

' --- Dans un module normal ---
Sub Demo()
    Dim e As clsEmployee
    Set e = New clsEmployee        ' crée une instance
    e.Name = "Sarah"
    e.Salary = 65000
    MsgBox e.Name & " costs " & e.AnnualCost   ' 84500
End Sub

Un Type regroupe des champs. Un class module va un cran plus loin : il regroupe les champs et le code qui agit dessus, et vous donne un véritable objet que vous pouvez créer, dont vous pouvez copier les références, et que vous pouvez stocker dans une Collection. C'est ce que VBA offre de plus proche de la programmation orientée objet — et, bien utilisé, cela transforme un fouillis de variables éparses et de Sub utilitaires en une poignée d'objets autonomes.

Ce que vous allez apprendre

  • Le modèle mental — un plan à partir duquel vous fabriquez des instances
  • Pourquoi il n'y a pas de mot-clé Class (le nom du module est le type)
  • Créer des instances — Set ... = New, et le piège As New
  • La règle qui surprend — les objets partagent, ils ne copient pas
  • Initialisation et libération — Class_Initialize, et le constructeur manquant
  • Quand une classe l'emporte sur un Type ou une Collection

Le modèle mental : un plan, pas le bâtiment

Un class module est un plan ; chaque New en construit une instance. Le plan clsEmployee décrit ce que tout objet employé possède (un nom, un salaire) et fait (AnnualCost). Ce n'est pas lui-même un employé — c'est le plan. Set e = New clsEmployee construit un employé bien réel avec ses propres données ; faites-le trois fois et vous avez trois objets indépendants, chacun avec son nom et son salaire, tous bâtis d'après le même plan.

Gardez cette distinction en tête. Presque toutes les confusions autour des class modules — « pourquoi n'y a-t-il pas de nom dans la classe ? », « pourquoi modifier un objet en a-t-il changé un autre ? » — se dissipent dès qu'on sépare le plan (la classe) d'une instance (un objet créé par New).

Pourquoi il n'y a pas de mot-clé Class

Venant d'autres langages, on ouvre un class module en cherchant une ligne du genre Class clsEmployee. Il n'y en a pas, et la taper est une erreur de compilation. En VBA, le nom du class module est le nom du type. Vous renommez le type d'objet en renommant le module dans la fenêtre Propriétés (F4), pas avec un mot-clé dans le code.

Le déroulé est donc : insérez un class module, appuyez sur F4, réglez (Name) sur clsEmployee (le préfixe cls est la convention courante), et commencez à déclarer ses membres directement. Le fichier est la classe ; son nom est le type que vous écrivez après As.

Créer des instances : Set = New, et le piège As New

Il y a deux façons de créer un objet, et elles ne sont pas équivalentes :

' Explicite (recommandé)
Dim e As clsEmployee
Set e = New clsEmployee     ' créé exactement ici, sur cette ligne

' Auto-instanciation (plus net en apparence, cache deux pièges)
Dim e As New clsEmployee    ' PAS encore créé — créé à la première utilisation

La forme As New est séduisante parce qu'elle tient sur une ligne, mais elle cache deux vrais problèmes :

  • Vous ne pouvez jamais tester If e Is Nothing. Avec As New, à l'instant où vous touchez e pour le vérifier, VBA l'instancie — donc Is Nothing est en pratique toujours False. Vous perdez la possibilité de demander « cet objet a-t-il seulement été créé ? ».
  • Il ressuscite tout seul. Affectez Nothing à une variable As New, puis référencez-la de nouveau, et VBA crée en silence une nouvelle instance — un objet zombie qui réapparaît alors que vous le croyiez détruit.

Règle : préférez Dim e As clsEmployee + Set e = New clsEmployee. Cela crée l'objet à une ligne prévisible, et cela garde Is Nothing porteur de sens, pour vous prémunir contre les objets non initialisés. Et n'oubliez jamais le Set : écrire e = New clsEmployee sans lui déclenche l'erreur 91, « Variable objet ou variable de bloc With non définie » — la même règle valeur-contre-objet qui veut que les objets s'affectent avec Set, pas avec =.

La règle qui surprend : les objets partagent, ils ne copient pas

C'est l'image inversée de l'article sur le Type, et c'est la source la plus profonde des bugs de class module. Un objet est un type référence. Set b = a ne copie pas l'objet — il copie la référence, si bien que a et b pointent désormais vers la même instance :

Dim a As clsEmployee, b As clsEmployee
Set a = New clsEmployee
a.Salary = 50000
Set b = a               ' les deux noms -> UNE seule instance
b.Salary = 70000        ' modifie l'objet partagé
Debug.Print a.Salary    ' 70000  — a « a changé tout seul »

Si vous vouliez en réalité deux employés indépendants, Set b = a est un bug. VBA n'a aucune copie automatique pour les objets ; vous écrivez une méthode Clone qui renvoie une nouvelle instance avec les mêmes valeurs de champs. Et si ce que vous vouliez vraiment dès le départ, c'était la copie à l'affectation, c'est le signal qu'un Type — un type valeur — était le meilleur modèle. Savoir de quelle sémantique vous avez besoin, partager ou copier, est toute la raison de comprendre les deux.

Initialisation et libération : Class_Initialize et le constructeur manquant

Une classe peut exécuter du code automatiquement à la naissance ou à la mort d'une instance :

Private Sub Class_Initialize()     ' s'exécute au  Set e = New clsEmployee
    mSalary = 0                    ' placez les valeurs par défaut ici
End Sub

Private Sub Class_Terminate()      ' s'exécute quand la dernière référence disparaît
    ' fermez les fichiers, libérez les handles, etc.
End Sub

Le hic : Class_Initialize ne prend aucun argument. VBA n'a pas de constructeur paramétré — vous ne pouvez pas écrire New clsEmployee("Sarah", 65000). Vous créez d'abord l'objet, puis vous réglez ses propriétés. Comme ce pas de deux est fastidieux et facile à oublier, le contournement standard est une petite fonction fabrique dans un module normal :

Function NewEmployee(nm As String, sal As Currency) As clsEmployee
    Dim e As clsEmployee
    Set e = New clsEmployee
    e.Name = nm
    e.Salary = sal
    Set NewEmployee = e
End Function
' Set e = NewEmployee("Sarah", 65000)   ' une seule ligne lisible

Ma règle générale : toute classe que vous créez plus d'une ou deux fois mérite une fonction fabrique. Elle vous donne le constructeur paramétré que VBA a laissé de côté, et elle garde la création en un seul endroit au lieu de lignes Set + propriétés éparpillées.

Quand une classe l'emporte sur un Type ou une Collection

Sortez un class module dès qu'au moins l'un de ces points est vrai :

  • Données et comportement vont de pair — l'enregistrement devrait valider, mettre en forme ou calculer des choses sur lui-même, plutôt que de voir cette logique éparpillée dans des Sub utilitaires.
  • Vous avez besoin de nombreux objets indépendants et autonomes — des commandes, des factures, des employés — idéalement rangés dans une Collection, qui accepte les objets mais pas un Type.
  • Vous voulez masquer les détails internes — exposer une surface propre via des propriétés et garder les champs de stockage Private.

Si aucun de ces points ne tient et que vous voulez seulement faire voyager des champs ensemble avec des copies bon marché, un Type est plus léger et plus honnête. Ne construisez pas une classe pour un sac de trois valeurs — mais dès l'instant où ce sac doit faire quelque chose, une classe est exactement ce qu'il faut.

Comment ExcelMaster aide

Les class modules sont le repaire des bugs « ça compile mais ça se comporte bizarrement » : le zombie As New, la modification par référence partagée qui change un objet « tout seul », le Set oublié qui déclenche l'erreur 91. Chacun reste invisible jusqu'à ce qu'il morde, et chacun découle d'une règle facile à énoncer et facile à oublier sous la pression d'une échéance.

ExcelMaster vous laisse décrire l'objet voulu — « un Employee avec un nom, un salaire et une méthode qui renvoie le coût annuel, dont je peux garder une liste » — et il écrit la classe avec un Set ... = New explicite, une fonction fabrique, des champs de stockage Private exposés via des propriétés, et une Collection pour les contenir. Vous obtenez du VBA orienté objet idiomatique et sans pièges, sans avoir à vous souvenir de toutes les façons dont New et Set peuvent vous surprendre.

Questions fréquentes

Qu'est-ce qu'un class module en VBA ?

Un class module est l'endroit où vous définissez votre propre type d'objet — un plan qui regroupe des données (des champs) et du comportement (des méthodes et des propriétés). Une fois défini, vous en créez des instances indépendantes avec New. C'est ainsi que VBA prend en charge les objets personnalisés, un cran au-delà d'un Type, qui ne contient que des données.

Comment créer une instance de classe en VBA ?

Déclarez une variable du type de la classe et affectez-lui une nouvelle instance avec Set et New : Dim e As clsEmployee, puis Set e = New clsEmployee. Le mot-clé Set est obligatoire pour les objets ; l'omettre (e = New clsEmployee) déclenche l'erreur 91. Après la création, réglez ses propriétés : e.Name = "Sarah".

Quelle est la différence entre Dim As New et Set New en VBA ?

Dim e As clsEmployee + Set e = New clsEmployee crée l'objet à cette ligne précise et garde If e Is Nothing porteur de sens. Dim e As New clsEmployee diffère la création jusqu'à la première utilisation, ce qui rend Is Nothing toujours False et recrée l'objet en silence si vous l'affectez à Nothing puis le touchez à nouveau. Préférez la forme explicite Set ... = New.

Une classe VBA prend-elle en charge un constructeur avec paramètres ?

Non. L'événement Class_Initialize s'exécute automatiquement à la création d'une instance, mais il ne prend aucun argument ; vous ne pouvez donc pas écrire New clsEmployee("Sarah", 65000). Le contournement standard est une fonction fabrique, dans un module normal, qui crée l'objet, règle ses propriétés et le renvoie — ce qui vous donne une façon paramétrée et tenant sur une ligne de construire l'objet.

Quand utiliser un class module plutôt qu'un Type ou une Collection ?

Utilisez une classe quand l'enregistrement a besoin de comportement (des méthodes), quand vous voulez de nombreux objets indépendants que vous pouvez stocker dans une Collection, ou quand vous voulez masquer des champs internes derrière des propriétés. Si vous avez seulement besoin de faire voyager des champs ensemble avec des copies indépendantes bon marché, un Type est plus léger et plus clair.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 04/08/2026.

Guides associés : VBA Type · VBA Property · VBA Dim · VBA Collection · VBA Dictionary