I. INTRODUCTION

Cet article n'est pas le premier à développer ce sujet (cf les cours et tutoriels). Cependant, j'ai cherché, dans celui-ci, à traiter le sujet sans code (pour les non initiés) et avec un peu de code (pour les accros).
Les filtres seront appliqués soit par choix dans des listes déroulantes dépendantes (Formulaire SANS code), soit par double-clic dans une des colonnes du sous-formulaire (Formulaire AVEC code).

II. LES CAHIERS DES CHARGES

II-A. La recherche sans code

Le but est de pouvoir, au travers d'un sous-formulaire :
- afficher la fiche d'un employé en récupérant des critères de filtre dans des listes déroulantes combinées.
- imprimer le résultat des filtres en affichant dans l'état le détail des critères appliqués.

La mise à jour automatique des listes se fera via des macros simples.

On entendra par "listes combinées", des listes dont le contenu sera en fonction des choix faits dans les autres listes affichées (aussi bien en amont qu'en aval).

II-B. La recherche avec code VBA

Le but est de pourvoir, à partir d'un sous-formulaire, filtrer les données en double-cliquant sur les colonnes de celui-ci.
Le double-clic pourra se faire dans un ordre quelconque.
Le résultat sera imprimable. Dans l'état, on retrouvera le détail des critères du filtre appliqué.

II-C. Les tables de la base de données

La base de données est constituée de 5 tables

Tables Objet Clé Primaire Relation Avec (Clé étrangère) Table liée
T_Employes Liste le détail des employés de la Société CodeEmploye    
T_Agences Liste les agences du Groupe CodeAgence CodeAgence T_Employes
T_Diplomes Liste les Diplomes des employés CodeDiplome CodeDiplome T_Employes
T_PosteOccupe Liste les différents postes de l'entreprise CodePosteOccupe CodePosteOccupe T_Employes
T_SituationFamille Liste les différentes situations de famille (Marié, Célibataire ...) CodeFamille CodeFamille T_Employes


Image non disponible
Le modèle relationnel de la base de données utilisée


La base de données est disponible dans le chapitre "TELECHARGEMENT"

III. LES FORMULAIRES

III-A. La recherche sans code

Image personnelle La composition de ce formulaire se déroule en 7 étapes.
     1) La création des listes déroulantes combinées
     2) La composition du sous-formulaire
     3) La création de la zone de liste dépendante des listes de critères
     4) La récupération des statistiques
     5) La récupération du nombre de fiches (avec respect du singulier et du pluriel)
     6) Le bouton qui réinitialise le formulaire
     7) Le bouton d'impression du résultat du filtre

III-A-1. Les listes déroulantes combinées

Je ferai plusieurs remarques par rapport à la création des listes:
     - La liste affiche la mention " ---Tous--- " au-dessus des valeurs
     - Les données sont triées par ordre croissant

III-A-1-a. Création de la liste des agences via l'assistant

Image personnelle Le formulaire principal n'est lié à aucune table. On le dit alors "indépendant".
Cliquez donc sur l'onglet "Formulaires" dans la fenêtre "Base de données" et double-cliquez sur "Créer un formulaire en mode Création"
Image personnelle Cliquez sur l'outil "Zone de liste déroulante" dans la boite à outils.
Cliquez sur le formulaire à l'endroit où vous souhaitez implanter votre liste.
Access ouvre alors un assistant.
Nous suivrons donc toutes les étapes de celui-ci.

Etape 1 :

Image personnelle Dans cette étape, Access nous donne le choix pour alimenter notre liste.
Laissez le choix par défaut, car les données seront issues d'une table.

Etape 2 :

Image personnelle Access nous affiche donc la liste des tables ou des requêtes disponibles.
Choisissez la table "T_Agences".

Etape 3 :

Image personnelle A ce niveau de l'assistant, nous allons choisir les éléments qui nous seront nécessaires dans notre liste.
Cliquez sur le bouton affichant ">>" afin de récupérer les deux champs.

Etape 4 :

Image personnelle Cette phase nous propose de trier les données de notre liste.
Choisissez de trier les données par Agence.

Etape 5 :

Image personnelle Nous pouvons à ce niveau, modifier la largeur de nos colonnes. Access cache la colonne clé par défaut.
Laissez-la masquée. Ainsi après notre choix, Access affichera le nom de l'agence choisie et non son code. (Une liste déroulante ne pouvant afficher l'information d'une seule colonne à la fois. Cependant, il est à noter que si plusieurs champs font intégrés de la requête source de notre liste, ceux-ci seront visibles lors du déroulement de la liste, mais que dans tous les cas, Access n'affichera dans le contrôle de liste que le contenu sélectionné du premier champ de celle-ci dont la largeur de la colonne est supérieure à 0 cm).

Etape 6 :

Image personnelle Nous voici arrivés au terme de l'assistant.
Il suffit de saisir ici un texte qui s'affichera à la gauche de notre liste.
Si cela n'est pas fait par défaut, tapez "Agence".

Procédez de la même façon avec les 3 autres listes en utilisant les tables :
     - T_Diplomes (nom de la liste : cboDiplome)
     - T_PosteOccupe (nom de la liste : cboPosteOccupe)
     - T_SituationFamille (nom de la liste : cboFamille).

III-A-1-b. Personnalisation de la liste

Cette phase de la création de notre contrôle va nous permettre de :
     - Renommer le contrôle qui pour l'instant a reçu un nom par défaut (ModifiableX - X étant un numéro affecté par Access).
     - Modifier le contenu de la liste afin de pouvoir la rendre solidaire des 3 autres.
     - Ajouter les expressions critères dans la requête source de la liste.
     - Ajouter dans la source de notre liste la mention " --- Tous --- ".
En cliquant droit sur le contrôle, affichez les propriétés.

Première modification : Changer le nom de notre contrôle.

