SUPPRESSION DES DOUBLONS D'UNE COMBOBOX

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 - 10 mars 2009 à 15:49
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 - 11 mars 2009 à 08:12
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/49469-suppression-des-doublons-d-une-combobox

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
11 mars 2009 à 08:12
ah ah, exact, je l'avais pas vu, le niveau expert !
bigfish_le vrai Messages postés 1835 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 20 novembre 2013 15
10 mars 2009 à 18:21
Salut,

j'ajouterais que en VBA et en general, les données proviennent d'un tableau. Par exemple avec excel il est courant de faire

Me.MaCombobox.list() = Sheets("feuil1").range("A1:A10").Value

ors si cette plage de cellules contient des doublons et que l'on veut les supprimer il existe d'autre methodes propre a excel. Ces methodes son souvent plus rapide que les methodes par boucle.

en voici une :
la methode suivante suppose que les données sont en colonne et qu'elles sont reperees par une etiquette.

Pour l'exemple je reprends la liste proposé par Renfield. Son etiquette est "Fruit" (de la liste pas de Renfield ;)

Fruit
Banane
BANANE
BANANE
Pomme
Raisin
Poire
Pomme
Fraise
Fraise
Kiwi

Sub ListeSansDoublon(ByRef MaPlage As Range, ByRef MaCombobox As Object)
If Not MaCombobox Is Nothing And Not MaPlage Is Nothing Then
If TypeOf MaCombobox Is ComboBox Then
Application.ScreenUpdating = False
' utilisation du filre élaboré des données
MaPlage.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
' le filtre élaboré a besoin d'une colonne de donné avec etiquette
' donc pour ne pas mettre cette etiquette dans la liste on ce decale d'une ligne vers le bas
Set MaPlage = MaPlage.Offset(1, 0).Resize(MaPlage.Rows.Count - 1, 1)
' les données en doubles on été cachées par le filtre
' il suffit donc de ne recupérer que ce qui est visible
Set MaPlage = MaPlage.SpecialCells(xlCellTypeVisible)
' comme on ne peut pas attribuer les valeurs d'une plage composée de plusieurs area a une combobox
' on vas contourner le probleme par un copy paste des valeurs sur une plage temporaire
MaPlage.Copy
Range("Z1").PasteSpecial Paste:=xlPasteValues ' ici la plage temporaire est la colonne Z
MaCombobox.List() = Selection.Value
' on desactive le filtre
ActiveSheet.ShowAllData
' on efface la zone temporaire
Selection.ClearContents
' on centre l'affichage sur la plage d'origine
MaPlage.Cells(1, 1).Activate
Application.ScreenUpdating = True
End If
End If
End Sub

D'autre part un niveau expert pour ça ?!?!... et en plus a l'attention des débutants...
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
10 mars 2009 à 16:04
on pourrais imaginer ce genre de code, pour VBA :

Private Sub Command1_Click()
With Combo1
.Clear
.AddItem "Banane"
.AddItem "BANANE"
.AddItem "BANANE"
.AddItem "Pomme"
.AddItem "Raisin"
.AddItem "Poire"
.AddItem "Pomme"
.AddItem "Fraise"
.AddItem "Fraise"
.AddItem "Kiwi"
End With

SUPPRESSION_DOUBLON_COMBOBOX Combo1, vbTextCompare
End Sub

Private Sub SUPPRESSION_DOUBLON_COMBOBOX(ByRef voCBO As Object, Optional ByVal veCompare As VbCompareMethod = vbBinaryCompare)
Dim i As Long
Dim j As Long
If Not Nothing Is voCBO Then
If TypeOf voCBO Is ComboBox Then
With voCBO
Do While i < .ListCount
For j = .ListCount - 1 To i + 1 Step -1
If StrComp(.List(i), .List(j), veCompare) = 0 Then
.RemoveItem j
End If
Next j
i = i + 1
Loop
End With
End If
End If
End Sub

en VB6, on procéderait différemment, mais là, on a pas accès à un hWnd, donc...

encore une fois, je précise qu'il est plus simple, rapide et pertinent de ne pas ajouter les elements en double, tout simplement...

soit, par exemple:

Private Sub Command1_Click()
Combo1.Clear
AddItem Combo1, "Banane"
AddItem Combo1, "BANANE"
AddItem Combo1, "BANANE"
AddItem Combo1, "Pomme"
AddItem Combo1, "Raisin"
AddItem Combo1, "Poire"
AddItem Combo1, "Pomme"
AddItem Combo1, "Fraise"
AddItem Combo1, "Fraise"
AddItem Combo1, "Kiwi"
End Sub

Private Sub AddItem(ByRef voCBO As Object, ByRef vsItem As String, Optional ByVal veCompare As VbCompareMethod = vbTextCompare)
Dim i As Long
If Not Nothing Is voCBO And LenB(vsItem) Then
If TypeOf voCBO Is ComboBox Then
With voCBO
For i = 0 To .ListCount - 1
If StrComp(.List(i), vsItem, veCompare) = 0 Then
Exit Sub
End If
Next i
.AddItem vsItem
End With
End If
End If
End Sub
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
10 mars 2009 à 15:51
j'ajouterais que tu recoit un parametre Object
tu ne teste pas qu'il soit bien affecté ni qu'il s'agit bien d'un Combobox (ou ListBox)
ni qu'elle est triée.

i n'est pas déclaré.

on pourrait imaginer un parametre permettant de spécifier si on souhaite tenir compte de la casse ou non.

bref. beaucoup de maladresse dans ces quelques lignes de code
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
10 mars 2009 à 15:49
n'est-ce pas encore plus pratique de n'ajouter un élément que s'il n'est pas déjà présent ?

ton code n'est valable que si ta combobox est triée

enfin, tu aurais pu parcourir ta liste de l'element n à l'element 1 (en ajoutant Step -1 dans la commande For)
Rejoignez-nous