Filtre par sélection dans formulaire, avec titres dynamiques et liaison avec état

Modification dynamique de titres de formulaires en fonction des filtres par sélection et tris, et modifications des états correspondants.

18 commentaires Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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, étaient 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-B. Illustration

I-B-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:

Image non disponible

I-B-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-B-3. Aperçus

Voici le formulaire à l'ouverture avec tous les enregistrement non triés.

Image non disponible


Voici le même formulaire filtré sur "Produits laitiers" avec tri décroissant sur "Qté en stock"

Image non disponible

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

Image non disponible

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.

Image non disponible

II. Application

II-A. Création du formulaire

La création du formulaire est classique.

Image non disponible


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 textes 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 filtres.
Comme fixé dans les objectifs, l'utilisateur ne pourra filtrer que sur les 3 zones de textes 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.

Image non disponible


Dans l'explorateur de projet (Ctrl + R) nous avons bien un nouveau module "Module1".

Image non disponible


Positionnons la souris sur "Module1" et ouvrons la fenêtre de propriétés. (F4).
Renommons "Module1" en "Fonctions".

Image non disponible

Dans l'explorateur double-cliquons sur "Fonctions".
Nous sommes maintenant dans la fenêtre de saisie du code correspondant au module.

Image non disponible


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 3 variables correspondant aux valeurs des 3 colonnes sur lesquelles nous allons pouvoir filtrer.

Code module Fonctions
Sélectionnez

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

Code module Fonctions
Sélectionnez

'------------------------------------------------------------
' 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 appelerons quand nous cliquerons sur "Tous les produits".

Code module Fonctions
Sélectionnez

'--------------------------------------------------------------
'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.

Code module Fonctions
Sélectionnez

'--------------------------------------------------------------
'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:

Code module Fonctions
Sélectionnez

'--------------------------------------------------------------
'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 dane 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.

Image non disponible


Si nous avions créé notre menu de façon classique, nous aurions appelé la fonction dans les propriétés du bouton comme ceci:

Image non disponible


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:

 
Sélectionnez
 
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 les mêmes champs portent le même nom.

Pour ce faire, le plus simple est de se placer sur le formulaire et de l'enregistrer sous:

Image non disponible


Puis nous l'ouvrons en mode création et nous faisons les modifications de présentation et de mise en page souhaitées.

Image non disponible

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:

Image non disponible


Nous allons créer maintenant un module "Synchro_Etats" afin de récupérer ces valeurs.

Code module Syncro_Etats
Sélectionnez
			
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'exprssion 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é 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'Etat
    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.

 
Sélectionnez

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 oeuvre, permet dans de petites applications, de naviguer dans des formulaires de façon très intuitive, en obtenant immédiatement des résultats explicites.

Vous pouvez télécharger le fichier servant d'exemple

IV. Remerciements

Un grand Merci à Philippe JOCHMANS, Jeannot 45, Jacques-Jean et Pierre FAUCONNIER pour leurs corrections et leurs remarques avisées, ainsi qu'à toute l'équipe de DVP.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2009 Jean-Damien GAYOT. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.