Image personnelle Après avoir affiché les propriétés, cliquez sur l'onglet "Autres" et saisissez : "cboAgence".
J'ai préfixé le nom avec "cbo" puisqu'il s'agit d'une liste déroulante c'est à dire une combobox.
Ce principe de préfixage permet de savoir, en relisant les noms des objets de notre base, de quel type d'objet il s'agit.
Je vous conseille à ce propos la lecture de l'article de Agyronet sur les conventions typographiques dans le Code Visual Basic

Seconde modification : Rendre la liste dépendante des 3 autres.

Image personnelle Cliquez sur l'onglet "Données" puis cliquez dans la propriété "Contenu".
Deux boutons s'affichent alors sur la droite du formulaire.
Cliquez sur le bouton contenant "...".
Access affiche alors la fenêtre de génération des requêtes.
Image personnelle Afin de rendre les 4 listes solidaires, nous allons ajouter la table "T_Employes". Par ce biais, on obtiendra un lien avec les autres listes.
On ajoutera dans le contenu de la requête les champs "CodeDiplome", "CodePosteOccupe", "CodeFamille". Ils ne seront pas affichés car ils servent uniquement de support à nos critères.

Troisième modification : Ajouter les critères sous les champs CodeDiplome, CodePosteOccupe, CodeFamille.
Si pour les Utilisateurs confirmés la création d'une expression ne pose pas de problème particulier, je vais quand même repasser en détail les manipulations à faire pour créer une expression critère en utilisant le générateur d'expressions.
Avant de passer au pas à pas pour la création de l'expression, il me faut préciser que la fonction que nous allons utiliser est une fonction conditionnelle du même type que la fonction SI() d'Excel. En effet, nous ne récupèrerons la valeur de la liste déroulante que si un choix a été fait dans la liste.
Ainsi, sous le champ "GExpression2", si la liste CodeDiplome affiche la mention " ---Tous--- " alors je n'ai pas de critère sinon je récupère la valeur du choix.
Cette fonction qui s'appelle VraiFaux dans Access s'articule comme SI.
Elle se décompose en trois arguments:
=VraiFaux(Condition; Valeur si Condition vraie; Valeur si condition fausse).

Etape 1 :

Image personnelle Pour lancer le générateur d'expression, il faut revenir dans l'écran générateur des requêtes.
     - Cliquez droit sur la liste déroulante "cboAgence" et affichez les propriétés.
     - Dans l'onglet "Données", cliquez dans la propriété "Contenu" puis sur le bouton tout à droite.
     - Cliquez dans la ligne "Critères" sous le champ "CodeDiplome" (cf la petite loupe).
     - Cliquez sur l'outil "générateur d'expressions" (Cf la grande loupe).

Etape 2 :

Image personnelle Nous allons composer la partie "Condition" de notre fonction.
Suivez les étapes ci-dessous :
     1) Tapez =GExpression2
     2) Double-Cliquez une fois sur le "+" du dossier "Formulaires".
     3) Cliquez une Fois sur le "+" du dossier "Formulaires chargés".
     4) Cliquez une fois sur le nom du formulaire qui nous intéresse.
     5) Double-cliquez sur le nom de la liste que nous sommes occupés à lier (ici "cboDiplome").
     6) Tapez =0 (Valeur de notre liste si la mention " ---Tous--- " est affichée).

Etape 3 :

Image personnelle On continue avec le second argument : Valeur si condition Vraie.
Comme précédemment, suivons le pas à pas :
     1) Tapez ";" le traditionnel séparateur d'arguments.
     2) Double-cliquez sur le "+" du dossier "Tables".
     3) Cliquez une fois sur le dossier "T-Employes".
     4) Le générateur ajoute "expr". Cliquez simplement sur le mot et supprimez le.

Etape 4 :

Image personnelle Enfin, nous allons terminer notre fonction en créant le troisième argument :
     1) Cliquez une fois sur le nom du formulaire qui nous intéresse.
     2) Double-cliquez sur le nom de la liste que nous sommes occupés à lier (ici c'est toujours "cboDiplome").
     3) Le générateur ajoute "expr" comme précédemment, on le supprime sans état d'âme et on ferme l'expression par une parenthèse.

Il ne nous reste plus qu'à valider et à recommencer la même opération pour les 2 autres champs de la requête.
Enfin, vous avez compris que pour lier les autres listes entre-elles, il faut faire la même chose pour les 3 autres.
A vous de jouer. Allez-y doucement, cela vous évitera quelques recherches assommantes...

Quatrième modification : Ajouter la mention "Tous" dans la liste.
Nous devrons intervenir dans la syntaxe SQL de la requête source de notre liste.
Il nous faut donc retourner dans les propriétés de notre liste afin d'afficher le générateur de requête.

Image personnelle Nous commençons à connaître le chemin :
     - Clic droit sur le contrôle.
     - Clic "Propriétés" puis onglet "Données".
     - Clic dans la propriété "Contenu" puis sur le bouton à droite de la ligne.
     - Dans le générateur de requête, cliquez sur la liste des affichages disponibles.
     - Choisissez alors "SQL


Image non disponible

Cliquez à la fin de la syntaxe affichée, supprimez le caractère ";" et tapez :
UNION SELECT 0, " ---Tous---" FROM T_Agences Fermer la fenêtre Sql et cliquez sur Oui pour enregistrer les modifications.

Quelques explications sur la syntaxe saisie.
     - Dans une requête UNION il doit y avoir autant de champs dans les deux requêtes réunies.
     - La mention " ---Tous---" est entre guillemets, texte oblige.
     - Remarquez l'espace avant les tirets de la mention "Tous". Ainsi en triant sur l'Agence, "Tous" sera en première ligne.
Vous trouverez une autre méthode pour ajouter "Tous" dans une liste dans la F.A.Q
Il vous reste donc à réaliser ce même travail sur les 3 autres listes du formulaire

III-A-2. Création du sous-formulaire

III-A-2-a. Création de la source

Image non disponible

Voici l'image de la requête source de notre sous-formulaire. Nous aurons besoin de recréer les mêmes critères que dans les différentes listes. En effet, lorsqu'un choix est fait dans une des listes, il faut que le sous-formulaire soit mis à jour en fonction du choix.
Nous retrouvons sous les quatre champs codes (Agence, Diplôme, Famille, PosteOccupe) la même syntaxe "VraiFaux" que nous avions créée dans nos différentes listes du formulaire principal.
Enregistrez la requête sous le nom de "R_Personnel"

