I. Ce dont il s'agit▲
Imaginez un formulaire pour comptabiliser les opérations bancaires d'une association caritative.
Un formulaire père avec quatre fils qui détaillent les différents mouvements enregistrés à l'extrait de la banque. (Exemple repris de Tutoriel pour gérer une association avec Access)
Dans une première approche, ceci :
Dans la section pied de chacun des sous-formulaires, deux infos (en gris foncé) :
- le nombre de postes détaillés ;
- le total de ces postes.
Le pied s'affiche au bas de l'espace que nous avons réservé au conteneur du sous-formulaire :
Et ce, quel que soit le nombre de lignes que comporte le détail.
Ce que nous souhaitons, c'est que le pied soit collé juste en dessous de la dernière ligne de détail, comme ceci :
Bref, ce que nous voulons, c'est que la hauteur de l'espace réservé aux conteneurs des sous-formulaires s'adapte automatiquement pour que la section Pied apparaisse juste en dessous du dernier détail (ou de l'espace réservé à l'encodage du suivant).
Et si le nombre de lignes de détail s'avère trop grand pour les afficher toutes, nous ajouterons une barre de défilement verticale au sous-formulaire concerné.
II. Préparons le terrain▲
II-A. Convention de nommage▲
Les conteneurs des sous-formulaires seront nommés : CTNRnomDuSousFormulaire.
Exemple
II-B. Des repères pour indiquer la hauteur maximum des sous-formulaires▲
Nous insérons dans le formulaire principal un contrôle « Trait » par sous-formulaire pour indiquer la limite de sa hauteur maximale autorisée.
Nous convenons de nommer ces contrôles : « BasCTNRnomDuSousFormulaire » et leur propriété « Visible » est positionnée sur Non :
III. Une sous-routine pour adapter la hauteur du conteneur de sous-formulaire▲
III-A. Le code▲
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.
47.
48.
49.
50.
51.
52.
53.
54.
Option
Compare Database
Option
Explicit
Public
Sub
AmenagerTailleSF
(
LeForm As
Access.Form
, LeSF As
Access.SubForm
)
Dim
EspaceNecessaire As
Long
, EspaceLibre As
Long
, iAffichables As
Integer
On
Error
GoTo
GestionErreurs
With
LeSF
'Calculer l'espace nécessaire pour afficher tous les enregistrements
.Form.RecordsetClone.MoveLast
'pour pouvoir ensuite compter le nbre d'enregistrements
EspaceNecessaire =
.Form.Section
(
acHeader).Height
_
+
.Form.Section
(
acFooter).Height
_
+
.Form.Section
(
acDetail).Height
_
*
(
.Form.RecordsetClone.RecordCount
-
.Form.AllowAdditions
) 'Ceci revient à ajouter 1 si ajout autorisé
'Calculer l'espace disponible et le nbre d'enregistrements affichables
EspaceLibre =
LeForm
(
"Bas"
&
LeSF.Name
).Top
-
.Top
iAffichables =
Int
(((
EspaceLibre -
.Form.Section
(
acHeader).Height
-
.Form.Section
(
acFooter).Height
) /
_
.Form.Section
(
acDetail).Height
))
'Limitation au maximum possible
If
EspaceNecessaire >
EspaceLibre Then
'trop pour tout afficher
.Height
=
EspaceLibre
.Form.InsideHeight
=
EspaceLibre
.Form.ScrollBars
=
2
'pour afficher une barre de défilement verticale
'Afficher les derniers enregistrements de la liste
.SetFocus
DoCmd.GoToRecord
, , acNewRec 'afficher l'emplacement de l'ajout si permis, sinon erreur 2105 et instruction suivante
DoCmd.GoToRecord
, , acLast
DoCmd.GoToRecord
, , acPrevious, iAffichables -
1
+
.Form.AllowAdditions
'se positionner sur le dernier
DoCmd.GoToRecord
, , acLast
Else
.Height
=
EspaceNecessaire
.Form.InsideHeight
=
EspaceNecessaire
.Form.ScrollBars
=
0
' pas de barre de défilement verticale
'Afficher tous les enregistrements et se positionner sur le dernier
.SetFocus
DoCmd.GoToRecord
, , acFirst
DoCmd.GoToRecord
, , acLast
End
If
End
With
GestionErreurs
:
Select
Case
Err
.Number
Case
0
'Pas d'erreur
Exit
Sub
Case
3021
'Pas d'enregistrement dans le sous-formulaire
Resume
Next
Case
2105
'Pas d'ajout permis dans le sous-formulaire
Resume
Next
Case
Else
MsgBox
"Erreur dans AmenagerTailleSF : "
&
vbLf
&
"N° erreur : "
&
Err
.Number
&
" "
&
Err
.Description
, vbCritical
End
Select
End
Sub
III-B. Explication du code▲
4 : la procédure demande deux paramètres : l'objet formulaire qui appelle et l'objet conteneur du sous-formulaire qui doit être redimensionné.
7 : les instructions With
et End
With
(ligne 42) permettent d'abréger l'écriture. Entre ces deux instructions au lieu d'écrire par exemple
« LeSf.Form.Section
(
acHeader).Height
»
on pourra abréger et n'écrire que « .Form.Section
(
acHeader).Height
».
9-14 : on calcule la hauteur qui serait nécessaire pour afficher tous les enregistrements.
On additionne la hauteur de la section « En-tête », la hauteur de la section « Pied » et autant de fois la hauteur de la section « Détail » qu'il y a d'enregistrements à afficher.
On ajoute encore à cela une fois la hauteur de la section « Détail » pour l'espace (éventuel) d'un ajout d'un nouvel enregistrement.
N.B. Si les ajouts sont autorisés la propriété .Form.AllowAdditions vaut -1, sinon 0.
17 : par différence entre la propriété « Haut » du trait repère et celle du sous-formulaire, on détermine l'espace maximum que peut occuper le sous-formulaire déployé.
18 - 19 : le nombre d'enregistrements qui pourront s'afficher ensemble égale la partie entière Ent
(
) du quotient de la hauteur disponible divisée par la hauteur d'une section détail.
21 - 41 : de deux choses l'une :
- EspaceNecessaire > EspaceLibre => il n'y a pas assez de place pour tout afficher :
23 : on attribue au sous-formulaire la hauteur maximum disponible,
24 : on ajuste la fenêtre,
25 : on ajoute une barre de défilement verticale,
27 - 32 : on fait voyager le sélecteur pour afficher toutes les dernières lignes. Y compris la ligne vierge pour l'ajout éventuel. Une erreur 2105 sera levée si la propriété « Ajout autorisé » est à Non. Cette erreur éventuelle est trappée et on continue ;
- on a assez de place pour tout montrer :
34 : on attribue au sous-formulaire la hauteur nécessaire,
35 : on ajuste la fenêtre,
36 : sans barre de défilement,
38 - 40 : on met le focus sur le dernier enregistrement.
IV. Quand et comment déclencher cette sous-routine▲
IV-A. À chaque lecture d'un enregistrement du formulaire principal▲
Nous aurons donc, dans l'événement « Sur activation » :
Option
Compare Database
Option
Explicit
Private
Sub
Form_Current
(
)
'Moduler la taille des sous-formulaires
Call
AmenagerTailleSF
(
Me, Me.CTNRsfDons
)
Call
AmenagerTailleSF
(
Me, Me.CTNRsfAutresRecettes
)
Call
AmenagerTailleSF
(
Me, Me.CTNRsfFrais
)
Call
AmenagerTailleSF
(
Me, Me.CTNRsfActionsHum
)
End
Sub
IV-B. À chaque ajout ou suppression d'enregistrement dans le sous-formulaire▲
Donc lors des événements « Après insertion » et « Après suppression » :
2.
3.
4.
5.
6.
7.
8.
9.
10.
Option
Compare Database
Option
Explicit
Private
Sub
Form_AfterDelConfirm
(
Status As
Integer
)
Call
AmenagerTailleSF
(
Me.Parent
, Me.Parent.ActiveControl
): Me.Requery
End
Sub
Private
Sub
Form_AfterInsert
(
)
Call
AmenagerTailleSF
(
Me.Parent
, Me.Parent.ActiveControl
): Me.Requery
End
Sub
On peut écrire plusieurs instructions sur une même ligne de code, en les séparant par un deux-points. (Par exemple, lignes 5 et 9.)
V. Téléchargement▲
L'exemple en version Access2000 peut être téléchargé ici.
VI. Remerciements▲
Merci à Pierre Fauconnier pour ses remarques techniques au sujet de la syntaxe des gestions d'erreurs (utilisation de Case
0
pour éviter des Exit
Sub
dans le corps de la procédure).
Merci à Arkham46 pour l'amélioration du code : passer les objets en paramètres, plutôt que leur nom. En l'occurrence écrirePublic
Sub
AmenagerTailleSF
(
LeForm As
Access.Form
, LeSF As
Access.SubForm
)
plutôt quePublic
Sub
AmenagerTailleSF
(
LeNomDuForm as
String
, LeNomDuSubForm As
String
).
Merci à f-leb pour la correction orthographique.