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 SubII-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 SubIII. 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