Voici un tableau reprenant les différentes expressions utilisées.

Champ Expression critère
CodePosteOccupe VraiFaux([Formulaires]![F_FiltreSansCode]![cboPosteOccupe]=0;[T_Employes].[CodePosteOccupe];[Formulaires]![F_FiltreSansCode]![cboPosteOccupe])
CodeDiplome VraiFaux([Formulaires]![F_FiltreSansCode]![cboDiplome]=0;[T_Employes].[CodeDiplome];[Formulaires]![F_FiltreSansCode]![cboDiplome])
CodeAgence VraiFaux([Formulaires]![F_FiltreSansCode]![cboAgence]=0;[T_Employes].[CodeAgence];[Formulaires]![F_FiltreSansCode]![cboAgence])
CodeFamille VraiFaux([Formulaires]![F_FiltreSansCode]![cboSituationFamille]=0;[T_Employes].[CodeFamille];[Formulaires]![F_FiltreSansCode]![cboSituationFamille])

III-A-2-b. Création du sous-formulaire

III-A-2-b-i. Création de l'entête et de la section Détail
Image personnelle Cliquez sur le groupe "Formulaires".
Double-cliquez sur "Créer un formulaire en mode Création".
Affichez les sections Entête et pied de formulaire.
Affichez la fenêtre des propriétés et cliquez dans l'onglet "Données".
Dans la propriété "Source", sélectionnez la requête "R_Personnel".
Positionnez les champs comme dans l'image ci-contre.
III-A-2-b-ii. Création du pied de formulaire

Remarquez les champs statistiques implantés dans le Pied de formulaire. Ceux-ci permettront de récupérer les données dans le formulaire principal.

Ci-dessous le détail des champs statistiques (nom du contrôle et Source contrôle)

Nom du Controle Source Contrôle
txNbPersonnelSF =Compte([NomEmploye])
txtMasseSalarialeSF =Somme([SalaireActuel])
txtMoyenneSalaireSF =Moyenne([SalaireActuel])
txtMaxSalaireSF =Max([SalaireActuel])
txtMinSalaireSF =Min([SalaireActuel])

III-A-2-c. Les propriétés

III-A-2-c-i. Propriétés du sous-formulaire
Image personnelle Cliquez droit sur l'extérieur du formulaire et affichez les propriétés.
Paramétrez le en reportant les différentes propriétés comme ci-contre.
On remarquera la propriété : "Affichage par défaut : Formulaires continus".
Ce paramétrage permettra d'afficher plusieurs enregistrements l'un au-dessous de l'autre.
III-A-2-c-ii. La section Pied de formulaire
Image personnelle Cliquez sur l'onglet "Format" ou "Toutes" des propriétés du pied de formulaire et mettez la propriété "Visible" sur Non

III-A-2-d. Implantation du sous-formulaire

Image personnelle Affichez en côte à côte la fenêtre base de données et le formulaire principal en mode création.
Cliquez maintenu sur le SF_FiltreSansCode et glissez dans le formulaire principal à l'endroit souhaité.

III-A-3. Création de la zone de liste

La zone de liste a pour but d'afficher les noms des salariés issus des différents filtres appliqués par les listes déroulantes. La source de celle-ci est donc également liée aux quatre listes de choix.

Image personnelle Ouvrez le formulaire principal en mode création.
Dessinez le contrôle zone de liste.
Cliquez droit sur celui-ci et affichez les propriétés.
Voici ci-contre les différentes propriétés à modifier.

III-A-4. Récupération des statistiques

Image personnelle Dans le formulaire principal, nous implanterons 4 champs indépendants qui nous permettront de récupérer les valeurs calculées dans le pied du sous-formulaire.
Voir dans le tableau ci-dessous les caractéristiques des différents champs.
Nom du contrôle Source du Contrôle
txtMasseSalariale =SF_FiltreSansCode.Formulaire!txtMasseSalarialeSF
txtMoyenneSalaire =SF_FiltreSansCode.Formulaire!txtMoyenneSalaireSF
txtSalaireMaxi =SF_FiltreSansCode.Formulaire!txtMaxSalaireSF
txtSalaireMini =SF_FiltreSansCode.Formulaire!txtMinSalaireSF


Ces expressions de calcul pourront être créées par l'intermédiaire du générateur d'expressions. Voir l'utilisation plus haut dans cet article.

III-A-5. Récupération du nombre de fiches

Image personnelle La récupération du nombre de fiches ne devrait pas poser de problèmes car il s'agit de récupérer la valeur dans le pied de formulaire du sous-formulaire, donc comme ci-dessus. Cependant, il nous faut respecter l'accord du mot "fiche" en fonction du nombre trouvé.
Nous utiliserons donc la fonction VraiFaux qui nous avons déjà expliquée plus haut et une concaténation du mot "fiche" au singulier ou au pluriel suivant le cas.

L'expression à créer dans la propriété "SourceContrôle" du contrôle "txtNbSalaries" est donc :

=VraiFaux(SF_FiltreSansCode.Formulaire!txNbPersonnelSF <=1 ;SF_FiltreSansCode.Formulaire!txNbPersonnelSF & " Fiche";SF_FiltreSansCode.Formulaire!txNbPersonnelSF & " Fiches")

III-A-6. le bouton "Effacer tous les filtres"

III-A-6-a. Implantation du bouton

Ce bouton est implanté via la boite à outils. Le dessin de celui-ci ne présente pas de difficultés particulières. Cependant, il faudra bien lui appliquer une action lorsqu'on cliquera dessus. Dans un premier temps, cliquez sur le bouton "Assistants de contrôle" de la boîte à outils afin de désactiver ceux-ci.
Cliquez à nouveau dans la boîte à outils sur l'outil "Bouton" et dessinez un rectangle sur le formulaire principal.
Afficher les propriétés du bouton et modifier les propriétés suivantes :
     - Nom (onglet "Autres") : btnEffacerTout
     - Légende (onglet : "Format") : Effacer tous les filtres

