Plusieurs valeurs dans OpenArgs
Comment transmettre plusieurs arguments d’ouverture (
OpenArgs
) dans les commandesOpenForm
etOpenReport
?
Principe
OpenArgs
est le dernier argument de la commande OpenForm
et, pour les versions récentes d’Access, de la commande OpenReport
. OpenArgs
permet de passer des informations quelconques au formulaire ou à l’état qu’on est en train d’ouvrir. Le formulaire/l’état peut ensuite faire ce qu’il veut de ces OpenArgs
(c’est vous qui voyez !).
Exemple :
1 |
DoCmd.OpenForm "frm Personnes", acNormal, ,, ,, "Inisan" |
Dans le formulaire d’arrivée (frm Personnes
), la valeur « Inisan
» est récupérée par :
1 2 |
Dim strNom As String strNom = Nz(Me.OpenArgs, "") |
Le problème d’OpenArgs
est qu’on ne peut transmettre qu’une seule valeur chaîne. Comment transmettre dans ce cas plusieurs valeurs ?
Première solution
Une première approche consiste à transmettre les différents arguments en les séparant par un délimiteur quelconque (un caractère non utilisé en général). Par exemple, pour transmettre un nom, un prénom et un score :
1 |
DoCmd.OpenForm "frm Personnes", acNormal, ,,,, "Inisan;Hervé;200" |
Du côté du formulaire ou de l’état final, il faut ensuite séparer les valeurs en se repérant sur le délimiteur. La fonction Split()
est votre amie pour cela. Du style :
1 2 3 4 5 |
Dim varValeurs As Variant varValeurs = Split(Me.OpenArgs, ";") Debug.Print "Valeur1 = " & varValeurs(0) Debug.Print "Valeur2 = " & varValeurs(1) Debug.Print "Valeur3 = " & varValeurs(2) |
Cette gestion peut convenir dans certains cas. Mais j’y verrais quelques problèmes :
- Les arguments ne sont pas identifiés clairement. C’est seulement l’ordre qui les différencie. Dans mon exemple, le nom est toujours supposé être avant le prénom, et avant le score. Vous devez par conséquent toujours savoir que la valeur 1 est le prénom. Ou définir des constantes pour éviter cela.
- Les arguments doivent toujours être fournis dans l’ordre, pour la même raison.
Deuxième solution
Voici une variante, qui consiste à passer les paramètres d’une manière inspirée de XML. C’est un peu plus lourd, mais :
- Les arguments sont identifiés par un nom, donc plus faciles à maintenir.
- Ils peuvent être fournis dans le désordre.
- Le système est extensible.
1 2 |
DoCmd.OpenForm "frm Personnes", acNormal, ,, ,, _ "<nom>Inisan</nom><prénom>Hervé</prénom><score>200</score>" |
Bien sûr, on ne vas pas s’emm…bêter à chaque fois à formater les arguments avant d’appeler OpenForm
, et à les retranscrire dans l’autre sens pour les exploiter. Voici 2 fonctions qui vont nous simplifier la tâche (à recopier dans un module standard, vous commencez à être habitués :-)).
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
' --- ' AJOUT D'UN ARGUMENT OPENARG ' --- ' Function ArgSet( _ ByRef strArgs As String, _ ByVal strArgName As String, _ ByVal varArgValue As Variant) As String Dim strTemp As String strTemp = StringFormat("<{0}>{1}</{0}>", _ strArgName, varArgValue) strArgs = strArgs & strTemp ArgSet = strTemp End Function ' --- ' LECTURE D'UN ARGUMENT OPENARG ' --- ' Function ArgGet( _ ByVal strArgs As String, _ ByVal strArgName As String) As String Dim regexp As VBScript_RegExp_55.regexp Dim mc As VBScript_RegExp_55.MatchCollection Dim m As VBScript_RegExp_55.Match Dim strResult As String ' RegExp pour lire l'argument de la forme <arg>xyz</arg> Set regexp = New VBScript_RegExp_55.regexp regexp.IgnoreCase = True regexp.Pattern = "<(" & strArgName & ")>(.*)</\1>" ' Extraction de la valeur strResult = "" Set mc = regexp.Execute(strArgs) If mc.Count > 0 Then Set m = mc(0) strResult = m.SubMatches(1) End If ' Valeur de retour ArgGet = strResult End Function |
Pour que les fonctions ci-dessus fonctionnent, vous devez…
- Relier la bibliothèque d’expressions rationnelles VBScript à votre projet. Oui, je sais, on pourrait faire sans, mais le code est bien plus compact avec ! 😉
- Intégrer également la fonction
StringFormat()
à votre projet (voir cette page du blog).
VBA ne gère pas nativement les expressions rationnelles, vous devez donc ajouter à votre projet la bibliothèque qui le fait :
- Démarrez VBE (Visual Basic Editor).
- Cliquez sur le menu Outils / Références.
- Dans la liste des références, cochez Microsoft VBScript Regular Expressions (5.5, à ce jour).
Exemple
La première fonction – ArgSet
() – ajoute un argument et sa valeur, formatés, à une chaîne de caractères destinée à servir d’OpenArgs
. Vous l’utilisez comme ceci, avant d’ouvrir votre formulaire ou état :
1 2 3 4 5 6 |
Dim strArgs As String ArgSet strArgs, "Nom", "Inisan" ArgSet strArgs, "Prénom", "Hervé" ArgSet strArgs, "Score", 200 DoCmd.OpenForm "frm Personnes", acNormal, ,, ,, strArgs |
Ensuite, dans le formulaire ou l’état cible, vous pouvez extraire les arguments par leur nom, grâce à la fonction inverse, ArgGet()
:
1 2 3 4 5 6 7 8 9 |
Dim strArgs As String Dim strNom As String Dim strPrenom As String Dim intScore As Integer strArgs = Nz(Me.OpenArgs, "") strNom = ArgGet(strArgs, "Nom") strPrenom = ArgGet(strArgs, "prénom") intScore = Val(ArgGet(strArgs, "Score")) |
J’ai finnalement trouvé l’erreur:
il faut corriger la ligne 34 :
soit regexp.Pattern = « (.*) »
par regexp.Pattern = « (.*) »
Merci pour le retour ! Effectivement, suite à la migration du site, des \ ont disparu dans certains bouts de code. La RegEx est la suivante :
J’ai également corrigé dans l’article.
Bonjour
J’ai tester votre exemple et cela ne fonctionne pas (aucune erreur mais également aucune valeur correspondante n’est trouvé à l’appel de ArgGet).. Il semble y avoir une erreur sur l’expression suivante :
regexp.Pattern = « (.*) »
Note : j’ai access 2013 (pourrait-il y avoir une nouveauté qui ferait en sorte que cela ne fonctionne plus ?)
Merci
Frere Marc > Oui, la démarche est applicable aux formulaires.
OpenArgs
a existé d’ailleurs dans les formulaires avant d’être implanté dans les états. Normalement, on doit pouvoir aussi récupérer les infos dans unForm_Current
.Dans la question, il manque un « s » à
Me.OpenArgs
. Ça pourrait venir de là ?Cette démarche est-elle applicable aussi au formulaire ? Lorsque je tente de récupérer la valeur « me.OpenArg », celle-ci est null, or on devrait me semble-t-il « récupérer » après l’ouverture du formulaire (par OpenForm) mais pas nécessairement à l’ouverture du formulaire en question mais aussi en instance(form_Current) ?! Sinon excellente démarche. Cela pour éviter l’utilisation d’une variable publique
merci pour l’astuce 🙂
osiman > Ça marche effectivement aussi avec des variables publiques.
Le problème des variables publiques (quand il commence a y en avoir beaucoup) est que leur gestion n’est pas « super-propre » : il faut les organiser de façon rigoureuse, penser à les initialiser avant leur utilisation, toujours considérer qu’elles peuvent potentiellement avoir été modifiées par différentes procédures/fonctions.
Et se servir d’une variable publique comme « messager » d’une valeur pour un traitement ultérieur est un peu artificiel : l’idéal est que le message soit directement transmis à son destinataire (d’où
OpenArgs
).Pour toutes ces raisons, on conseille souvent d’éviter, si possible bien sûr, les variables publiques. Ça permet de cloisonner les blocs d’application, et de mieux en gérer la maintenance.
Bonjour,
à la place d’openargs j’ai l’habitude de renseigner une variable publique que je récupére ensuite dans le form ou report ouvert.
quel est l’avantage d’openargs ?