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

VBA Controls dans Excel — parcourir la collection Controls et référencer un contrôle par son nom

|

VBA Controls dans Excel — parcourir la collection Controls et référencer un contrôle par son nom

TL;DR — Chaque contrôle d'un UserForm vit à un seul endroit : la collection Controls du formulaire. Atteignez-la avec Me.Controls, parcourez-la avec For Each, et adressez n'importe quel contrôle par son nom sous forme de chaîne — Me.Controls("txtName"). C'est cette collection qui garde court un formulaire de vingt champs : une boucle au lieu de vingt lignes nommées. Filtrez les contrôles que vous visez avec TypeName ou TypeOf, car la collection contient aussi des étiquettes, des cadres et des boutons.

Private Sub cmdClear_Click()
    Dim ctl As MSForms.Control
    ' Vider chaque zone de texte du formulaire en une seule boucle:
    For Each ctl In Me.Controls
        If TypeOf ctl Is MSForms.TextBox Then ctl.Value = ""
    Next ctl
End Sub

Vous atteignez un contrôle en tapant son nom : txtName.Value, lstItems.Clear. Cela fonctionne quand vous connaissez le contrôle au moment d'écrire le code. La collection Controls sert au cas où vous ne le connaissez pas — vous voulez chaque zone de texte, ou un contrôle dont le nom a été construit à l'exécution. C'est le pivot de la famille des contrôles UserForm, et les trois guides ici la complètent. La collection Controls est la façon d'adresser les contrôles en masse ; une TextBox renvoie toujours une String, si bien qu'un nombre saisi reste du texte tant que vous ne le convertissez pas ; et un Frame est le conteneur qui donne à un ensemble de boutons radio son propre groupe. Maîtrisez la collection, la chaîne et le conteneur, et les contrôles individuels — ListBox, ComboBox, CheckBox — se lisent tous de la même façon : un contrôle est un objet que vous atteignez via le formulaire et auquel vous parlez à travers ses propriétés.

Ce que vous allez apprendre

  • Ce qu'est Me.Controls, et pourquoi un formulaire est une collection plutôt qu'un écran
  • Parcourir chaque contrôle avec For Each et agir sur ceux que vous visez
  • Filtrer par type avec TypeName et TypeOf pour ignorer les étiquettes et les cadres
  • Atteindre un contrôle par son nom sous forme de chaîne, pour des formulaires construits depuis des données
  • Ajouter des contrôles à un formulaire pendant qu'il tourne
  • Le choix de jugement : quand une boucle vaut mieux que vingt références nommées

Le modèle mental : un formulaire est une collection d'objets contrôles

Un UserForm ressemble à un écran, mais pour votre code, c'est une collection. Me.Controls est cette collection — chaque zone de texte, étiquette, bouton, cadre et liste déroulante que vous avez déposés sur le formulaire, tenus comme des objets que vous pouvez compter et parcourir. Me.Controls.Count vous dit combien il y en a ; Me.Controls(0) est le premier (la collection est indexée à partir de zéro). Me désigne le formulaire dans lequel le code s'exécute, donc dans le module propre d'un UserForm, Me.Controls et Controls signifient la même chose.

MsgBox "This form has " & Me.Controls.Count & " controls"

Une fois que vous voyez le formulaire comme une collection, les parties répétitives du code de formulaire disparaissent. Vous arrêtez d'écrire txt1, txt2, txt3 et vous commencez à écrire une boucle.

Parcourir chaque contrôle avec For Each

For Each parcourt la collection. La variable de contrôle est typée MSForms.Control — le type générique que partage chaque contrôle :

Dim ctl As MSForms.Control
For Each ctl In Me.Controls
    Debug.Print ctl.Name
Next ctl

C'est le schéma derrière « vider le formulaire », « recueillir chaque valeur », « tout désactiver pendant que je travaille ». Mais la collection contient tous les contrôles — y compris ceux que vous ne visiez pas — si bien qu'une boucle brute qui écrit ctl.Value plante sur la première étiquette, parce qu'une étiquette n'a pas de Value. C'est le problème suivant.

Filtrer par type avec TypeName et TypeOf

Tous les contrôles n'ont pas la propriété que vous voulez. Un Label n'a pas de .Value ; un CommandButton n'a pas de .Text. Touchez le mauvais et vous obtenez une erreur d'exécution 438, « Object doesn't support this property or method ». Filtrez donc d'abord. TypeName(ctl) renvoie le type sous forme de chaîne ; TypeOf ctl Is le teste directement :

For Each ctl In Me.Controls
    If TypeOf ctl Is MSForms.TextBox Then
        ctl.Value = ""                 ' sans risque : seules les zones de texte atteignent cette ligne
    End If
Next ctl

Utilisez TypeOf ... Is dans un If — c'est le test idiomatique. Utilisez TypeName(ctl) quand vous voulez le nom du type dans un message ou un Select Case portant sur plusieurs types. La règle : n'appelez jamais une propriété à l'intérieur d'un For Each sur Controls sans avoir d'abord prouvé que le contrôle est d'un type qui la possède.

Atteindre un contrôle par son nom

C'est là que la collection porte ses fruits. Vous pouvez l'indexer par une chaîne de nom, et cette chaîne peut être construite à l'exécution :

Dim i As Long
For i = 1 To 5
    Me.Controls("txtDay" & i).Value = ""   ' txtDay1 ... txtDay5
