[VBA Excel] Listbox

Signaler
Messages postés
83
Date d'inscription
jeudi 22 novembre 2007
Statut
Membre
Dernière intervention
4 septembre 2014
-
Messages postés
83
Date d'inscription
jeudi 22 novembre 2007
Statut
Membre
Dernière intervention
4 septembre 2014
-
Bonjour,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /??>



 




Je suis en train de travailler sur une base de données et je voudrais réaliser un userform qui me permettrait de sélectionner l'élément qui servira de référence dans la suite de mon étude.



 




En gros pour choisir cette référence, il me faut croiser 3 colonnes


- nom


- année


- domaine


Il peut y avoir des redondances (un même nom à diverses années et pour divers domaines)



 




En gros ce que je souhaiterais faire, ce sont 3 listbox qui reprendrais ces 3 colonnes nom, domaine et année, sans doublon, classée par ordra alphanumériqueet quand je sélectionne un élement d'une colonne celà enlève des choix dans les autres.


Cà correspond en fait aux filtres automatiques sur ces 3 colonnes, mais je souhaite une méthode détournée pour que l'utilisateur n'ait pas accès à la base de données directement.



 




Est-ce que quelqu'un aurait une petite piste ?

2 réponses

Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
18
Peut-être en passant par les filtres élaborés sans doublons ?
Si tu utilises le filtre élaboré avec l'enregistreur de macro, tu verras le code nécessaire pour le faire.
Tu pourrais alors utiliser des colonnes vides pour effectuer ce tri sans doublon et charger tes listbox.

Si ça te semble trop compliqué ou trop de manipulations, peut-être pourrais-tu regarder du côté d'ADO et faire des requêtes sur cette "base de données".
Avec un "Select Distinct Champ From Table"
tu pourrais ressortir les valeurs uniques sans doublons.

Autrement, tu peux charger tes listes en vérifiant si la donnée à insérer est déjà là ou non. Simple boucle For...Next et une petite Function de vérification.

MPi²
Pour ceux qui programment sous Office, n'oubliez pas qu'il existe un forum dédié à ces applications VBA....... ICI
Messages postés
83
Date d'inscription
jeudi 22 novembre 2007
Statut
Membre
Dernière intervention
4 septembre 2014

J’ai trouvé la solution à mon pb sur les sites :



http://silkyroad.developpez.com/VBA/ControlesUserForm/#LII-C


et



http://boisgontierjacques.free.fr/pages_site/formulairecascade.htm


et voici le résultat :



<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>
 




Private Sub userform_initialize()



   






    'codage des noms des champs dynamiques



   
ActiveWorkbook.Names.Add Name:="An", RefersTo:="=OFFSET(Cells(2,ColA),,,CountA((" & Columns(ColA).Address & ") - 1)"






    ActiveWorkbook.Names.Add Name:="Collectivité", RefersTo:="=OFFSET(Cells(2,ColC),,,CountA(" & Columns(ColC).Address & ") - 1)"






    ActiveWorkbook.Names.Add Name:="Domaine", RefersTo:="=OFFSET(Cells(2,ColD),,,CountA(" & Columns(ColD).Address & ") - 1)"






 







    Ch_Nom






    Ch_An






    Ch_Domaine






    On Error Resume Next






    ActiveSheet.ShowAllData






   







End Sub






 






Private Sub Collectivité_DropButtonClick()






    Ch_Nom





End Sub






 






Private Sub Domaine_DropButtonClick()






    Ch_Domaine





End Sub






 






Private Sub An_DropButtonClick()






    Ch_An





End Sub






 






Private Sub An_Change()






    filtre





End Sub






 






Private Sub Domaine_Change()






    filtre





End Sub






 






Private Sub Collectivité_Change()






    filtre





End Sub






 






