Se positionner dans un formulaire ou un sous-formulaire
Une question revient souvent sur les forums du site : comment se positionner sur un enregistrement précis, dans un sous-formulaire ? Il a plusieurs méthodes pour résoudre ce problème, en voici une facile à réutiliser…
En fait, on va en profiter pour utiliser une méthode qui s’applique aux formulaires comme aux sous-formulaires.
Le scénario
- Je dispose d’un formulaire, sur lequel est « posé » un sous-formulaire qui donne la liste des articles, pour le flux concerné.
- Peu importent les noms du formulaire et du sous-formulaire, il ne servent pas dans la suite.
- Par contre, le container de sous-formulaire s’appelle
sfmArticles
. - Le formulaire est lié à une table
tbl Flux
dont la clef primaire est numérique. - Le sous-formulaire est lié à une table
tbl Flux Articles
dont la clef primaire est numérique également.
Je souhaite maintenant ajouter 2 boutons : l’un pour se positionner sur un flux précis, l’autre pour se positionner sur un article précis. Le positionnement se fera à partir du numéro de flux ou d’article :
- Je tape un numéro dans la zone de texte en haut à droite (
txtNumero
). - Je clique sur l’un des 2 boutons.
- Access me positionne là où il faut… ou me signale une erreur si le numéro n’est pas trouvé.
Une petite fonction pratique
Comme c’est le genre de besoin qu’on a très régulièrement dans une base Access, autant en faire une « boîte noire » réutilisable. Recopiez la fonction suivante dans un module standard de votre base de données :
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 |
' --- ' SE POSITIONNER SUR UN ENREGISTREMENT DE FORMULAIRE ' --- ' Function ChercherEnregistrement( _ frm As Access.Form, _ strCritere As String) _ As Boolean ' Variables Dim rst As dao.Recordset Dim blnResultat As Boolean ' Le Recordset Set rst = frm.Recordset ' Chercher l'enregistrement blnResultat = False rst.FindFirst strCritere If Not rst.NoMatch Then frm.Bookmark = rst.Bookmark blnResultat = True End If ' Libérer les objets Set rst = Nothing ChercherEnregistrement = blnResultat End Function |
La fonction reçoit 2 paramètres :
- L’objet Formulaire (ou Sous-formulaire) dans lequel on souhaite se positionner.
- Le critère permettant de trouver l’enregistrement.
Elle renvoie True
si le positionnement a pu se faire, et False
si on n’a pas trouvé l’enregistrement.
Pour info, le principe consiste à récupérer le jeu d’enregistrements (Recordset
) qui alimente le formulaire, et à y déclencher une recherche (FindFirst
). Si on trouve un enregistrement, on fait en sorte que le signet (Bookmark
) de l’enregistrement trouvé soit appliqué au formulaire. Ce qui équivaut à « déplacer » le formulaire sur le signet en question…
Se positionner dans le formulaire
En guise d’application, on va s’occuper du bouton Atteindre le flux.
- Faites apparaître les propriétés de ce bouton.
- Donnez-lui un nom (dans mon cas :
btnAfficherFlux
). - Activez l’onglet Evénement de la fenêtre Propriétés.
- Définissez l’événement
Sur clic
comme ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Private Sub btnAfficherFlux_Click() Dim strCritere As String ' Petite vérification If Not IsNumeric(Me.txtNumero) Then MsgBox "La valeur cherchée doit être numérique !", vbExclamation Exit Sub End If ' Le critère strCritere = "[Numéro Flux] = " & Me.txtNumero ' Recherche de l'enregistrement If Not ChercherEnregistrement(Me, strCritere) Then MsgBox "Flux introuvable !", vbExclamation End If End Sub |
Le code fait ceci :
- On vérifie que la zone de saisie contient bien un nombre (rappelez-vous que les numéros de flux et d’articles sont… des nombres dans ce scénario).
- On constitue ensuite le critère de recherche.
- Enfin et surtout, on appelle la fonction
ChercherEnregistrement()
écrite plus haut en lui passant : le formulaire en cours (Me
), et le critère. - Si la fonction renvoie
False
, on affiche un message d’erreur.
Se positionner dans le sous-formulaire
La bonne nouvelle, c’est que la technique s’applique aussi aux sous-formulaires. Seul l’objet Formulaire change. Voici donc le code du bouton Atteindre l’article :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Private Sub btnAfficherArticle_Click() Dim strCritere As String ' Petite vérification If Not IsNumeric(Me.txtNumero) Then MsgBox "La valeur cherchée doit être numérique !", vbExclamation Exit Sub End If ' Le critère strCritere = "[Numéro Article] = " & Me.txtNumero ' Recherche de l'enregistrement If Not ChercherEnregistrement(Me.sfmArticles.Form, strCritere) Then MsgBox "Article introuvable !", vbExclamation End If End Sub |
L’objet Sous-formulaire est obtenu par Me.sfmArticles.Form
. Et c’est tout !
Pour plus de détails sur cette syntaxe, consultez l’article Sous-formulaires : une mise au point.
Merci pour ce didacticiel !!… Quelle joie de voir son application fonctionner !
Merci pour le retour. C’est aussi une joie de voir que ça peut dépanner ! 🙂
Bonjour,
J’espérais avoir trouvé une solution à mon problème (décrit ci dessous), mais il me renvoi une erreur dans la fonction :
run-time error ‘3070’
le moteur Jet ne reconnait pas ‘EE000004’ (ceci est bien la valeur à trouver) comme nom de champ valide ou expression !!!
et il bloque sur la ligne rst.FindFirst srtCritere
toute aide qui me permettrait de pouvoir me positionner sur l’enregistrement souhaité serait la bien venue.
Merci
Dans un application, j’ai un formulaire continu qui contient pas mal de ligne, les utilisateurs ne peuvent pas modifier directement dans ce formulaire, il passent par un petit form popup qui s’ouvre avec un double click sur le champ a modifier.
Sur clic d’un bouton dans le popup le champ à modifier dans mon formulaire (d’origine) se met à jour sans problème grâce au ‘requery’ le problème est que requery ‘rafraichi’ tout le formulaire et renvoi le focus sur le premier champ de la première ligne; c’est gênant pour l’utilisateur qui modifie la 1418 éme ligne et qui après modif est bon pour retrouver sa ligne si il a d’autre chose à y modifier.
Bref je cherche un moyen pour remettre le focus idéalement sur le champ sur lequel il a fait un double clic ou au pire sur la ligne concernée.
Je pensais à un truc du genre gotorecord … mais je vois pas trop.
Tu dois avoir une erreur dans ton expression de critère. Quelle est ta ligne
strCritere = ...
?lune212 > Ta méthode pour alimenter la variable
strCritere
(ou ta variableparam
) est incorrecte : tu passes la valeur de formulaire uniquement, alors qu’il faudrait passes un filtre SQL valide.Tu peux t’inspirer de mon exemple, en regardant comment est construite
strCritere
dans le blocbtnAfficherArticle_Click
.Bonjour j ai utlisé ton code mais j’ai une erreur (argument non valide) et le débugger s’arrete à rst.FindFirst strCriter…je ne comprends pas … à l’aide svp
Function ChercherEnregistrement(frm As Access.Form, strCritere As String) As Boolean
‘——————————————————–
‘ Variables
Dim rst As dao.Recordset
Dim blnResultat As Boolean
‘Le Recordset
Set rst = frm.Recordset
‘Chercher l ‘enregistrement
blnResultat = False
MsgBox strCritere
rst.FindFirst strCritere
‘Si recherche réussie la valeur de NoMatch est à False
If Not rst.NoMatch Then
frm.Bookmark = rst.Bookmark
blnResultat = True
End If
‘Libérer les objets
Set rst = Nothing
ChercherEnregistrement = blnResultat
End Function
Private Sub recherche_affaire_Click()
Dim param As String
‘ Vérifier si la valeur est numérique
If Not IsNumeric(Me.rechercher_affaire) Then
MsgBox « La valeur cherchée doit être numérique ! », vbExclamation
Exit Sub
End If
param = Form![rechercher_affaire]
If Not ChercherEnregistrement(Me, param) Then
MsgBox « Numéro d’affaire introuvable ! », vbExclamation
End If
End Sub
sara > L’article est en ligne, c’est à cette adresse. Ouala !
OK Merci énormément HERVE Inisan 🙂
sara > J’ai prévu un article d’ici quelques jours. A suivre… 🙂
Oui pourquoi par le changement de couleur de la ligne rechercher pour d’être plus visible, donc comment je peut le faire ?
Merci Hervé 🙂
sara > Le clignotement n’est peut-être pas une bonne idée (vite fatiguant). Mais un changement de couleur de la ligne, par exemple (par mise en forme conditionnelle).
Bonjour Hervé,
Merci beaucoup, effectivement, c’est une solution interessante…
Mais je veux savoir est ce que possible quand il positionne sur un enregistrement précis la ligne de l’enregistrement commance à clignoter d’une couleur précis pour d’être visible. Je voudrais savoir s’il est possible de leur réaliser?
Soso > Faire un formulaire de recherche très générique n’est pas forcément facile, parce que la recherche dépend des noms de tables, des noms de champs, des types de données, etc. S’il s’agit de retrouver un enregistrement précis, peut-être qu’une liste déroulante de recherche peut convenir ?
Bonjour,
Bravo pour ce site, il est vraiment très clair!!
Voilà, j’ai plusieurs formulaires et je veux faire un formulaire de recherche avec deux champs : Nom du formulaire et N° de la page qui est AutoNumérique. L’objectif de ce formulaire de recherche est de pouvoir donner la possibilité de remplir les champs manquants qui n’ont pas pu être compléter lors d’une précédente saisie.
Je m’explique : J’ouvre mon formulaire puis je remplis les champs et je valide. Cette opération je la renouvèle régulièrement, ce qui fait que j’aurai plusieurs enregistrements. Par contre, il peut arriver un jour où je ne remplis pas la totalité des champs pour que je les remplisse une prochaine fois. Après quelques enregistrements, je décide de retourner à l’enregistrement incomplet. Donc, grâce à mon formulaire de recherche, je peux retrouver l’enregistrement très facilement et pouvoir le compléter. C’est valable pour tous les formulaires que j’ai. J’espère avoir été clair. Je voudrais savoir s’il est possible de leur réaliser?
Je vous remercie pour votre réponse.
Soso
saved68 > Pour la 2ème question : il est possible de masquer certains champs dans la partie « Liste » (ou « Feuille de données ») du formulaire double-affichage. Il suffit de faire un clic droit sur le champ, et de choisir Masquer. Ça permet de limiter le nombre d’informations dans cette liste.
Pour la 1ère question, concernant les classes : pour n’avoir que les élèves d’une classe, il faut filtrer le formulaire sur la classe en question. Ça peut se faire soit de façon interactive (sélection de la classe sur le formulaire normal, clic droit, filtre), ou avec un peu de VBA (filtrage par liste déroulante).
Ouala !
Merci beaucoup, effectivement, c’est une solution interessante… mais…
Mais, j’aurai aimé que sur ce formulaire n’apparaisse que les élèves de la classe dans laquelle l’élève sur le formulaire apparait… cela ne semble possible qu’en triant la table…
De plus, dans ce formulaire, j’ai aussi le nom des parents dans un autre onglet, et dans un troisième onglet, les éventuels suivis. Dès que je clique sur un des onglets, la table se déplace, pour afficher les informations, alors que je ne voudrais que n’apparaisse que le nom des élèves…. suis je trop gourmande?
merci pour tes infos en tous les cas!
savec
saved68 > Oui. Il suffit :
Affichage par défaut = Formulaire double affichage
.C’est tout !
On peut si nécessaire régler le double affichage par les autres options qui parlent de « double affichage », dans le même onglet de propriétés. Pratique, non ? 🙂
je possède access 2010… et c’est possible de le faire automatiquement??……
saved68 > Tu as quelle version d’Access ? A partir d’Access 2007, il y a une fonctionnalité qui fait ça automatiquement… 🙂
Bonjour,
Bravo pour ce site, il est vraiment très clair!!
Mais…. je pense avoir trouver une partie de la réponse, mais je n’en suis pas sure!
Voilà, j’ai un formulaire avec les fiches de mes élèves. dans ce formulaire, j’ai mis un sous formulaire qui affiche tous les élèves de la classe, d’un élève afficher dans le formulaire.
Je voudrais savoir s’il est possible, quand je selectionne un autre élève de la classe (qui se trouve dans le sous formulaire) de voir sa fiche s’afficher? (j’espère etre assez claire….)
Je vous remercie pour votre réponse
saved
C’est tout à fait ça! Je n’étais en effet pas sur la bonne piste. Il s’agissait bien de filtrer mon sous-formulaire et non pas d’atteindre un enregistrement spécifique de mon sous-formulaire.
J’ai donc trouvé la solution à mon problème sur le site web suivant: http://www.pcastuces.com/pratique/w…
Voici les lignes de codes qui m’ont permit de mettre en place le filtre:
strFiltre = « [dligne_date] BETWEEN » & dtmPremierJourDuMois & » AND » & dtmDernierJourDuMois
Me.Filter = strFiltre
Me.FilterOn = True
Merci d’avoir pris en compte ma demande
Lucas > A priori, dans ton cas, il ne s’agit pas d’atteindre une ligne du sous-formulaire, mais plutôt de filtrer le sous-formulaire sur un critère. Est-ce que c’est bien ça ?
Sinon, en passant : j’éviterais les enchaînements de conversion sur la date : date => chaîne => numérique. On peut extraire directement le mois (numérique) d’une date, sans passer par la chaîne. La fonction
Month()
est ton amie. 🙂Bonjour Hervé,
Ce scénario de positionnement dans un sous-formulaire se rapproche beaucoup de ce que je souhaite réaliser dans mon propre projet, seulement voilà mon projet comporte une différence de taille qui ne me permet pas de mettre en œuvre ce positionnement. Je m’explique:
•Je dispose d’un formulaire «frmSaisieJournaliereDetaillee», sur lequel est « posé » un sous-formulaire «sfrmSaisieJournaliereDetaillee_InsertionDate» qui donne la liste des jours travaillées (sous forme de date jj/mm/aaaa), pour un employé concerné.
•Le formulaire est lié à une table «dentete» qui contient uniquement le nom des employés (ce sont les clefs primaires).
•Le sous-formulaire est lié à une table «dligne» qui contient également le nom des employés et les dates travaillées pour chaque employés (ce sont tous 2 des clefs primaires).
-A l’aide des flèches de navigation, je peux sélectionner un à un les différents employés dont le nom s’affiche dans une zone de texte de mon formulaire. En fonction de l’employé sélectionné, ses dates travaillées s’affichent alors dans le sous-formulaire en colonne les unes à la suite des autres avec la possibilité pour l’employé de saisir de nouvelles dates à la suite de la dernière date affichée.
C’est là que se trouve la faille de mon projet. Pour l’instant les employés n’ont rentrés que les jours travaillés du mois de Juillet, mais arrivé au mois de Décembre il y aura déjà 184 jours (moins les weekends et jours fériés) d’affiché, et je vous laisse imaginer le nombre de jours qui s’afficheront dans 5 ans…
Mon idée aurait donc été de rajouter une zone de texte ou une liste déroulante dans le sous-formulaire (ou le formulaire à voir…) qui contiendrait tous les mois de l’année. Ainsi, j’aurai la possibilité de n’afficher que les dates travaillées correspondant au mois sélectionné (suivra ensuite une liste déroulante des différentes années pour sélectionner la bonne année =] ).
Seulement voilà, comme je le disais, à la différence de ce qui est présenté dans l’article, mes tables sont bien liés entre elles par le nom des employés ce qui me permet de rechercher les dates travaillées pour un employés donné mais je n’ai pas la possibilité de rechercher les dates correspondant à un mois donné… 🙁
La question est donc de savoir s’il existe un moyen (autre que de modifier toute la structure de ma base de donnée et de mes relations entre chaque table) pour effectuer cette recherche et s’il est possible d’extraire uniquement les dates de ma table «dligne» correspondant au mois sélectionné?
Dites oui! Dites oui!!! 🙂 🙂 🙂
PS: Le fait de récupérer le mois sous forme de string puis de le transformer en numérique [ex: « Juillet » -> 04] puis de rechercher dans le Recordset toutes les dates qui sont de la forme jj/04/aaaa et enfin de les afficher est une des solutions à laquelle j’ai pensé mais je ne sais pas du tout si cela pourrait marcher et comment la mettre en place n’étant pas du tout à l’aise avec les Recordset… =]
Merci du fond du coeur pour avoir eu le courage de lire mon « commentaire/roman » et pour peut-être réussir à trouver une solution à mon problème.
Lucas
vanillie > La plupart des articles est déjà applicable à Access 2010. En fait, pour chaque article, les tags (en haut d’article) donnent les versions concernées. En général de 97 à 2010.
Les captures d’écran de cet article sont d’ailleurs faites sous Access 2010.
Bonjour
Allez-vous adapter ce site pour access 2010?