III-A-6-b. La macro "Initialisation des contrôles"


Image non disponible Image non disponible

Description de la fenêtre "Macro"
Au niveau de l'image de gauche :
     1) Bouton qui affiche ou masque la colonne "Nom de la Macro". (marquée également par (1) à gauche de l'image).
      En identifiant les macros par un nom cela nous permet d'en regrouper plusieurs dans une même feuille.
     2) Colonne "Action" : permet de choisir l'action que la macro devra exécuter.
     3) Colonne "Commentaire" : reçoit un texte explicitant l'action exécutée.

Au niveau de l'image de droite :
     1) Argument : Zone permettant de paramétrer l'action à exécuter.
     2) Aide contextuelle sur l'argument en cours de renseignement. (A noter : F1 toujours de rigueur pour compléter l'information).

Nous allons écrire une macro qui va initialiser les différents éléments de notre formulaire à l'ouverture de celui-ci ou en cliquant sur le bouton que nous venons de dessiner.

Pour écrire une macro :
     - Dans la fenêtre "Base de données", cliquez sur l'objet "Macros" puis "Nouveau".
     - Dans la fenêtre affichée, cliquez sur l'outil marqué (1) dans l'image de gauche ci-dessus.(La colonne "Nom de la macro" s'affiche. (Numérotée (1) également)).
     - Dans la colonne de gauche : Saisir un nom suffisamment évocateur de l'action de la macro (Ici : Initialisation).
     - Dans la seconde colonne intitulée "Action", sélectionnez l'action "DéfinirValeur". En choisissant une action, le volet des arguments s'affiche.
     - Renseignez les arguments comme dans le tableau ci-dessous.

Il y aura autant d'actions "DéfinirValeur" qu'il y aura de contrôles à initialiser.

Action Expression Valeur
DéfinirValeur [Formulaires]![F_FiltreSansCode]![cboAgence] 0
DéfinirValeur [Formulaires]![F_FiltreSansCode]![cboDiplome] 0
DéfinirValeur [Formulaires]![F_FiltreSansCode]![cboPosteOccupe] 0
DéfinirValeur [Formulaires]![F_FiltreSansCode]![cboSituationFamille] 0


Lorsque les valeurs sont affectées aux différentes listes, il faut "Actualiser" le sous-formulaire et la zone de liste. Nous allons donc ajouter deux actions à notre macro comme indiqué ci-dessous.

Action Nom du Contrôle
Actualiser SF_FiltreSansCode
Actualiser lstEmploye


Il faut maintenant enregistrer la macro. Cliquez sur "Enregistrer" puis saisissez le nom "M_ManipulationsControles"

Image personnelle Il ne nous reste plus qu'à implanter la macro sur le bouton.
     - Cliquez droit sur le bouton.
     - Affichez les propriétés.
     - Cliquez sur l'onglet "Evènements".
     - Cliquez dans la propriété : sur clic.
     - Cliquez sur la liste déroulante à droite (Voir la loupe).
     - Choisissez dans la liste proposée la macro à implanter (ici : M_ManipulationsControles.Initialisation).

III-A-7. Le bouton "Imprimer le filtre"

III-A-7-a. Implantation du bouton

Ce bouton est bâti de la même façon que le précédent. Je vous laisse donc le réaliser.
Les propriétés modifiées seront :
     - Nom (onglet "Autres") : btnImprimerFiltre
     - Légende (onglet : "Format") : Imprimer le filtre

III-A-7-b. La macro "Imprimer le Filtre"

Cette macro aura pour but de lancer l'impression en mode Aperçu. Elle se construira de la même façon que la précédente.
     - Cliquez sur l'objet Macros.
     - Cliquez sur Nouveau.
     - Afficher la colonne Nom de la macro en cliquant sur l'outil concerné.
     - Tapez Imprimer. Ce sera le nom de notre macro.
     - Saisissez les différents éléments de la macro repris dans le tableau ci-dessous.
     - Puis enregistrer la macro sous le nom "M_ImprimerFiltre" et fermer.

Action Nom de l'état Affichage
OuvrirEtat E_ListePersonnelFiltreeSansCode Aperçu avant impression


Image personnelle Il faut donc maintenant implanter la macro sur l'évènement Sur Clic du bouton.
Pour réaliser cette opération, nous passerons par la fenêtre des propriétés.
     - Cliquez droit sur le bouton.
     - Cliquez sur l'onglet Evènements.
     - Cliquez dans l'évènement Sur Clic.
     - Ouvrez la liste déroulante et choisissez la macro M_ImprimerFilte.Imprimer

III-A-8. La macro de "Mise à jour des Listes"

Nous avons donc nos quatre listes qui nous permettront de faire le choix de nos différents critères.
Après chaque choix, il est donc nécessaire que les enregistrements répondant aux critères choisis s'affichent dans le sous-formulaire et que conjointement, les listes se mettent à jour puisqu'elles sont toutes dépendantes les unes des autres.
Nous allons donc écrire une nouvelle macro que nous irons implanter dans la feuille "M_ManipulationsControles".

Commençons par ouvrir la feuille "M_ManipulationsControles" en cliquant sur le groupe "Macros".
Cliquez droit sur le nom de la feuille puis cliquez sur "Modifier".

III-A-8-a. Composition de la macro "MiseAJour"

Image personnelle Positionnez vous sous la dernière ligne de la macro précédente en laissant une ligne vierge. (Cette ligne vide n'a pas de rôle particulier, si ce n'est simplement pour bien structurer notre feuille. Le nom de la macro suffit à Access pour interrompre le déroulement de la macro précédente). Composez la macro en reprenant les actions et les arguments décrits dans le tableau ci-dessous.


Nom de la macro Action Argument Commentaire
MiseAJour Actualiser cboAgence Actualise la liste "cboAgence"
  Actualiser cboDiplome Actualise la liste "cboDiplome"
  Actualiser cboPosteOccupe Actualise la liste "cboPosteOccupe"
  Actualiser cboSituationFamille Actualise la liste "cboSituationFamille"
  Actualiser SF_FiltreSansCode Actualise le sous-formulaire "SF_FiltreSansCode"
  Actualiser lstEmploye Actualise la liste "lstEmploye"


III-A-8-b. Implantation de la macro

Image personnelle Il va falloir maintenant implanter sur chaque liste déroulante la macro que nous venons d'écrire.
     - Ouvrez le formulaire "F_FiltreSansCode" en mode Création.
     - Cliquez droit sur la première liste et affichez les propriétés.
     - Cliquez dans l'onglet "Evènements" puis dans l'évènement "Après MAJ".
     - Ouvrez la liste déroulante et choisissez la macro : "M_ManipulationsControles.MiseAJour".

Répétez cette opération sur les quatre listes déroulantes du formulaire.

III-A-9. Ouverture du formulaire "Fiche Employé"

III-A-9-a. Présentation de la fiche détaillée

Image personnelle Comme prévu dans le cahier des charges, les critères posés dans les listes entrainent l'affichage d'un certain nombre de prénoms dans la liste "lstEmploye".
En double-cliquant sur un des prénoms, Access doit nous afficher le formulaire ci-contre.
Ce formulaire ne présentant pas de difficultés particulières, je vous laisse le soin de créer la fiche détaillée comme vous l'entendez.
Il faut néanmoins écrire une macro qui permettra d'ouvrir celui-ci.

III-A-9-b. Création et implantation de la macro "M_OuvrirFiche"

Dans le groupe "Macros" faites "Nouveau" et composez la macro comme détaillée dans la tableau ci-dessous. Cette fois-ci, il ne sera pas nécessaire de faire afficher la colonne des noms puisque notre feuille ne contiendra qu'une seule macro.

Action Commentaire
OuvrirFormulaire Ouvre le formulaire F_FicheDetaillee sur l'enregistrement sélectionné


L'action "OuvrirFormulaire" demande plusieurs arguments. Voir le tableau ci-dessous.

Argument Expression
Nom Formulaire F_FicheDetaillee
Affichage Formulaire
Nom Filtre  
Condition WHERE [CodeEmploye]=[Formulaires]![F_FiltreSansCode]![lstEmploye]
Mode Données  
Mode Fenêtre Standard


Fermez et enregistrez la macro sous le nom de "M_OuvrirFiche"
Pour implanter la macro, il nous faire appel aux propriétés de la liste "lstEmploye" :
     - Cliquez droit sur le contrôle.
     - Affichez les propriétés et cliquez dans l'onglet "Evènements".
     - Cliquez dans la propriété "sur Double Clic".
     - Dans la liste déroulante, choisissez la macro "M_OuvirFiche".
     - Enregistrez le formulaire.

III-A-10. Initialisation du formulaire principal

Pour en terminer avec le formulaire de filtre sans code, il nous reste à l'initialiser à l'ouverture.
Nous procèderons comme pour les listes déroulantes.
     - Affichez les propriétés du formulaire.
     - Cliquez dans l'onglet "Evènements".
     - Cliquez dans la propriété : "Sur Ouverture".
     - Ouvrez la liste déroulante et choisissez la macro "M_ManipulationsControles.Initialisation".
     - Enregistrez puis fermez votre formulaire.

Voilà, notre formulaire de consultation multicritères sans code est terminé !

III-B. La recherche avec code VBA

Image personnelle La composition de ce formulaire se déroule en 6 étapes :
     1) La Création et l'implantation du sous-formulaire.
     2) La création de la liste des employés.
     3) L'implantation et la programmation du bouton "Effacer tout".
     4) L'implantation et la programmation du bouton "Imprimer le filtre".
     5) La récupération des données statistiques.
     6) Le code VBA

