Académique Documents
Professionnel Documents
Culture Documents
Cet article destin aux habitus de Microsoft Access connaissant les bases du langage VBA
et du langage SQL vous propose un moyen de mettre en place un systme de contrle des
donnes avant leur enregistrement en se basant sur un mcanisme propre quasiment
tous les SGBD mais un peu cach sous Microsoft Access.
-2-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
Si l'utilisateur tente une saisie ne correspondant pas la rgle, voici ce qu'il se passe :
Dans l'exemple, l'utilisateur tente de saisir la donne directement dans la table. N'ayez
pas peur, ce mcanisme de contrainte est aussi valable lorsque l'utilisateur opre sa saisie
depuis un formulaire ou que celle-ci est automatise par une requte ou par du code VBA.
La proprit Message si Erreur permet quant elle de dfinir le message qui sera affich si la contrainte n'est pas
respecte. Le but tant d'obtenir quelque chose de plus explicite que l'image ci-dessus. Toutefois, tant donn que
dans bien des cas, le dveloppeur gre lui-mme ces propres messages d'alerte dans son code VBA, cette proprit
dispose donc d'un intrt limit.
Malheureusement, l'efficacit de la proprit ValideSi se limite exclusivement tester la valeur de la donne saisie
par rapport une rgle de gestion basique. Ainsi, il est possible de vrifier la taille d'un texte, l'appartenance d'une
date un intervalle, la supriorit d'un nombre une constante, etc. Par contre il est impossible de faire rfrence
aux donnes dj inscrites dans la base.
Prenons l'exemple d'une table tblLimite qui dfinirait le montant maximum autoris pour la saisie des factures. Cette
rgle de gestion n'a pas vraiment de sens dans la vie relle mais permet d'noncer clairement mes propos.
-3-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
La dfinition suivante de la proprit ValideSi parat priori juste, tout du moins du point de vue du sens :
[TTCFacture]<=(SELECT Limite FROM tblLimite)
II - ADODB et CONSTRAINT
Pour passer outre la limitation de la clause ValideSi vue plus haut, il est ncessaire de construire la contrainte
manuellement l'aide d'une instruction SQL aprs la cration de la table l'aide de l'instruction suivante :
Il est plus intressant de la faire aprs la cration de la table tout simplement car cela vous
permet de bnficier auparavant des assistants pour mettre en place vos champs,vos
cls et vos index.
ALTER TABLE nom de la table
ADD CONSTRAINT nom de la contrainte
CHECK (clause de la contrainte)
Mais ce n'est pas aussi simple. Essayez de lancer cette instruction SQL depuis le gnrateur de requtes et vous
vous apercevrez qu'elle est refuse sous prtexte qu'une erreur de syntaxe serait prsente au sein de la clause
CHECK. Et pourtant, je peux vous assurer que l'instruction ci-dessus est valide.
Le problme est que le gnrateur de requte, tout comme l'assistant de cration de tables, refuse de faire rfrence
des donnes externes la saisie. Il en est de mme pour les codes VBA bass sur DAO.
La solution consiste lancer la requte de dfinition de la contrainte en utilisant un accs Jet OLE DB depuis une
connexion ADODB. Pour faire simple, ADODB est un mode d'accs aux donnes assez proche de DAO (d'un point
de vue structure) mais destin avant tout des moteurs de bases de donnes plus volus (SQL Server idalement).
Ce n'est pas le cas ici, mais toujours est-il qu'il va permettre de faire ce que l'on souhaite. Il est inutile ce stade de
savoir comment ouvrir une connexion ADODB puisque depuis Access 2000, cette connexion est accessible aisment
en VBA l'aide de la proprit :
Application.CurrentProject.Connection
-4-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
L'objet Connection retourn expose une mthode Execute permettant de lancer un ordre SQL. C'est donc cette
mthode qui sera utilise pour lancer la requte.
Il suffit donc de lancer le bloc d'instructions suivant depuis un module VBA :
Sub Contrainte()
Dim strSQL As String
strSQL = "ALTER TABLE tblFacture ADD CONSTRAINT LimiteMontant " & _
"CHECK (TTCFacture<(SELECT limite FROM tblLimite))"
Application.CurrentProject.Connection.Execute strSQL
End Sub
Si l'utilisateur tente maintenant de saisir un montant suprieur celui de la limite dfinie dans la table tblLimite, sa
saisie est refuse :
-5-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
La contrainte CHECK vrifie alors que le montant du rglement est infrieur ou gal celui de la facture. Le lien entre
la facture concerne par le rglement et l'enregistrement dans la table tblFacture est assur par la clause WHERE
idFacture=tblreglement.idFacture qui signifie :
"La ligne de la table tblFacture o l'idFacture est gal l'idFacture de la table tblReglement en cours de
modification "
IV - Contraintes calcules
Il s'agit l de la partie la plus complexe de mise en place de contraintes. Prenons comme exemple une contrainte
devant rpondre la rgle de gestion suivante :
La somme des rglements d'une facture ne doit pas tre suprieure au montant total de la facture.
Son code SQL serait :
ALTER TABLE tblReglement
ADD CONSTRAINT SommeReglementMaxi
CHECK
(
(
SELECT Sum(MontantReglement)
FROM tblReglement tblReglementCalcul
WHERE tblReglementCalcul.idFacture=tblreglement.idfacture
)
<=
(
SELECT TTCFacture
FROM tblFacture
WHERE idFacture=tblreglement.idfacture
)
)
La partie de droite est simple, il s'agit de la mme que celle vue plus haut. Elle retourne le montant TTC de la facture
correspondante au rglement.
Si celle de gauche a aussi un sens trs simple : retourner la somme des rglements pour cette facture, son
criture est plus complexe. En effet, lors de la cration ou de la modification d'un rglement, le moteur travaille sur
la table tblReglement et l'enregistrement en cours est compos de IdReglement, idFacture, MontantReglement,
DateReglement, CommentaireReglement. Rien n'indique les montants dj rgls pour cette facture cet instant.
Pour connaitre ce montant, il faut accder une nouvelle vue de la table tblReglement (comme une photocopie).
C'est sur cette vue que sera effectu le calcul. Schmatiquement, c'est comme si deux tableaux taient ouverts en
mme temps. Le stylo de la main droite est prt remplir le premier, pendant que l'oeil, aid de l'index de la main
gauche, vrifie que le montant ne dpassera pas la somme restant payer sur le second tableau. Et comme il est
-6-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
impossible d'ouvrir deux fois le mme objet avec le mme nom, SQL impose d'utiliser un alias pour le deuxime
appel, d'o l'instruction :
FROM tblReglement tblReglementCalcul
La clause :
tblReglementCalcul.idFacture=tblreglement.idfacture
Permet ainsi de faire le lien entre les deux vues en se basant sur l'idFacture.
Et puis, pourquoi pas, ne pas interdire la modification des donnes tous les lundis :
ALTER TABLE tblLimite
ADD CONSTRAINT InterditLundi
CHECK (Weekday(date())<>2=TRUE )
Comme vous le voyez, la puissance du code SQL permet de satisfaire quasiment toutes les exigences. Attention
cependant : il s'agit de code SQL Access et non de code VBA. Vous ne pouvez donc pas faire appel aux lments
propres VBA, tels que les fonctions personnalises d'un module par exemple. De plus sous Access 2007, les
champs valeurs multiples ne peuvent pas intgrer la clause CHECK.
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
Pour pouvoir supprimer une table, il est ncessaire de supprimer toutes les contraintes
s'y rattachant.
CONSTRAINT ...
n'tant pas reconnue, il est impossible de modifier le code de dfinition d'une contrainte. La solution : supprimer
et recrer.
Malheureusement, comme vous pouvez le constater l'exemple de code ci-dessus affiche qu'une contrainte n'est
pas respecte mais est incapable d'noncer laquelle. A ce stade de l'excution, bien que l'vnement OnError
du formulaire soit dclench aucune information concernant l'erreur n'a t envoye au code qui s'excute. C'est
seulement quand l'vnement OnError sera termin que la gestion d'erreur en VBA va pouvoir tre utilise via un
objet Err. L'astuce, provenant de Thierry Gasperment, consiste donc dmarrer la minuterie du formulaire dans
l'vnement OnError de telle sorte capturer l'erreur sa sortie en tentant une nouvelle fois d'enregistrer les
donnes.
Private Sub Form_Error(DataErr As Integer, Response As Integer)
Select Case DataErr
Case 3317 ' erreur de validation de containte
' Lance la minuterie
Me.TimerInterval = 1
-8-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
Le principe de cette procdure est simple. Il consiste dcouper le message d'erreur pour y rcuprer le nom de la
contrainte. Pour cela, il faut s'appuyer sur le message d'erreur d'origine dfini par la fonction AccessError. Dans ce
message d'origine, le nom de la contrainte est remplac par le paramtre " |2 ". Il suffit donc de localiser ce paramtre
dans le message d'erreur complet pass la fonction pour tre en mesure de dfinir la variable lRule qui contiendra,
ainsi, le nom de la contrainte ayant lev l'erreur.
-9-
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/
Enfin, la structure SELECT CASE permet de personnaliser le message afficher en fonction du nom de la contrainte
trouv.
IX - Conclusion
La mise en place de telles contraintes est certes un peu fastidieuse car loigne de tout assistant graphique mais
elle apporte un vritable plus en terme de cohrence et d'intgrit de vos donnes. En outre, en tant ainsi gre
directement par le moteur de base de donnes, vous avez la garantie qu'aucun programme tiers ne viendra
l'encontre des rgles de gestion que vous avez dfinies. Ceci n'est vraiment pas ngligeable quand on sait quel
point l'interconnexion des applications Office est mise en jeu dans les dveloppements professionnels.
Car si l'heure actuelle votre code VBA prsent dans vos formulaires suffit grer les contraintes que vous avez
nonces, qu'en sera-t-il demain pour un autre programme ralis par un autre prestataire qui attaquera directement
votre base de donnes ?
J'adresse un remerciement tout particulier Thierry Gasperment pour son astuce concernant la capture de l'erreur
au sein d'un formulaire.
- 10 -
Copyright 2009 Christophe Warin. Aucune reproduction, mme 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 intrts.
http://warin.developpez.com/access/contraintes/