Sub Ch_Nom()






    Set MonDico = CreateObject("Scripting.Dictionary")






    For i = 1 To Range("Collectivité").Count






        If Range("Domaine")(i) Like Me.Domaine And CStr(Range("An")(i)) Like Me.An Then






            temp = Range("Collectivité")(i)






            If Not MonDico.Exists(temp) Then






                MonDico.Add temp, temp






            End If






        End If






    Next i






    MonDico.Add "*", "*"






    temp = MonDico.items






    Call Tri(temp, LBound(temp), UBound(temp))






    Me.Collectivité.list = temp





End Sub






 






Sub Ch_An()






    Set MonDico = CreateObject("Scripting.Dictionary")






    For i = 1 To Range("An").Count






        If Range("Collectivité")(i) Like Me.Collectivité And Range("Domaine")(i) Like Me.Domaine Then






            temp = Range("An")(i)






            If Not MonDico.Exists(temp) Then






                MonDico.Add temp, temp






            End If






        End If






    Next i






    MonDico.Add "*", "*"






    temp = MonDico.items






    Call Tri(temp, LBound(temp), UBound(temp))






    Me.An.list = temp





End Sub






 






Sub Ch_Domaine()






    Set MonDico = CreateObject("Scripting.Dictionary")






    For i = 1 To Range("Domaine").Count






        If Range("Collectivité")(i) Like Me.Collectivité And CStr(Range("An")(i)) Like Me.An Then






            temp = Range("Domaine")(i)






            If Not MonDico.Exists(temp) Then






                MonDico.Add temp, temp






            End If






        End If






    Next i






    MonDico.Add "*", "*"






    temp = MonDico.items






    Call Tri(temp, LBound(temp), UBound(temp))






    Me.Domaine.list = temp





End Sub






 





Sub Tri(a, gauc, droi) ' Quick sort



    Ref = CStr(a((gauc + droi) \ 2))



   
g gauc: d droi






    Do






        Do While CStr(a(g)) < Ref: g g + 1: <?xml:namespace prefix st1 ns = "urn:schemas-microsoft-com:office:smarttags" /??><st1:place w:st="on">Loop</st1:place>






        Do While Ref < CStr(a(d)): d = d - 1: <st1:place w:st="on">Loop</st1:place>






       
If g <= d Then




            temp a(g): a(g) a(d): a(d) = temp






            g g + 1: d d - 1






        End If






    Loop While g <= d






    If g < droi Then Call Tri(a, g, droi)






    If gauc < d Then Call Tri(a, gauc, d)





End Sub






 






Sub filtre()






    Dim Cellule






    Cellule = Cells(1, ColP)






    On Error Resume Next






    ActiveSheet.ShowAllData






    Cellule.AutoFilter Field:=1, Criteria1:=Me.Collectivité






    If Me.An <> "*" Then Cellule.AutoFilter Field:=3, Criteria1:=Me.An






    Cellule.AutoFilter Field:=2, Criteria1:=Me.Domaine





End Sub






 






Private Sub B_OK_Click()






   
CollectR = Me.Collectivité



    DomR = Me.Domaine



    AnR = Me.An




    Call LigneRef






 
   ActiveSheet.ShowAllData






    Unload ChxRef





End Sub






 






Sub LigneRef()






    Dim ligne As Integer






    If Range("A:A").SpecialCells(xlCellTypeVisible).Areas(1).Count > 1 Then






       
ligne = 2        'pas de filtre



    Else                 'il y a un filtre



       
ligne = Range("A:A").SpecialCells(xlCellTypeVisible).Areas(2).Item(1).Row






    End If






    LgR = ligne





End Sub






 





mais par contre j’ai un problème maintenant pour nommer mes champs dynamiques car je ne sais pas à l’avance que la plage nommé An sera dans la colonne C. Ce que j’ai marqué dans le code ci-dessus ne marche pas et me provoque l’erreur d’exécution 1004



Il faudrait donc pouvoir nommer le champ avec un nom de colonne variable, mais je ne sais pas comment faire …





 




La syntaxe basique est la suivante :



ActiveWorkbook.Names.Add Name:="An", RefersTo:="=OFFSET($C$2,,,CountA($C:$C) - 1)"