III-B-1. Le sous-formulaire "SF_FiltreAvecCode"

III-B-1-a. Création et propriétés du sous-formulaire

Image personnelle Ce formulaire ne présente pas de difficultés majeures.

La source de celui-ci est une requête composée de :
     - T-Employes (Récupération du CodeEmploye)
     - T_Agences (Récupération du nom de l'Agence)
     - T_Diplomes (Récupération du libellé du diplôme)
     - T_PosteOccupe (Récupération de la fonction occupée)
     - T_SituationFamille (Récupération du libellé de la situation de famille).

L'organisation des contrôles
Les étiquettes ont été placées dans l'entête de formulaire et alignées avec les zones de texte dans la section "Détail".

Le pied de formulaire
Dans le pied de formulaire, déposez une zone de texte indépendante.
Modifiez les propriétés de ce contrôle comme ci-dessous :
     - Nom : txtMasseSalarialeSF
     - Source Contrôle : =Somme([SalaireActuel])

Ce sous-formulaire sera implanté dans le formulaire principal
Image personnelleLes propriétés du sous formulaire
Voici ci-contre les différentes propriétés à modifier dans le sous-formulaire.

Pensez à positionner la propriété "Visible" du pied de formulaire sur "NON"

III-B-1-b. Implantation du sous-formulaire

Image personnelle Le formulaire principal n'est attaché à aucune source (Formulaire indépendant). Pour implanter le sous-formulaire, affichez en côte à côte un nouveau formulaire et la fenêtre "Base de données".
Cliquez maintenu sur le sous-formulaire "SF_FiltreAvecCode" et glissez sur le nouveau formulaire.
Nous n'aurons pas à gérer de Champ Père, ni de Champ Fils.

III-B-2. La liste "lstEmploye"

Image personnelle Créez la zone de liste qui va afficher le nom des salariés sélectionnés. Celle-ci sera totalement gérée par le code. Modifiez les propriétés comme ci-contre. Positionnez la de manière harmonieuse sur votre formulaire (à chacun ses goûts !!!).

III-B-3. Le bouton "Effacer tout"

En mode "Création", dessinez un bouton de commande après avoir désactivé l'assistant.
Affichez les propriétés de celui-ci et modifiez comme ci-dessous :
     - Nom : btnEffacerLesCriteres
     - Légende : Effacer tout

III-B-4. Le bouton "Imprimer le filtre"

On procèdera comme ci-dessus. Les propriétés à modifier sont :
     - Nom : btnImprimerFiltre
     - Légende : Imprimer le Filtre

III-B-5. La récupération des statistiques

Afin de récupérer la masse salariale calculée dans le pied du sous-formulaire, implantez une zone de texte dans le formulaire principal sous le sous-formulaire.
Créez l'expression de calcul dans la source contrôle de celui-ci par le générateur d'expression ou en tapant : =SF_FiltreAvecCode.Formulaire!txtMasseSalarialeSF

III-B-6. Le Code VBA dans le formulaire

On trouvera du code sur plusieurs évènements du formulaire et de ses objets :
     - sur Ouverture du formulaire principal
     - sur Chargement du sous-formulaire
     - sur Clic du bouton "Effacer tout"
     - sur Clic du bouton "Imprimer le filtre"
     - sur Double-clic de la zone de liste "Employés"

III-B-6-a. La procédure "sur Ouverture" du formulaire principal

Cette procédure doit, en fait, afficher tout le contenu. Elle sera donc également utilisée sur le "clic" du bouton "Effacer tout". Nous écrirons un routine qui pourra être appelée plusieurs fois

 
Sélectionnez

Sub InitialisationFormulaire()
' Initialisation des variables
p_strSqlWhere = ""

'Réinitialisation du tableau Critères
For p_intCompteur = 0 To UBound(p_tabCriteres, 2)
    p_tabCriteres(1, p_intCompteur) = "Pas de critère pour ce champ"
Next

' Initialisation du sous formulaire et réinitialisation
Me.SF_FiltreAvecCode.Form.RecordSource = cstSourceFiltre
Me.SF_FiltreAvecCode.Requery

' Initialisation de la zone de liste et réinitialisation
Me.lstEmploye.RowSource = cstSourceFiltre
Me.lstEmploye.Requery

End Sub

Dans ce code, on peut remarquer la partie "Réinitialisation des variables"

 
Sélectionnez

' Initialisation des variables
p_strSqlWhere = ""

'Réinitialisation du tableau Critères
For p_intCompteur = 0 To UBound(p_tabCriteres, 2)
    p_tabCriteres(1, p_intCompteur) = "Pas de critère pour ce champ"
Next

Ces variables ont été déclarées en public car elles sont réutilisées dans différentes procédures du projet.
La variable p_strSqlWhere est de type string, elle représente la clause WHERE qui sera appliquée à la source du sous-formulaire et récupère par concaténation, les différents critères sélectionnés.
D'autre part, la variable p_tabCritères() est une variable tableau dont l'objet est de stocker les valeurs de critères choisies pour les imprimer dans l'état (voir cahier des charges).

 
Sélectionnez

' Initialisation du sous formulaire et réinitialisation
Me.SF_FiltreAvecCode.Form.RecordSource = cstSourceFiltre
Me.SF_FiltreAvecCode.Requery

' Initialisation de la zone de liste et réinitialisation
Me.lstEmploye.RowSource = cstSourceFiltre
Me.lstEmploye.Requery

Il s'agit là de l'affectation de la source "cstSourceFiltre" au sous-formulaire et à la zone de liste. Cette constante est déclarée "Public" puisqu'elle sera réutilisée comme source de l'état.
Cette procédure étant mise en place, on peut l'implanter sur l'évènement "Sur Ouverture" du formulaire

 
Sélectionnez

Private Sub Form_Open(Cancel As Integer)
    ' Initialisation du formulaire
    InitialisationFormulaire
End Sub

III-B-6-b. La procédure "sur Clic" du bouton "Effacer tout"

En fait, il s'agit ici de réinitialiser tous les objets du formulaire principal.

 
Sélectionnez

Private Sub btnEffacerLesCriteres_Click()
    ' Initialisation du formulaire
    InitialisationFormulaire
End Sub

III-B-6-c. La procédure "Sur Chargement" du sous-formulaire

Il s'agit en fait d'une procédure qui permettra d'appliquer facilement le même process sur tous les contrôles du sous-formulaire. En effet, chaque contrôle du sous-formulaire est sensé réagir à un double-clic récupérant la valeur du champ pour l'utiliser en tant que critère. Cela sous-entend qu'il faut répéter la même procédure pour chaque contrôle (Ouf !!!, il n'y en aurait que 5).
Afin d'éviter un travail fastidieux, nous allons implanter par programmation, dans la propriété "sur double clic" de chaque contrôle concerné, une fonction qui récupèrera notre critère sélectionné.

 
Sélectionnez

