I. Introduction▲
Pour afficher des données et pour les analyser, on utilise les formulaires et états sous forme tabulaire ou feuille de données.
C'est bien sûr ce qui est le plus utilisé.
Mais parfois il peut être judicieux, à l'ouverture de l'application, de pouvoir afficher quelques chiffres-clés.
Le formulaire d'accueil par exemple peut ainsi contenir quelques informations représentatives.
Dans ce cas, on peut tout à fait afficher des résultats dans un simple Label ou dans une Zone de Texte.
Nous verrons également que la même technique peut servir pour afficher des résultats dans une MsgBox.
Ce tutoriel s'adresse en particulier aux débutants.
I-A. Illustration▲
Pour étayer ces propos, nous allons nous servir d'une adaptation de la base "Les Comptoirs" dans laquelle nous utiliserons 4 tables :
- la table "Fournisseurs" ;
- la table "Produits" ;
- la table "DetailsCommandes" ;
- la table "LitigesFour".
I-A-1. Objectif 1▲
Notre premier objectif va être d'afficher dans un Label ou dans une MsgBox :
- le nombre de fournisseurs ;
- le nombre de produits ;
- le nombre de litiges.
Soit le résultat de trois requêtes distinctes.
I-A-2. Objectif 2▲
Notre deuxième objectif va être d'afficher dans une Zone de texte ou une MsgBox le Top 15 des produits les plus vendus.
I-A-3. Vues globales▲
Voici donc une vue de ce que nous voulons obtenir à l'ouverture de l'application.
Si nous cliquons sur le bouton "MsgBox" à côté de notre Label :
Comme vous pouvez le voir, nous en profitons pour personnaliser les textes en fonction des résultats.
Si nous cliquons sur le bouton "MsgBox" à côté de notre Zone de Texte :
I-A-4. Première approche possible▲
Dans la première partie, nous aurions pu arriver à un résultat similaire, en utilisant des zones de textes séparées :
Ce qui nous aurait donné en mode création :
Dans ce cas nous utilisons comme source de nos zones de texte, une fonction de domaine "CpteDom".
Pour en savoir plus sur ces fonctions, un lien très utile : Les Fonctions de Domaine dans Access.
L'avantage est qu'il n'y a pas besoin d'avoir recours au code Vba.
Inconvénients :
- performances moindres dues aux fonctions de domaine ;
- nombre plus important de contrôles ;
- pas directement exploitable dans une MsgBox ;
- moins facile à utiliser pour personnaliser les textes en fonction du résultat (ergonomie du générateur d'expression).
II. Mise en place▲
Afin d'étendre les possibilités offertes, je vous proposerai plusieurs variantes sur la façon d'extraire les données.
II-A. Formulaire▲
Dans un premier temps il nous faut créer un Label ou Etiquette "Lbl_Infos1" et une Zone de Texte "Txt_Infos2" dans notre formulaire "Frm_Accueil".
Voici les propriétés principales du Label :
Et celles de la Zone de Texte :
II-B. Requêtes▲
La solution la plus simple avec Access est de passer par le générateur de requête pour extraire les chiffres dont nous avons besoin.
II-B-1. Requête "Qry_NbFournisseurs"▲
Cette requête va nous permettre de compter le nombre de fournisseurs.
II-B-2. Requête "Qry_NbProduits"▲
Cette requête va nous permettre de compter le nombre de produits.
II-B-3. Requête "Qry_NbLitiges"▲
Cette requête va nous permettre de compter le nombre de litiges fournisseurs.
II-B-4. Requête "Qry_TopProduits"▲
Cette requête va nous permettre d'établir le Top 15 des produits les plus vendus.
1) En mode Création :
Pour spécifier que nous voulons afficher les 15 premières valeurs :
- Soit nous faisons un clic droit "Propriétés" et nous mettons la valeur 15 sur "Premières valeurs" :
- Soit toujours avec le clic droit, nous passons en mode Sql et nous modifions ainsi :
2) Nous affichons les résultats en mode Feuilles de données :
II-C. Code Vba▲
Nous pouvons maintenant créer le code nous permettant de mettre en oeuvre ce que nous recherchons.
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 "Mdl_Synthèses".
Dans l'explorateur double-cliquons sur "Mdl_Synthèses".
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 devons également nous assurer que la référence "Microsoft DAO 3.xx Object Library" est bien cochée.
Pour cela :
Si elle n'est pas cochée, l'ajouter :
II-C-1. Routine pour Label et MsgBox correspondante▲
Nous pouvons maintenant créer une routine "InfosLblMsg" qui pourra être lancée pour l'affichage du Label ou de la MsgBox
Le code que nous allons créer va nous permettre de nous connecter et de parcourir des requêtes par l'intermédiaire de DAO.
Je vous invite à lire l'excellent tutoriel de Tofalu pour en comprendre les principes : Définition et manipulation de données avec DAO.
Nous commençons en déclarant nos variables.
Option
Compare Database
Option
Explicit
Sub
InfosLblMsg
(
TypeAffich As
Boolean
)
'TypeAffich : Dans ce cas -1 Pour Label ou 0 pour MsgBoxLbl
On
Error
GoTo
Err_Infos
Dim
oDb As
DAO.Database
Dim
oRst As
DAO.Recordset
Dim
IntNbFou As
Integer
' variable donnant le Nb de fournisseurs
Dim
IntNbPro As
Integer
' variable donnant le Nb de produits
Dim
IntNbLit As
Integer
' variable donnant le Nb de litiges
Dim
StrSyntFou As
String
' variable de synthèse en fonction du nombre de fournisseurs
Dim
StrSyntPro As
String
' variable de synthèse en fonction du nombre de produits
Dim
StrSyntLit As
String
' variable de synthèse en fonction du nombre de litiges
Dim
StrRecap As
String
' variable récapitulative du texte à afficher dans le Label ou MsgBox.
Nous poursuivons ce code en recherchant les informations nécessaires.
Set
oDb =
CurrentDb
'Nous comptons le nb d'enregistrements de la table fournisseurs
Set
oRst =
oDb.OpenRecordset
(
"Qry_NbFournisseurs"
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbFou
IntNbFou =
oRst.Fields
(
0
)
'Nous comptons le nb d'enregistrements de la table produits
Set
oRst =
oDb.OpenRecordset
(
"Qry_NbProduits"
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbPro
IntNbPro =
oRst.Fields
(
0
)
'Nous comptons le nb d'enregistrements de la table litiges
Set
oRst =
oDb.OpenRecordset
(
"Qry_NbLitiges"
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbLit
IntNbLit =
oRst.Fields
(
0
)
Nous utilisons l'argument "dbOpenSnapshot" car n'ayant pas à modifier, créer ou supprimer des données, nous pouvons nous connecter en lecture seule.
Nous pouvons maintenant attribuer nos résultats.
'Nous définissons le texte qui s'affichera dans la ligne de résultat "Fournisseur"
Select
Case
IntNbFou
Case
Is
=
0
'Si la valeur est égale à 0
StrSyntFou =
"Aucun fournisseur n'est enregistré."
Case
Is
=
1
'Si la valeur est égale à 1
StrSyntFou =
"1 fournisseur est référencé. "
Case
Is
>
1
'Si la valeur est supérieure à 1
StrSyntFou =
IntNbFou &
" fournisseurs sont référencés."
End
Select
'Nous définissons le texte qui s'affichera dans la ligne de résultat "Produits"
Select
Case
IntNbPro
Case
Is
=
0
'Si la valeur est égale à 0
StrSyntPro =
"Aucun produit dans le Plan de Vente."
Case
Is
=
1
'Si la valeur est égale à 1
StrSyntPro =
"1 seul produit enregistré dans le Plan de Vente."
Case
Is
>
1
'Si la valeur est supérieure à 1
StrSyntPro =
"Nous avons "
&
IntNbPro &
" produits dans le Plan de Vente."
End
Select
'Nous définissons le texte qui s'affichera dans la ligne de résultat "Litiges"
Select
Case
IntNbLit
Case
Is
=
0
'Si la valeur est égale à 0
StrSyntLit =
"Aucun litige n'est à signaler."
Case
Is
=
1
'Si la valeur est égale à 1
StrSyntLit =
"Nous avons 1 litige en cours."
Case
Is
>
1
'Si la valeur est supérieure à 1
StrSyntLit =
"Nous avons "
&
IntNbLit &
" litiges en cours."
End
Select
Déterminons le contenu du texte final à afficher :
'Nous récapitulons maintenant le contenu complet de ce que nous voulons afficher
StrRecap =
" Actuellement :"
&
vbCrLf
&
" - "
&
StrSyntFou &
vbCrLf
&
" - "
&
StrSyntPro &
&
" - "
&
StrSyntLit
'Nous pouvons maintenant attribuer à notre Label ou MsgBox le contenu de notre variable "StrRecap"
Select
Case
TypeAffich
Case
Is
=
-
1
'met à jour le Label
Form_Frm_Accueil.Lbl_Infos1.Caption
=
StrRecap
Case
Is
=
0
MsgBox
StrRecap 'Ouvre la MsgBox avec le même résultat
End
Select
'Nous fermons les connexions (dans le cas d'une utilisation DAO)
oRst.Close
oDb.Close
Set
oDb =
Nothing
Set
oRst =
Nothing
Exit_InfosLblMsg
:
Exit
Sub
Err_Infos
:
MsgBox
Err
.Description
Resume
Exit_InfosLblMsg
End
Sub
Dans la ligne récapitulative donnant le contenu de la variable "StrRecap" :
le "vbCrLf" correspond à un retour chariot et un passage à la ligne.
II-C-1-a. Variante avec requêtes intégrées au code▲
Nous pouvons par le code, éviter de créer des requêtes préalables et sélectionner directement des valeurs dans les tables.
Voici dans ce cas le code de la Suite1 :
Set
oDb =
CurrentDb
'Nous comptons le nb d'enregistrements de la table fournisseurs
Set
oRst =
oDb.OpenRecordset
(
"SELECT Count(N°_Fournisseur) FROM Tbl_Fournisseurs "
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbFou
IntNbFou =
oRst.Fields
(
0
)
'Nous comptons le nb d'enregistrements de la table produits
Set
oRst =
oDb.OpenRecordset
(
"SELECT Count(Ref_Produit) FROM Tbl_Produits "
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbPro
IntNbPro =
oRst.Fields
(
0
)
'Nous comptons le nb d'enregistrements de la table litiges
Set
oRst =
oDb.OpenRecordset
(
"SELECT Count(Id_Litige) FROM Tbl_LitigesFour "
, dbOpenSnapshot)
'Nous appliquons le résultat affiché dans la colonne1 à la variable IntNbLit
IntNbLit =
oRst.Fields
(
0
)
II-C-1-b. Variante avec fonction de domaine▲
Nous aurions pu utiliser les fonctions de domaine. Cela nous aurait permis de nous affranchir des requêtes et de la connexion DAO.
Cette solution peut sembler plus simple, mais se révèle moins performante pour des bases conséquentes.
Dans ce cas, notre Suite1 devient :
'Nous comptons le nb d'enregistrements de la table fournisseurs
IntNbFou =
DCount
(
"N°_Fournisseur"
, "Tbl_Fournisseurs"
)
'Nous comptons le nb d'enregistrements de la table produits
IntNbPro =
DCount
(
"Ref_Produit"
, "tbl_Produits"
)
'Nous comptons le nb d'enregistrements de la table litiges
IntNbLit =
DCount
(
"Id_Litige"
, "tbl_LitigesFour"
)
II-C-2. Routine pour Zone de Texte et MsgBox correspondante▲
Nous pouvons passer au code concernant la zone de texte ou la MsgBox.
Contrairement au code précédent nous exploiterons les résultats d'une seule requête.
Nous démarrons le code de cette nouvelle routine "InfosTxt" par la création des variables.
Sub
InfosTxt
(
TypeAffich As
Integer
)
'TypeAffich : Dans ce cas -1 Pour Zone de texte ou 0 pour MsgBoxTxt
On
Error
GoTo
Err_InfosTxt
Dim
oDb As
DAO.Database
Dim
oRst As
DAO.Recordset
Dim
StrNmArt As
String
' variable nom article.
Dim
IntNbArt As
Integer
' variable qté vendue.
Dim
StrSynt As
String
' variable résultat obtenu.
Nous nous connectons à la requête "Qry_Top_Produits" pour en extraire les résultats.
Set
oDb =
CurrentDb
'Nous créons la requête qui va déterminer le Top15 des produits les plus vendus.
Set
oRst =
oDb.OpenRecordset
(
"Qry_TopProduits"
, dbOpenSnapshot)
Nous continuons en affectant les résultats :
'Nous attribuons à la variable "StrNmArt" le résultat de la colonne 1 de la requête
'et à la variable "IntNbArt" le contenu de la colonne 2.
StrNmArt =
Nz
(
oRst.Fields
(
0
), ""
)
IntNbArt =
Nz
(
oRst.Fields
(
1
), 0
)
'Nous déterminons les résultats.
Select
Case
StrNmArt
Case
Is
=
""
'S'il n'y a pas d'enregistrement
StrSynt =
"Aucune vente enregistrée."
Case
Else
'Crée une boucle qui va déterminer les résultats sous la forme :
'" - Nb unités pour : NomDuProduit" (+ retour chariot + saut à la ligne pour résultat suivant).
StrSynt =
""
While
Not
oRst.EOF
StrSynt =
StrSynt &
" - "
&
oRst.Fields
(
1
) &
" unités"
&
" pour : "
&
oRst.Fields
(
0
) &
vbCrLf
oRst.MoveNext
Wend
End
Select
'Comme Source de la Zone de Texte ou comme contenu de la MsgBox_Txt, nous mettons un titre + le résultat de la boucle.
Select
Case
TypeAffich
Case
Is
=
-
1
'met à jour la Zone de Texte
Form_Frm_Accueil.Txt_Infos2.ControlSource
=
_
"="
&
""" Le top 15 des quantités vendues est le suivant :"
&
vbCrLf
&
vbCrLf
&
StrSynt &
""""
Case
Is
=
0
'Ouvre la MsgBox_Txt avec le même résultat" '
MsgBox
" Le top 15 des quantités vendues est le suivant :"
&
vbCrLf
&
vbCrLf
&
StrSynt
End
Select
'Nous fermons les connexions
oRst.Close
oDb.Close
Set
oDb =
Nothing
Set
oRst =
Nothing
Exit_InfosTxt
:
Exit
Sub
Err_InfosTxt
:
MsgBox
Err
.Description
Resume
Exit_InfosTxt
End
Sub
II-C-2-a. Variante▲
Comme pour la procédure "InfosLblMsg", nous pouvons intégrer directement la recherche des enregistrements, dans le code, sans passer par des requêtes.
Voici le code modifié de la Suite1 :
Dim
StrSql As
String
Set
oDb =
CurrentDb
'Nous créons la requête qui va nous déterminer le Top15 des produits les plus vendus.
StrSql =
"SELECT TOP 15 T2.Nom_Produit, Sum(T1.Quantité)"
&
_
"FROM Tbl_DetailsCommandes As T1 "
&
_
"INNER JOIN Tbl_Produits As T2 ON T2.Ref_Produit = T1.Ref_Produit "
&
_
"GROUP BY T2.Nom_Produit "
&
_
"ORDER BY Sum(T1.Quantité) DESC;"
Set
oRst =
oDb.OpenRecordset
(
StrSql, dbOpenSnapshot)
II-C-3. Code du formulaire d'Accueil▲
Il nous reste à appeler les différentes procédures sur le code du formulaire d'Accueil :
Option
Compare Database
Option
Explicit
Private
Sub
Cmd_Lbl_Click
(
)
'Nous appelons la procédure d'ouverture de la MsgBox
Call
InfosLblMsg
(
0
)
End
Sub
__________________________________________________________________________________________________________
Private
Sub
Cmd_Txt_Click
(
)
'Nous appelons la procédure d'ouverture de la MsgBox
Call
InfosTxt
(
0
)
End
Sub
__________________________________________________________________________________________________________
Private
Sub
Form_Open
(
Cancel As
Integer
)
'Nous appelons la procédure de remplissage du Label
Call
InfosLblMsg
(-
1
)
'Nous appelons la procédure de remplissage de la Zone de Texte
Call
InfosTxt
(-
1
)
'Nous mettons le Focus sur la Zone de Texte
Me.Txt_Infos2.SetFocus
'Nous mettons le Curseur au début de la Zone de Texte
Me.Txt_Infos2.SelStart
=
0
End
Sub
__________________________________________________________________________________________________________
Private
Sub
Cmd_Quit_Click
(
)
On
Error
GoTo
Err_Cmd_Quit_Click
DoCmd.Quit
Exit_Cmd_Quit_Click
:
Exit
Sub
Err_Cmd_Quit_Click
:
MsgBox
Err
.Description
Resume
Exit_Cmd_Quit_Click
End
Sub
III. Conclusion▲
Nous arrivons au terme de cet article.
Comme vous pouvez le constater, ce code permet d'obtenir des résultats intéressants dans des contrôles simples, sans passer obligatoirement par des sous-formulaires ou tableaux.
Nous avons également démontré que nous pouvions utiliser plusieurs techniques pour obtenir les mêmes résultats.
Pour ma part je préfère la solution avec connexion DAO et requêtes intégrées, car c'est une solution performante et standard.
C'est d'ailleurs sur cette solution qu'est basé le fichier Démo que vous pouvez télécharger ici.
IV. Remerciements▲
Un grand Merci à toute l'équipe de Dvp et plus particulièrement :
Pour leurs remarques et conseils avisés :
. Pierre Fauconnier
. Philippe JOCHMANS
. Jeannot45
. Argyronet
Pour ses corrections orthographiques et syntaxiques :
. Jacques jean