I. Ce dont il s'agit▲
Des dessins plutôt qu'un discours :
Si la valeur n'est pas dans la table, ce qui nous intéresse pour la prise de décision, c'est de connaître les deux bornes qui encadrent la valeur recherchée. Selon le contexte, on choisira alors :
- soit la borne inférieure, par exemple pour un tarif valable à partir de telle date ;
- soit la borne supérieure, par exemple pour le départ du prochain train ;
- voire une extrapolation basée sur ces deux valeurs…
II. Prérequis▲
Savoir consulter l'aide d'Access.
D'une manière générale, pour se documenter sur les propriétés d'un formulaire ou d'un état, ou de leurs contrôles : - afficher l'objet en mode création ; - cliquer sur la propriété, elle se met alors en surbrillance ; - enfoncer la touche <F1>. L'aide Access s'ouvre à la bonne page. On peut aussi : - ouvrir l'aide <F1>, choisir l'onglet « Aide intuitive » et suivre les instructions ; - ouvrir la fenêtre d'exécution (<Ctrl> + G), saisir un mot-clé, y placer le curseur de la souris et presser <F1>. |
III. L'objectif pédagogique▲
Pour chaque exemple concret, nous allons construire pas à pas un formulaire dans lequel l'utilisateur saisit une valeur et reçoit la réponse à sa question. L'objectif est de proposer, en détail, une démarche intellectuelle pour aborder le problème et le résoudre sans faire appel à du code VBA.
III-A. Liste des fonctions utilisées dans les exemples▲
Date()
Format()
MaxDom()
MinDom()
Nz()
RechDom()
Replace()
VraiFaux()
- cliquez sur la propriété Valeur par défaut et ensuite sur les trois points qui apparaissent à droite.
Si vous voulez une idée des principales fonctions intégrées :
et choisissez :
IV. Taux directeur en vigueur à la BCE à telle date▲
Dans ce chapitre, nous recherchons une valeur de format Date dans une table.
Créons un formulaire fBCE avec deux contrôles : zdtDate et ZdtTaux :
Ce formulaire est indépendant : il n'est relié à aucune source.
Remarquez la valeur par défaut de zdtDate : Date(), c'est une fonction intégrée d'Access qui affiche la date du jour. C'est donc la date d'aujourd'hui qui sera affichée - par défaut - à l'ouverture du formulaire. L'utilisateur saisira la date de son choix.
IV-A. Les étapes du raisonnement▲
IV-A-1. La question est-elle pertinente▲
La table renseigne des taux à partir du 6/11/08, dans notre formulaire, cela n'a pas de sens de demander le taux d'une date antérieure au 6/11/08.
Convenons que si la date introduite dans zdtDate est antérieure au 6/11/08, nous afficherons le texte : « Date invalide » dans le contrôle zdtTaux.
La fonction intégrée VraiFaux() convient pour ce genre de traitement, sa syntaxe est :
VraiFaux (
«Expr»;«SiVrai»;«SiFaux»)
Nous devons remplacer «Expr» par la traduction en « Access » du français « la date introduite en zdtDate est antérieure au 6/11/08 ».
Nous devons remplacer «SiVrai» par le texte : « Date invalide ».
Nous devons remplacer «SiFaux» par le taux en vigueur à la BCE à la date mentionnée. À ce stade du raisonnement, contentons-nous d'afficher le texte « On verra plus tard ».
Voici la syntaxe de la source de zdtTaux :
=
VraiFaux
(
[zdtDate]<
#6
/
11
/
08
#;"Date invalide"
;"On verra plus tard"
)
Remarquez :
le signe « = » devant la fonction dans la syntaxe de la propriété Source du contrôle ;
les crochets « [ ] » qui encadrent le nom du contrôle qui contient la valeur à comparer ;
les croisillons « # » qui encadrent la date ;
les guillemets doubles droits « " » qui encadrent les chaînes de caractères.
Testons le résultat :
Généralisons, au lieu de demander si zdtDate est antérieure au 6/11/08, demandons plutôt si zdtDate est antérieure à la plus petite DateChangement contenue dans la table TauxBCE.
La fonction intégrée MinDom() permet de trouver cette valeur :
MinDom (
«Expr»;«Domaine»;«Critère»)
«Expr» est le nom du champ à rechercher : en l'occurrence « DateChangement ».
«Domaine» est l'espace dans lequel rechercher : la table « TauxBCE ».
«Critère» permettrait de spécifier une condition pour préciser le choix. Cela n'est pas d'application dans le cas ici où nous demandons la plus petite date, sans restriction.
Ce qui nous donne :
=
MinDom
(
"DateChangement"
;"TauxBCE"
)
Pour le vérifier, nous allons ajouter - provisoirement - un contrôle zdtMartyr dans notre formulaire. Cela nous permettra de progresser en vérifiant pas à pas que la voie est bonne.
Dans la source de zdtTaux, nous allons remplacer #6/11/08# par son expression plus générale :
À ce stade de notre progression, le formulaire fonctionne correctement, si ce n'est que le taux n'est pas affiché lorsque la date est valide.
Plus tard, c'est maintenant.
IV-B. Comment trouver le taux à cette date ?▲
On va procéder en deux temps.
On va d'abord chercher la date du dernier changement par rapport à la date saisie dans zdtDate.
Quand on aura cette date, on recherchera le taux qui a alors été mis en vigueur.
IV-B-1. Quelle est la date du dernier changement de taux ?▲
C'est, dans TauxBCE, la plus grande date qui est antérieure - ou éventuellement égale - à la date saisie en zdtDate.
C'est l'occasion de faire connaissance avec la fonction intégrée :
MaxDom (
«Expr»;«Domaine»;«Critère»)
«Expr» : DateChangement.
«Domaine» : TauxBCE.
«Critère» : il faudra exprimer « qui est inférieure ou égale au contenu de zdtDate ».
Progressons pas à pas.
Tentons ceci dans zdtMartyr :
=
MaxDom
(
"DateChangement"
;"TauxBCE"
;"DateChangement <=#20/07/10#"
)
On s'attend à trouver : le 7 mai 2009, c'est-à-dire la date du dernier changement de taux avant le 20 juillet 2010.
Et pourtant :
Pourquoi ? Parce que Access a interprété #20/07/10# comme étant le 10 juillet 2020 !
Dans cette fonction, Access attend la date présentée à l'anglo-saxonne mm/jj/aa, en l'occurrence #07/20/10#.
Voici :
Dans les pays francophones, le format d'une date est généralement jj/mm/aa.
Dans les pays anglophones c'est mm/jj/aa.
Et par exemple au Japon aa/mm/jj ou plutôt : 火曜日年月日.
Dans Access, cela dépend du contexte, parfois il attend #jj/mm/aa# par exemple dans la fonction VraiFaux(), parfois il attend #mm/jj/aa#, comme ici, dans MaxDom().
L'interprétation par Access est parfois déconcertante :
Valeur | Interprétation |
#01/07/10# | « 7 janvier 2010 » |
#02/07/10# | « 7 février 2010 » |
#03/07/10# | « 7 mars 2010 » |
[...] | |
#12/07/10# | « 7 décembre 2010 » |
#13/07/10# | « 10 juillet 2013 » |
#14/07/10# | « 10 juillet 2014 » |
#2012/7/20# | « 20 juillet 2012 » |
#20/7/2012# | « 20 juillet 2012 » |
---
Continuons notre parcours du combattant, au lieu de nous référer à une date codée en dur, nous allons exprimer qu'il faut se référer au contenu de zdtDate.
Dans la source actuelle de zdtMartyr :
=
MaxDom
(
"DateChangement"
;"TauxBCE"
;"DateChangement <=#07/20/10#"
)
nous allons, dans le critère de la fonction, remplacer « 07/20/10 » par « ce qui se trouve en zdtDate sous la forme mm/jj/aa ».
Quelque chose comme :
le texte : "DateChangement <=#" ;
concaténé avec la date bien formatée de zdtDate ;
concaténé avec le texte : "#".
Pour bien formater le contenu de zdtDate, la syntaxe est :
Format
(
[zdtDate];"mm/dd/yy"
)
Remarquez l'équivalent anglo-saxon "mm/dd/yy" de "mm/jj/aa". (OK, tout serait plus simple si la planète entière parlait français ! Mais il y a eu cette tour à Babel…)
Concaténer se traduit par l'esperluette « & ».
La source de zdtMartyr devient :
=
MaxDom
(
"DateChangement"
;"TauxBCE"
;"DateChangement <=#"
&
Format
(
[zdtDate];"mm/dd/yy"
) &
"#"
)
C'est la date du dernier changement de taux avant la date saisie par l'utilisateur. C'est elle qui va nous servir pour trouver le taux alors en vigueur.
Pour plus de clarté, rebaptisons le contrôle zdtMartyr en zdtDateRef.
Voici où nous en sommes actuellement :
IV-B-2. Cherchons maintenant le taux qui a été alors mis en vigueur à la BCE▲
La fonction intégrée RechDom convient dans ce cas :
RechDom (
«Expr»;«Domaine»;«Critère»)
«Expr» : le nom de la valeur cherchée dans le domaine, en l'occurrence Taux ;
«Domaine» : le nom du domaine. Ici, la table TauxBCE ;
«Critère» : nous allons exprimer ici qu'il faut choisir l'enregistrement qui a pour DateChangement celle que nous avons logée dans zdtDateRef.
Ici aussi, le contexte veut que l'on reformate la date.
La syntaxe pour trouver le taux est donc :
=
RechDom
(
"Taux"
;"TauxBCE"
;"DateChangement=#"
&
Format
(
[zdtDateRef];"mm/dd/yy"
) &
"#"
)
IV-C. On est au bout▲
La dernière retouche :
C'est tout vu !
N.B. Sans le « = » initial.
On y est :
V. Le prochain Thalis▲
Dans ce chapitre, nous recherchons une valeur de format Heure dans une table.
V-A. Les étapes du raisonnement▲
V-A-1. Le cas banal▲
Avec l'heure saisie, il faut trouver dans la table DepartThalisBxlParis la valeur de HeureDepart immédiatement supérieure à l'heure saisie dans zdtHeure.
Si on s'inspire de notre explication précédente, la fonction intégrée :
MinDom (
«Expr»;«Domaine»;«Critère»)
répondra à cette demande.
Nous aurons :
«Expr» : HeureDepart ;
«Domaine» : DepartThalisBxlParis ;
«Critère» : l'heure qui est supérieure à celle mentionnée dans zdtHeure.
=
MinDom
(
"HeureDepart"
;"DepartThalisBxlParis"
;"HeureDepart>=#"
&
[zdtHeure] &
"#"
)
Remarquez l'analogie avec la syntaxe que nous avions adoptée pour une date : l'expression de l'heure est encadrée de croisillons « # ».
Une différence toutefois : il n'est pas nécessaire de personnaliser le format. Quel que soit le contexte, c'est partout « hh:mm[:ss] ».
V-A-2. Cas particulier : l'heure saisie est plus tard que le dernier train▲
Dans l'état actuel, voici ce que cela donne :
Rien ne s'affiche : en fait, puisque dans DepartThalisBxlParis, il n'y a pas d'HeureDepart qui est supérieure à 22:30.
Deux conséquences :
- la première, le résultat de :
=
MinDom
(
"HeureDepart"
;"DepartThalisBxlParis"
;"HeureDepart>=#"
&
[zdtHeure] &
"#"
)
est la valeur Null ;
- la seconde, vous passerez la nuit à Bruxelles et vous prendrez le train suivant, c'est-à-dire la plus petite valeur HeureDepart dans la table DepartThalisBxlParis.
C'est l'occasion d'utiliser la fonction intégrée :
Nz (
«Expr»;«ValeurSiNull»)
Avec cette fonction, on peut présenter une alternative :
avec «Expr», on exprime ce qu'il faut faire dans le cas banal ;
avec «ValeurSiNull», on exprime ce qu'il faut faire si la première branche donne un résultat égal à Null.
Dans notre cas, la deuxième branche de l'alternative sera le premier train :
MinDom
(
"HeureDepart"
;"DepartThalisBxlParis"
)
sans paramètre pour le critère.
Et notre formulaire est opérationnel :
Bon voyage !
VI. Quel signe zodiacal ?▲
Dans ce chapitre, nous recherchons une valeur de format Texte dans une table.
Les quatre chiffres de Debut (en format Texte) représentent, sous la forme mmjj, la date de début du Signe mentionné.
VI-A. Le cas banal▲
Il faut choisir Signe dans l'enregistrement de la table SignesZodiaque dont Debut est immédiatement inférieur ou égal à la date saisie, présentée sous la forme mmjj.
Exemple : pour 28 janvier 1955, il faut prendre « Verseau », car « 0121 » est la valeur immédiatement inférieure à « 0128 ».
On va donc opérer en deux temps :
- trouver la plus grande valeur de Debut qui est inférieure ou égale au mmjj de la date saisie dans zdtNaissance ;
- avec ce Debut, chercher dans SignesZodiaque le Signe correspondant.
Déjà vu !
MaxDom (
«Expr»;«Domaine»;«Critère»)
«Expr» : Debut.
«Domaine» : SignesZodiaque.
«Critère» :
le texte « Debut <= » concaténé avec
la valeur de Format([zdtNaissance];"mmdd") encadrée d'une paire de doubles-quotes (puisque c'est du texte).
«Critère» ressemblerait à ceci :
Debut <="0128"
le tout inclus dans une paire de quotes, il viendrait
"Debut <="0128""
Nous avons donc le signe « " » qui est lui-même inclus dans une paire de « " ». La règle est alors de doubler les « " » intérieurs, ainsi :
"Debut <=""0128"""
Notre fonction s'écrira donc :
MaxDom
(
"Debut"
;"SignesZodiaque"
;"Debut <="""
&
Format
(
[zdtNaissance];"mmdd"
) &
""""
)
Comme nous l'avions fait plus haut, ajoutons temporairement dans notre formulaire un contrôle zdtMartyr et affectons-lui comme propriété Source :
=
MaxDom
(
"Debut"
;"SignesZodiaque"
;"Debut <="""
&
Format
(
[zdtNaissance];"mmdd"
) &
""""
)
Il vient :
Recherchons maintenant le Signe qui correspond à cette valeur, d'abord en utilisant la valeur stockée dans zdtMartyr :
=
RechDom
(
"Signe"
;"SignesZodiaque"
;"Debut="""
&
[zdtMartyr] &
""""
)
que nous logeons dans la source de zdtSigne.
Vérifions le résultat :
C'est correct, même si, connaissant quelqu'un qui est né à cette date, on s'attendait plutôt à « s'agiter » comme réponse…
Et enfin, dans cette syntaxe remplaçons « [zdtSigne] » par sa formule, il vient :
=
RechDom
(
"Signe"
;"SignesZodiaque"
;"Debut="""
&
MaxDom
(
"Debut"
;"SignesZodiaque"
;"Debut <="""
&
Format
(
[zdtNaissance];"mmdd"
) &
""""
) &
""""
)
… et nous pouvons supprimer zdtMartyr.
Et hop, ça marche.
On est presque au bout.
VI-B. Et s'il n'y a pas de borne inférieure ?▲
Par exemple si la date de naissance est antérieure au 21 janvier, alors :
=
RechDom
(
"Signe"
;"SignesZodiaque"
;"Debut="""
&
MaxDom
(
"Debut"
;"SignesZodiaque"
;"Debut <="""
&
Format
(
[zdtNaissance];"mmdd"
) &
""""
) &
""""
)
donnera un résultat de valeur Null, alors qu'il faudrait « Capricorne ».
Qu'à cela ne tienne, nous connaissons déjà la fonction Nz().
Nous aménageons une dernière fois, la source de zdtSigne, qui devient :
=
nz
(
RechDom
(
"Signe"
;"SignesZodiaque"
;"Debut="""
&
MaxDom
(
"Debut"
;"SignesZodiaque"
;"Debut <="""
&
Format
(
[zdtNaissance];"mmdd"
) &
""""
) &
""""
);"Capricorne"
)
Et nous y sommes !
VII. Extrapolation entre deux bornes▲
Dans ce chapitre, nous recherchons une valeur numérique dans une table.
VII-A. La demande est-elle fondée ?▲
Commençons par exprimer que le nombre entré en zdtNombre est dans les limites de la table, c'est-à-dire : supérieur ou égal au plus petit Nombre de la table et inférieur ou égal au plus grand.
>=
MinDom
(
"Nombre"
;"Observations"
) Et <=
MaxDom
(
"Nombre"
;"Observations"
)
Utilisons les propriétés Valide si et Message si erreur du contrôle zdtNombre pour installer cette fonctionnalité dans le formulaire :
VII-B. Recherche de la borne inférieure▲
Pour la source de zdtBorneInf, on s'attend à une syntaxe comme celle-ci :
=
MaxDom
(
"Nombre"
;"Observations"
;"Nombre<="
&
[zdtNombre])
Remarquez que [zdtNombre] n'est pas encadré de délimiteurs - pas de doubles-quotes ni de croisillons - puisqu'il s'agit d'une valeur numérique !
Testons :
Cela ne fonctionne pas lorsqu'on cherche la borne inférieure avec 123,45. Par contre, on la trouve avec 100.
Access s'attend à un point « . » comme symbole décimal.
Dans vos paramètres régionaux, vous avez probablement choisi la virgule « , » comme symbole pour séparer la partie entière et les décimales.
En fait, il faut chercher avec « 123.45 » et non avec « 123,45 ».
Il nous faut donc remplacer la virgule par un point dans le contenu de zdtNombre.
La fonction Replace répond a ce but.
La syntaxe est la suivante :
Replace
(
«la chaîne de caractères originale»;«il y a»;«il faut»)
Pour plus de détails sur cette fonction, consultez l'aide (<F1> et saisissez « replace fonction » dans l'onglet Aide Intuitive puis<Entrée>).
En l'occurrence, la source de zdtBorneInf devient :
=
MinDom
(
"Nombre"
;"Observations"
;"Nombre>="
&
Replace
(
[zdtNombre];","
;"."
))
VII-C. Recherche de la valeur inférieure▲
Il suffit de rechercher dans la table Observations la Valeur qui correspond au Nombre contenu dans zdtNombre. Avec la même précaution quant au symbole décimal.
La source de zdtValeurInf :
=
RechDom
(
"Valeur"
;"Observations"
;"Nombre="
&
replace
(
[zdtBorneSup];","
;"."
))
VII-D. Recherche de la borne et de la valeur supérieures▲
Procédons par analogie.
La source de zdtNombreSup :
=
MinDom
(
"Nombre"
;"Observations"
;"Nombre>="
&
Replace
(
[zdtNombre];","
;"."
))
La source de zdtValeurSup :
=
RechDom
(
"Valeur"
;"Observations"
;"Nombre="
&
replace
(
[zdtBorneSup];","
;"."
))
VII-E. Variations entre les deux bornes▲
Ici, il s'agit simplement d'opérer la différence du contenu des contrôles respectifs.
La source de zdtDeltaBorne :
=
[zdtBorneSup]-
[zdtBorneInf]
La source de zdtDeltaValeur :
=
[zdtValeurSup]-
[zdtValeurInf]
VII-F. L'extrapolation proprement dite▲
VII-F-1. Cas banal : zdtNombre se situe entre deux bornes▲
Ici aussi, il s'agit d'une opération arithmétique : à la valeur de la borne inférieure, il faut ajouter la proportion de variation :
=
[zdtValeurInf]+(
[zdtDeltaValeur]*(
[zdtNombre]-
[zdtBorneInf]))/
[zdtDeltaBorne]
VII-F-2. Cas particulier : zdtNombre est une borne▲
Dans ce cas :
En effet, [zdtDeltaBorne] est égal à zéro ce qui rend la division illégale !
Il faut donc exprimer dans la source de zdtExtrapol : si zdtDeltaBorne = 0, alors ZdtExtrapol = zdtValeurInf ; sinon calculer l'extrapolation.
Schématiquement :
VraiFaux
(<
zdtDeltaBorne =
zéro>
;<
ZdtExtrapol =
zdtValeurInf>
;<
extrapoler>
)
C'est-à-dire :
=
VraiFaux
(
[zdtDeltaBorne]=
0
;[zdtValeurInf];[zdtValeurInf]+(
[zdtDeltaValeur]*(
[zdtNombre]-
[zdtBorneInf]))/
[zdtDeltaBorne])
Et voilà :
VII-F-3. Gorgée après gorgée ou cul sec ?▲
Nous avons progressé pas à pas en détaillant chaque étape du raisonnement pour calculer l'extrapolation.
Ainsi, pour concrétiser chaque étape, nous avons créé des contrôles pour y loger les résultats intermédiaires.
S'il s'avère que ces renseignements sont inutiles pour l'utilisateur final, il suffit de cacher les contrôles en attribuant la valeur « Non » à leur propriété Visible.
Mais on peut aussi court-circuiter toutes les étapes intermédiaires.
Il va sans dire que cette source n'a pas été écrite à la volée.
En réalité, je suis parti de ceci :
=
VraiFaux
(
[zdtDeltaBorne]=
0
;[zdtValeurInf];[zdtValeurInf]+(
[zdtDeltaValeur]*(
[zdtNombre]-
[zdtBorneInf]))/
[zdtDeltaBorne])
et j'ai patiemment remplacé tous les [zdtxxxxx] autres que [zdtNombre] par leur source (sauf le signe « = » initial).
Ce n'est pas nécessairement une bonne idée car c'est illisible, je l'ai fait pour montrer « simplement » que c'est possible.
VIII. Conclusion▲
Vous avez maintenant le pied à l'étrier pour l'emploi des fonctions intégrées.
IX. Base de données▲
X. Remerciements▲
Merci à Pierre Fauconnier qui m'a guidé dans la conception de ce tutoriel.
Merci à Patrice99 , _Max_ et f-leb pour leur relecture orthographique.