Private Sub Form_Load()
' Déclaration de la variable
Dim ctlEnCours As Control
' Redimensionnement du tableau
ReDim p_tabCriteres(1, p_intCompteur)

' Boucle sur toutes les zones de texte pour affecter la procédure de filtrage sur l'évènement DoubleClic
For Each ctlEnCours In Me.Controls
   If ctlEnCours.ControlType = acTextBox Then
        If Left(ctlEnCours.Name, 3) <> "txt" Then
            ctlEnCours.Properties("onDblClick") = "=FiltreDonnees('" & ctlEnCours.Name & "' , " & ctlEnCours.Name & ")"
            ' renseigne le tableau avec les noms de champs
            RemplirTabCriteres (ctlEnCours.Name)
      End If
   End If
Next ctlEnCours

' Désactivation de la variable
Set ctlEnCours = Nothing
End Sub

Dans cette procédure on remarquera :
     - La déclaration de la variable ctlEnCours
     - Le redimensionnement du tableau dynamique p_tabCriteres.

 
Sélectionnez

' Déclaration de la variable
Dim ctlEnCours As Control
' Redimensionnement du tableau
ReDim p_tabCriteres(1, p_intCompteur)

Dans le redimensionnement du tableau, on trouve une variable publique p_intCompteur qui est incrémentée dans un sous programme : RemplirTabCriteres que l'on verra un peu plus loin dans l'article.

 
Sélectionnez

