I. Introduction▲
Cet article tutoriel n'est pas destiné aux débutants mais aux utilisateurs moyens et avancés de Microsoft Access.
Sur le forum de nombreuses questions tournent autour des formulaires continus.
Ces formulaires qui offrent d'intéressantes possibilités présentent en contrepartie des contraintes dont il est difficile de s'affranchir.
La principale contrainte qui heurte tant d'utilisateurs est que dans un formulaire continu chaque contrôle n'existe qu'une fois en contradiction avec l'affichage.
Cet affichage multiple est trompeur, car si la valeur d'un contrôle lié à une source de données change à chaque enregistrement il n'en va pas de même pour tous les contrôles indépendants.
Dans le cas de mon tutoriel de gestion des images, il est impossible d'avoir un formulaire continu qui affiche les photos, on aura bien une liste mais la photo sera la même pour tous.
Ce tutoriel propose une solution pour y parvenir malgré tout.
Toutefois, je reste bien conscient que ce developpement n'est pas applicable à tous les cas, loin de là, mais il ouvre certaines pistes et a été pour moi un plaisant petit défi de programmation.
Il me permet surtout d'aborder ici de nombreux thèmes susceptibles d'intéresser les développeurs Access.
II. Rendu final de l'application▲
A gauche le formulaire issu du tutoriel Photos, et à droite le formulaire "pseudo-continu" construit par l'application que nous allons étudier.
III. Méthodologie▲
III-A. Démultiplier la source des données▲
Pour pallier aux défauts du mode continu, nous allons utiliser un formulaire en mode "normal", et donner l'impression à l'utilisateur qu'il travaille sur un formulaire continu.
L'idée est de démultiplier la source de données pour simuler un formulaire continu. Ainsi, si nous avons un formulaire avec : txtNom, txtPrenom, cmbVille nous allons construire une source de données avec : txtNom0, txtNom1, txtNom2 ... autant que nous souhaitons avoir de lignes sur notre formulaire continu.
La source de données passe de
en
III-B. Analyser le formulaire existant▲
L'étude portera sur deux critères essentiels : la hauteur finale du formulaire et le nombre de champs possible. Le nombre de champs d'une table Access ne peut excéder 255 caractères. L'application va récupérer le nombre de champs de la requête sous-jacente du formulaire et le multiplier par le nombre de lignes souhaitées.
Par une fonction API, nous allons récupérer la résolution verticale du PC et la comparer à la hauteur du formulaire (ici la zone de détail) multipliée par le nombre de lignes souhaitées.
III-C. Créer le formulaire▲
IV. Analyse du formulaire▲
IV-A. Nombre de champs de la données source▲
L'analyse du formulaire se fait au travers ... d'un formulaire, en voici une copie d'écran
Nous créons un bouton pour analyser le formulaire
Private
Sub
cmdAnalyse_Click
(
)
Dim
rec As
Recordset
Dim
NbFields As
Integer
' nous n'analyserons pas le formulaire lui meme
'
If
Me.lstForms
<>
Me.Name
Then
' ouverture du formulaire en mode caché
DoCmd.OpenForm
Me.lstForms
, acNormal, , , , acHidden
' récupération du recordset (OBJET) sous-jacent au formulaire
Set
rec =
Forms
(
Me.lstForms
).RecordsetClone
' récupération de la source de données (CHAINE)
Me.lblSQL.Caption
=
Forms
(
Me.lstForms
).RecordSource
' Utilisation de la propriété .Count de la collection Fields.
' ce nombre sera à multiplier par le nombre de lignes souhaitées
' pour calculer le nombre de la champs de la future table démultipliée
NbFields =
rec.Fields.Count
' fermeture du recordset et libération de mémoire
rec.Close
Set
rec =
Nothing
' Mise à jour des label d'analyse
Me.lblComment.Caption
=
Me.cmbNb
&
" x "
&
NbFields &
" = "
&
Me.cmbNb
*
NbFields &
" <= 255 Champs maximum"
Me.lblScreen.Caption
=
Me.cmbNb
&
" x "
&
Forms
(
Me.lstForms
).Détail.Height
/
20
&
" = "
&
_
Me.cmbNb
*
Forms
(
Me.lstForms
).Détail.Height
/
20
&
" en hauteur <= "
&
_
GetResolution
(
"V"
) &
" résolution verticale"
' Fermeture du formulaire sans sauvegarde
DoCmd.Close
acForm, Me.lstForms
, acSaveNo
Else
Me.lblSQL.Caption
=
""
Me.lblComment.Caption
=
"Opération impossible sur le formulaire courant"
Me.lblScreen.Caption
=
"Opération impossible sur le formulaire courant"
End
If
IV-B. Liste des formulaires ▲
Contrairement aux Tables et Requêtes nous ne pouvons directement accéder aux objets report et form sans les ouvrir.
C'est pourquoi nous les ouvrons en mode caché pour récupérer les informations nécessaires à l'analyse.
Pour alimenter la liste des formulaires, nous utilisons un SQL sur des tables systèmes, nous aurions également pu passer par les Containers.
Pour information voici la liste des containers ...
La table MsysObjects est une table système qui recense les objets de la base de données, nous la filtrons avec la constante dédiée aux formulaires -32768.
Nous attribuons le SQL suivant à la liste des formulaires.
SELECT
msysobjects.Id
, msysobjects.Name
FROM msysobjects
WHERE (((
msysobjects.Type
)=-
32768
));
IV-C. Connaître la résolution verticale du futur formulaire▲
Dernier point d'intérêt, nous récupérons la résolution verticale du système grâce à la fonction GetResolution() dont voici le code
Type
RECTANGLE
x1 As
Long
y1 As
Long
x2 As
Long
y2 As
Long
End
Type
Declare
Function
GetDesktopWindow Lib
"User32"
(
) As
Long
Declare
Function
GetWindowRect Lib
"User32"
(
ByVal
hWindow As
Long
, R As
RECTANGLE) As
Long
Function
GetResolution
(
ByVal
H_V As
String
) As
Long
Dim
R As
RECTANGLE
Dim
hWindow As
Long
Dim
RC As
Long
Dim
WindowResolution As
String
hWindow =
GetDesktopWindow
(
)
RC =
GetWindowRect
(
hWindow, R)
If
H_V =
"h"
Then
GetResolution =
(
R.x2
-
R.x1
)
Else
GetResolution =
(
R.y2
-
R.y1
)
End
If
End
Function
Nous pouvons maintenant passer à la démultiplication des données, accessible depuis le bouton créer données sur notre formulaire.
V. Démultiplication des données▲
V-A. Méthode▲
Cette opération est automatisée par la fonction DemultiplieSource.
Le code est commenté mais en voici la logique.
. Vérification que la limite des 255 champs n'est pas atteinte.
. Création de la structure de la table, copiée sur la source de données.
. Alimentation de la nouvelle table, Champ => Champ0, Nom => Nom0 etc.
. Mise à jour de la table.
Le but final est d'obtenir ceci :
V-B. Le code▲
Le code suivant opère ces différentes étapes.
Function
DemultiplieSource
(
ByVal
strTable As
String
, ByVal
intNb As
Integer
)
' strTable est le nom de la requête qui est source de données à démultiplier
' intNb est le nombre de lignes souhaitées pour le futur formulaire pseudo continu
Dim
newTbl As
TableDef
Dim
fld As
Field
Dim
recSource, recDest As
Recordset
Dim
i, j As
Integer
On
Error
GoTo
DS01
'Création des champs
' la fonction qui appelle ce code se charge de détruire la table "tblContinue"
' Vérification que la limite des 255 champs n'est pas atteinte
If
CurrentDb.TableDefs
(
strTable).Fields.Count
*
intNb <
255
Then
'Création de la table
Set
newTbl =
CurrentDb.CreateTableDef
(
"tblContinue"
)
'Boucle sur le nombre de lignes du futur formulaire
For
j =
0
To
intNb -
1
'Boucle sur les champs de la donnée source
' utilisation intensive de l'objet Fields et des propriétés de ces champs
For
i =
0
To
CurrentDb.TableDefs
(
strTable).Fields.Count
-
1
' nous nommons le Champ comme l'orginal plus un chiffre Nom devient Nom0, Nom1 ...
Set
fld =
newTbl.CreateField
(
CurrentDb.TableDefs
(
strTable).Fields
(
i).Name
&
j, _
CurrentDb.TableDefs
(
strTable).Fields
(
i).Type
, _
CurrentDb.TableDefs
(
strTable).Fields
(
i).Size
)
' la méthode .Append ajoute le champ défini lors du Set à la collection Fields
newTbl.Fields.Append
fld
Next
i
Next
j
' la méthode .Append ajoute la nouvelle table définie lors du Set à la collection TableDefs
CurrentDb.TableDefs.Append
newTbl
'Remplissage des données
Set
recSource =
CurrentDb.OpenRecordset
(
strTable, dbOpenDynaset)
Set
recDest =
CurrentDb.OpenRecordset
(
"tblContinue"
, dbOpenDynaset)
' ouverture des deux sources de données
If
Not
recSource.EOF
Then
' première passe recopie des champs
' recopie des champs à leur place originale
' Nom de l'enregistrement 1 sera Nom0 de l'enregistrement 1
recSource.MoveFirst
Do
While
Not
recSource.EOF
recDest.AddNew
For
j =
0
To
recSource.Fields.Count
-
1
If
Len
(
recSource.Fields
(
j)) >
0
Then
recDest.Fields
(
j) =
recSource.Fields
(
j)
Else
recDest.Fields
(
j) =
0
End
If
Next
j
recDest.Update
recSource.MoveNext
Loop
' passes suivantes avec décalage
' Nom de l'enregistrement 4 sera Nom1 de l'enregistrement 3
' Nom2 de l'enregistrement 2
' Nom3 de l'enregistrement 1
For
i =
1
To
intNb -
1
recSource.MoveFirst
recSource.Move
i
recDest.MoveFirst
Do
While
Not
recSource.EOF
' la méthode Edit rend modifiable l'enregistrement
recDest.Edit
For
j =
0
To
recSource.Fields.Count
-
1
If
Len
(
recSource.Fields
(
j)) >
0
Then
recDest.Fields
(
j +
(
i *
recSource.Fields.Count
)) =
recSource.Fields
(
j)
Else
recDest.Fields
(
j +
(
i *
recSource.Fields.Count
)) =
0
End
If
Next
j
' la méthode Update sauvegarde les modifications
recDest.Update
recDest.MoveNext
recSource.MoveNext
Loop
Next
i
End
If
' fermeture des jeux d'enregistrement et libération des ressources
recSource.Close
recDest.Close
Set
recSource =
Nothing
Set
recDest =
Nothing
Else
MsgBox
"le nombre de champs de la source à passer en mode pseudo continu dépasse 255, "
&
_
"merci de diminuer le nombre de champ ou le nombre de lignes"
, _
vbOKOnly
+
vbCritical
End
If
Exit
Function
DS01
:
Select
Case
Err
.Number
Case
3010
Resume
Next
Case
Else
MsgBox
Err
.Number
&
" : "
&
Err
.Description
, vbCritical
+
vbOKOnly
End
Select
Err
.Clear
End
Function
V-C. Points d'intérêt▲
V-C-1. Comment créer une table▲
Dim
newTbl As
TableDef
Set
newTbl =
CurrentDb.CreateTableDef
(
"NomDeLaTable"
)
CurrentDb.TableDefs.Append
newTbl
V-C-2. Comment créer un champ▲
Dim
fld As
Field
Set
fld =
UnObjetTable.CreateField
(
"Nom"
, acText, 50
)
UnObjetTable.Fields.Append
fld
Le reste du code consiste à de la manipulation de Recordset dont le maniement est expliqué ailleurs sur developpez.com
La source de données est prête, passons à la création du formulaire.
VI. Création du formulaire▲
VI-A. Méthode▲
. ouverture du formulaire source, et parallèlement création du nouveau formulaire.
. récupération de la source de données, démultiplication
. calcul des dimensions du formulaire
. création des contrôles ligne par ligne
. attribution de la source demultipliée
. attribution du module de code de mise à jour
. sauvegarde et nommage du formulaire
VI-B. Le code▲
Function
PseudoContinu
(
ByVal
strForm As
String
, _
ByVal
intNbLignes As
Integer
, _
Optional
ByVal
AddForm As
Boolean
=
True
)
'
' strForm : le nom du formulaire à rendre pseudo continu
' intNbLignes : le nombre de lignes du futur formulaire
' addForm : demande ou non la création du formulaire
' si AddForm = False, la fonction ne fait que créer les données
' si AddForm = True, la fonction crée les données et le formulaire
Dim
newForm As
Form
Dim
newCtl As
Control
Dim
ctl As
Control
Dim
prp As
Property
Dim
qry As
QueryDef
Dim
rec As
Recordset
Dim
mdl As
Module
Dim
i As
Integer
Dim
strSource As
String
Dim
MaxHeight, MaxWidth, intCount As
Long
intCount =
1
PseudoContinuNb =
intNbLignes
'Nettoyage des tables
If
ExistTable
(
"tblContinue"
) Then
DoCmd.SetWarnings
False
DoCmd.DeleteObject
acTable, "tblContinue"
DoCmd.SetWarnings
True
End
If
' Ouverture du formulaire à cloner
DoCmd.OpenForm
strForm, acDesign, , , , acHidden
' Récupération de la source de données
strSource =
Forms
(
strForm).RecordSource
If
InStr
(
strSource, " "
) >
0
Then
' il y a un espace dans la source ce qui indique qu'il s'agit d'un SQL et non d'une table ou requête
'création de la requete puis creation de la table temporaire
DoCmd.SetWarnings
False
' si la requête existe : attribution du SQL
If
ExistQuery
(
"rqtPseudoContinu"
) Then
CurrentDb.QueryDefs
(
"rqtPseudoContinu"
).SQL
=
strSource
Else
' création de la requête et attribution du SQL
Set
qry =
CurrentDb.CreateQueryDef
(
"rqtPseudoContinu"
, strSource)
CurrentDb.QueryDefs.Append
qry
End
If
' nous exécutons une requête création de table pour transformer la source en table "tblPseudoContinu"
DoCmd.RunSQL
"SELECT * INTO tblPseudoContinu FROM [rqtPseudoContinu]"
DoCmd.SetWarnings
True
DemultiplieSource "tblPseudoContinu"
, intNbLignes
DoCmd.RunSQL
"DROP TABLE tblPseudoContinu"
Else
'indique que la source n'est qu'une table
'création de la table temporaire
DemultiplieSource strSource, intNbLignes
End
If
If
AddForm Then
' Création du formulaire pseudo continu
Set
newForm =
CreateForm
' Trouver le point le plus bas du formulaire
' Nous balayons les contrôles Boutons exceptés pour connaître la taille maximale d'une ligne de notre futur formulaire
For
Each
ctl In
Forms
(
strForm).Controls
If
ctl.ControlType
<>
acCommandButton Then
If
ctl.Top
+
ctl.Height
>
MaxHeight Then
MaxHeight =
ctl.Top
+
ctl.Height
End
If
If
ctl.Left
+
ctl.Width
>
MaxWidth Then
MaxWidth =
ctl.Left
+
ctl.Width
End
If
End
If
Next
ctl
' Attribution des dimensions du nouveau formulaire
' La largeur est définie par le formulaire : Form.Width
' La hauteur est définie par la zone de détail
newForm.Width
=
MaxWidth +
10
newForm.Détail.Height
=
(
MaxHeight +
10
) *
intNbLignes
For
i =
0
To
intNbLignes -
1
For
Each
ctl In
Forms
(
strForm).Controls
Select
Case
ctl.ControlType
Case
acCommandButton
Case
Else
Set
newCtl =
CreateControl
(
newForm.Name
, _
ctl.ControlType
, _
acDetail, , , _
ctl.Left
, _
ctl.Top
+
(
MaxHeight +
10
) *
i, _
ctl.Width
, _
ctl.Height
)
newCtl.Visible
=
ctl.Visible
Select
Case
ctl.ControlType
Case
acTextBox, acComboBox, acListBox
newCtl.ControlSource
=
ctl.ControlSource
&
i
Case
Else
End
Select
newCtl.Name
=
ctl.Name
&
i
Select
Case
ctl.ControlType
Case
acLabel
newCtl.Caption
=
ctl.Caption
Case
Else
End
Select
End
Select
Next
ctl
' Création de la barre de démarquation
Set
newCtl =
CreateControl
(
newForm.Name
, acLine, acDetail, , , _
5
, _
(
MaxHeight +
10
) *
i +
MaxHeight +
2
, _
MaxWidth -
10
, _
0
)
newCtl.Name
=
"drwBarre"
&
i
newCtl.SpecialEffect
=
2
Next
i
'attribution des données
newForm.RecordSource
=
"tblContinue"
'attribution du formulaire de code
newForm.HasModule
=
True
'attention le fichier contient le code standard doit être dans le chemin de l'appli
'c'est ce module qui permettra de mettre à jour les modifications
newForm.Module.AddFromFile
CurrentProject.Path
&
"\modFormContinu.cls"
'sauvegarde
newForm.Tag
=
strForm &
"-pseudo continu"
&
intNbLignes
DoCmd.Close
acForm, newForm.Name
, acSaveYes
End
If
'fermeture du formulaire source, inutile de sauvegarder
DoCmd.Close
acForm, strForm, acSaveNo
'renommage du formulaire
For
i =
0
To
CurrentDb.Containers
(
2
).Documents.Count
-
1
If
CurrentDb.Containers
(
2
).Documents
(
i).DateCreated
>
Now
-
10
/
24
/
3600
Then
'document créé depuis moins de 10 secondes c'est le bon
DoCmd.Rename
strForm &
"-Continu"
, acForm, CurrentDb.Containers
(
2
).Documents
(
i).Name
End
If
Next
i
End
Function
VI-C. Points d'intérêt▲
VI-C-1. Savoir si une table ou une requête existe▲
Ce code nous permet d'utiliser les fonctions très pratiques de test d'existence de table et requête.
Function
ExistQuery
(
ByVal
strQry As
String
) As
Boolean
On
Error
GoTo
EQ01
If
CurrentDb.QueryDefs
(
strQry).Name
=
strQry Then
ExistQuery =
True
Exit
Function
Else
ExistQuery =
False
End
If
EQ01
:
Select
Case
Err
.Number
Case
3265
ExistQuery =
False
Case
Else
ExistQuery =
False
End
Select
Err
.Clear
End
Function
Function
ExistTable
(
ByVal
strTbl As
String
) As
Boolean
On
Error
GoTo
EQ01
If
CurrentDb.TableDefs
(
strTbl).Name
=
strTbl Then
ExistTable =
True
Exit
Function
Else
ExistTable =
False
End
If
EQ01
:
Select
Case
Err
.Number
Case
3265
ExistTable =
False
Case
Else
ExistTable =
False
End
Select
Err
.Clear
End
Function
VI-C-2. Manipuler un objet QueryDef▲
QueryDef est la définition d'une requête.
QueryDefs est la collection des objets requête.
Créer une requête avec CreateQueryDef et .Append
Dim
qry As
QueryDef
Set
qry =
CurrentDb.CreateQueryDef
(
"NomDeLaRequete"
, ChaineSQL)
CurrentDb.QueryDefs.Append
qry
Attribuer un SQL à une requête
CurrentDb.QueryDefs
(
"NomDeLaRequete"
).SQL
=
ChaineSQL
VI-C-3. Manipuler un objet Form▲
Créer un formulaire
Dim
newForm as
Form
Set
newForm =
CreateForm
Parcourir les contrôles d'un formulaire OUVERT.
Dim
ctl As
Control
For
Each
ctl In
Forms
(
"MonFormulaire"
).Controls
' votre code
Next
ctl
VI-C-4. Créer des contrôles▲
Dim
newCtl as
Control
Set
newCtl =
CreateControl
(
"MonForm"
, acTextBox, "ZoneduForm"
, , , 0
, 0
, 100
, 30
)
' O => Gauche, 0 => Haut, 100 => Largeur, 30 => Hauteur
newCtl.Name
=
"MonControle"
Attribuer une source
newCtl.ControlSource
=
"Nomd-unChampdeLaSourceLieeAuFormulaire"
VI-C-5. Attribuer un module à un formulaire▲
Nous avons de côté un module sous forme de fichier texte que notre code intègre au formulaire.
Son fonctionnement sera décrit dans la partie suivante
ObjetFormulaire.HasModule
=
True
ObjetFormulaire.Module.AddFromFile
VariableChainePointantSurUnFichierTexte
Nous avons attribué un module de code qui permettra de mettre à jours les enregistrements dans la table d'origine qui n'est maintenant plus liée à notre formulaire.
VII. Fonctions de mise à jour des données▲
Le formulaire fonctionne, mais si l'utilisateur modifie des données, la table source n'est pas mise à jour, nous allons remédier à cela.
VII-A. Méthode▲
Il faut impérativement qu'une modification d'un enregistrement soit répercutée sur la table source, mais aussi sur les enregistrements démultipliés.
Comme précisé sur le schéma ci-dessous
. traquer les modifications dans les contrôles du formulaire pseudo continu
. mettre à jour la table source
. mettre à jour les enregistrements suivants et précédents
VII-B. Le code▲
Private
Sub
Form_Load
(
)
Dim
ctl As
Control
For
Each
ctl In
Me.Controls
Select
Case
ctl.ControlType
Case
acTextBox, acListBox, acComboBox, acCheckBox, _
acOptionButton, acOptionGroup
'représente la quasi majorité des cas possibles
' à adapter si besoin
ctl.BeforeUpdate
=
"=GoUpdate('"
&
ctl.Name
&
"', "
&
CurrentRecord &
")"
Case
Else
'ne rien faire
End
Select
Next
ctl
Set
ctl =
Nothing
End
Sub
Function
GoUpdate
(
ByVal
ctlName As
String
, _
ByVal
CurrRec As
Long
)
Dim
i, j As
Integer
Dim
intRelative As
Integer
Dim
intCont As
Integer
Dim
lngMaxRow, lngMinRow As
Long
Dim
rec As
Recordset
CurrRec =
Me.CurrentRecord
' récupère le nombre maximum de contrôles
intCont =
CInt
(
Right
(
Me.Tag
, 1
))
' mise à jour des enregistrements précédents et suivants
Set
rec =
Me.RecordsetClone
intRelative =
CInt
(
Right
(
ctlName, 1
))
lngMaxRow =
intRelative +
CurrRec
lngMinRow =
Max
(
1
, lngMaxRow -
intCont +
1
)
rec.MoveFirst
rec.Move
lngMinRow -
1
For
j =
Min
(
intCont -
1
, lngMaxRow -
1
) To
0
Step
-
1
If
j <>
intRelative Then
rec.Edit
rec.Fields
(
Left
(
ctlName, Len
(
ctlName) -
1
) &
j).Value
=
Me.Controls
(
ctlName)
rec.Update
End
If
rec.MoveNext
Next
j
rec.Close
' mise à jour de la table source
Set
rec =
CurrentDb.OpenRecordset
(
"rqtPseudoContinu"
, dbOpenDynaset)
rec.MoveFirst
rec.Move
lngMaxRow -
1
rec.Edit
rec.Fields
(
Left
(
ctlName, Len
(
ctlName) -
1
)).Value
=
Me.Controls
(
ctlName)
rec.Update
rec.Close
Set
rec =
Nothing
End
Function
Function
Max
(
ByVal
n1 As
Long
, ByVal
n2 As
Long
) As
Long
If
n1 >=
n2 Then
Max =
n1
Else
Max =
n2
End
If
End
Function
Function
Min
(
ByVal
n1 As
Long
, ByVal
n2 As
Long
) As
Long
If
n1 <
n2 Then
Min =
n1
Else
Min =
n2
End
If
End
Function
VII-C. Points d'intérêt▲
VII-C-1. Traquer les modifications▲
ctl.BeforeUpdate
=
"=GoUpdate('"
&
ctl.Name
&
"', "
&
CurrentRecord &
")"
Nous attribuons une fonction sur l'événement BeforeUpdate d'un contrôle.
Cette attribution de code en balayant dynamiquement les contrôles au chargement du formulaire (OnLoad) permet de ne pas avoir à écrire toutes les fonctions Private Sub MonControle_BeforeUpdate() qui seraient impossible à prévoir toutes.
CurrentRecord permet de connaître le numéro de l'enregistrement courant, indispensable pour le retrouver dans la table source.
VII-C-2. Effectuer les mises à jour▲
Nous manipulons le recordset du formulaire grâce à RecordSetClone, qui est le clone du recordset du formulaire. Je pense qu'il est peu utile ici de détailler la manière dont le code se déplace dans les jeux d'enregistrement.
VIII. Application au tutoriel Photos▲
Nous avons vu comment notre application pouvait construire totalement un formulaire pseudo-continu.
Nous allons maintenant l'exploiter dans le cadre de notre précédent tutoriel de gestion de photos.
En adaptant quelque peu le code nous allons pouvoir obtenir un formulaire qui a l'apparence d'être continu et qui permet néanmoins d'afficher une photo différente par "ligne".
Private
Sub
Form_Current
(
)
Dim
ctl As
Control
' Gestion des erreurs
'On Error GoTo Catch02
' si la photo n'est pas définie, on affiche la photo blank.jpg
For
Each
ctl In
Me.Controls
If
ctl.ControlType
=
acImage Then
If
Len
(
Me.Controls
(
"Photo"
&
Right
(
ctl.Name
, 1
))) >
0
Then
ctl.Picture
=
Me.Controls
(
"Photo"
&
Right
(
ctl.Name
, 1
))
Else
ctl.Picture
=
CurrentProject.Path
&
"\images\blank.jpg"
End
If
DisplayPhoto ctl.Name
End
If
Next
ctl
Exit
Sub
Catch02
:
Select
Case
Err
.Number
Case
2114
'Cas d'un type de fichier photo non supporté ...
MsgBox
"Le format de l'image n'est supporté par le contrôle image Picture"
, vbCritical
+
vbOKOnly
, "Application Photos"
Case
2220
'Cas d'un emplacement non valide du fichier images
MsgBox
"Le fichier image n'a pas été trouvé à l'emplacement indiqué"
, vbCritical
+
vbOKOnly
, "Application Photos"
Case
Else
' tout autre cas d'erreur
MsgBox
"Erreur inattendue : "
&
Err
.Number
&
vbCrLf
&
Err
.Description
, vbCritical
+
vbOKOnly
, "Application Photos"
End
Select
Err
.Clear
End
Sub
Sub
DisplayPhoto
(
ByVal
ctlImage As
String
)
' Traitement en fonction de la taille de l'image
' regarde si la hauteur de l'image dépasse celle du controle Picture
If
Me.Controls
(
ctlImage).ImageHeight
>
Me.Controls
(
ctlImage).Height
Then
' met le controle en mode zoom
Me.Controls
(
ctlImage).SizeMode
=
3
Else
' met le contrôle en mode respect de la taille originale
Me.Controls
(
ctlImage).SizeMode
=
0
End
If
' si la largeur dépasse et qu'on est en mode taille réelle ...
If
(
Me.Controls
(
ctlImage).ImageWidth
>
Me.Controls
(
ctlImage).Width
) And
(
Me.Controls
(
ctlImage).SizeMode
) =
0
Then
' on met en mode zoom
Me.Controls
(
ctlImage).SizeMode
=
3
End
If
End
Sub
IX. Conclusions▲
Notre application fonctionne et permet une navigation de type continu tout en affichant bien la photo liée à chaque salarié.
Cet article-tutoriel montre qu'on peut toujours arriver à ses fins sur Access même si la dépense d'énergie n'est pas toujours appropriée à la demande des utilisateurs.
D'autres solutions pour remédier aux limites des formulaires continus existent, certaines vous seront bientôt présentées ici.
D'ici là bon codage, et merci de m'avoir lu jusqu'au bout ;)