TL;DR — Un
Type(un type défini par l'utilisateur, ou UDT) vous laisse nommer une forme une fois et transporter tous ses champs dans une seule variable. Au lieu de jongler avec trois tableaux qui doivent rester alignés par index, vous obtenez un seul tableau d'enregistrements. UnTypeest un type valeur : affecterb = acopie chaque champ, si bien que les deux variables sont indépendantes — l'inverse d'une instance de classe, qui, elle, est partagée. Déclarez-le en haut d'un module standard, et ne sortez un class module que lorsque l'enregistrement doit faire quelque chose.
' Tout en haut d'un module standard, avant tout Sub ou Function :
Type Employee
Name As String
Age As Long
Salary As Currency
End Type
Sub Demo()
Dim e As Employee ' une seule variable contient les trois champs
e.Name = "Sarah"
e.Age = 34
e.Salary = 65000
Dim copy As Employee
copy = e ' COPIE PAR VALEUR — chaque champ est dupliqué
copy.Salary = 99000 ' modifier la copie NE touche PAS e
MsgBox e.Salary ' toujours 65000
End Sub
La plupart des macros VBA qui « suivent plusieurs informations sur un même
élément » finissent en tableaux parallèles — names(), ages(), salaries() —
qui doivent tous rester dans le même ordre. Triez-en un en oubliant les autres, et
le nom de la ligne 5 se retrouve rattaché au salaire de la ligne 12, sans la
moindre erreur pour vous prévenir. Un Type règle le problème à la racine : les
champs ne peuvent plus se désolidariser, puisqu'ils vivent dans une seule variable.
Ce que vous allez apprendre
- Le modèle mental — une ligne de tableau vue comme une seule variable
- Où un
Typedoit être déclaré (et pourquoi à l'intérieur d'unSubça échoue) - La règle qui surprend — un
Typecopie, il ne partage pas - Le vrai gain — un seul tableau d'enregistrements au lieu de tableaux parallèles
- La limite dure — un
Typene peut porter aucun comportement ni entrer dans uneCollection Typeou class module — comment choisir
Le modèle mental : une ligne de tableau vue comme une seule variable
Voyez un Type comme une ligne de tableau promue au rang de variable. Dans une
feuille de calcul, la ligne d'un employé aligne côte à côte un nom, un âge et un
salaire ; un Type vous donne le même regroupement dans le code. Vous définissez
les colonnes une fois (Type Employee ... End Type), et chaque
Dim e As Employee est une nouvelle ligne dotée de ces mêmes cases.
C'est toute l'idée : cessez de faire circuler des valeurs éparses qui vont
pourtant ensemble, et faites plutôt circuler une seule chose étiquetée. Une
fonction qui a besoin d'un employé prend un unique argument Employee, pas trois
paramètres que vous devez maintenir dans le bon ordre.
Où un Type doit être déclaré
Une déclaration Type se place au niveau module — tout en haut d'un module
standard, au-dessus de toute procédure. Mettez-la à l'intérieur d'un Sub et le
projet refuse de compiler. C'est ce qui piège ceux qui traitent Type comme
Dim : Dim est une instruction que vous exécutez à l'intérieur d'une procédure,
tandis que Type est une déclaration qui définit une forme pour tout le module,
voire tout le projet.
Deux règles de placement à mémoriser :
Public Type(la valeur par défaut au niveau module) rend le type utilisable dans tout le projet. UtilisezPrivate Typepour le cantonner à un seul module.- Vous ne pouvez pas déclarer un
Public Typedans un class module — VBA le refuse avec « Impossible de définir un type défini par l'utilisateur public dans un module objet privé ». Gardez vosTypepartagés dans un module normal (Module1, ou un moduleTypesdédié), pas dans une classe ni dans le code d'une feuille.
La règle qui surprend : un Type copie, il ne partage pas
C'est la chose la plus importante à comprendre au sujet d'un Type, car c'est
précisément là qu'il diffère d'un objet. Un Type est un type valeur. Quand
vous écrivez copy = e, VBA duplique chaque champ dans une variable toute
neuve et indépendante :
Dim a As Employee, b As Employee
a.Salary = 50000
b = a ' copie complète de tous les champs
b.Salary = 70000 ' ne modifie que b
Debug.Print a.Salary ' 50000 — a n'est pas touché
Comparez avec une instance de classe, où Set b = a
fait de a et b deux noms pour le même objet : modifier l'un modifie l'autre.
Si vous vous êtes déjà fait piéger par un objet qui change « tout seul » après
l'avoir affecté quelque part, la copie à l'affectation d'un Type est l'antidote —
et souvent exactement ce que vous voulez.
Le seul endroit où la copie n'a pas lieu, c'est le passage à une procédure. Un
argument Type est ByRef par défaut, si bien qu'un Sub peut modifier votre
original :
Sub GiveRaise(emp As Employee) ' ByRef par défaut
emp.Salary = emp.Salary * 1.1 ' modifie l'enregistrement de l'appelant
End Sub
Passez-le en ByVal si vous voulez que la procédure appelée travaille sur une
copie privée — la même règle ByRef contre ByVal qui
régit les variables ordinaires.
Le vrai gain : un seul tableau d'enregistrements
C'est ici qu'un Type justifie sa place. Au lieu de N tableaux parallèles que vous
devez aligner à la main, vous déclarez un seul tableau d'enregistrements :
Dim staff(1 To 100) As Employee
staff(1).Name = "Sarah"
staff(1).Salary = 65000
staff(2).Name = "Tom"
staff(2).Salary = 58000
' Triez, filtrez ou réordonnez staff() et chaque champ suit —
' un nom ne peut plus jamais se désynchroniser de son salaire.
Le mode de défaillance ainsi éliminé est silencieux et vicieux : avec names(),
ages() et salaries() en tableaux distincts, toute
opération qui en réordonne un — un tri, une insertion, une suppression —
désynchronise les autres, à moins de penser à l'appliquer à tous à l'identique.
Avec un tableau d'Employee, il n'y a plus rien à synchroniser, car les champs ne
se sont jamais quittés.
La limite dure : aucun comportement, et pas de Collection
Un Type est délibérément bête — il porte des données, et rien d'autre. Cela lui
vaut deux limites dures qui vous disent quand vous l'avez dépassé :
- Il ne peut pas avoir de méthodes. Dès l'instant où votre enregistrement doit
faire quelque chose — valider son propre âge, se mettre en forme sous forme de
chaîne, recalculer un total —, un
Typene peut rien pour vous. Le comportement relève d'un class module. - Il ne peut pas entrer dans une
Collectionni unDictionary. Ces conteneurs stockent des valeursVariant, et un type défini par l'utilisateur ne peut pas être converti enVariant. Essayezcoll.Add eavec unTypeet VBA refuse. Si vous avez besoin d'un conteneur d'enregistrements extensible et indexé par clé, cela suffit à justifier le passage à une classe, dont les instances sont des objets qu'uneCollectionaccepte.
Type ou class module : comment choisir
Type (UDT) |
Class module | |
|---|---|---|
| Contient | Des données seulement | Des données et du comportement |
| Catégorie | Type valeur | Type référence (objet) |
b = a |
Copie tous les champs | Set b = a partage une seule instance |
| Déclaré dans | Un module standard, au-dessus des procédures | Son propre class module |
Stockable dans une Collection ? |
Non | Oui |
| Créé avec | Dim e As Employee |
Set e = New clsEmployee |
| Idéal quand | Les champs doivent juste voyager ensemble | L'enregistrement a besoin de méthodes ou doit vivre dans une collection |
Ma règle générale : si les champs doivent seulement rester ensemble et que vous
voulez des copies indépendantes bon marché, un Type est le bon outil — sortir une
classe ici, c'est de la sur-ingénierie. Passez à une classe dès que l'enregistrement
a besoin d'un comportement, ou dès qu'il vous faut en garder beaucoup dans une
Collection. Tout l'entre-deux relève du jugement, et « commencez par le Type,
promouvez-le plus tard » est une valeur par défaut tout à fait saine.
Comment ExcelMaster aide
Choisir entre des tableaux parallèles, un Type et une véritable classe — puis se
souvenir qu'un Type copie là où un objet partage — est exactement le genre de
choix de modélisation qu'on rate subtilement. Les bugs qui en découlent (un tableau
désynchronisé, un objet qui a muté « tout seul ») compilent sans broncher et ne se
révèlent que plus tard.
ExcelMaster vous
laisse plutôt décrire les données. Dites « je dois suivre le nom, l'âge et le
salaire d'une liste d'employés et les trier par salaire », et il modélise les
enregistrements à votre place — un tableau d'un Type, avec le tri appliqué pour
que rien ne se désynchronise — et explique, dans le code, quand il aurait plutôt
choisi une classe. Vous obtenez la bonne structure sans avoir à garder en tête
toutes les règles du valeur-contre-référence.
Questions fréquentes
Qu'est-ce qu'un Type en VBA ?
Un Type (type défini par l'utilisateur, ou UDT) est une structure de données
personnalisée qui regroupe plusieurs champs liés sous un même nom — par exemple un
Employee avec Name, Age et Salary. Vous le déclarez une fois avec
Type ... End Type en haut d'un module standard, puis vous l'utilisez comme
n'importe quel autre type : Dim e As Employee. Il laisse des valeurs liées
voyager ensemble dans une seule variable au lieu de variables séparées et faciles à
désynchroniser.
Quelle est la différence entre un Type et un class module en VBA ?
Un Type ne contient que des données et c'est un type valeur — en affecter
un à un autre copie chaque champ, donc les deux sont indépendants. Un
class module contient données et comportement (des
méthodes) et c'est un type référence — Set b = a fait pointer les deux noms
vers la même instance. Utilisez un Type pour un enregistrement passif ; utilisez
une classe quand l'enregistrement a besoin de méthodes ou doit être stocké dans une
Collection.
Où déclarer un Type en VBA ?
Au niveau module, au-dessus de toute procédure, dans un module standard.
Déclarer un Type à l'intérieur d'un Sub ou d'une Function est une erreur de
compilation. Utilisez Public Type (la valeur par défaut) pour le partager dans
tout le projet, ou Private Type pour le limiter à un seul module. Vous ne pouvez
pas déclarer un Public Type dans un class module.
Peut-on stocker un Type VBA dans une Collection ou un Dictionary ?
Non. Une Collection et un Dictionary stockent des valeurs Variant, et un type
défini par l'utilisateur ne peut pas être converti en Variant ; coll.Add someType
échoue donc. Si vous avez besoin d'un conteneur d'enregistrements extensible ou
indexé par clé, utilisez plutôt un class module — ses
instances sont des objets qu'une Collection accepte — ou gardez les
enregistrements dans un tableau du Type.
Affecter une variable Type à une autre copie-t-il ou partage-t-il les données ?
Il copie. Comme un Type est un type valeur, b = a duplique chaque champ dans
une variable indépendante ; modifier b ensuite n'affecte pas a. C'est l'inverse
des objets (les instances de classe), où Set b = a partage une seule instance. La
seule exception est le passage d'un Type à une procédure, qui est ByRef par
défaut et peut donc modifier l'enregistrement de l'appelant.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 04/08/2026.
Guides associés : VBA Class Module · VBA Property · VBA Data Types · VBA Array · VBA ByRef contre ByVal
