Je cherche à réaliser des listes déroulantes imbriquées dans un Userform. Après des recherches j’ai trouvé ce qui m’a servi à faire mon test. J’ai créé un Userform avec deux ComboBox, j’ai rentré le code mais dès que je lance l’exécution j’ai le message d’erreur suivant :
Erreur d’exécution 438
Propriété ou méthode non géré par cet objet
J’ai bien essayé de comprendre cette erreur mais je n’y suis pas parvenu.
1) Il faut absolument éviter les .Select, ActiveCell, Selection, ... en VBA.
2) il faut éviter de déclarer toutes les variables avec une portée globales, il faut limiter leur portée au strict nécessaire.
J'aurais écrit ton code comme ceci :
Option Explicit
Private Sub UserForm_Initialize()
' Procédure permettant d'initailiser
' les données de la liste Rubrique.
Dim colonne As Long
' Initialisation des Variables.
colonne = 2 ' Numéro de la Première colonne.
' Création d'une boucle pour charger toutes les rubriques.
With Sheets("Donnees")
Do While .Cells(2, colonne).Value <> "" ' Tant qu'il y a des valeurs sur la ligne 2.
FrmSaisie.CboRubriques.AddItem .Cells(2, colonne).Value
colonne = colonne + 1
Loop
End With
End Sub
Private Sub CboRubriques_Change()
' Procédure permettant d'initialiser
' les données de la liste Sous-Rubrique.
Dim i As Long
Dim j As Long
Dim colonne As Long
' Initialisation variables.
i = 2
' On vide la liste des sous-rubriques.
FrmSaisie.CboSousRubriques.Clear
' On travaille sur la feuille données
With Sheets("Donnees")
' On boucle pour récupérer les sous rubriques de chaque rubriques.
Do While .Cells(2, i).Value <> ""
' On test que le nom de rubriques soit bien identique.
If .Cells(2, i).Value = FrmSaisie.CboRubriques.Value Then ' Si oui
' Récupération du N° de colonne
colonne = .Cells(2, i).Column
End If
i = i + 1
Loop
' On initialise le numéro de ligne à 3.
j = 3
' On boucle sur les colonnes pour récupérer les sous-rubriques.
Do While .Cells(j, colonne).Value <> ""
' On charge les villes dans la liste déroulante
FrmSaisie.CboSousRubriques.AddItem .Cells(j, colonne)
j = j + 1
Loop
End With
' On affiche la première valeur par défaut.
CboSousRubriques.ListIndex = 0
End Sub
Private Sub BtnFermeture_click()
Unload Me
End Sub
Tout d'abord je souhaiterais te remercier d'avoir répondu aussi rapidement.
Je viens de tester ton code et cela fonctionne parfaitement. J'ai même pu ajouter des rubriques et sous-rubriques qui ont toutes étaient prises en compte.
Concernant tes deux remarques je vais me pencher sur la première, que je n'ai pas bien compris.
Pour la seconde, tu es partisan de déclare les variables au début de chaque procédure, j'en prends bonne note.
Ton aide me permet de continuer à avancer, car je suis loin d'avoir finalisé mon classeur.
Encore merci à toi
Mistral
1) En VBA il n'est pratiquement jamais nécessaire de sélectionner un objet (Classeur, feuille, cellule, objet, ...) pour agir avec. Il suffit de définir l'objet avec lequel on souhaite travailler.
Par contre, il est vivement déconseillé d'utiliser l'objet actif (ActiveCell, ActiveSheet, ....) car non seulement c'est plus lent (il faut le selectionner) mais c'est une des principales sources de dysfonctionnement des macros.
2) Je ne suis partisan de rien ! Il y a les bonnes méthodes et les autres.
Je conseille, d'une part de typer les variables correctement en fonction du besoin, et d'autre part de limiter la portée des variables au strict nécessaire (Locale, Privée, Publique, Globale, en favorisant les moindres portées)
J'aurais une autre question si tu le veux bien.
Toujours dans le même formulaire j'ai une zone de texte "TxtD_C" que je voudrais renseigner en fonction de la valeur d'une Combobox "CboSousRubriques"
Pour cela j'ai rentré le code suivante :
Private Sub TxtD_C_AfterUpdate() TxtD_C = Application.WorksheetFunction.VLookup(CboSousRubriques, Sheets("Donnees").Range("SourceD_C"), 2, 0) End Sub
Mais quand j'affiche le formulaire ma zone de texte reste vide.
D'avance merci.
Cordialement
Mistral
Private Sub CboSousRubriques_Change()
Dim c As Range
With Worksheets("Donnees").Range("SourceD_C").Columns(1)
Set c = .Find(CboSousRubriques.Value, , xlValues, xlWhole)
End With
If Not c Is Nothing Then TxtD_C.Text = c.Offset(0, 1).Value Else TxtD_C.Text = ""
End Sub