' Boucle sur toutes les zones de textes pour affecter la procédure de filtrage sur l'évènements DoubleClic
For Each ctlEnCours In Me.Controls
   If ctlEnCours.ControlType = acTextBox Then
        If Left(ctlEnCours.Name, 3) <> "txt" Then
            ctlEnCours.Properties("onDblClick") = "=FiltreDonnees('" & ctlEnCours.Name & "' , " & ctlEnCours.Name & ")"
            ' renseigne le tableau avec les noms de champs
            RemplirTabCriteres (ctlEnCours.Name)
      End If
   End If
Next ctlEnCours

Ci-dessus la boucle qui teste le type de contrôle et qui implante la fonction FiltreDonnees sur l'évènement "sur Double Clic".
Au fur et à mesure de la boucle, on renseigne le tableau p_tabCriteres par l'appel de la procédure :

 
Sélectionnez

      ' renseigne le tableau avec les noms de champs
            RemplirTabCriteres (ctlEnCours.Name)

Dans le cahier des charges, on nous demande de faire apparaître les critères sélectionnés dans l'entête de l'état. Pour pouvoir récupérer les valeurs, je les stocke dans un tableau.

 
Sélectionnez

Sub RemplirTabCriteres(ByVal strNomChamp As String)
    ' Procédure qui permettra de respecter la consigne du cahier des charges : Imprimer les critères sélectionnés dans l'état.
    ' On récupère les noms des champs dans un tableau avec comme valeur par défaut : "Pas de critère pour ce champ"
    If p_intCompteur > 0 Then
      ReDim Preserve p_tabCriteres(1, p_intCompteur)
    End If
      ' renseigne le tableau avec les noms de champs et la mention par défaut
      ' qui seront affichés dans l'état
      p_tabCriteres(0, p_intCompteur) = strNomChamp
      p_tabCriteres(1, p_intCompteur) = "Pas de critère pour ce champ"
      p_intCompteur = p_intCompteur + 1
End Sub

Dans cette procédure je ferai simplement un commentaire :

 
Sélectionnez

    If p_intCompteur > 0 Then
      ReDim Preserve p_tabCriteres(1, p_intCompteur)
    End If

Ce test vérifie que le tableau contient des valeurs et redimensionne celui-ci tout en préservant le contenu déjà stocké.
Enfin, il nous reste à découvrir la procédure FiltreDonnees

 
Sélectionnez

Function FiltreDonnees(ByVal strNomChamp As String, ByVal varValeurChamp As Variant)
    ' Teste le contenu du controle
    If IsNumeric(varValeurChamp) Then
        ' Initialisation du contenu de p_strSqlWhere sans ajout de quotes si le contenu est ALPHA
        If p_strSqlWhere = "" Then
            p_strSqlWhere = "WHERE " & strNomChamp & " = " & varValeurChamp
        Else
            p_strSqlWhere = p_strSqlWhere & " AND " & strNomChamp & " = " & varValeurChamp
        End If
    Else
        ' Initialisation du contenu de p_strSqlWhere avec ajout des quotes si le contenu est ALPHA
        If p_strSqlWhere = "" Then
            p_strSqlWhere = "WHERE " & strNomChamp & " = '" & varValeurChamp & "'"
        Else
            p_strSqlWhere = p_strSqlWhere & " AND " & strNomChamp & " = '" & varValeurChamp & "'"
        End If
    End If
    
    ' Récupération de critère sélectionné afin de reporter ces données dans l'état
    For p_intCompteur = 0 To UBound(p_tabCriteres, 2)
        If p_tabCriteres(0, p_intCompteur) = strNomChamp Then
            p_tabCriteres(1, p_intCompteur) = varValeurChamp
            Exit For
        End If
    Next
    
    ' réactualisation du sous formulaire
    Me.RecordSource = cstSourceFiltre & p_strSqlWhere
    Me.Requery
    
    ' réactualisation de la zone de liste du formulaire principal
    With Forms("F_FiltreAvecCode").Controls("lstEmploye")
        .RowSource = cstSourceFiltre & p_strSqlWhere
        .Requery
    End With
    
End Function

Comme vous pourrez le constater, il s'agit d'une fonction.
Or une fonction est sensée retourner une valeur mais pour ce cas, j'ai écrit une procédure "Function" car je ne peux pas faire appel à une procédure de type Sub directement dans une propriété du formulaire

 
Sélectionnez

    ' Teste le contenu du contrôle
    If IsNumeric(varValeurChamp) Then
        ' Initialisation du contenu de p_strSqlWhere sans ajout de quotes si le contenu est ALPHA
        If p_strSqlWhere = "" Then
            p_strSqlWhere = "WHERE " & strNomChamp & " = " & varValeurChamp
        Else
            p_strSqlWhere = p_strSqlWhere & " AND " & strNomChamp & " = " & varValeurChamp
        End If
    Else
        ' Initialisation du contenu de p_strSqlWhere avec ajout des quotes si le contenu est ALPHA
        If p_strSqlWhere = "" Then
            p_strSqlWhere = "WHERE " & strNomChamp & " = '" & varValeurChamp & "'"
        Else
            p_strSqlWhere = p_strSqlWhere & " AND " & strNomChamp & " = '" & varValeurChamp & "'"
        End If
    End If

Cette partie de la procédure permet de tester le type de valeur récupérée afin d'ajouter les "'" autour de la valeur critère si celle-ci est alpha

 
Sélectionnez

    ' Récupération de critère sélectionné afin de reporter ces données dans l'état
    For p_intCompteur = 0 To UBound(p_tabCriteres, 2)
        If p_tabCriteres(0, p_intCompteur) = strNomChamp Then
            p_tabCriteres(1, p_intCompteur) = varValeurChamp
            Exit For
        End If
    Next

Cette partie du code complète le tableau en stockant la valeur du critère sélectionné.

III-B-6-d. La procédure "sur Clic" du bouton "Imprimer le filtre"

 
Sélectionnez

Private Sub btnImprimerFiltre_Click()
On Error GoTo Err_btnImprimerFiltre_Click

    Dim stDocName As String

    stDocName = "E_ListePersonnelFiltreeAvecCode"
    DoCmd.OpenReport stDocName, acPreview

