XL 2016 VBA Curiosité ComboBox

Dudu2

XLDnaute Barbatruc
Bonjour,

Lorsqu'une ComboBox:
- (1) est chargée via la propriété ComboBox.List
et
- (2) parmi les valeurs chargées certaines sont numériques,
la valorisation ultérieure de la ComboBox.Value = x avec une valeur numérique de sa propre liste ne positionne pas le ComboBox.ListIndex sur la valeur en question et est valorisé à -1.

Ce n'est pas le cas si les conditions (1) et (2) ne sont pas réunies où le ComboBox.ListIndex prend alors une valeur correcte correspondant à la position de la valeur dans la liste.

J'ai tout essayé mais la seule option a été de passer par une fonction qui charge les valeurs de ComboBox.List en Tableau et les compare à la valeur à charger pour corriger le ComboBox.ListIndex.
Mais peut-être y a -t-il un moyen plus direct ? (Un petit sujet de réflexion sans caractère essentiel)

Edit: fichier corrigé à 18h33
 

Pièces jointes

  • Classeur1.xlsm
    25.6 KB · Affichages: 24
Dernière édition:

Dudu2

XLDnaute Barbatruc
Bonsoir @patricktoulon,
J'ai posé la question histoire de distraire un peu la compagnie parce qu'à mon avis, y a rien qu'on puisse faire.
Je pense à un bug VBA ComboBox.

J'ai eu à faire face à ça lors d'un rechargement de formulaire à partir de données enregistrées.
Et j'ai dû faire cette fonction pour repositionner le ListIndex.
VB:
'----------------------------------------------------
'Lorsqu'une ComboBox (1) est chargée via sa propriété
'List (ComboBox.List =) et non pas avec sa propritété
'ListFillRange (ComboBox.ListFillRange =) et qu'on la
'valorise (ComboBox.Value =) avec une de ses valeurs
'de liste (2) numérique, sa propriété ListIndex est
'valorisée à -1 !
'Ce n'est pas le cas si les conditions (1) & (2) ne
'sont pas réunies, auquel cas sa propriété ListIndex
'indique bien la position de la valeur dans la liste.
'----------------------------------------------------
Private Sub ComboBoxValeur(ByRef ComboBox As ComboBox, ByVal Valeur As Variant)
    Dim i As Integer
    Dim TabValeurs() As Variant
 
    'Valorise la ComboBox
    ComboBox.Value = Valeur
 
    'ComboBox valorisée avec une de ses valeurs texte
    If ComboBox.ListIndex >= 0 Then Exit Sub
 
    'ComboBox valorisée avec une de ses valeurs numériques
    TabValeurs = ComboBox.List
 
    For i = LBound(TabValeurs, 1) To UBound(TabValeurs, 1)
        If CStr(TabValeurs(i, 0)) = CStr(Valeur) Then Exit For
    Next i
 
    'Valeur trouvée, corrige le ListIndex
    If i <= UBound(TabValeurs) Then
        ComboBox.ListIndex = i
    End If
End Sub
 

Dranreb

XLDnaute Barbatruc
Bonsoir.
Personnellement je ne garnis jamais une List de ComboBox avec un tableau contenant des nombres.
Je les convertis toujours préalablement en String. Et je vous recommande de faire de même. De toute façon sa Value sera un Variant/String, alors autant que tous les éléments de sa List en soient aussi. J'avais depuis longtemps constaté des anomalies de ce genre à la frappe notamment: il ne propose pas de suite prise de sa List si ce sont des nombres.
 

patricktoulon

XLDnaute Barbatruc
re
Dudu2
Tiens fait cette petite expérience
ajoute l'event dans la feuille de la combo
VB:
Private Sub ComboBox1_Change()
If ComboBox1.ListIndex > -1 Then ComboBox2_ValueFromList True
End Sub
et modifie ta sub comme suit
VB:
Public Sub ComboBox2_ValueFromList(Optional active As Boolean = False)
   If Not active Then
   'ActiveSheet.ComboBox2.ListFillRange = ""
    ActiveSheet.ComboBox2.List = ActiveSheet.Range("B1:B3").Value
    ActiveSheet.ComboBox2.Value = 2020
    'ActiveSheet.ComboBox2.Value = CDbl(2020)
    'ActiveSheet.ComboBox2.Value = CStr(2020)
    'ActiveSheet.ComboBox2.Value = Format(2020, "0000")
    End If
    If active = True Then MsgBox "ComboBox2.ListIndex = " & ActiveSheet.ComboBox2.ListIndex
End Sub

1er essai lance la macro a partir du menu macro
2d essai click sur ton bouton

donc le focus sur la shape appelante'bouton 4'
surprenant non!!!
en même temps pas tant que ça si observe de plus près
;)
ça confirme mon idée sur l’accès en charge

maintenant 3eme essai test tout simplement ta sub d'origine en l'appelant du menu macro

voila maintenant tu sais ce que fait listfillrange parallèlement a remplir ta liste

et donc tout devient plus clair quand on connait le comportement d'une shape sélectée

pour moi ça n'est donc pas un bug mais bel et bien une méthode
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
@job75,

