I. Introduction▲
Un des buts des formulaires est de consulter des données enregistrées dans des tables, soit directement, soit par l'intermédiaire de requêtes.
Afin de pouvoir affiner ces consultations, des outils de tris et de filtres se révèlent rapidement indispensables.
Plusieurs outils existent pour sélectionner des données, entre autres :
- la fonction recherche standard d'Office ;
- des outils de recherche avancée ;
- les fonctions de filtrage (par sélection, par formulaire, hors sélection…).
Or je me suis aperçu que ce qui était très utilisé dans les petites applications, c'était la fonction de filtre par sélection et les deux fonctions de tri, car elles permettent d'affiner une recherche de façon très intuitive en fonction des résultats qui apparaissent à l'écran.
C'est donc sur ce point que nous allons nous pencher, en y ajoutant quelques petites fonctionnalités permettant de rendre ces fonctions basiques encore plus conviviales.
Ce tutoriel s'adresse à des débutants en Vba, et le fichier exemple peut être ouvert avec Access 2000-2007.
I-A. Illustration▲
I-A-1. Base de départ▲
Pour le démontrer, nous nous baserons sur une petite application avec des tables provenant de la base « Les Comptoirs » et sur une requête permettant d'avoir des stocks par catégories de produits, noms de produits et sociétés.
Voici cette requête avec le générateur de requêtes :
I-A-2. Objectifs▲
Nous aurons quatre objectifs :
- notre formulaire pourra être trié sur tous les champs, et filtré sur trois (« Nom de catégorie », « Nom du produit », « Société ») ;
- les titres et résultats du formulaire se modifieront dynamiquement en fonction des filtres ;
- un état correspondant au tri et filtre du formulaire pourra être imprimé ;
- l'application doit pouvoir fonctionner avec le Runtime.
J'ai fait le choix de mettre les boutons de commande dans une barre de menus. Nous aurions tout aussi bien pu le faire à partir du ruban, ou à partir de boutons directement dans le formulaire.
I-A-3. Aperçus▲
Voici le formulaire à l'ouverture avec tous les enregistrements non triés.
Voici le même formulaire filtré sur « Produits laitiers » avec tri décroissant sur « Qté en stock »
Vous remarquerez que le titre et le pied de formulaire ont repris les critères de filtre.
Nous allons filtrer une nouvelle fois sur la Société « Formaggi Fortini s.r.l. » toujours avec le même bouton de filtre
Le titre et le pied de formulaire ont de nouveau été modifiés en conséquence.
Et pour finir, nous imprimons un état, qui reprend tous les éléments de filtres, tris et titres du formulaire.
II. Application▲
II-A. Création du formulaire▲
La création du formulaire est classique.
Il aura comme Source notre requête « Qry_Stocks ».
Les zones de texte auront comme Source contrôle les champs de cette même requête.
Dans l'en-tête de formulaire, nous placerons un label que nous nommerons « Lbl_Titre » auquel nous donnerons comme légende une valeur quelconque, par exemple « Stock total ».
Dans le détail du formulaire, nous nommerons les zones de texte avec les noms suivants:
- Txt_Societe ;
- Txt_Categorie ;
- Txt_CodeProduit ;
- Txt_NomProduit ;
- Txt_QteStock ;
- Txt_PU ;
- Txt_MontStock.
Dans le pied de formulaire, nous placerons une zone de texte nommée « Txt_Total ».
Elle aura comme Source contrôle « =Somme([Montant_Stock]) ».
Nous enregistrons, et si nous passons en mode formulaire, nous avons bien tous nos enregistrements.
II-A-1. Code Vba▲
II-A-1-a. Démarrage du code▲
Nous allons nous intéresser maintenant aux différents boutons de commande et en particulier les boutons de filtre.
Comme fixé dans les objectifs, l'utilisateur ne pourra filtrer que sur les trois zones de texte significatives suivantes :
- Txt_Societe ;
- Txt_Categorie ;
- Txt_NomProduit.
Il faut donc créer les différentes fonctions correspondantes, en prenant en compte le fait que nous voulons que « Lbl_Titre », et « Txt_Total » reprennent les différents critères de filtre.
Pour cela, ouvrons l'éditeur Vba (Alt + F11) et insérons un module.
Dans l'explorateur de projet (Ctrl + R) nous avons bien un nouveau module « Module1 ».
Positionnons la souris sur « Module1 » et ouvrons la fenêtre de propriétés. (F4).
Renommons « Module1 » en « Fonctions ».
Dans l'explorateur, double-cliquons sur « Fonctions ».
Nous sommes maintenant dans la fenêtre de saisie du code correspondant au module.
Si elle n'est pas présente, nous ajoutons la ligne « Option Explicit ».
Cette option nous obligera à déclarer toutes nos variables, et avoir ainsi un code plus performant.
Nous pouvons maintenant déclarer trois variables correspondant aux valeurs des trois colonnes sur lesquelles nous allons pouvoir filtrer.
Option
Compare Database
Option
Explicit
Dim
Cat As
String
'variable sélection colonne "Catégorie"
Dim
Soc As
String
'variable sélection colonne "Société"
Dim
Pro As
String
'variable sélection colonne "Nom produits"
II-A-1-b. Code tris et filtres▲
Puis nous créons les deux fonctions de tri
'------------------------------------------------------------
' Tri_croissant
'-----------------------------------------------------------
Public
Function
Tri_croissant
(
)
On
Error
GoTo
Tri_croissant_Err
DoCmd.RunCommand
acCmdSortAscending
Tri_croissant_Exit
:
Exit
Function
Tri_croissant_Err
:
MsgBox
Error
$
Resume
Tri_croissant_Exit
End
Function
'------------------------------------------------------------
' Tri_décroissant
'------------------------------------------------------------
Public
Function
Tri_decroissant
(
)
On
Error
GoTo
Tri_decroissant_Err
DoCmd.RunCommand
acCmdSortDescending
Tri_decroissant_Exit
:
Exit
Function
Tri_decroissant_Err
:
MsgBox
Error
$
Resume
Tri_decroissant_Exit
End
Function
Nous ajoutons maintenant le code permettant d'afficher tous les enregistrements.
Nous mettons également à blanc les valeurs des variables et nous personnalisons « Lbl_Titre » et « Txt_Total ».
C'est cette fonction que nous appellerons quand nous cliquerons sur « Tous les produits ».
'--------------------------------------------------------------
'Afficher tous les enregistrements
'------------------------------------------------------------
Public
Function
Filtre_Tous
(
)
On
Error
GoTo
Filtre_Tous_Err
'Affiche tous les enregistrements
DoCmd.ShowAllRecords
'Met les 3 variables de colonnes à blanc
Soc =
""
Cat =
""
Pro =
""
'Change le label Lbl_Titre
Form_Frm_Stock.Lbl_Titre.Caption
=
"Stock total"
&
" au "
&
Date
'Change la zone de texte Txt_Total
Form_Frm_Stock.Txt_Total.ControlSource
=
_
"="
&
""" Le montant total du stock est de """
&
"&"
&
"FormatCurrency(Sum([Montant_Stock]))"
Filtre_Tous_Exit
:
Exit
Function
Filtre_Tous_Err
:
MsgBox
Error
$
Resume
Filtre_Tous_Exit
End
Function
Nous ajoutons maintenant le code permettant de filtrer une colonne et de stocker les variables correspondantes.
Nous en profitons pour mettre un message d'alerte, si l'utilisateur veut filtrer sur une colonne autre que celles imposées.
'--------------------------------------------------------------
'Filtrer une colonne du formulaire Frm_Stock
'------------------------------------------------------------
Public
Function
Filtre_Select
(
)
On
Error
GoTo
Filtre_Select_Err
'Détermine la valeur des variables en fonction de la zone de texte qui a le focus
Select
Case
Screen.ActiveControl
Case
Form_Frm_Stock.Txt_Societe
'Affecte la valeur de la zone ayant le focus à la variable
Soc =
Form_Frm_Stock.Txt_Societe
'Lance la commande Access filtrer par sélection
DoCmd.RunCommand
acCmdFilterBySelection
'Appelle la fonction de mise à jour de Lbl_Titre et Txt_Total
Call
Titres
Case
Form_Frm_Stock.Txt_NomProduit
Pro =
Form_Frm_Stock.Txt_NomProduit
DoCmd.RunCommand
acCmdFilterBySelection
Call
Titres
Case
Form_Frm_Stock.Txt_Categorie
Cat =
Form_Frm_Stock.Txt_Categorie
DoCmd.RunCommand
acCmdFilterBySelection
Call
Titres
Case
Else
'Message si l'utilisateur essaie de filtrer sur un champ autre que ceux définis
Call
MsgBox
_
(
"Vous ne pouvez filtrer que les colonnes Produits , Société et Catégorie"
, vbExclamation
, "Attention"
)
End
Select
Filtre_Select_Exit
:
Exit
Function
Filtre_Select_Err
:
MsgBox
Error
$
Resume
Filtre_Select_Exit
End
Function
Dans cette dernière procédure, nous avons appelé une fonction « Titres » qui va nous permettre de mettre à jour « Lbl_Titre » et « Txt_Total ». Nous allons donc ajouter cette fonction :
'--------------------------------------------------------------
'Titre et pied de formulaire dynamiques en fonction des filtres
'------------------------------------------------------------
Public
Function
Titres
(
)
On
Error
GoTo
Titres_Err
Dim
Tot As
String
'variable de la Zone de texte Txt_Total du pied de formulaire
'détermine un exemple de résultat
If
Soc Like ""
Then
Tot =
"Le montant du stock "
&
Cat &
" "
&
Pro &
" est de "
Else
Tot =
"Le montant du stock "
&
Cat &
" "
&
Pro &
" de la société "
&
Soc &
" est de "
End
If
'Met à jour le label Lbl_Titre dans l'en-tête du formulaire
Form_Frm_Stock.Lbl_Titre.Caption
=
"Stock "
&
Cat &
" "
&
Pro &
" "
&
Soc &
" au "
&
Date
'Met à jour la zone de texte Txt_Total dans le pied du formulaire
Form_Frm_Stock.Txt_Total.ControlSource
=
_
"="
&
""" Le montant est de """
&
"&"
&
"FormatCurrency(Sum([Montant_Stock]))"
Form_Frm_Stock.Txt_Total.ControlSource
=
_
Replace
(
Form_Frm_Stock.Txt_Total.ControlSource
, " Le montant est de "
, Tot)
Titres_Exit
:
Exit
Function
Titres_Err
:
MsgBox
Error
$
Resume
Titres_Exit
End
Function
Nous avons ainsi toutes les fonctions nécessaires à la personnalisation de nos titres.
II-A-1-c. Affectation des fonctions aux boutons▲
Il faut maintenant affecter à nos boutons de commande, les fonctions écrites plus haut.
Dans l'exemple fourni, j'ai créé les boutons dynamiquement dans une barre de menu. Je ne reviendrai pas sur la façon de les créer, cela ayant déjà été évoqué dans plusieurs tutoriels.
Voici cependant une vue du code permettant de faire appel à une des fonctions.
Si nous avions créé notre menu de façon classique, nous aurions appelé la fonction dans les propriétés du bouton comme ceci :
Si nous avions préféré créer des boutons directement dans le formulaire, nous aurions sur l'évènement OnClick de notre bouton ajouté la ligne suivante :
Call
Filtre_Select
II-B. Création de l'état▲
Pour imprimer les résultats du formulaire, nous avons deux solutions :
- ajouter un en-tête de page sur notre formulaire. Mais ce n'est pas l'idéal…
- avoir un état reprenant tous les paramètres de notre formulaire, et dont nous pourrons personnaliser la mise en page.
C'est cette deuxième solution que nous adopterons.
Pour que cela fonctionne, il faut que les contrôles du formulaire et de l'état pointant vers le même champ portent le même nom.
Pour ce faire, le plus simple est de se placer sur le formulaire et de l'enregistrer sous :
Puis nous l'ouvrons en mode création et nous faisons les modifications de présentation et de mise en page souhaitées.
II-B-1. Code Vba▲
II-B-1-a. Reprise des paramètres de filtres, tris et titres▲
Maintenant, il ne nous reste plus qu'à récupérer les critères du formulaire.
Quand vous filtrez un formulaire, Access crée une expression de chaîne de ce type visible dans les propriétés du formulaire :
Nous allons créer maintenant un module « Synchro_Etats » afin de récupérer ces valeurs.
Option
Compare Database
Option
Explicit
Public
Function
Report_Synchro
(
FrmFilter As
Form, RepFilter As
Report)
'FrmFilter : Variable Nom du formulaire
'RepFilter : Variable Nom de l'état correspondant
Dim
ExpFiltre As
String
'Variable expression de filtre
Dim
ExpTri As
String
'Variable expression de tri
ExpFiltre =
FrmFilter.Filter
'Récupère l'expression de filtre du formulaire
ExpTri =
FrmFilter.OrderBy
'Récupère l'expression de tri du formulaire
RepFilter.RecordSource
=
FrmFilter.RecordSource
'affecte à l'état la même source que le formulaire
'Si le formulaire est filtré, nous attribuons à l'état l'expression stockée dans la variable ExpFiltre
If
FrmFilter.FilterOn
Then
RepFilter.Filter
=
ExpFiltre
RepFilter.FilterOn
=
True
Else
RepFilter.FilterOn
=
False
End
If
'Si le formulaire est trié, nous attribuons à l'état l'expression stockée dans la variable ExpTri
If
FrmFilter.OrderByOn
Then
RepFilter.OrderBy
=
ExpTri
RepFilter.OrderByOn
=
True
Else
RepFilter.OrderByOn
=
False
End
If
'Donne la valeur Lbl_Titre du Formulaire au Label correspondant de l'Etat
RepFilter.Lbl_Titre.Caption
=
FrmFilter.Lbl_Titre.Caption
'Donne la valeur Txt_Total du Formulaire à la zone de texte correspondante de l'état
RepFilter.Txt_Total.ControlSource
=
FrmFilter.Txt_Total.ControlSource
End
Function
Comme vous pouvez le voir, nous avons rajouté en fin de fonction, le code permettant également de récupérer les valeurs du label « Lbl_Titre » et de la zone de texte « Txt_Total ».
Je vous encourage à avoir dans tous les formulaires et états de votre application les mêmes noms de titre et résultat si vous voulez profiter au maximum de la fonction.
II-B-1-b. Ouverture de l'état▲
Il ne nous reste plus qu'à appeler notre fonction « Syncro_Etats » sur l'évènement Ouverture de notre état.
Option
Compare Database
Option
Explicit
Private
Sub
Report_Open
(
Cancel As
Integer
)
'Appelle la fonction synchro de l'état
Call
Report_Synchro
(
Form_Frm_Stock, Report_Rpt_Stock)
End
Sub
III. Conclusion▲
Nous arrivons au terme de cet article.
Comme vous pouvez le constater, ce code facile à mettre en œuvre permet dans de petites applications, de naviguer dans des formulaires de façon très intuitive, en obtenant immédiatement des résultats explicites.
IV. Remerciements▲
Un grand Merci à Philippe JOCHMANS, Jeannot 45, Jacques-Jean et Pierre FAUCONNIER pour leurs corrections et leurs remarques avisées, ainsi qu'à Claude LELOUP pour sa relecture orthographique.