FAQ MS-Access
FAQ MS-AccessConsultez toutes les FAQ
Nombre d'auteurs : 140, nombre de questions : 926, dernière mise à jour : 15 juin 2021
- Comment afficher une table ou une requête dans un contrôle Sous-formulaire sans créer de nouveau formulaire ?
- Comment ne pas enregistrer les données des contrôles d'un formulaire avant validation par l'utilisateur ?
- Comme faire pour que le survol du bouton Commande0 fasse apparaître le bouton Commande1 et que, si on repasse sur Commande0, le bouton Commande1 disparaisse à nouveau ?
- Comment centrer un formulaire ?
- Comment savoir si un contrôle existe dans un formulaire ?
- Comment faire défiler un texte dans un formulaire ?
- Comment empêcher la navigation entre formulaires via la barre des tâches ?
- Comment faire passer un formulaire ouvert en mode acDialog en arrière-plan ?
- Comment créer dynamiquement un formulaire ?
- Comment insérer une ligne blanche (enregistrement vide) dans un sous-formulaire affiché en mode feuille de données ?
- Comment passer en mode Edit dans un champ dont le format est différent du masque de saisie ?
- Comment savoir si nouvel enregistrement ou enregistrement modifié ?
- Comment positionner le curseur à gauche du champ ou sélectionner le contenu du champ ?
- Comment déterminer la position d'un formulaire à l'écran ?
- Comment vérifier à la sortie d'une InputBox que le type de donnée rentrée est bien du numérique ?
- Comment masquer un sous-formulaire vide ?
- Comment empêcher l'utilisateur de cliquer à l'extérieur du formulaire (comme pour une MsgBox) ?
- Comment enlever les boutons de navigation d'un formulaire en VBA ?
- Comment utiliser la saisie semi-automatique dans les contrôles de mes formulaires ?
- Dans un formulaire en mode continu, comment rendre invisible un bouton pour certaines lignes ?
- Comment "zoomer" sur le contenu d'un contrôle de type texte ?
- Pourquoi le temps d'ouverture de mes formulaires à onglets est-il trop important ?
- Comment transmettre le nom du formulaire appelant à l'ouverture d'un formulaire ?
- Complément au tutoriel de recherche multicritère de cafeine : comment enregistrer dans une requête le résultat de la recherche multicritère ?
- Comment créer dynamiquement des contrôles de type Rectangle sur le formulaire en cours ?
- Comment faire repartir un GIF qui a cessé de s'animer ?
- Comment ne pas ouvrir un formulaire si celui est vide ?
- Comment éviter l'erreur d'un paramètre non reconnu pour un graphique basé sur une requête paramétrée ?
- Comment compter le nombre d'enregistrements d'un sous-formulaire ?
- Comment savoir si les contrôles ont été remplis dans un formulaire ?
Une astuce pour créer un sous-formulaire de façon classique :
- mettez votre formulaire en mode création ;
- affichez votre fenêtre de base de données à côté de votre formulaire ;
- affichez la liste des requêtes ;
- faites un cliquer-glisser de l'icône de votre requête dans votre formulaire.
=> Cette méthode crée un nouveau formulaire qui s'insère dans le contrôle sous-formulaire...
=> Voici comment faire pour ne pas créer de nouveau formulaire :
- dans votre formulaire principal, créez un contrôle sous-formulaire/sous-état (sans assistant si possible) ;
- dans les propriétés de cet objet, allez dans l'onglet Données ;
- dans la propriété Objet Source, choisissez votre requête ou votre table.
Il faut mettre ce code dans l'événement Avant MAJ du formulaire ou du contrôle concerné :
If
MsgBox
(
"Valider la mise à jour ?"
, vbOKCancel
) =
vbCancel
Then
MsgBox
"L'opération de mise à jour a été annulée"
, vbInformation
Cancel =
true
' annule l'opération
Exit
Sub
And
If
Exit Sub permet de sortir de la procédure en cours c'est-à-dire celle de la mise à jour.
Option
Compare Database
Option
Explicit
Private
AModifier As
Boolean
Private
Sub
Commande0_MouseMove
(
Button As
Integer
, Shift As
Integer
, X As
Single
, Y As
Single
)
If
AModifier Then
AModifier =
False
Commande1.Visible
=
Not
Commande1.Visible
Else
'rien à faire
End
If
End
Sub
Private
Sub
Détail_MouseMove
(
Button As
Integer
, Shift As
Integer
, X As
Single
, Y As
Single
)
AModifier =
True
End
Sub
AModifier est une variable qui va servir de tampon.
En effet, la procédure MouseMove se produit tant que la souris se déplace sur le contrôle Commande0.
Donc, il faut réussir à éviter que la procédure se reproduise tant que ta souris n'est pas sortie du bouton.
Donc, il faut que, lors de la première exécution, on lui signale qu'il ne faut pas qu'elle se reproduise. La procédure commence donc par tester s'il faut modifier ou non :
If
AModifier Then
Si c'est le cas, alors, il y a modification de la variable tampon, signalant ainsi qu'il ne faut plus modifier :
AModifier =
False
Puis on inverse la visibilité en cours de Commande1 :
Commande1.Visible
=
Not
Commande1.Visible
Par contre, s'il ne faut pas modifier, aucune action n'est entreprise :
Else
' Rien à faire
End
If
Supposons que Commande0 soit dans la section Détail. Dès que la souris va sortir du bouton, elle va donc passer sur le Détail. C'est ici qu'il va falloir jouer sur la valeur de la variable tampon afin de la remettre à vrai pour que, dès que la souris retournera sur Commande0, on puisse considérer qu'il faut modifier la visibilité de Commande1.
D'où le code MouseMove sur la section Détail :
Private
Sub
Détail_MouseMove
(
Button As
Integer
, Shift As
Integer
, X As
Single
, Y As
Single
)
AModifier =
True
End
Sub
Comme la variable AModifier est disponible pour deux procédures distinctes, il faut que sa portée soit sur le module. Il s'agit de la déclarer en tête de module :
Private
AModifier As
Boolean
Après avoir obtenu la position d'un formulaire, on va le centrer maintenant pour rendre "joli". Reprenons dès le début, on va créer un type POSITION pour la position de notre formulaire et ajouter quelques API Windows qui s'avèrent utiles pour déterminer les propriétés de l'écran et déplacer le formulaire. Dans la section des déclarations d'un nouveau module juste après Option Explicit, ajouter ce bout de code :
Private
Type
Position
Left
As
Long
Top As
Long
Right
As
Long
Bottom As
Long
End
Type
' --Pour obtenir les coordonnées de la fenêtre parent
Public
Declare
Function
GetParent Lib
"user32"
(
ByVal
hwnd As
Long
) As
Long
' --Pour obtenir les coordonnées de notre formulaire
Public
Declare
Function
GetWindowRect Lib
"user32"
(
ByVal
hwnd As
Long
, _
lpRect As
Position) As
Long
' --Pour obtenir les coordonnées de l'écran
Public
Declare
Function
GetDesktopWindow Lib
"user32"
(
) As
Long
' --Pour positionner et dimensionner la fenêtre
Public
Declare
Function
MoveWindow Lib
"user32"
(
ByVal
hwnd As
Long
, _
ByVal
x As
Long
, ByVal
y As
Long
, ByVal
nWidth As
Long
, _
ByVal
nHeight As
Long
, ByVal
bRepaint As
Long
) As
Long
Pour positionner au centre notre formulaire, on fait appel à une procédure Positionner() dont on passe le formulaire à centrer. Dans notre exemple, c'est un bouton qui centre le formulaire et donc on fait appel à la fonction avec Me.
Private
Sub
Centrer_Click
(
)
Call
Positionner
(
Me)
End
Sub
Revenons au module précédent et ajoutons ce code commenté :
Public
Sub
Positionner
(
frm As
Form)
Dim
FParent As
Position '--Fenêtre parent
Dim
Fenetre As
Position
Dim
Largeur As
Integer
Dim
Hauteur As
Integer
Dim
LParent As
Integer
' --Largeur fenêtre parent
Dim
HParent As
Integer
' --Hauteur fenêtre parent
Dim
PParent As
Long
' --Posion parent
On
Error
GoTo
Erreur
' --Trouver les coordonnées de mon formulaire à centrer
PParent =
GetParent
(
frm.hwnd
)
' --Obtenir les coordonnées de mon formulaire et celles de son parent
Call
GetWindowRect
(
frm.hwnd
, Fenetre)
' --Si le parent est la fenêtre Access, pas de soustraction
If
PParent <>
Application.hWndAccessApp
Then
Call
GetWindowRect
(
PParent, FParent)
Else
' --Les coordonnées du Desktop
Call
GetWindowRect
(
GetDesktopWindow
(
), FParent)
End
If
' --Calcul de la largeur et de la hauteur du parent
With
FParent
LParent =
.Right
-
.Left
HParent =
.Bottom
-
.Top
End
With
' --Calcul de la largeur et de la hauteur de mon formulaire
With
Fenetre
Largeur =
.Right
-
.Left
Hauteur =
.Bottom
-
.Top
.Left
=
(
LParent -
Largeur) \
2
.Top
=
(
HParent -
Hauteur) \
2
End
With
' --Centrer mon formulaire
Call
MoveWindow
(
frm.hwnd
, Fenetre.Left
, Fenetre.Top
, Largeur, Hauteur, bRepaint:=
True
)
Exit
Sub
Erreur
:
MsgBox
"Erreur : "
&
Err
.Number
&
vbCrLf
&
Err
.Description
End
Sub
Function
ExistControl
(
ByVal
frm As
Form, ByVal
ctlName As
String
) As
Boolean
' frm contient le nom du formulaire, ctlName contient le nom du contrôle
On
Error
Resume
Next
If
IsError
(
frm.Controls
(
ctlName).Tag
) Then
Err
.Clear
Exit
Function
Else
ExistControl =
True
End
If
End
Function
Dans votre formulaire vous mettez une étiquette (lblInfos) contenant le texte voulu.
Mettre la propriété minuterie de l'onglet événements à 500 (ms).
En regardant bien les propriétés des événements du formulaire, vous trouverez la propriété Sur Minuterie.
Dedans, vous choisissez [Procédure événementielle], vous cliquez sur les 3... à droite et vous tombez dans la procédure :
Private
sub
Form_Timer
(
)
lblInfos.Caption
=
Mid
(
lblInfos.Caption
, 2
) &
Left
(
lblInfos.Caption
, 1
)
End
Sub
Menu Outils/Options
Onglet Affichage : décocher Fenêtres dans la barre des tâches.
Lorsque l'on ouvre un état depuis un formulaire ouvert en mode acDialog, l'état apparaît derrière le formulaire, ce qui se révèle être un problème. On ne peut demander explicitement au formulaire d'aller en arrière-plan, il faut donc jouer sur sa propriété visible :
nous mettons la propriété visible à false à l'ouverture de l'état, puis à true lors de sa fermeture.
De cette manière, à la fermeture de l'état, le formulaire réapparaît à l'identique.
Pourquoi a-t-on besoin de créer dynamiquement un formulaire quand l'assistant d'Access le fait parfaitement et rapidement ?
Si on veut par exemple afficher une table en mode continu et que le nombre de colonnes de la table varie par exemple
ou quand on ne veut afficher que quelques colonnes d'une table, notre méthode sera appliquée comme filtre alors.
Soit sql la chaîne SQL contenant les colonnes d'une table à afficher :
sql =
"SELECT T.CHAMP1, T.CHAMP2, T.CHAMP5 FROM T"
Cette fonction permet de créer un formulaire dynamiquement et de le mettre en page, d'ajouter aussi des événements... il est conseillé d'utiliser un formulaire existant au lieu de créer un nouveau formulaire parce que Access aura du mal dans le cas de la création d'un nouveau formulaire à voir ce formulaire récemment créé. Dans cet exemple nous utilisons un formulaire existant soit "F_AFFICHAGE" que nous modifions à notre guise.
Public
Function
create_form
(
sql As
String
) As
Boolean
Dim
frm As
Form
Dim
rst As
Recordset
dim
ctl as
control
dim
i, j as
integer
' --Ouvrir le formulaire en mode modification et caché
DoCmd.OpenForm
"F_AFFICHAGE"
, acDesign
, , , , acHidden
' --Suppression de tous les contrôles avant de les créer à nouveau
For
Each
ctl In
Forms!F_AFFICHAGE.Controls
DeleteControl "F_AFFICHAGE"
, ctl.Name
Next
ctl
' --Source de données de mon formulaire
Forms![F_AFFICHAGE].RecordSource
=
sql
Set
rst =
Currentdb.OpenRecordset
(
sql)
' --Nous ne pensons pas que vous aurez plus de 100 contrôles
Dim
controle
(
1
To
100
) As
Control
' --Création des contrôles
If
rst.RecordCount
<>
0
Then
i =
1
j =
1000
While
i <
rst.Fields.Count
' --Créer le contrôle i
Set
controle
(
i) =
CreateControl
(
"F_AFFICHAGE"
, acTextBox)
' --Lui affecter un nom
controle
(
i).Name
=
"TXT_"
&
rst.Fields
(
i).Name
' --Le positionner sur le formulaire
controle
(
i).Left
=
100
+
j
' --Définir sa largeur
controle
(
i).Width
=
1150
' --Définir sa couleur de fond
controle
(
i).BackColor
=
"14742270"
' --Définir son effet visuel
controle
(
i).SpecialEffect
=
0
controle
(
i).BackStyle
=
0
controle
(
i).BorderStyle
=
1
' --Source de données de ce contrôle
controle
(
i).ControlSource
=
rst.Fields
(
i).Name
i =
i +
1
j =
j +
1150
Wend
End
If
' --Création des en-têtes
j =
1000
i =
1
While
i <
rst.Fields.Count
Set
controle
(
i) =
CreateControl
(
"F_AFFICHAGE"
, acTextBox, acHeader)
controle
(
i).Name
=
"HD_"
&
rst.Fields
(
i).Name
controle
(
i).Left
=
100
+
j
controle
(
i).Width
=
1150
controle
(
i).Height
=
700
controle
(
i).BackColor
=
"10081789"
controle
(
i).SpecialEffect
=
0
controle
(
i).BorderStyle
=
1
controle
(
i).TextAlign
=
2
controle
(
i).FontWeight
=
700
controle
(
i).ControlSource
=
"='"
&
rst.Fields
(
i).Name
&
"'"
i =
i +
1
j =
j +
1150
Wend
rst.close
set
rst =
Nothing
' --Sauvegarder le formulaire
DoCmd.Save
acForm, "F_AFFICHAGE"
End
Function
Vous pouvez enrichir cet exemple en vous rendant sur l'aide d'Access pour d'autres propriétés telles que SpecialEffect ou BorderStyle mais aussi ajouter un événement
tel qu'un double-clic en cherchant OnDblClick ou OnClick...
Voilà vous n'avez maintenant qu'à changer la requête SQL et votre formulaire est prêt en quelques secondes.
Tout le pas à pas qui suit concerne la source du sous-formulaire (SF).
Créer un champ Ordre (type numérique) qui servira de tri. Il n'est pas obligatoire qu'il soit physiquement présent dans le formulaire.
Code sur Double clic (le double-clic concerne le sélecteur du SF qui doit donc être affiché) :
Private
Sub
Form_DblClick
(
Cancel As
Integer
)
' Crée un enregistrement et insère un compteur dans le champ Ordre.
Dim
Compteur As
Integer
Application.Echo
False
Compteur =
Me![Ordre]
DoCmd.GoToRecord
, , acNewRec
Me![Ordre].Value
=
Compteur +
1
Me.Requery
Numerotation_Click
Application.Echo
True
End
Sub
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Private
Sub
Numerotation_Click
(
)
' Renumérote les enregistrements.
Dim
rcs As
DAO.Recordset
Dim
i As
Integer
Set
rcs =
Me.RecordsetClone
i =
1
rcs.MoveFirst
While
Not
rcs.EOF
rcs.Edit
rcs!Ordre =
i
rcs.Update
rcs.MoveNext
i =
i +
2
Wend
rcs.Close
Set
rcs =
Nothing
Me.Requery
End
Sub
Pour finir, sur le formulaire principal, événement sur Activation :
Private
Sub
Form_Current
(
)
Me.NomDuSousFormulaire.Form.OrderBy
=
" Ordre"
Me.NomDuSousFormulaire.Form.OrderByOn
=
True
End
Sub
Ce qui active le tri sur le champ Ordre.
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
La touche clavier F2 permet de passer en mode Edit dans un champ. Vous pouvez l'utiliser en entrant dans votre champ l'instruction.
SendKeys "{F2}"
Il faut que le test porte sur un contrôle dépendant que l'utilisateur doit obligatoirement remplir. Le formulaire concerné doit bien sûr être un formulaire lié.
If
IsNull
(
Me.MonControleObligatoire.oldvalue
) Then
' On est en ajout
Else
' On est en modification
End
If
Positionner le curseur à gauche :
Private
sub
MonTXT_Click
(
)
MonTXT.Selstart
=
0
End
sub
Sélectionner le contenu :
Private
sub
MonTXT_Click
(
)
MonTXT.SelStart
=
0
MonTXT.SelLength
=
Len
(
MonTXT)
End
sub
Une position est définie par quatre coordonnées : droite, gauche, bas et haut. Nous allons donc créer un type POSITION pour nos quatre coordonnées. Dans la section déclarations copier et coller ce code :
Private
Type
rect
Left
As
Long
Top As
Long
Right
As
Long
Bottom As
Long
End
Type
Pour déterminer la position de notre formulaire actif, nous ferons appel à une API GetWindowRect. Toujours dans la section déclaration ajouter ce code :
Private
Declare
Function
GetWindowRect Lib
"User32"
_
(
ByVal
hwnd As
Long
, lpRect As
RECT) As
Long
Dans un formulaire, ajouter un bouton dont le code de l'événement sur clic est le suivant :
Private
Sub
Position_Click
(
)
Dim
Position As
rect
Call
GetWindowRect
(
Me.hwnd
, Position)
With
Position
MsgBox
"Position de mon formulaire"
&
vbCrLf
&
"Gauche:"
&
.Left
&
vbCrLf
_
&
"Droite:"
&
.Right
&
vbCrLf
&
"Inférieur:"
&
.Bottom
&
vbCrLf
&
"Supérieur :"
&
.Top
End
With
End
Sub
La position du formulaire est donnée en pixels. Certainement vous vous dites ce que vous pourriez faire avec les positions du formulaire ? Justement c'est très utile si vous voulez "figer" un formulaire ou changer l'emplacement d'un formulaire sur l'écran, il suffit pour ça d'utiliser la fonction MoveSize de DoCmd et dont la traduction est DéplacerDimensionner. Un exemple d'utilisation de cette méthode :
DoCmd.MoveSize
2440
, 2400
, , 4000
Attention, cette propriété prend les coordonnées en twips (1 twip = 1/20 de point). Pour plus d'informations et d'exemples sur toutes ces fonctions rendez-vous sur l'aide d'Access.
Voici une fonction qui vous permet de saisir une valeur numérique :
Function
InputBoxNumeric
(
ByVal
PromptZ As
String
, _
ByVal
TitleZ As
String
, ByVal
DefaultZ As
String
) As
Double
' PromptZ : texte dans l'InputBox
' TitleZ : titre à donner à l'InputBox
' DefaultZ : valeur par défaut
Dim
rep As
String
Start01:
rep =
InputBox
(
PromptZ, TitleZ, DefaultZ)
If
Len
(
rep) >
0
Then
If
IsNumeric
(
rep) Then
InputBoxNumeric =
CDbl
(
rep)
Exit
Function
Else
MsgBox
"Une valeur numérique est attendue, merci de refaire la saisie"
GoTo
Start01
End
If
Else
MsgBox
"une valeur numérique est attendue, merci de refaire la saisie"
GoTo
Start01
End
If
End
Function
Me.MonSousFormulaire.Visible
=
(
Me.MonSousFormulaire.Form.RecordsetClone.RecordCount
>
0
)
Il faut définir la propriété Fen modale du formulaire à Oui.
L'utilisateur ne pourra ainsi accéder à un autre formulaire tant qu'il n'aura pas fermé celui-ci.
Il n'est pas possible de le faire directement.
Cependant, voici comment obtenir un résultat similaire :
- [*]Première solution : remplacer les zones de texte par des zones de liste modifiables qui elles adoptent ce comportement par défaut ;
- [*]Deuxième solution : par DAO, ouvrir un Recordset sur la table, sélectionner le premier enregistrement et le mettre dans la zone de texte si c'est le seul. Sinon, laisser l'utilisateur continuer à taper.
Le truc, c'est de faire :
1/ Une table avec deux champs
ID Boolean
BTN OLEObject
Dans ID, Vrai sur la première ligne et Faux sur la seconde.
Dans BTN, en face de Vrai, l'image d'un bouton, en face de Faux un carré coloré, de la même couleur que le fond du formulaire.
2/ Une requête qui fait le test et renvoie une colonne contenant Vrai si le test est vérifié, Faux sinon.
3/ Une requête qui lie cette colonne calculée, booléenne, avec le champ ID de la table.
4/ Se servir de la seconde requête comme source du sous-formulaire.
Et voilà !
Après, en jouant sur l'ensemble des événements :
Sur souris enfoncée ;
Sur Souris relâchée ;
Sur Clic,
on peut tester si le champ ID est Vrai=> on fait l'action.
Si on fait l'action :
sur souris enfoncée, on affiche une image de bouton enfoncé ;
sur souris relâchée, on remet l'image standard du bouton ;
sur clic, on déclenche l'action.
Programmez les deux événements Sur Entrée et Sur Sortie.
Sur entrée, le format de police change en plus gros.
Sur sortie, le format de police change en plus petit.
Exemple ici pour une zone de texte se nommant "Texte1" :
Private
Sub
Texte1_Enter
(
)
Texte1.FontSize
=
18
End
Sub
Private
Sub
Texte1_Exit
(
Cancel As
Integer
)
Texte1.FontSize
=
8
End
Sub
À noter que depuis Access 2000, il est possible d'utiliser la mise en forme conditionnelle et plus particulièrement ici, une condition de type Champ Actif (cf. lien ci-dessous).
Lien : La mise en forme conditionnelle sous Access 2000/XP/2003
En règle générale il est toujours intéressant de disperser le rapatriement des données.
Quand on a un formulaire à onglets, il vaut mieux rafraîchir les données sur chaque onglet plutôt qu'un gros chargement au début pour tous à la fois.
Ouvrir un formulaire grâce à la ligne de code :
DoCmd.OpenForm
nomformulaire, , , , , , Me.Name
Dans le formulaire que vous venez d'ouvrir, vous pouvez alors suivant le formulaire appelant (dont le nom est contenu dans OpenArgs) exécuter un code différent :
Select
Case
OpenArgs
Case
"frmX"
' Ici ce que vous voulez :
MsgBbox "frmX="
&
openArgs
Case
"frmY"
:
' Ici ce que vous voulez :
MsgBox
"frmY="
&
openArgs
End
Select
Vous pouvez vous servir du résultat renvoyé par votre procédure de recherche multicritère pour créer ou modifier une requête enregistrée dans votre base de données.
La première étape consiste à récupérer l'instruction SQL définie par la procédure Sub RefreshQuery(). Vous avez plusieurs possibilités pour cela.
La première qui vient à l'esprit est de rendre la variable String SQL disponible aux autres procédures du module du formulaire de recherche.
Au lieu de faire :
Private
Sub
RefreshQuery
(
)
Dim
SQL As
String
Dim
SQLWhere As
String
...
End
Sub
Faire :
Dim
SQL As
String
Private
Sub
RefreshQuery
(
)
Dim
SQLWhere As
String
...
End
Sub
Une autre solution pour éviter d'étendre la portée de la variable SQL est de récupérer directement l'instruction SQL dans la propriété RowSource de la liste mise à jour par RefreshQuery(). Dans ce cas inutile de modifier le code du tutoriel.
La seconde étape consiste à utiliser du code DAO pour créer ou mettre à jour la requête grâce à l'objet DAO.Querydef.
Exemple pour deux boutons de commande à placer dans le formulaire de recherche :
Private
Sub
btnCréerRequête_Click
(
)
'****************************
' Facultatif si la variable SQL mise à jour dans Sub RefreshQuery est de niveau module :
' Dim SQL As String
' SQL = Me!lstResults.RowSource
'****************************
Dim
NomQDF as
String
' Faites ici tous vos tests pour vous assurer d'un nom valide pour la requête à créer :
NomQDF =
InputBox
(
"Entrer un nom pour la recherche en cours :"
)
if
NomQDF =
""
then
msgbox
"Vous n'avez pas indiqué de nom valide pour la requête."
exit
sub
end
if
' Création de la requête
CurrentDb.CreateQueryDef
NomQDF, SQL
End
Sub
Private
Sub
btnModifierRequête_Click
(
)
'****************************
' Facultatif si la variable SQL mise à jour dans Sub RefreshQuery est de niveau module :
' Dim SQL As String
' SQL = Me!lstResults.RowSource
'****************************
' Modification de la requête
CurrentDb.QueryDefs
(
"NomRequête"
).SQL
=
SQL
End
Sub
Les codes sont donnés à titre d'exemple sans gestion des erreurs.
Ceci ne peut se faire sur un sous-formulaire ouvert, il faut donc passer par ces étapes :
- refermer le sous-formulaire ;
- l'ouvrir en mode création ;
- le modifier ;
- le fermer ;
- le rouvrir en mode normal.
Ce qui donne le code suivant :
Dim
rct As
Rectangle
Me.ssForm.SourceObject
=
""
'on ferme le sous-formulaire
DoCmd.OpenForm
"Formulaire"
, acDesign, , , , acHidden 'on le rouvre en mode création et caché
Set
rct =
CreateControl
(
"Formulaire"
, acRectangle, , ""
, ""
, 200
, 200
, 3000
, 9400
) 'on trace le rectangle
rct.BackColor
=
vbBlack
DoCmd.Close
acForm, "Formulaire"
'on ferme le formulaire
Me.ssForm.SourceObject
=
"Formulaire"
'on rouvre le sous-formulaire dans le formulaire principal
Set
rct =
Nothing
'on libère la mémoire
Où "ssForm" est le nom du contrôle de sous-formulaire du formulaire principal et "Formulaire" le nom du sous-formulaire dans lequel nous créons le rectangle.
Lien : Est-il possible de créer dynamiquement des contrôles ?
Parfois lorsque l'on cache un formulaire, lorsque celui-ci réapparaît les GIF le composant restent inanimés.
La solution est de redéfinir la propriété filename du GIF pour le faire repartir :
gif.filename
=
gif.filename
Imaginons que nous appelions un formulaire sur clic d'un bouton d'un autre formulaire.
Le formulaire appelé est basé sur une requête ou une table.
Voici le code à mettre sur le bouton qui demande l'ouverture du formulaire (vous pouvez le mettre sur autre chose qu'un bouton bien évidemment) :
Private
Sub
btnOuvrir_Click
(
)
On
Error
GoTo
Err_btnOuvrir_Click
Dim
stDocName As
String
Dim
stLinkCriteria As
String
stDocName =
"NomFormulaire"
' On ne veut que certains enregistrements dans le formulaire à ouvrir
' On ne veut donc que les enregistrements dont le champ ID est égal
' à la valeur du contrôle MonControleFiltre du formulaire
stLinkCriteria =
"[ID]="
&
Me![MonControleFiltre]
' On ouvre le formulaire en passant le filtre en paramètre
DoCmd.OpenForm
stDocName, , , stLinkCriteria
Exit_btnOuvrir_Click
:
Exit
Sub
Err_btnOuvrir_Click
:
If
Err
=
2501
Then
Resume
Exit_btnOuvrir_Click
MsgBox
Err
.Description
Resume
Exit_btnOuvrir_Click
End
Sub
Ensuite voici le code à mettre dans le formulaire que l'on veut ouvrir :
Private
Sub
Form_Open
(
Cancel As
Integer
)
If
Me.RecordsetClone.RecordCount
=
0
Then
MsgBox
"Le formulaire ne s'ouvre pas car il est vide."
, vbInformation
Cancel =
True
'Annule l'ouverture
End
If
End
Sub
Le code que nous mettons sur l'événement Sur clic du formulaire appelant a pour seul but d'intercepter une erreur générée par le code de fermeture du formulaire.
Quand vous tentez d'associer une requête contenant un paramètre à un graphique, vous obtenez l'erreur :
"Le moteur de base de données Microsoft ne reconnaît pas '[Forms]![NomDuFormulaire]![NomDuChamp]' en tant que nom de champ ou expression correcte"...
Pour y remédier, il faut définir le paramètre dans la requête :
- en mode modification de la requête, dans le menu : Requête --> Paramètres : mettre le nom complet du paramètre :[Forms]![NomDuFormulaire]![NomDuChamp] et son type de donnée ;
- ce qui donne en SQL (pour un entier par exemple) :
PARAMETERS
[Forms]
![NomDuFormulaire]
![NomDuChamp]
Short;
Lien : Comment définir un type pour les paramètres d'une requête ?
Lien : Quels sont les types de champ ?
Ce code vous permet de récupérer le nombre d'enregistrements d'un sous-formulaire :
With
Forms
(
"Mon formulaire principal"
).Controls
(
"Mon sous-formulaire"
).Form.RecordsetClone
.MoveLast
debug.print
.RecordCount
End
with
Ce code vous permet de savoir si toutes les ComboBox ont été renseignées, et cela vous place dans le premier combobox non renseigné :
Sub
TestCtrl
(
)
Dim
Ctrl As
control
For
Each
Ctrl In
Me.Controls
If
TypeOf Ctrl Is
ComboBox Then
If
Ctrl.Value
=
""
Or
IsNull
(
Ctrl.Value
) Then
MsgBox
"Toutes les listes doivent avoir une information"
, vbOKOnly
+
vbExclamation
, "Sélection"
Ctrl.SetFocus
Exit
Sub
End
If
End
If
Next
Ctrl
End
Sub
Pour les TextBox, il vous faut changer la ligne :
If
TypeOf Ctrl Is
ComboBox Then
par
If
TypeOf Ctrl Is
TextBox Then