ComboBox

Retour vers Access

Combobox pour afficher Enr suivant critère (Filtre) - 11 Oct 2018

Utiliser une liste déroulante

 

But : Utiliser une liste déroulante pour filtrer un formulaire ou un rapport semble être un cauchemar. Nous allons donc tenter de démonter la mécanique. Il faut d'abord définir la méthode de travail d'une liste déroulante.

NB : Le nom des contrôles dans les codes de cette page correspondent aux contrôles du fichier en exemple. Personnalisez le code avec les noms que vous avez implémentés dans votre application

A quoi sert-elle ? En fait, on peut très bien comparer son travail à une requête classique. On peut l'utiliser sur un formulaire qui contient déjà des enregistrements, mais on peut aussi l'utiliser à partir d'un formulaire indépendant qui nous sert de menu et à partir duquel nous pouvons ouvrir un autre formulaire ou un état (aussi appellé rapport)

Comment s'y prendre ?

  1. Après avoir créé une table, une requête sur cette table et un formulaire basé sur la requête en utilisant le mode tabulaire, on pose un contrôle combobox(zone de liste) sur notre formulaire. Une boîte de dialogue s'ouvre automatiquement et nous propose 3 possibilités de traiter le changement opéré dans la liste déroulante. Il faut choisir la 3ème possibilité
  2. On suit ensuite le processus en répondant aux différentes questions. On désigne les données qui seront affichées dans la liste déroulante
  3. On modifie la légende de l'étiquette (label) associée à la zone de liste avant de cliquer sur le bouton "Terminer"
  4. Cela fait on se positionne sur la liste déroulante, on personnalise son nom et surtout sa propriété contenu où l'on ajoute le mot DISTINCT car il est inutile d'afficher plusieurs fois une même donnée
  5. et ça ne fonctionne pas comme on aurait pu le croire... Pourquoi ? parce que Access a créé une macro intégrée mais qui s'intitule "RechercherEnregistrement" et qui en fait déplace le focus (curseur) sur le premier enregistrement répondant au critère. Or nous, nous souhaitons appliquer un filtre, c'est à dire ne conserver à l'écran que les enregistrements répondant au critère choisi. Il faut donc ajouter une macro "AppliquerFiltre", par contre, on peut recopier la formule vers le nouvel emplacement, cela évite les erreurs de syntaxe
  6. On supprime la macro "RechercherEnregistrement", on garde bien entendu la macro "AppliquerFiltre" et on sauve les modifications (Attention aux croix de fermeture car elles sont tellement proches qu'il y a un risque d'effacer ce que l'on vient de faire)
  7. On peut maintenant sélectionner une valeur dans la liste déroulante et voir que le formulaire s'adapte, n'affiche que les enregistrements qui correspondent au critére défini
  8. Conserver la mention sélectionnée dans la combobox peut déranger, on peut la supprimer, pour cela il faut compléter la macro incorporée comme suit :

On peut obtenir le même résultat avec VBA... il faut supprimer toute macro intégrée puisque inutile et on posera le code suivant sur l'événement "Après MAJ". Dans notre fichier exemple, cela donne


Private Sub CBox_Pays_AfterUpdate()
  DoCmd.ApplyFilter , "[pays] = '" & CBox_Pays & "'"
  CBox_Pays = ""
End Sub

Placez aussi un bouton sur le formulaire pour réafficher tous les enregistrements, sur son événement "Sur click"


Private Sub Btn_Tous_Click()
  DoCmd.ShowAllRecords
End Sub

Et si on veut filtrer un sous-formulaire ? Imaginons que l'on souhaite afficher notre requête dans un formulaire au format feuille de données, si on souhaite ajouter des contrôles de notre crû, il faudra transformer ce formulaire (en mode feuille de données) en sous-formulaire dans un formulaire indépendant et à partir de là on ne peut plus utiliser la méthode "ApplyFiltrer" puisque notre formulaire principal n'est associé à aucune requête.il est indépendant ou vierge si vous préférez.

Il faut donc donner une instruction directement au sous-formulaire comme ceci

Private Sub ZL_Recherche_AfterUpdate()
  Me.SF_Clients_FeuilledeDonnées.Form.Filter = "pays = '" & Me.ZL_Recherche & "'"
  Me.SF_Clients_FeuilledeDonnées.Form.FilterOn = True
  Me.ZL_Recherche = ""
End Sub

J'aime bien utiliser "Me", qui ici représente le formulaire principal, parce que dès que je tape le point qui le suit, Access me présente la liste des contrôles et méthodes qui existent pour cet objet "Me" et ainsi de suite. Cela permet de libeller une syntaxe correcte mais on peut le supprimer pour une meilleure clarté du code, c'est selon vos goûts

Cliquez ici pour télécharger le fichier FiltreAvecZoneDeListe

Dans les dernières versions d'Access, on peut créer un formulaire de navigation avec des onglets. Les contrôles (listes déroulantes, boutons etc. ) sont alors placés sur des formulaires qui deviennent, sur les onglets, des sous-formulaires . Il faut donc utiliser le code ci-dessus. Une autre syntaxe peut être ci-dessous (en personnalisant le nom de la liste déroulante placée sur le sous-formulaire et du champ filtré). Si vous pratiquez autrement, vous recevrez un message d'erreur stipulant que votre formulaire n'est lié à aucune table ou requête car en effet, le formulaire de navigation est totalement indépendant, il n'y a aucune source de données qui lui est attribuée. Access se mélange les pinceaux, il ne comprend plus à quel formulaire s'adresser et tente d'exécuter le code sur le formulaire de navigation. Pourtant si le sous-formulaire est exécuté directement sans passer par le formulaire de navigation, il peut fonctionner car dans ce cas, il n'est plus considéré comme sous-formulaire. Cela peut dérouter certains utilisateurs

Private Sub cbboxNomAdh_AfterUpdate()
 monfiltre = "AdhérentsId = " & CInt(cbboxNomAdh)
   
 Me.FilterOn = False
 Me.Filter = monfiltre
 Me.FilterOn = True
End Sub

Vous pouvez aussi utiiser la méthode astucieuse du site Bonbache

J'ai suivi les instructions de cette vidéo dans le fichier exemple sur le champ "pays"

En synthèse il faut :

  1. Créer une requête en plaçant sur le champ "pays" un critére de filtre [Formulaires]![F_Bonbache]![Moteur]
  2. Créer un (sous)formulaire basé sur cette requête et lui imposer un format feuille de données
  3. Créer un formulaire indépendant (vierge, que je vais nommer "principal" dans la suite des explications) et y tirer le (sous)formulaire (idem lui imposer le format feuille de données)
  4. Placer une zone de texte sur le formulaire principal que l'on appelle "Moteur"
  5. Placer une zone de liste appellée "Liste_Pays"
  6. ensuite on ajoute le code vba suivant
    Private Sub Liste_Pays_Click()
      Me.Moteur.SetFocus
      If Me.Liste_Pays.Visible = True Then Me.Liste_Pays.Visible = False
      Me.Moteur.Value = Me.Liste_Pays.Value
      DoCmd.Requery
    End Sub
    Private Sub Moteur_Change()
      If Me.Liste_Pays.Visible = False Then Me.Liste_Pays.Visible = True
      Me.Liste_Pays.RowSource = "SELECT DISTINCT pays FROM Q_Clients WHERE pays LIKE'" & Me.Moteur.Text & "*'"
    End Sub
    Function Masquer_Liste()
      If Me.Liste_Pays.Visible = True Then Me.Liste_Pays.Visible = False
    End Function

Quand vous ouvrez le formulaire principal, le sous formulaire est vide. Quand on écrit une première lettre dans la textbox, la zone de liste apparaît en affichant le résultat du code SQL. Plus vous ajoutez de lettres, plus la liste s'affine. Sélectionnez une valeur dans la liste, elle s'inscrit dans la textbox ET grâce à DoCmd.Requery tout se réaffiche mais cette fois comme la textbox contient une valeur le sous formulaire peut appliquer le critère de filtre et afficher les enregistrements correspondants. Remarque, à l'ouverture du formulaire principal, il avait aussi appliqué le critère de filtre = la textbox mais comme elle était vide, le sous formulaire est apparu vide aussi. Si vous voulez contrôler l’exécution, placez DoCmd.Requery en remarque et utiliser le bouton "Appliquer"

Et c'est tout... regardez la vidéo pour plus de détails

Il y a d'autres manières d'automatiser des filtres, par exemple de 0-9 et A-Z, avec plusieurs listes déroulantes, etc...

Retournez sur la page Access pour les retrouver

Fin