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

VBA ListBox dans Excel — Le remplir, lire la sélection et le piège MultiSelect

|

VBA ListBox dans Excel — Le remplir, lire la sélection et le piège MultiSelect

TL;DR — Un ListBox affiche une liste et retient ce que l'utilisateur a choisi. Remplissez-le en un coup avec ListBox1.List = Range("A2:A50").Value. Lisez un choix unique avec .ListIndex (la ligne en base 0, ou -1 pour rien) et .Value (le texte choisi). Le piège : dès que .MultiSelect est actif, .Value passe à Null et cesse de vous renseigner — vous devez parcourir .Selected(i) pour récolter chaque choix.

' ListBox a selection unique : lire l'unique choix
Private Sub cmdOK_Click()
    If ListBox1.ListIndex = -1 Then
        MsgBox "Please pick a name first."
        Exit Sub
    End If
    MsgBox "You picked " & ListBox1.Value      ' .Value = le texte selectionne
End Sub

Un ListBox est un contrôle sur un UserForm, et la première chose à bien saisir est l'idée unique qui sous-tend chaque contrôle : un contrôle est un objet vivant que vous lisez à travers ses propriétés, jamais la valeur elle-même. Les éléments vivent dans .List ; le choix de l'utilisateur vit dans une propriété distincte — .ListIndex ou .Selected — jamais dans la boîte prise comme un tout. Presque chaque question « mon ListBox ne renvoie rien » lit la mauvaise propriété.

Ce que vous allez apprendre

  • Le modèle mental qui relie ListBox, ComboBox et CheckBox
  • Deux façons de remplir un ListBox — .List = Range.Value en un coup, ou .AddItem dans une boucle
  • Comment lire une sélection unique avec .ListIndex et .Value, et ce que signifie -1
  • Le piège numéro un : .Value passe à Null sous MultiSelect, si bien que vous devez parcourir .Selected(i)
  • Comment vider une liste, afficher plusieurs colonnes et la lier à une feuille avec .RowSource
  • Quand un ListBox est le bon contrôle et quand un ComboBox convient mieux

Le modèle mental : la boîte contient la liste, une propriété contient le choix

Voyez un ListBox comme une fenêtre sur une liste d'éléments. Deux choses différentes vivent à deux endroits différents :

ListBox1.List           ' les ELEMENTS - ce qui est affiche dans la boite
ListBox1.ListIndex      ' le CHOIX     - quelle ligne est selectionnee (base 0, -1 = aucune)
ListBox1.Value          ' le TEXTE du choix - n'a de sens qu'en selection unique
ListBox1.Selected(i)    ' True/False pour la ligne i - seule lecture fiable sous MultiSelect

Cette séparation, c'est tout le contrôle. Quand vous affectez .List, vous chargez les éléments. Quand l'utilisateur clique sur une ligne, VBA ne modifie pas .List — il modifie .ListIndex et bascule .Selected. Ainsi « qu'a choisi l'utilisateur ? » ne trouve jamais sa réponse en regardant la liste ; on y répond en lisant les propriétés de sélection. Fixez cela et le reste n'est que détail.

Remplir un ListBox : un coup vaut mieux qu'une boucle

Vous verrez deux façons de remplir une liste. Celle vers laquelle tendre d'abord affecte une colonne entière d'un coup :

Private Sub UserForm_Initialize()
    ' Remplir depuis une colonne de la feuille en une seule affectation - rapide et simple
    ListBox1.List = Sheet1.Range("A2:A50").Value
End Sub

.List accepte un tableau 2D, et Range.Value est un tableau 2D (voyez VBA Range), si bien qu'une seule ligne charge cinquante lignes. N'utilisez .AddItem que lorsque les éléments sont calculés un à un et que vous n'avez aucun tableau sous la main :

Dim i As Long
For i = 1 To 5
    ListBox1.AddItem "Quarter " & i    ' ajouter des elements construits a la volee
Next i

.AddItem dans une grosse boucle est le chemin lent — chaque appel est un aller-retour distinct vers le contrôle. Si les données sont déjà dans une plage ou un tableau, affectez .List une seule fois. Pour vider la boîte avant de la remplir à nouveau, appelez ListBox1.Clear.

Lire une sélection unique : ListIndex et Value

Pour un ListBox ordinaire à sélection unique, deux propriétés répondent à tout. .ListIndex est le numéro de ligne (base 0) de la sélection — et il vaut -1 quand rien n'est sélectionné, la garde que vous devriez toujours vérifier en premier. .Value est le texte de la ligne sélectionnée :

If ListBox1.ListIndex = -1 Then
    MsgBox "Nothing selected."          ' -1 est le signal 'aucun choix pour l'instant'
Else
    MsgBox "Row " & ListBox1.ListIndex & ": " & ListBox1.Value
End If

Vérifier .ListIndex = -1 avant de lire .Value, c'est toute la différence entre un formulaire qui guide l'utilisateur et un formulaire qui agit sur une sélection vide. C'est la même discipline que garder un résultat de Find avant de l'utiliser.

Le piège numéro un : MultiSelect rend .Value inutile

Voici l'erreur qui fait tourner les gens en rond. Un ListBox possède une propriété MultiSelect. Laissez-la à sa valeur par défaut (fmMultiSelectSingle) et .Value fonctionne. Passez-la à fmMultiSelectMulti ou fmMultiSelectExtended pour que l'utilisateur puisse cocher plusieurs lignes — et .Value passe à Null. Elle ne reflète plus du tout la sélection, car « la valeur » n'a aucun sens quand trois lignes sont choisies.

