Excel VBA 2 COMBOBOX dont la seconde reste avec doublon
Bonjour,
J'ai réussi à créer un formulaire simple avec 2 combobox en cascade l'une dépendante de l'autre. Mon souci c'est que je n'ai pas réussi à trouver le bon code pour que la seconde combobox soit elle aussi sans doublons.
Je m'explique un peu plus:
Combobox1 = une liste de titres (celle ci pas de souci elle est bien sans doublons) colonne A dans mon excel
Combobox2 = une entreprise (celle ci parfois j'ai Entreprise A, puis à nouveau Entreprise A, mais le doublon est tout simplement relatif à une autre ligne ce sont dans les textboxs que les informations sont changeantes)
Après avoir fais choix dans les combobox, les données s'inscrivent dans des TextBox. J'ai réussi à placer dans mon formulaire (USERFORM) des boutons "précédents", et "suivants" pour naviguer les enregistrements une fois que j'ai mon titre de sélectionné et l'entreprise qui l'a en gestion.
Tous les codes différents que j'ai tenté d'adapter ne fonctionne pas. De plus j'ai aussi un bouton ajouter et modifier, si bien que si je modifie déjà le début de mes codes VBA, tout le reste ressort en bug. Je ne m'en sors absolument pas. Etant donné que je suis vraiment dans les prémices, si une bonne âme voulait bien me donner un coup de pouce mais le plus simple possible!!
Pourtant ma demande est simple, je cherche un bout de code soit à rajouter, soit juste adapter avec déjà ce que j'ai pour que je puisse avoir en Combobox2 une fois l'entreprise (même si pour le même titre je l'a retrouverai) Pour naviguer d'un enregistrement à un autre, je ne réutilise pas de combobox, mais uniquement mes boutons précédents et suivants.
Je vous remercie pour vos retours et votre aide par avance.
[u]Voici le code de mon formulaire:
[/u]Option Explicit
Dim Ws As Worksheet
Dim NbLignes As Integer
Dim TextBox As Integer
Private Sub UserForm_Initialize()
Dim j As Long 'déclare la variable J
Dim i As Integer
Set Ws = Sheets("Base")
NbLignes = Ws.Range("A65536").End(xlUp).Row
With Me.ComboBox2
.ColumnCount = 2
.ColumnWidths = "-1;0"
End With
InitCombo1
Sub InitCombo1()
Dim j As Long
Dim Mondico As Object
Set Mondico = CreateObject("Scripting.dictionary")
For j = 2 To NbLignes
Mondico(Ws.Range("A" & j).Value) = ""
Next j
With Me.ComboBox1
.Clear
If Mondico.Count > 0 Then
.List = Application.Transpose(Mondico.keys)
End If
End With
End Sub
Private Sub ComboBox1_Change()
Dim j As Long
Nettoyage
Me.ComboBox2.Clear
If Me.ComboBox1.ListIndex = -1 Then Exit Sub
With Me.ComboBox2
For j = 2 To NbLignes
If Ws.Range("A" & j) = Me.ComboBox1 Then
.AddItem Ws.Range("B" & j)
.List(.ListCount - 1, 1) = j
End If
Next j
End With
End Sub
Private Sub ComboBox2_Change()
Dim Ligne As Long
Dim i As Integer
Nettoyage
If Me.ComboBox2.ListIndex = -1 Then Exit Sub
Ligne = Me.ComboBox2.List(Me.ComboBox2.ListIndex, 1)
For i = 1 To 15
Me.Controls("TextBox" & i) = Ws.cells(Ligne, i).Value
Next i
End Sub
Sub Nettoyage()
Dim i As Integer
For i = 1 To 15
Me.Controls("TextBox" & i) = ""
Next i
End Sub
'Pour le bouton Modifier
Private Sub CommandButton2_Click()
Application.ScreenUpdating = False
Dim Ligne As Long
Dim i As Integer
Dim Ctrl As Control
If Me.ComboBox1.ListIndex = -1 Then Exit Sub
Ligne = Me.ComboBox2.List(Me.ComboBox2.ListIndex, 1)
For i = 1 To 15
If Me.Controls("TextBox" & i).Visible = True Then
Ws.cells(Ligne, i) = Me.Controls("TextBox" & i).Value
End If
Next i
MsgBox ("Modification, Complement enregistrés") .
End If
Application.ScreenUpdating = True
End Sub
Private Sub CommandButton4_Click()
Application.ScreenUpdating = False
Dim Ligne As Integer
Dim i As Integer
If MsgBox(" Ajout ?"), vbYesNo, "Demande de confirmation") = vbYes Then 'condition : si oui au message
Ligne = Ws.Range("a65536").End(xlUp).Row + 1 'Permet de se positionner sur la dernière ligne de tableau NON VIDE
For i = 1 To 15
Ws.cells(Ligne, i) = Me.Controls("TextBox" & i).Value
Next i
End If
' Affiche une boîte de message
MsgBox ("Nouvelle saisie enregistrée")
Unload Me ' Vide et ferme l'Userform ( formulaire)
UserForm1.Show vbModeless 'Affiche le formulaire
Application.ScreenUpdating = True
End Sub
Private Sub CommandButton9_Click()
If ComboBox2.ListIndex < (ComboBox2.ListCount - 1) Then
ComboBox2.ListIndex = ComboBox2.ListIndex + 1
Else
MsgBox "Vous avez atteint la fin des enregistrements."
End If
End Sub
Private Sub CommandButton10_Click()
If ComboBox2.ListIndex > 0 Then
ComboBox2.ListIndex = ComboBox2.ListIndex - 1
Else
MsgBox "Il n'existe pas d'enregistrement précédent."
End If
End Sub
Bonjour et bienvenue sur le forum
Tu devrais joindre ton fichier complet, quitte à modifier les données éventuellement sensibles...
Bye !
- Messages
- 4'097
- Excel
- 2021 FR 64 bits
- Inscrit
- 13/06/2016
- Emploi
- bénévole associations Goutte d'Or
Bonsoir,
Essayer ce début de code :
Option Explicit
Dim Ws As Worksheet
Dim NbLignes As Integer
Dim Titres As Object, Entreprises As Object
Private Sub UserForm_Initialize()
Dim j As Long 'd?clare la variable J
Dim i As Integer
Set Ws = Sheets("Base")
NbLignes = Ws.Range("A65536").End(xlUp).Row
With Me.ComboBox2
.ColumnCount = 2
.ColumnWidths = "-1;0"
End With
InitCombo1
End Sub
Sub InitCombo1()
Dim j As Long
Dim titre As String, entreprise As String
Set Titres = CreateObject("Scripting.dictionary")
For j = 2 To NbLignes
titre = Ws.Range("A" & j).Value
entreprise = Ws.Range("B" & j).Value
If Not Titres.exists(titre) Then Set Titres(titre) = CreateObject("Scripting.dictionary")
Set Entreprises = Titres(titre)
If Not Entreprises.exists(entreprise) Then Entreprises(entreprise) = j
Set Titres(titre) = Entreprises
Next j
With Me.ComboBox1
.Clear
If Titres.Count > 0 Then .List = Application.Transpose(Titres.keys)
End With
End Sub
Private Sub ComboBox1_Change()
Dim j As Long
Dim entreprise As Variant
If Me.ComboBox1.ListIndex = -1 Then Exit Sub
Nettoyage
Set Entreprises = Titres(Me.ComboBox1.Value)
With Me.ComboBox2
.Clear
For Each entreprise In Entreprises.keys
.AddItem entreprise
.List(.ListCount - 1, 1) = Entreprises(entreprise)
Next entreprise
End With
End Sub
Bonjour,
Je vous remercie infiniment pour votre réponse, et votre début de code fonctionne à merveille. Je n'ai plus du tout de doublons que ce soit dans la combobox1 mais aussi dans la seconde (combobox2).
Par contre je ne voudrais pas user à nouveau de vos compétences, mais à présent j'obtiens dans mes textboxs informations du premier enregistrement qui va concerné le titre et l'entreprise, exemple:
Dans mon tableau Excel:
Titre (Colonne A- Entreprise (colonne B - référencé (colonneC)
Gribouille - GESTOR - a/256
Gribouille - GESTOR - b/698
Gribouille - TARTEMPION - c/452
Avec le code que vous m'avez communiqué quand je fais dérouler mon Choix et que je veux visionner "Gribouille" ensuite dans la seconde combobox, je fais choix de l'entreprise (comme les listes peuvent être en grands nombres, je ne voulais pas de doublons dans la seconde combobox, c'était mon problème initial); Donc avec le nouveau code qui réponds à la suppression des doublons, dés que j'ai choisi mon entreprise, je n'ai que le résultat dans les TextBox de la première ligne de ma base soit : "a/256
Ce qui est fort normal puisque le code permet de filtrer. J'ai conçu mon formulaire pour qu'avec mon bouton suivant je puisse d'un clic dessus faire changer juste mes textbox puisque dans mes listes j'ai fais le bon choix, mais que je puisse ainsi faire défiler (par mes boutons précédents et suivants) les autres lignes relatives à mon choix dans ce cas : "gribouille avec l'entreprise GESTOR".
Quand je fais appel à mes boutons précédents et suivants tels que je les ai codé, mais du fait que je suis complétement débutante il me manque dans ce cas ci une partie pour adapter, je ne fais que récupérer la première ligne suivante ou précédente , exemple:
j'ai Gribouille / GESTOR -> a/256
Bouton suivant: Gribouille / TARTEMPION -> c/452
Votre code me va très bien par ce que je selectionne dans les combobox, mais alors comment puis je juste en activant mon bouton précédent et suivant , voici actuellement le code pour mes deux boutons précédents et suivants , encore merci pour votre aide:
'pour précedent
Private Sub CommandButton10_Click()
If ComboBox2.ListIndex > 0 Then
ComboBox2.ListIndex = ComboBox2.ListIndex - 1
Else
MsgBox "Il n'existe pas d'enregistrement précédent."
End If
'pour suivant
Private Sub CommandButton9_Click()
If ComboBox2.ListIndex < (ComboBox2.ListCount - 1) Then
ComboBox2.ListIndex = ComboBox2.ListIndex + 1
Else
MsgBox "Vous avez atteint la fin des enregistrements."
End If
End Sub
- Messages
- 4'097
- Excel
- 2021 FR 64 bits
- Inscrit
- 13/06/2016
- Emploi
- bénévole associations Goutte d'Or
Bonjour,
J'ai remplacé vos 2 boutons "suivant" et "précédent" par une scrollbar à insérer dans votre formulaire
Les lignes à afficher sont gérées via une variable tableau au niveau du module. La ligne courante affichée est également une variable au niveau module.
Ajout du tri des titres et entreprises via ma fonction personnalisée de tri d'un dictionnaire.
ci-dessous code modifié et correctement indenté.
NB : le nombre de lignes d'une feuille est variable selon la version d'Excel, mieux vaut utiliser des instructions génériques.
Option Explicit
Dim Ws As Worksheet
Dim NbLignes As Integer
Dim Titres As Object, Entreprises As Object
Dim Lignes(), Ligne As Long
Private Sub UserForm_Initialize()
Dim j As Long 'déclare la variable J
Dim i As Integer
Set Ws = Sheets("Base")
NbLignes = Ws.Columns("A").Find("*", SearchDirection:=xlPrevious).Row
With Me.ComboBox2
.ColumnCount = 1
End With
InitCombo1
End Sub
Sub InitCombo1()
Dim i As Integer, j As Long
Dim titre As String, entreprise As String
Dim tb_lignes()
Set Titres = CreateObject("Scripting.dictionary")
For j = 2 To NbLignes
titre = Ws.Range("A" & j).Value
entreprise = Ws.Range("B" & j).Value
If Not Titres.exists(titre) Then Set Titres(titre) = CreateObject("Scripting.dictionary")
Set Entreprises = Titres(titre)
If Not Entreprises.exists(entreprise) Then Entreprises(entreprise) = Array(): i = 0
tb_lignes = Entreprises(entreprise): ReDim Preserve tb_lignes(i): tb_lignes(i) = j: i = i + 1
Entreprises(entreprise) = tb_lignes
Set Titres(titre) = Entreprises
Next j
Call tri_dico_AZ(Titres)
With Me.ComboBox1
.Clear
If Titres.Count > 0 Then .List = Application.Transpose(Titres.keys)
End With
End Sub
Private Sub ComboBox1_Change()
Dim j As Long
Dim entreprise As Variant
If Me.ComboBox1.ListIndex = -1 Then Exit Sub
Nettoyage
Set Entreprises = Titres(Me.ComboBox1.Value)
Call tri_dico_AZ(Entreprises)
With Me.ComboBox2
.Clear
If Entreprises.Count > 0 Then .List = Application.Transpose(Entreprises.keys)
End With
End Sub
Private Sub ComboBox2_Change()
If Me.ComboBox2.ListIndex = -1 Then Exit Sub
Nettoyage
Lignes = Entreprises(Me.ComboBox2.Value)
Me.ScrollBar1.Min = 0: Me.ScrollBar1.Max = UBound(Lignes): Me.ScrollBar1.Value = Me.ScrollBar1.Min
ScrollBar1_Change
End Sub
Private Sub ScrollBar1_Change()
Dim i As Integer
Ligne = Lignes(ScrollBar1.Value)
For i = 1 To 15
Me.Controls("TextBox" & i) = Ws.Cells(Ligne, i).Value
Next i
End Sub
Sub Nettoyage()
Dim i As Integer
For i = 1 To 15
Me.Controls("TextBox" & i) = ""
Next i
End Sub
'Pour le bouton Modifier
Private Sub CommandButton2_Click()
Application.ScreenUpdating = False
Dim i As Integer
Dim Ctrl As Control
If Me.ComboBox1.ListIndex = -1 Then Exit Sub
For i = 1 To 15
If Me.Controls("TextBox" & i).Visible = True Then Ws.Cells(Ligne, i) = Me.Controls("TextBox" & i).Value
Next i
MsgBox ("Modification, Compl?ment enregistr?s")
Application.ScreenUpdating = True
End Sub
Private Sub CommandButton4_Click()
Application.ScreenUpdating = False
Dim Ligne As Integer
Dim i As Integer
If MsgBox(" Ajout ?", vbYesNo, "Demande de confirmation") = vbNo Then Exit Sub
Ligne = Ws.Columns("A").Find("").Row 'Permet de se positionner sur la dernière ligne de tableau NON VIDE
For i = 1 To 15
Ws.Cells(Ligne, i) = Me.Controls("TextBox" & i).Value
Next i
' Affiche une boîte de message
MsgBox ("Nouvelle saisie enregistrée")
Unload Me ' Vide et ferme l'Userform ( formulaire)
UserForm1.Show vbModeless 'Affiche le formulaire
Application.ScreenUpdating = True
End Sub
Function tri_dico_AZ(ByVal dico As Object)
Dim tb_clés(): ReDim tb_clés(dico.Count)
Dim tb_items(): ReDim tb_items(dico.Count)
Dim clé As Variant, clé1 As Variant
Dim nb_sup As Long, i As Long
'// Stockage d'une clé et de l'item correspondant respectivement dans les tableaux tb_clés et tb_items
'// selon le nombre de fois où l'ensemble des clés est inférieur ou égal à la clé courante
For Each clé1 In dico.keys
i = 0
For Each clé In dico.keys
If clé <= clé1 Then i = i + 1
Next clé
tb_clés(i) = clé1
If IsObject(dico(clé1)) Then Set tb_items(i) = dico(clé1) Else tb_items(i) = dico(clé1)
Next clé1
'// Réinitialisation du dictionnaire et remplissage à partir des tableaux tb_clés et tb_items
dico.RemoveAll
For i = 1 To UBound(tb_clés)
dico.Add tb_clés(i), tb_items(i)
Next i
End Function
Tout d'abord je tiens infiniment à vous remercier, cela m'aide énormément et je reprends goût à persévérer...
Mon formulaire ne fonctionne pas car il s'arrête, à la combobx2 , en surlignant en jaune :
Lignes (il m'indique un message erreur de compilation, variable non définie)
Sniff sniff...
J'ai bien intégré les scollbar comme indiqué.
Merci beaucoup.
NE PAS TENIR COMPTE DE MON PRECEDENT POST,
JE n'avais pas repris le tout début "OPTION EXPLICIT"!!!Quelle andouille...
MERCI THEV encore et encore, si vous saviez comment j'ai cherhché pendant des semaines sans arriver à un résultat concret!!!
Je termine comme cela est indiqué par le forum, par le petit logo résolu, mais encore une fois mille mercis pour cette attention que vous m'avez alors consacré et les bons codes afin d'arriver à quelques choses !!!
Site d'entres aides super!!!
- Messages
- 4'097
- Excel
- 2021 FR 64 bits
- Inscrit
- 13/06/2016
- Emploi
- bénévole associations Goutte d'Or
Lignes (il m'indique un message erreur de compilation, variable non définie)
Vous avez sans doute oublié les déclarations de variable au niveau du module avant toute procédure Sub
Option Explicit
Dim Ws As Worksheet
Dim NbLignes As Integer
Dim Titres As Object, Entreprises As Object
Dim Lignes(), Ligne As Long
Private Sub UserForm_Initialize()
Par ailleurs, j'ai amélioré ma réponse précédente en ajoutant le tri de vos titres et entreprises dans vos Comboboxes.