Comment ajuster la taille d'un sous-formulaire en fonction du nombre de ses enregistrements

Claude Leloup

Voici une occasion pour vous familiariser avec les instructions VBA qui permettent de manipuler les propriétés d'un formulaire. Commentez

- Titre : Comment ajuster la taille d'un sous-formulaire en fonction du nombre de ses enregistrements

- Auteur : Claude Leloup

- Parution : 21 octobre 2015

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2015 Claude Leloup. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Ce dont il s'agit

- II. Préparons le terrain

- II-A. Convention de nommage

- II-B. Des repères pour indiquer la hauteur maximum des sous-formulaires

- III. Une sous-routine pour adapter la hauteur du conteneur de sous-formulaire

- III-A. Le code

- III-B. Explication du code

- IV. Quand et comment déclencher cette sous-routine

- IV-A. À chaque lecture d'un enregistrement du formulaire principal

- IV-B. À chaque ajout ou suppression d'enregistrement dans le sous-formulaire

- V. Téléchargement

- VI. Remerciements

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

AmenagerTailleSF

1. Option Compare Database

2. Option Explicit

4. Public Sub AmenagerTailleSF(LeForm As Access.Form, LeSF As Access.SubForm)

5. Dim EspaceNecessaire As Long, EspaceLibre As Long, iAffichables As Integer

6. On Error GoTo GestionErreurs

8. With LeSF

9. 'Calculer l'espace nécessaire pour afficher tous les enregistrements

10. .Form.RecordsetClone.MoveLast 'pour pouvoir ensuite compter le nbre d'enregistrements

11. EspaceNecessaire = .Form.Section(acHeader).Height _

12. + .Form.Section(acFooter).Height _

13. + .Form.Section(acDetail).Height _

14. * (.Form.RecordsetClone.RecordCount - .Form.AllowAdditions) 'Ceci revient à ajouter 1 si ajout autorisé

16. 'Calculer l'espace disponible et le nbre d'enregistrements affichables

17. EspaceLibre = LeForm("Bas" & LeSF.Name).Top - .Top

18. iAffichables = Int(((EspaceLibre - .Form.Section(acHeader).Height - .Form.Section(acFooter).Height) / _

19. .Form.Section(acDetail).Height))

21. 'Limitation au maximum possible

22. If EspaceNecessaire > EspaceLibre Then  'trop pour tout afficher

23. .Height = EspaceLibre

24. .Form.InsideHeight = EspaceLibre

25. .Form.ScrollBars = 2 'pour afficher une barre de défilement verticale

26. 'Afficher les derniers enregistrements de la liste

27. .SetFocus

28. DoCmd.GoToRecord , , acNewRec 'afficher l'emplacement de l'ajout si permis, sinon erreur 2105 et instruction suivante

29. DoCmd.GoToRecord , , acLast

30. DoCmd.GoToRecord , , acPrevious, iAffichables - 1 + .Form.AllowAdditions

31. 'se positionner sur le dernier

32. DoCmd.GoToRecord , , acLast

33. Else

34. .Height = EspaceNecessaire

35. .Form.InsideHeight = EspaceNecessaire

36. .Form.ScrollBars = 0  ' pas de barre de défilement verticale

37. 'Afficher tous les enregistrements et se positionner sur le dernier

38. .SetFocus

39. DoCmd.GoToRecord , , acFirst

40. DoCmd.GoToRecord , , acLast

41. End If

42. End With

43. GestionErreurs:

44. Select Case Err.Number

45. Case 0        'Pas d'erreur

46. Exit Sub

47. Case 3021     'Pas d'enregistrement dans le sous-formulaire

48. Resume Next

49. Case 2105 'Pas d'ajout permis dans le sous-formulaire

50. Resume Next

51. Case Else

52. MsgBox "Erreur dans AmenagerTailleSF : " & vbLf & "N° erreur : " & Err.Number & " " & Err.Description, vbCritical

53. End Select

54. 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 » :

1. Option Compare Database

2. Option Explicit

4. Private Sub Form_AfterDelConfirm(Status As Integer)

5. Call AmenagerTailleSF(Me.Parent, Me.Parent.ActiveControl): Me.Requery

6. End Sub

8. Private Sub Form_AfterInsert()

9. Call AmenagerTailleSF(Me.Parent, Me.Parent.ActiveControl): Me.Requery

10. 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 écrire
Public Sub AmenagerTailleSF(LeForm As Access.Form, LeSF As Access.SubForm)
plutôt que
Public Sub AmenagerTailleSF(LeNomDuForm as String, LeNomDuSubForm As String).

Merci à f-leb pour la correction orthographique.