I. Ce que l'on veut réaliser▲
Soit une table de mouvements comptables :

On voudrait un état dans lequel chacun des journaux (Achats, Caisse…) est paginé individuellement :
II. Si vous êtes pressé▲
… que vous n'aimez pas lire et que seul le résultat vous intéresse, voici comment y arriver :
- construisez votre état en vous inspirant de ce schéma :
- dans le module associé à l'état, vous collez aveuglément ce code :
Option Compare Database
Option Explicit
Dim sCtlGroupe As String
Dim sValGroup As String
Dim sChampGroupe As String
Dim oColTable As Collection
Public Sub MaJoColTable(Groupe As String, NumPage As Integer)
On Error GoTo GestionErreurs
If NumPage > oColTable(Groupe) Then
oColTable.Remove Groupe
oColTable.Add NumPage, Groupe
End If
GestionErreurs:
Select Case Err.Number
Case 0 'pas d'erreur
Case 5 'pas encore dans la collection
oColTable.Add NumPage, Groupe
End Select
End Sub
Public Function GetPages(Groupe As String) As Integer
GetPages = oColTable(Groupe)
End Function
Private Sub Report_Open(Cancel As Integer)
On Error GoTo GestionErreurs
'Recherche du nom du contrôle qui contient le champ de groupage
sChampGroupe = Me.Report.GroupLevel(0).ControlSource '<----- le niveau de regroupement le plus élevé
'Construire la propriété Contrôle source du champ txtNumerotation
Me.txtNumerotation.ControlSource = "="" Page "" & [Page] & "" sur "" & getpages([" & sChampGroupe & "])"
'Initialiser la collection
Set oColTable = New Collection
GestionErreurs:
Select Case Err.Number
Case 0 'pas d'erreur
Case Else
MsgBox "Erreur dans Report_Open N° " & Err.Number & " " & Err.Description
End Select
End Sub
Private Sub EntêteGroupe0_Format(Cancel As Integer, FormatCount As Integer)
' Provoquer la réinitialisation de [Page] au changement de Groupe
Me.Page = 1
End Sub
Private Sub ZonePiedPage_Format(Cancel As Integer, FormatCount As Integer)
Call MaJoColTable(Me(sChampGroupe), Me.Page)
End Sub
Private Sub Report_Close()
Dim E As Integer
'Libérer l'objet collection de la mémoire
For E = 1 To oColTable.Count
oColTable.Remove 1
Next
Set oColTable = Nothing
End SubMais, si vous voulez comprendre pourquoi ça marche, faites l'effort de lire la suite…
III. L'idée qui sous-tend la programmation▲
III-A. À propos des propriétés Page et Pages d'un état dans Access▲
|
|
La propriété Page spécifie le numéro de la page en cours lors de l'impression. Sélectionnez recommencera la numérotation à partir de 1 pour le groupe en cours de traitement. |
III-B. On va forcer Access à construire l'état en deux temps▲
- On place dans l'état, un contrôle avec comme source =[Pages].
- À chaque changement de groupe, dans l'événement Au formatage de l'entête de groupe, on remet la propriété [Page] à 1.
- À chaque formatage d'une page, dans l'événement Au formatage du pied de page, on mémorise dans un tableau interne la paire : Nom du groupe/N° de page. Dans ce tableau, on ne retient pour un même Nom du groupe que la ligne qui contient le plus grand N° de page.
En d'autres mots, quand Access a fini sa première passe, le tableau contient une ligne par Nom de groupe et son N° de page le plus élevé, donc le nombre de pages de ce groupe.
- Au deuxième passage, Access sera en mesure de compléter la valeur du contrôle txtNumerotation dont la source a été construite à l'ouverture, dans notre exemple :
IV. Analyse détaillée du code VBA▲
IV-A. Définition des variables▲
Option Compare Database
Option Explicit
Dim sCtlGroupe As String
Dim sValGroup As String
Dim sChampGroupe As String
Dim oColTable As CollectionElles sont définies en tête de module pour que leur valeur soit disponible tant que l'état est ouvert.
IV-B. Dans l'événement Sur ouverture▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Private Sub Report_Open(Cancel As Integer)
On Error GoTo GestionErreurs
'Recherche du nom du contrôle qui contient le champ de groupage
sChampGroupe = Me.Report.GroupLevel(0).ControlSource '<----- le niveau de regroupement le plus élevé
'Construire la propriété Contrôle source du champ txtNumerotation
Me.txtNumerotation.ControlSource = "="" Page "" & [Page] & "" sur "" & getpages([" & sChampGroupe & "])"
'Initialiser la collection
Set oColTable = New Collection
GestionErreurs:
Select Case Err.Number
Case 0 'pas d'erreur
Case Else
MsgBox "Erreur dans Report_Open N° " & Err.Number & " " & Err.Description
End Select
End Sub
Commentaires
4 : syntaxe pour retrouver le nom de la colonne qui contient les valeurs à regrouper.
6 : par exemple, si l'instruction 4 a révélé que « Journal » est le nom de la colonne à regrouper, la propriété Contrôle source du champ txtNumerotation sera :
=" Page " & [Page] & " sur " & getpages([Journal]).
IV-C. Dans l'événement « Au formatage » entête de groupe▲
Private Sub EntêteGroupe0_Format(Cancel As Integer, FormatCount As Integer)
' Provoquer la réinitialisation de [Page] au changement de Groupe
Me.Page = 1
End SubOn recommence la numérotation à 1.
IV-D. Dans l'événement « Au formatage » du pied de page▲
Private Sub ZonePiedPage_Format(Cancel As Integer, FormatCount As Integer)
Call MaJoColTable(Me(sChampGroupe), Me.Page)
End SubAvec en paramètres la valeur du groupe et le N° de la page en cours, on appelle la routine de mise à jour de la table interne.
L'algorithme est le suivant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Public Sub MaJoColTable(Groupe As String, NumPage As Integer)
On Error GoTo GestionErreurs
If NumPage > oColTable(Groupe) Then
oColTable.Remove Groupe
oColTable.Add NumPage, Groupe
End If
GestionErreurs:
Select Case Err.Number
Case 0 'pas d'erreur
Case 5 'pas encore dans la collection
oColTable.Add NumPage, Groupe
End Select
End Sub
Commentaire du code
3 : si la clé Groupe (la rubrique du journal) n'est pas encore dans la collection, une erreur N° 5 sera générée. On récupère cette dernière aux instructions 10 et 11, où on ajoute l'item à la collection.
Par contre, si la clé est déjà présente avec un N° de page inférieur, on l'élimine pour la remplacer par une paire Nouveau N° de page/Rubrique.
IV-E. À la fermeture de l'état▲
Private Sub Report_Close()
Dim E As Integer
'Libérer l'objet collection de la mémoire
For E = 1 To oColTable.Count
oColTable.Remove 1
Next
Set oColTable = Nothing
End SubV. Téléchargement▲
La base de données de test au format Access2000 est disponible ici.
VI. Remerciements▲
Merci à tee_grandbois pour ses remarques.
Merci à Jean-Philippe AMBROSINO (argyronet) pour la relecture technique et les corrections pour améliorer la qualité du code.
Merci à f-leb, Winjerome et dourouc05 pour la correction orthographique.