Sous MultiSelect, la seule lecture fiable est de parcourir chaque ligne et de tester .Selected(i) :

Dim i As Long, chosen As String
For i = 0 To ListBox1.ListCount - 1     ' les lignes vont de 0 a ListCount - 1
    If ListBox1.Selected(i) Then
        chosen = chosen & ListBox1.List(i) & vbCrLf
    End If
Next i
MsgBox "You chose:" & vbCrLf & chosen

Deux détails font ou défont cette boucle. Elle va de 0 à .ListCount - 1, parce que les lignes sont en base 0 tout comme les bornes de tableau — une erreur d'indice ici perd silencieusement la dernière ligne. Et elle lit le texte de l'élément avec .List(i), non .Value, car .Value est Null dans ce mode. Si vous avez bâti un formulaire, activé la multi-sélection plus tard, et que votre code a cessé de voir les sélections, voilà pourquoi.

Plusieurs colonnes, et la liaison à une feuille

Deux propriétés couvrent les cas courants « il me faut plus qu'une simple liste ». .ColumnCount et .List (un tableau 2D) permettent à un ListBox d'afficher plusieurs colonnes — un identifiant et un nom côte à côte — tandis que .BoundColumn décide quelle colonne .Value renvoie. Et .RowSource lie la boîte directement à une plage de feuille, de sorte qu'elle suit les cellules sans aucun code de remplissage :

ListBox1.ColumnCount = 2
ListBox1.RowSource = "Sheet1!A2:B50"    ' deux colonnes, liees en direct a la feuille
ListBox1.BoundColumn = 1                ' .Value renvoie la colonne 1 (l'ID)

.RowSource est pratique mais couple le formulaire à une disposition de feuille précise ; affecter .List depuis un tableau garde le formulaire indépendant de l'endroit où vivent les données. Pour un formulaire de saisie qui survit à un seul classeur, préférez l'affectation par tableau.

ListBox ou ComboBox ? Choisissez selon le ressenti du choix

Un ListBox et un ComboBox se lisent presque à l'identique, alors choisissez sur le comportement, non la syntaxe. Tendez vers un ListBox quand les options doivent être visibles d'un coup d'œil ou quand l'utilisateur peut en choisir plus d'une — la multi-sélection est un tour propre au ListBox. Tendez vers un ComboBox quand la place est comptée, que la réponse est une valeur unique, et qu'une liste déroulante repliée sur une seule ligne fait plus net. Si vous vous surprenez à vouloir une case à cocher par ligne, c'est probablement un ListBox multi-sélection qu'il vous faut.

Comment ExcelMaster vous aide

Les deux erreurs de cette page coûtent du temps réel : lire .Value sur un ListBox multi-sélection (et récolter Null), et agir sur une sélection sans d'abord vérifier .ListIndex = -1. Les deux sont faciles à écrire et discrètes à échouer.

ExcelMaster vous laisse décrire le formulaire en mots simples — « une liste de clients que l'utilisateur peut multi-sélectionner, puis écrire les choisis dans une feuille » — et il câble le UserForm, remplit le ListBox depuis vos données, et lit la sélection de la bonne façon (en parcourant .Selected(i) quand la multi-sélection est active, en gardant .ListIndex sinon). Vous gardez le classeur et le code.

Questions fréquentes

Comment remplir un ListBox depuis une plage en VBA ?

Affectez la valeur de la plage à .List en une seule instruction : ListBox1.List = Sheet1.Range("A2:A50").Value. Comme Range.Value est un tableau 2D et que .List en accepte un, cela charge toute la colonne d'un coup. N'utilisez .AddItem que pour des éléments que vous construisez un à un dans une boucle, et appelez .Clear d'abord si vous remplissez à nouveau une boîte qui a déjà des lignes.

Comment obtenir l'élément sélectionné d'un ListBox en VBA ?

Pour un ListBox à sélection unique, lisez .Value pour le texte ou .ListIndex pour le numéro de ligne (base 0) ; .ListIndex vaut -1 quand rien n'est sélectionné, alors vérifiez cela d'abord. Pour un ListBox multi-sélection, .Value est Null — parcourez For i = 0 To ListBox1.ListCount - 1 et collectez chaque ligne où .Selected(i) vaut True.

Pourquoi mon ListBox .Value est-il vide ou Null ?

Parce que MultiSelect est activé. Quand .MultiSelect vaut fmMultiSelectMulti ou fmMultiSelectExtended, la propriété .Value est toujours Null — elle ne peut pas représenter plusieurs lignes sélectionnées. Lisez plutôt la sélection en parcourant .Selected(i) de 0 à .ListCount - 1, et lisez chaque élément avec .List(i).

Comment vider tous les éléments d'un ListBox ?

Appelez ListBox1.Clear. Cela retire chaque ligne. Si la boîte est liée avec .RowSource, mettez d'abord .RowSource = "", car une liste liée se reconstruit depuis la plage. Pour n'effacer que la sélection courante sans retirer les éléments, mettez .ListIndex = -1 (sélection unique) ou parcourez .Selected(i) = False (multi-sélection).

Quelle est la différence entre un ListBox et un ComboBox ?

Un ListBox affiche plusieurs lignes à la fois et peut autoriser plusieurs sélections ; un ComboBox se replie sur une seule ligne, affiche une liste déroulante et n'autorise qu'un seul choix (et, en option, la saisie libre). Utilisez un ListBox quand les options doivent être visibles ou multi-choix, un ComboBox quand la place est comptée et qu'une seule réponse suffit.

Testé dans

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

Guides associés : VBA ComboBox · VBA CheckBox · VBA UserForm · VBA Range · VBA For Loop