Next i

Un formulaire avec des champs nommés de txtDay1 à txtDay5 a besoin d'une boucle, pas de cinq lignes. C'est ainsi que fonctionnent les formulaires pilotés par les données : les noms suivent une convention, et le code les construit. Le piège fait écho à celui d'Application.Run et CallByName dans la famille de la réflexion — le nom est une chaîne, donc le compilateur ne peut pas le vérifier. Une faute de frappe comme "txtDya1" ne provoque pas de soulignement rouge ; c'est une erreur d'exécution quand la ligne s'exécute. Construisez le nom à partir d'un schéma connu, et protégez-le avec On Error si une partie provient de données.

Ajouter des contrôles à un formulaire pendant qu'il tourne

La collection n'est pas figée. Controls.Add crée un contrôle pendant que le formulaire est ouvert, ce qui permet de construire un formulaire dont la taille dépend des données — une ligne de champs par enregistrement :

Dim box As MSForms.TextBox
Set box = Me.Controls.Add("Forms.TextBox.1", "txtDynamic", True)
box.Top = 10: box.Left = 10: box.Width = 120

Le premier argument est la classe du contrôle, le second son nom, le troisième s'il est visible. Les contrôles ajoutés dynamiquement n'ont aucun événement de code associé, à moins de les câbler avec une classe WithEvents — une technique réelle, mais à réserver aux cas où une disposition fixe ne peut vraiment pas faire le travail.

Le choix de jugement : quand une boucle vaut mieux que vingt références nommées

La collection Controls est puissante, ce qui la rend facile à surutiliser. La règle honnête : si vous avez une poignée de contrôles que vous connaissez par leur nom, txtName.Value est plus clair que Me.Controls("txtName").Value, et le compilateur le vérifie. La boucle mérite sa place quand les contrôles sont nombreux et uniformes — vingt champs de jour, une grille de saisies, chaque zone de texte du formulaire — ou quand le nom est réellement décidé par les données. Une boucle sur trois contrôles, c'est de la frime ; une boucle sur vingt est la seule façon sensée de l'écrire. Choisissez la collection quand elle supprime une vraie répétition, pas pour prouver que vous en êtes capable.

Comment ExcelMaster vous aide

Les échecs ici sont discrets et tardifs : un For Each qui plante sur l'unique étiquette que vous avez oubliée, un nom de contrôle construit depuis des données qui ne correspond plus, une propriété appelée sur le mauvais type. Tous se manifestent par la même erreur 438 ou un « introuvable », à l'exécution, sur un formulaire qui semblait terminé.

ExcelMaster vous laisse décrire le comportement du formulaire — « vider chaque zone de texte », « lire toutes les saisies dans une ligne », « construire cinq champs de jour à partir d'une liste » — et il écrit la boucle Controls avec le filtre de type et le garde-fou de nom déjà en place. Vous gardez le formulaire et le code, et vous évitez la chasse aux erreurs à l'exécution.

Questions fréquentes

Qu'est-ce que la collection Controls en VBA ?

C'est la collection de tous les contrôles d'un UserForm, atteinte via Me.Controls. Chaque élément est un objet contrôle — une zone de texte, une étiquette, un bouton, un cadre ou une liste déroulante. Vous pouvez les compter avec .Count, les parcourir avec For Each, et en atteindre un par index ou par son nom sous forme de chaîne. C'est la façon standard d'agir sur de nombreux contrôles à la fois au lieu de les nommer un par un.

Comment parcourir tous les contrôles d'un UserForm ?

Déclarez une variable As MSForms.Control et utilisez For Each ctl In Me.Controls. À l'intérieur de la boucle, testez le type avec TypeOf ctl Is MSForms.TextBox avant de toucher une propriété, car la collection contient aussi des étiquettes et des boutons qui n'ont pas cette propriété et déclencheraient l'erreur 438.

Comment référencer un contrôle par un nom stocké dans une chaîne ?

Indexez la collection avec la chaîne : Me.Controls("txtName"). Le nom peut être construit à l'exécution, comme Me.Controls("txtDay" & i). Comme le nom est une chaîne, une faute de frappe n'est pas détectée avant que la ligne ne s'exécute — elle déclenche une erreur « introuvable » — construisez donc le nom à partir d'un schéma connu et protégez-le.

Pourquoi ma boucle For Each sur Controls déclenche-t-elle l'erreur 438 ?

Parce que vous avez appelé une propriété que le contrôle courant n'a pas — le plus souvent .Value ou .Text sur un Label, un Frame ou un CommandButton. La collection Controls contient tous les types, filtrez donc avec TypeOf ctl Is MSForms.TextBox (ou le type visé) avant de lire ou d'écrire cette propriété.

Puis-je ajouter des contrôles à un formulaire pendant qu'il tourne ?

Oui. Me.Controls.Add("Forms.TextBox.1", "txtNew", True) en crée un à l'exécution, ce qui permet de construire un formulaire dimensionné aux données. Réglez ensuite son Top, son Left et son Width. Les contrôles ajoutés dynamiquement n'ont aucun gestionnaire d'événement à moins de les connecter avec une classe WithEvents.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 28/09/2026.

Guides associés : VBA TextBox · VBA Frame · VBA UserForm · VBA ListBox · VBA ComboBox · VBA CheckBox · VBA On Error