Valider un champ de saisie
Comment contrôler la saisie d’un champ en VBA, et faire en sorte que l’utilisateur reste sur ce champ si sa saisie est incorrecte ?
(si vous débutez sur Access, cet article sera l’occasion de tester les événementsBeforeUpdate
qui font partie des plus importants…)
Avant de commencer…
Il y a plein de manières de contrôler qu’une saisie est correcte ; cet article concerne uniquement la validation au niveau Formulaires. Rappelons que, comme toujours dans Access, plus vous intervenez tôt, mieux ça vaut ! Ce qui veut dire que vous devriez déjà avoir défini des contraintes dans vos tables. En vrac :
- vos tables ont toutes une clef primaire (ce qui est une contrainte en soi) ;
- les champs obligatoires sont marqués
Null interdit = Oui
(et sans douteChaîne vide autorisée = Non
) ; - les champs qui doivent suivre des règles particulières ont leurs propriétés
Valide si
etMessage si erreur
de renseignées ; - idem pour les tables, si des règles particulières doivent comparer plusieurs champs ;
- les champs dont les valeurs doivent être uniques (hors clef primaire) ont un index sans doublons ;
- …
Dans cet article, je suppose que tout ça est déjà en place. On va surtout s’intéresser à la validation d’un champ unique, au niveau du formulaire, qui complète ce qui précède en permettant :
- d’effectuer des validations plus complexes que de simples comparaisons ;
- d’afficher des messages personnalisés ;
- de bien gérer le comportement de l’interface en fonction des erreurs (doit-on rester sur le champ ? doit-on ouvrir un autre formulaire ? etc.)
On reprend !
Le scénario est donc le suivant :
- Vous avez un formulaire quelconque.
- L’un des champs de saisie s’appelle
txtValeur
, et doit recevoir une valeur entre 0 et 100. - Si l’utilisateur tape une valeur incorrecte, il doit rester sur ce champ
txtValeur
, et ne pas pouvoir se déplacer ailleurs.
Mise en place
- Ouvrez votre formulaire en mode Création.
- Faites apparaître les propriétés du champ (clic du bouton droit, puis Propriétés).
- Activez l’onglet Evénement.
- Cliquez dans l’événement appelé
Avant MAJ
. Une liste déroulante apparaît : sélectionnez[Procédure événementielle]
. - Cliquez ensuite sur les points de suspension à droite de l’événement. Vous accédez à l’événement Visual Basic.
- Recopiez le code ci-dessous, pour l’exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Private Sub txtValeur_BeforeUpdate(Cancel As Integer) If Not IsNumeric(Me.txtValeur) Then ' Si la valeur saisie est numérique, ' on affiche donc un message d'avertissement MsgBox "Vous devez taper une valeur numérique !", _ vbExclamation ' Annuler la suite des opérations Cancel = True ElseIf Me.txtValeur > 100 Then ' Si la valeur saisie est supérieure à 100, ' on affiche également un message d'avertissement MsgBox "Les valeurs supérieures à 100 ne sont pas autorisées !", _ vbExclamation ' Annuler la suite des opérations Cancel = True End If End Sub |
Le premier test vérifie si la saisie est bien numérique, et le second vérifie qu’on ne dépasse pas 100… Pour tester :
- Passez en mode Formulaire.
- Tapez un texte ou un nombre dans le champ.
- Essayez de changer de champ.
Comment ça marche ?
- Quand l’utilisateur sort du champ, la nouvelle saisie doit être validée. Avant qu’elle ne soit transférée définitivement dans le champ, Access – VBA en fait – déclenche l’événement
BeforeUpdate
(Avant Mise à jour). - Access transmet à l’événement une variable
Cancel
, préréglée surFalse
(Annuler = Faux
; traduire par : « ne pas interrompre la suite des événements »).
Pour l’anecdote, cette variable est passée par référence. En d’autres termes : si vous la modifiez dans votre code, c’est l’original transmis par Access qui est modifié (et c’est là l’intérêt de la chose !). - Une fois que tout le code VBA placé dans
BeforeUpdate
est terminé, Access reprend la main et récupère la variableCancel
.
Si celle-ci a gardé sa valeurFalse
, la suite des opérations continue (ce qui veut dire : transférer la saisie dans le champ).
Par contre, siCancel
vautTrue
(Annuler = Vrai
), le train d’opérations s’arrête (le champ reste invalidé, et aucun déplacement n’est autorisé).
Et pour ceux qui préfèrent les schémas avec plein de couleurs et de flèches dans tous les sens 🙂 :
Cancel
est-il de type Integer, et pas Boolean ?Pour chipoter, c’est vrai qu’une valeur
True/False
devrait être booléenne. L’Integer qui traîne ici est un héritage des vieilles versions d’Access 🙂 …Et si on écrivait autrement ?
Quand on débute, on est souvent tenté d’écrire cette variante, où les Cancel = True
ont été remplacés par des Exit Sub
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Private Sub txtValeur_BeforeUpdate(Cancel As Integer) If Not IsNumeric(Me.txtValeur) Then ' Si la valeur saisie est numérique, ' on affiche donc un message d'avertissement MsgBox "Vous devez taper une valeur numérique !", _ vbExclamation ' Pas bon : Exit Sub ElseIf Me.txtValeur > 100 Then ' Si la valeur saisie est supérieure à 100, ' on affiche également un message d'avertissement MsgBox "Les valeurs supérieures à 100 ne sont pas autorisées !", _ vbExclamation ' Pas bon : Exit Sub End If End Sub |
Si vous avez suivi, les Exit Sub
forcent la sortie du bloc de code, mais ne modifient pas la variable Cancel
, qui vaut donc toujours False
. Par conséquent, la suite standard des opérations s’enchaîne : le champ est validé et on passe au champ suivant. Et ce n’est pas du tout ce qu’on souhaite ici !
Rien n’empêche par contre d’écrire ce qui suit, qui est une combinaison des 2, et qui allègera le code si vous avez beaucoup de tests à faire. Dans ce bout de code, on force une sortie à chaque fois qu’une condition n’est pas respectée (tout en modifiant l’état de la variable Cancel
bien sûr).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Private Sub txtValeur_BeforeUpdate(Cancel As Integer) If Not IsNumeric(Me.txtValeur) Then ' Si la valeur saisie est numérique, ' on affiche donc un message d'avertissement MsgBox "Vous devez taper une valeur numérique !", _ vbExclamation ' Annuler la suite des opérations Cancel = True Exit Sub End If If Me.txtValeur > 100 Then ' Si la valeur saisie est supérieure à 100, ' on affiche également un message d'avertissement MsgBox "Les valeurs supérieures à 100 ne sont pas autorisées !", _ vbExclamation ' Annuler la suite des opérations Cancel = True Exit Sub End If ' D'autres tests ici... End Sub |
Défauts de cette approche
Cette approche de validation peut servir dans de nombreux cas, mais elle a quand même un défaut majeur, à bien prendre en compte : la validation n’est déclenchée que si :
- l’utilisateur passe sur le champ ;
- l’utilisateur effectue une mise à jour du champ.
Ce qui est logique : l’événement BeforeUpdate
n’a pas de raison d’être déclenché… s’il n’y a pas eu mise à jour du champ !
Et pour contrôler plusieurs champs ?
Le formulaire lui-même
dispose d’un événement Avant MAJ
. Celui-ci est déclenché avant que tous les champs ne soient transférés dans la base. C’est d’ailleurs un meilleur endroit pour programmer ce type de validation parce que :
- L’événement se produit systématiquement dès qu’il y a eu modification des données (peu importe le champ modifié).
- Il vaut mieux avoir un traitement global et centralisé des erreurs de saisie, plutôt que des bouts de code attachés à chaque champ.
- L’ergonomie est meilleure pour l’utilisateur, parce qu’il reçoit un message seulement en fin de validation, et non pas à chaque déplacement.
bonjour
Je veux construire une BDD avec un champ dans une table qui s’intitule date et cette date doit être de moins de 5 ans au moment ou je la rentre dedans
je n’arrive pas à faire ma contrainte
merci de votre aide
Il s’agit de 5 ans avant la date du jour, systématiquement ? (donc 5 années glissantes ?)
bonjour et merci
je veut une methode pour videz le champ si la saisie n est pas valide
j’essai de faire champ= » » apres le cancel et aussi avant le cancel ds le sub l’evenement avant maj mais tjs rien a passe
Ceci devrait marcher, dans l’événement « Après MAJ » :
bonjour oui ça c’est fait avant mais le problème comment reste dans le champ sans sortir au champ suivant
pas de solutrion je pense
un autre question svp porquoi le end sub malgre le cancel fait son role je pense quand on a deux condition a teste ness pas ??????
C’est expliqué dans l’article : le Cancel n’arrête pas l’exécution en lui-même (on ne fait que renseigner une variable). Donc si on veut sortir de la procédure avant la fin, on a besoin du
Exit Sub
.En fait, c’est l’un ou l’autre des choix :
merciiiiiiiiiiiiiiiiiiiiiii pour l’explication
pierre > En allant à l’essentiel, il faut déjà tester les paragraphes « On reprend ! » et « Mise en place« . Si ces 2 points fonctionnent, la partie technique est ok, c’est déjà un bon point.
Le reste n’est que du clapotis 🙂 (des explications détaillées sur quelque chose qui n’est pas si simple effectivement, et qui se comprend mieux avec une petite expérience de VBA).
rien compris !!!!