Exit_btnImprimerFiltre_Click:
    Exit Sub

Err_btnImprimerFiltre_Click:
    MsgBox Err.Description
    Resume Exit_btnImprimerFiltre_Click
    
End Sub

Il s'agit d'une procédure simple, créée à partir de l'assistant lors de la génération du bouton.

III-B-6-e. La procédure "sur Double Clic" de la liste lstEmploye

 
Sélectionnez

Private Sub lstEmploye_DblClick(Cancel As Integer)
    DoCmd.OpenForm "F_FicheDetaillee",,, "CodeEmploye = " & lstEmploye
End Sub

Il s'agit de l'ouverture du formulaire "F_FicheDetaillee" en fonction de CodeEmploye récupéré dans la zone de liste.

IV. LES ETATS

IV-A. L'état sans code

IV-A-1. Description de l'état

Image personnelle Cet état ne présente pas de difficultés particulières dans sa réalisation. Pour plus d'informations sur la création d'un état, je vous encourage à lire : Description de la création d'un état.
On remarquera cependant que dans l'entête d'état, on retrouve 4 contrôles indépendants dénommés :
     - txtAgence
     - txtDiplome
     - txtPosteOccupe
     - txtSituationFamille

Ces champs seront renseignés par une macro placée sur l'évènement "au formatage" de la section "Entête d'état".

IV-A-2. La macro "MiseAJourControle"

Pour créer cette macro, nous allons ouvrir la feuille macro "M_ImprimerFiltre".
     - Cliquez sur le groupe "Macros".
     - Cliquez droit sur la macro "M_ImprimerFiltre".
     - Cliquez "Mode Création".
     - Dans la colonne "Nom macro", tapez "MiseAJourControle".
Renseignez les actions et les arguments comme dans le tableau ci-dessous :

Nom Macro Action Elément Expression
MiseAjourControle DéfinirValeur [États]![E_ListePersonnelFiltreeSansCode]![txtAgence] VraiFaux([Formulaires]![F_FiltreSansCode]![cboAgence]=0;"Pas de critère sur ce champ";[Formulaires]![F_FiltreSansCode]![cboAgence].[column](0))
  DéfinirValeur [États]![E_ListePersonnelFiltreeSansCode]![txtDiplome] VraiFaux([Formulaires]![F_FiltreSansCode]![cboDiplome]=0;"Pas de critère sur ce champ";[Formulaires]![F_FiltreSansCode]![cboDiplome].[column](0))
  DéfinirValeur [États]![E_ListePersonnelFiltreeSansCode]![txtSituationFamille] VraiFaux([Formulaires]![F_FiltreSansCode]![cboSituationFamille]=0;"Pas de critère sur ce champ";[Formulaires]![F_FiltreSansCode]![cboSituationFamille].[column](0))
  DéfinirValeur [États]![E_ListePersonnelFiltreeSansCode]![txtPosteOccupe] VraiFaux([Formulaires]![F_FiltreSansCode]![cboPosteOccupe]=0;"Pas de critère sur ce champ";[Formulaires]![F_FiltreSansCode]![cboPosteOccupe].[column](0))


Fermez la macro et enregistrez.

IV-A-3. Implantation de la macro

Image personnelle Pour implanter la macro, il nous faut afficher les propriétés de l'entête d'état :
     - Affichez l'état en mode création.
     - Cliquez droit dans la section "Entête d'état".
     - Affichez la fenêtre des "Propriétés".
     - Cliquez dans l'onglet "Evènements".
     - Cliquez dans l'évènement "Au formatage".
     - Choisissez dans la liste déroulante, la macro "M_ImprimerFiltre.MiseAjourControle".


Fermez l'état et enregistrez.

IV-B. L'état avec Code

IV-B-1. Description de l'état

Cet état est la copie conforme de l'état sans code, cependant la source de celui-ci variera en fonction des critères qui seront sélectionnés.
On aura donc deux procédures dans cet état :
     - A l'ouverture de l'état qui récupéra une source.
     - Au formatage de l'entête d'état pour récupérer les critères sélectionnés.

IV-B-2. Le Code VBA

IV-B-2-a. La procédure "Sur Ouverture" de l'état

 
Sélectionnez

Private Sub Report_Open(Cancel As Integer)
    Me.RecordSource = cstSourceFiltre & p_strSqlWhere

Il s'agit ici, de l'affectation de la source qui est composée de la concaténation de la constante cstSourceFiltre et de la variable p_strSqlWhere.

IV-B-2-b. La procédure "Au Formatage" de l'entête de l'état

 
Sélectionnez

Private Sub EntêteÉtat_Format(Cancel As Integer, FormatCount As Integer)
    For p_intCompteur = 0 To UBound(p_tabCriteres, 2)
        Me.Controls("lblCritere" & p_intCompteur).Caption = p_tabCriteres(0, p_intCompteur)
        Me.Controls("txtCritere" & p_intCompteur) = p_tabCriteres(1, p_intCompteur)
    Next
End Sub

Il s'agit d'une boucle qui relit le tableau p_tabCriteres et qui affecte, aux différents contrôles en fonction de leur type :
     - soit le nom du champ
     - soit la valeur du critère ou la mention par défaut

V. CONCLUSION

J'ai voulu montré par cet article, deux façons d'appréhender une recherche multicritères.
Elle vient compléter les méthodes déjà décrites par :
     - Caféine dans son article : Recherche Multi-critères
     - Loufab dans son article : Formulaire de recherche prêt à l'emploi.

VI. TELECHARGEMENT

La base exemple : Recherche Multi-Critères

VII. REMERCIEMENTS

Je voudrais remercier l'ensemble de l'équipe DVP qui fait un travail énorme qui a fait de Développez.com ce qu'il est aujourd'hui et qui nous tire toujours vers le haut.
Merci beaucoup également à :
     - Philippe Jochmans pour ses conseils avisés.
     - Heureux-Oli pour sa relecture attentive.