Tout transformer en String est en effet une méthode pour palier ce comportement étrange.
Mais alors ça veut dire qu'il faut toujours faire attention au chargement à partir d'un Range et passer par un table de String.
VB:
Sub ComboBox2_ValueFromList()
    Dim TabVal() As Variant
    Dim i As Integer
    Dim j As Integer
    
    'Chargement du Range en table
    TabVal = ActiveSheet.Range("B1:B3").Value
    
    'Transformation des valeur en String
    For i = 1 To UBound(TabVal, 1)
        For j = 1 To UBound(TabVal, 2)
            TabVal(i, j) = CStr(TabVal(i, j))
        Next j
    Next i
    
    ActiveSheet.ComboBox2.ListFillRange = ""
    
    'Chargement de la table de String en ComboBox
    ActiveSheet.ComboBox2.List = TabVal
    
    ActiveSheet.ComboBox2.Value = "2020"
    MsgBox "ComboBox2.ListIndex = " & ActiveSheet.ComboBox2.ListIndex
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
ou
VB:
Sub ComboBox2_ValueFromList()
    Dim TabVal() As Variant
    Dim i As Integer
    Dim X&
    'Chargement du Range nen table
    TabVal = ActiveSheet.Range("B1:B3").Value
    
    'Transformation des valeur en String
    'For i = 1 To UBound(TabVal, 1)
        'TabVal(i, 1) = CStr(TabVal(i, 1))
    'Next i
    
    ActiveSheet.ComboBox2.ListFillRange = ""
    
    'Chargement de la table de String en ComboBox
    ActiveSheet.ComboBox2.List = TabVal
    
    x = Application.IfError(Application.Match(2020, ActiveSheet.ComboBox2.List, 0), -1) - 1
       ActiveSheet.ComboBox2.ListIndex = x
    'ActiveSheet.ComboBox2.Value = "2020"
    MsgBox "ComboBox2.ListIndex = " & ActiveSheet.ComboBox2.ListIndex
End Sub
 

Dudu2

XLDnaute Barbatruc
Ok, donc soit mise en formule des valeurs numériques (si on y pense), soit recherche avec Application.Match.

Je crois que je vais finir par charger les ComboBox avec un fonction généraliste (autant que possible).
VB:
'------------------------------------------------------------
'Chargement d'une ComboBox à partir d'un Range ou d'une Table
'en s'assurant que les items de la ComboBox sont tous de type
'String pour éviter les comportements étranges sur les items
'de type valeurs numériques.
'------------------------------------------------------------
'https://www.excel-downloads.com/threads/vba-curiosite-combobox.20051806/
'------------------------------------------------------------
Sub ComboBoxListLoad(ByRef Cmb As ComboBox, ByRef RngOrTab As Variant, Optional ItemFormat As String = "@")
    Dim TabVal() As Variant
    Dim TabValArea() As Variant
    Dim Area As Range
    Dim i As Long
    Dim k As Long
    Dim ErrNumber As Variant
    
    'Suppression du ListFillRange / RowSource éventuel
    On Error Resume Next
    Cmb.ListFillRange = ""  'ComboBox non UserForm
    Cmb.RowSource = ""      'ComboBox UserForm
    On Error GoTo 0

    'L'argument est de type Range
    If TypeOf RngOrTab Is Range Then
        
        'D'une seule  cellule
        If RngOrTab.Cells.Count = 1 Then
            ReDim TabVal(1 To 1)
            TabVal(1) = RngOrTab.Value
        
        'De plusieurs cellules
        Else
            ReDim TabVal(1 To RngOrTab.Cells.Count)
            k = 0
            
            'Parcours des Areas du Range
            For Each Area In RngOrTab.Areas
                TabValArea = Area.Columns(1).Value
                
                For i = 1 To UBound(TabValArea, 1)
                    TabVal(k + i) = TabValArea(i, 1)
                Next i
                k = k + UBound(TabValArea, 1)
            Next Area
        End If
        
    'L'argument est de type Tableau
    Else
        On Error Resume Next
        i = UBound(RngOrTab, 2)
        ErrNumber = Err.Number
        On Error GoTo 0
        
        'Table à 1 dimension
        If ErrNumber <> 0 Then
            TabVal = RngOrTab
        
        'Table à 2 dimensions
        Else
            For i = LBound(TabVal, 1) To UBound(TabVal, 1)
                TabVal(i) = RngOrTab(i, 1)
            Next i
        End If
    End If

    'Conversion des valeurs en String ou mise au format
    For i = LBound(TabVal) To UBound(TabVal)
        TabVal(i) = Format(TabVal(i), ItemFormat)
    Next i
    
    'Chargement de la ComboBox
    Cmb.List = TabVal
End Sub
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Il y a plein de fonctionnalités généralistes dans cette ressource :
(dont celle dont il était question: toutes les listes fabriquées son composées de String, classées et sans doublon, et la réécriture dans un tableau des valeurs de la ligne les retransforme en nombres s'il y a lieu, sauf demande expresse à l'initialisation.)
 

Discussions similaires

Statistiques des forums

Discussions
312 393
Messages
2 088 006
Membres
103 695
dernier inscrit
acimi