I. Introduction▲
Par l'intermédiaire de l'étude de trois cas, nous allons décrire comment alimenter un même état avec différentes sources. 
		Cet article s'adresse à toute personne désirant alléger les objets de sa base ou rencontrant des difficultés de paramétrages. 
II. 1er cas : Filtrer la source au clic du bouton▲
Présentation de l'exemple▲
Une entreprise de fabrique de fauteuils et canapés souhaite imprimer le planning de fabrication des différents ateliers.
II-A. De quoi avons-nous besoin ?▲
II-A-1. Les tables▲
La table T_Articles qui contiendra toutes les informations sur l'article. Pour notre exemple nous n'aurons besoin que du CodeArticle (Clé primaire) et de la désignation de l'article.
		La table T_Ateliers qui contiendra deux informations : le CodeAtelier (Clé primaire) et le LibelAtelier.
		La table T_Productions qui contiendra les informations de la fabrication. À remarquer que la table ne contient aucune clé primaire. En effet le même n° OF sera repris pour le même article dans un atelier différent.
		Les tables seront jointes par les relations ci-dessous : 

II-A-2. Le formulaire▲
Il aura pour rôle de permettre à l'utilisateur de sélectionner un atelier et en cliquant sur le bouton « Imprimer le Planning » de lancer l'impression.

II-A-3. Un état▲
Qui sera l'objet de notre étude.

II-B. Description des objets▲
II-B-1. L'état▲
L'état sera bâti sur une requête dont la structure est montrée ci-dessous et la structure ci-contre :
| 
                 
  | 
              
                 
  | 
            
II-B-2. Le formulaire▲
Il s'agit en fait d'un formulaire indépendant, c'est-à-dire qu'aucune source ne lui est attachée. 
		On déposera sur celui-ci une liste déroulante indépendante et un bouton de commande. 
II-B-2-a. La liste déroulante▲

Pour alimenter notre liste déroulante, nous disposerons de trois solutions :
Source de la liste déroulante (ComboBox)
- Créer une liste de valeurs ;
 - À partir de la table T_Ateliers ;
 - À partir d'une requête UNION.
 
II-B-2-a-i. Créer une liste de valeurs▲
(Cela suppose que nous ne disposons pas de table T_Ateliers.)
		Soit en suivant les étapes de l'assistant.
		Soit en modifiant les valeurs des propriétés de la liste (voir ci-dessous).
| 
                     
  | 
                  
                     On remarquera que dans cette méthode on interviendra dans trois onglets :  | 
                
II-B-2-a-ii. À partir d'une table de la base de données▲
On procédera par l'assistant liste déroulante afin de générer l'objet. On n'oubliera pas de nommer notre liste cboAtelier.
Le nom de l'objet se définit dans la fenêtre des propriétés sur l'onglet « Autres ».
II-B-2-a-iii. Avec une requête UNION▲
Par cette méthode, on pourra intégrer la mention « TOUT » en entête de liste.
		Après avoir créé la liste comme précédemment :
		- appelez les propriétés de la liste par clic droit sur l'objet ;
		- cliquez dans l'onglet Données ;
		- cliquez dans la ligne Contenu et modifiez la syntaxe comme précisé dans l'image de droite.
| 
                     
  | 
                  
                     
  | 
                
Pour plus d'informations sur le langage SQL, allez voir là.
II-B-2-b. Le bouton de commande▲
Nous utiliserons le contrôle « Bouton » de la barre d'outils.
		En fait l'impression se lancera sur le clic de ce bouton. Il faut donc écrire une petite procédure événementielle.
Rappel : Affichez la fenêtre des Propriétés et dans l'onglet Événements, cliquez dans l’événement sur clic :
Private Sub btnImprimerAtelier_Click()
        'Déclaration d'une variable locale
        Dim intCompteur As Integer
        ' Teste la valeur choisie dans la liste du formulaire
        ' Si celle-ci est > 0 cela signifie qu'on a choisi un atelier précis
        If cboAtelier > 0 Then
            DoCmd.OpenReport "E_ImprimerPlanning", , , "CodeAtelier = " & cboAtelier
        Else
            ' Sinon on boucle pour imprimer l'ensemble des Ateliers en incrémentant un compteur de boucle
            For intCompteur = 1 To 7
                DoCmd.OpenReport "E_ImprimerPlanning", , , "CodeAtelier = " & intCompteur
            Next
        End If
    End SubIII. 2d cas : Changer la source au clic du bouton▲
III-A. Présentation de l'exemple▲
Une entreprise de fabrique de fauteuils et canapés souhaite imprimer les statistiques de production des différents ateliers (Par jour/par semaine/par mois).
III-B. De quoi avons-nous besoin ?▲
III-B-1. Les tables▲
La table T_Performances qui contiendra toutes les informations sur les résultats de l'atelier (Quantité prévue, Quantité réalisée, date de production, mois de production,année de production).
		La table T_Ateliers qui contiendra deux informations : le CodeAtelier (Clé primaire) et le LibelAtelier
		.
		Les tables seront reliées par les relations ci-dessous :

III-B-2. Le formulaire▲
Il aura pour rôle de permettre à l'utilisateur de sélectionner une période. Cette période pourra, par défaut, être la période en cours ou par l'intermédiaire d'un bouton …« Définir l'étendue… » une période précisée par l'utilisateur grâce à un contrôle Calendrier. Enfin, en cliquant sur le bouton « Imprimer le Planning » l'utilisateur lancera l'impression.
| 
                 
  | 
              
                 
  | 
            
III-B-3. L'état▲
III-C. Description des objets▲
III-C-1. Le formulaire▲
III-C-1-a. Création et paramétrages par défaut▲
Il sera bâti sur un formulaire indépendant et sera la plaque tournante de notre process.
		Étudions tout d'abord la structure de notre formulaire de choix de la périodicité. 
		On remarquera que le pied de formulaire contient le contrôle Calendrier ainsi que les champs correspondant au choix des dates. Dans l'image de droite, on retrouvera les différentes propriétés par défaut du formulaire. 
Afin de pouvoir manipuler confortablement les infos contenues dans le formulaire, il est fortement conseillé de nommer CHAQUE objet utilisé.
		Ainsi on trouvera :
		1 - grpFrequence / 2 - lblQuotidien / 2 - lblHebdo / 2 - lblMensuel (Chaque étiquette du grpFrequence)
		3 - btnEtendu / 4 - btnImprimer / 5 - objCalendrier / 6 - txtDebutPeriode / 7 - txtFinPeriode 
III-C-1-b. Initialisation du formulaire▲
Imaginons ce que doit faire l'utilisateur lors de la demande d'impression des statistiques.
		Celui-ci appelle le formulaire en cliquant sur un bouton du formulaire principal dédié à cet effet. 
		On doit donc gérer l'apparence du formulaire à l'ouverture de celui-ci. On fera donc déclencher une procédure événementielle à l'Ouverture du formulaire.
		Pour créer cette procédure, on affichera la fenêtre des propriétés et dans l'onglet « Événements » on recherchera l'événement : « Sur Ouverture »
		Dans la fenêtre VBE nous écrirons la procédure suivante : 
Private Sub Form_Open(Cancel As Integer)
        ' Initialisation du formulaire
        ' Rend le pied de formulaire invisible
        Me.Section(acFooter).Visible = False
        ' Initialise les textes dans les différentes options du groupe grpFrequence
        lblquotidien.Caption = "Tous les jours du mois en cours"
        lblHebdo.Caption = "Toutes les semaines du mois en cours"
        lblMensuel.Caption = "Tous les mois de l'année en cours"
        ' Initialise le texte du bouton  
        btnEtendue.Caption = "Définir l'étendue ..."
        ' Initialisation de variables utilisées dans le process
        ' Ces variables ont été déclarées publiques dans un module spécifique 
        ' (c'est-à-dire reconnue dans l'ensemble du projet VBA) 
        ' Remarque : le préfixe des variables permet de reconnaitre à la lecture le type d'info stockée)
        boolEtendue = False
        strIntituleMois = ""
        intAnneeTraitee = Year(Date)
        ' Initialise le contrôle calendrier à la date du jour
        objCalendrier.Value = Date
        'Exécute la commande "Ajuster à la taille du formulaire" du menu "Fenêtre" 
        'de la barre de menus "Formulaire" - Voir la remarque ci-dessous
        DoCmd.DoMenuItem acFormBar, 7, 6, 0, acMenuVer70
    End SubCette syntaxe a été remplacée à partir de Access 97 par RunCommand avec l'utilisation d'une constante intrinsèque.
Voir la syntaxe ci-dessous :
DoCmd.RunCommand acCmdSizeToFitFormIII-C-1-c. Utilisation du formulaire▲
Lorsque l'utilisateur ouvre le formulaire, deux situations peuvent se présenter :
		1) impression sur la date en cours (Formulaire en mode réduit) ;
		2) impression par rapport à une période précisée (Formulaire en mode étendu). 
III-C-1-d. Le formulaire réduit▲
L'utilisateur peut donc choisir trois périodes différentes.
		De chacune d'entre-elles va découler l'extraction de données dépendant de la fréquence choisie.
		Ce même processus sera repris pour chaque situation sélectionnée.
III-C-1-d-i. La fréquence quotidienne▲
| 
                     Formulaire  | 
                  
                     Requête associée  | 
                
|---|---|
| 
                     
  | 
                  
                     Public Const cstPerformances As String = "SELECT R_StatProductionPrevue.DateProduction As DProduct, " & _  | 
                
On remarquera deux points :
- la séquence SQL est stockée dans une constante publique afin d'alléger le code VBA lors de l'utilisation de la requête dans la procédure ;
 - que l'on fait appel à deux requêtes préalables. Celles-ci sont des requêtes « Analyse croisée ». Voir ci-dessous les structures :
 
| 
                     
  | 
                  
                     
  | 
                
III-C-1-d-ii. La fréquence hebdomadaire▲
| 
                     Formulaire  | 
                  
                     Requête associée  | 
                
|---|---|
| 
                     
  | 
                  
                     Public Const cstPerformancesHebdo As String = "SELECT DatePart(""ww"",[R_StatProductionRealisee.DateProduction]) AS DProduct, " & _  | 
                
On remarquera l'utilisation de la fonction DatePart(« "ww »",DateProduction) qui permettra de calculer le n° de la semaine de la date en cours.
(Les guillemets sont doublés parce qu'ils sont utilisés à l'intérieur d'une chaîne de caractères.)
Pour plus d'informations sur les fonctions de Date c'est par ici.
III-C-1-d-iii. La fréquence mensuelle▲
| 
                     Formulaire  | 
                  
                     Requête associée  | 
                
|---|---|
| 
                     
  | 
                  
                     Public Const cstPerformancesMensuelles As String = "SELECT T_Mois.LibelMois AS DProduct, " & _  | 
                
On remarquera la présence de la table T_Mois qui permettra de récupérer l'intitulé du mois par rapport au mois courant.
III-C-1-e. L'état▲
III-C-1-e-i. Description de l'état▲
L'état sera bâti sur une requête dont la structure est montrée ci-dessous et la structure ci-contre :
On remarquera que le contrôle contenant « Semaine » sera modifié par VBA en fonction du choix de la fréquence (Nom de l'objet : txtFrequence).
		La requête sous-jacente est traitée dans le code VBA en fonction de la périodicité choisie. 
		On verra ci-dessous la séquence SQL pour chaque périodicité concernée.
III-C-1-e-ii. Ouverture de l'état▲
Nous avons d'une part récupéré la séquence SQL par rapport à la période sélectionnée, nous venons de générer la Clause WHERE.
		Le reste du process s'exécute à l'ouverture de l'état. 
Private Sub Report_Open(Cancel As Integer)
            ' La variable octFrequence déclarée publique a été initialisée lors du choix de la fréquence dans le formulaire
            Select Case octFrequence
                Case Is = 1
                    'Initialisation du libellé de la zone de texte txtFrequence
                    txtFrequence.Caption = "Date"
                    ' C'est donc ici que sera initialisé la source de notre état
                    Me.RecordSource = cstPerformances & strEtendue
                Case Is = 2
                    txtFrequence.Caption = "Semaine"
                    Me.RecordSource = cstPerformancesHebdo & strEtendue
                Case Is = 3
                    txtFrequence.Caption = "Mois"
                    Me.RecordSource = cstPerformancesMensuelles & strEtendue
            End Select
        End SubIII-C-1-e-iii. Lancer l'impression▲
Le choix de la fréquence étant fait, l'utilisateur lancera alors l'impression en cliquant sur le bouton concerné. 
		Bien sûr, on aura écrit une procédure sur l’événement Clic du bouton btnImprimer (n° 4).
Private Sub btnImprimer_Click()
    ' Variable booléenne qui permet de connaitre l'état du formulaire 
    ' teste si le formulaire en mode Réduit
    If boolEtendue = False Then
        ' Initialise la variable par rapport au mois de la date en cours
        strIntituleMois = IntituleMois(Date)
        ' Création de la clause WHERE afin de la concaténer à la constante correspondant au choix de la fréquence
        ' octFrequence est une variable publique qui est initialisée lors du clic sur une des options dans le formulaire
        Select Case octFrequence
        Case Is = 1
           ' strEtendue : Variable publique récupérant la clause WHERE générée
            strEtendue = "WHERE R_StatProductionRealisee.MoisProduction = " & Month(Date) _ 
                         & " AND R_StatProductionRealisee.AnneeProduction = " & Year(Date)
        Case Is = 2
            ' Recherche le N° de semaine du premier jour du mois en cours et
            'le N° de semaine du dernier jour du mois en cours
            octNumSemaineDebut = DatePart("ww", DateSerial(Year(Date), Month(Date), 1))
            octNumSemaineFin = DatePart("ww", DateSerial(Year(Date), Month(Date), Day(DateSerial(Year(Date), Month(Date) + 1, 0))))
            ' Création de la clause WHERE
            strEtendue = "WHERE DatePart(""ww"",[R_StatProductionRealisee.DateProduction]) BETWEEN " _
                         & octNumSemaineDebut & " AND " & octNumSemaineFin & _
                         " GROUP BY DatePart(""ww"",[R_StatProductionRealisee.DateProduction])"
        Case Is = 3
            intNumAnnee = Year(Date)
            strEtendue = " WHERE R_StatProductionRealisee.AnneeProduction = " & intNumAnnee & _
                                  " GROUP BY T_Mois.LibelMois, R_StatProductionRealisee.MoisProduction " & _
                                  " ORDER BY R_StatProductionRealisee.MoisProduction"
        End Select
        ' dans la partie ELSE on traite la partie concernant le formulaire étendu
    Else
    ….
    ….
    End If
    ' Ferme le formulaire en cours
        DoCmd.Close
    ' Ouvre l'état des Performances en mode aperçu avant impression
        DoCmd.OpenReport "E_Performances", acViewPreview
    End SubIII-C-1-f. Conclusion sur le formulaire réduit▲
- En cliquant sur une fréquence : Initialisation la variable octFrequence.
 - En cliquant sur le bouton « Imprimer ».
Récupération de la constante SQL correspondant à la fréquence choisie.
Création de la clause WHERE correspondant à la fréquence choisie.
Ouverture de l'état « E_Performances ». - Sur l'ouverture de l'état
Initialisation de l'étiquette txtFrequence.
Création de la clause WHERE correspondant à la fréquence choisie.
Affectation de la nouvelle source de l'état en concaténant la constante SQL et la variable strEtendue. 
III-C-1-g. Le formulaire étendu▲
III-C-1-g-i. Activation du mode étendu▲
| 
                     
  | 
                  
                     En cliquant sur le bouton « Définir l'étendu », le formulaire affiche le pied de formulaire jusque là invisible et modifie les différents affichages de périodes ainsi que le texte affiché dans le bouton qui devient « Masquer le calendrier ». Voici ci-dessous la description de la procédure qui se trouve implantée dans l'événement « sur Clic » du bouton « btnEtendu » (n° 3 )  | 
                
Private Sub btnEtendue_Click()
        ' Teste sur le texte affiché sur le bouton
        If Screen.ActiveControl.Caption = "Définir l'étendue ..." Then
            ' Rend visible le pied de formulaire
            Me.Section(acFooter).Visible = True
             ' Change la légende du bouton et des étiquettes des options
            btnEtendue.Caption = "Masquer le Calendrier"
            lblquotidien.Caption = "Tous les jours dans la période choisie"
            lblHebdo.Caption = "Toutes les semaines dans la période choisie"
            lblMensuel.Caption = "Tous les mois dans la période choisie"
            ' Initialise le calendrier à la date du jour
            objCalendrier.Value = Date
            intAnneeTraitee = Year(Date)
            objCalendrier.Requery
            '  initialisation Pointeur de repérage du formulaire étendu
            boolEtendue = True
        Else
            ' Repositionne les valeurs du mode réduit
            Me.Section(acFooter).Visible = False
            btnEtendue.Caption = "Définir l'étendue..."
            lblquotidien.Caption = "Tous les jours du mois en cours"
            lblHebdo.Caption = "Toutes les semaines du mois en cours"
            lblMensuel.Caption = "Tous les mois de l'année en cours"
            ' Réinitialise la variable booléenne sur FAUX
            boolEtendue = False
        End If
        ' Exécute la commande "Ajuste à la taille du formulaire" du Menu "Fenêtre" 
        'de la barre de menus "Formulaire" - Voir Remarque
        DoCmd.DoMenuItem acFormBar, 7, 6, 0, acMenuVer70
    End SubCette syntaxe a été remplacée à partir de Access 97 par RunCommand avec l'utilisation d'une constante intrinsèque (voir ci-dessous) :
DoCmd.RunCommand acCmdSizeToFitFormComme pour le mode réduit on retrouvera trois situations.
| 
                     Fréquence quotidienne  | 
                  
                     Fréquence hebdomadaire  | 
                  
                     Fréquence mensuelle  | 
                
|---|---|---|
| 
                     
  | 
                  
                     
  | 
                  
                     
  | 
                
On remarquera que le texte des contrôles txtDebutPeriode et txtFinPeriode est modifié en fonction de la fréquence. Cette initialisation se fait sur le changement de fréquence (événement Après MAJ de grpFrequence).
On trouvera ci-dessous la description de la procédure :
Private Sub grpFrequence_AfterUpdate()
        ' Intitalisation de la variable octFrequence
        octFrequence = grpFrequence
        ' Intitalisation des zones de saisie des limites de période
        txtDebutPeriode = Null
        txtFinPeriode = Null
        Select Case octFrequence
            Case Is = 1
                lblDebut.Caption = "1er Jour "
                lblFin.Caption = "Dernier Jour"
            Case Is = 2
                lblDebut.Caption = "1re Semaine "
                lblFin.Caption = "Dernière Semaine"
            Case Is = 3
                lblDebut.Caption = "1er Mois "
                lblFin.Caption = "Dernier Mois"
        End Select
    End SubIII-C-1-g-ii. Le contrôle Calendrier▲
Pour paramétrer la procédure événementielle, il faut d'abord nommer notre objet dans l'onglet « Autres ». (On lui donnera le nom de « objCalendrier ») 
		Cliquez droit sur l'objet et choisir la commande « Créer une commande »
		La fenêtre VBE s'affiche. 
		Dans la liste en haut à droite, sélectionnez l'événement « sur clic » 
Private Sub objCalendrier_Click()
        If IsNull(txtDebutPeriode) Then
            Select Case octFrequence
                Case Is = 1
                    txtDebutPeriode = CDate(objCalendrier)
                   ' Récupération de la date au format utilisé dans les requêtes
                    strDateDebut = Format(CDate(objCalendrier),"mm/dd/yy)
                Case Is = 2
                    octNumSemaineDebut = DatePart("ww", CDate(objCalendrier.Value))
                    txtDebutPeriode = octNumSemaineDebut
                Case Is = 3
                    strMoisDebut = IntituleMois(CDate(objCalendrier))
                    octMoisDebut = Month(CDate(objCalendrier))
                    txtDebutPeriode = strMoisDebut
            End Select
        Else
            Select Case octFrequence
            Case Is = 1
                If CDate(objCalendrier) < txtDebutPeriode Then
                    MsgBox "Erreur de choix" & vbCrLf & "La fin de la période indiquée est antérieure au début de la période", vbInformation, "Statistiques des performances"
                    Exit Sub
                Else
                    txtFinPeriode = CDate(objCalendrier)
                    strDateFin = Format(CDate(objCalendrier),"mm/dd/yy")
                End If
            Case Is = 2
                octNumSemaineFin = DatePart("ww", CDate(objCalendrier.Value))
                ' Test de contrôle de saisie
                If octNumSemaineFin < octNumSemaineDebut Then
                    ' Si le n° de semaine fin est inférieur au n° de semaine début, contrôle sur l'année
                    If Year(txtDebutPeriode) = Year(txtFinPeriode) Then
                         MsgBox "Erreur de choix" & vbCrLf & "La fin de la période indiquée est antérieure au
                        début de la période", vbInformation, "Statistiques des performances"
                    Exit Sub
                    End if
                Else
                    txtFinPeriode = octNumSemaineFin
                End If
            Case Is = 3
                strMoisFin = IntituleMois(CDate(objCalendrier))
                octMoisFin = Month(CDate(objCalendrier))
                If octMoisFin < octMoisDebut Then
                    MsgBox "Erreur de choix" & vbCrLf & "La fin de la période indiquée est antérieure au début de la période", vbInformation, "Statistiques des performances"
                    Exit Sub
                Else
                    txtFinPeriode = strMoisFin
                End If
            End Select
        End If
        intAnneeTraitee = Year(CDate(objCalendrier))
    End SubIII-C-1-g-iii. Lancer l'impression▲
Les constantes qui seront récupérées sont les mêmes que pour le mode réduit, par contre les clauses WHERE dépendent de la fréquence choisie.
		Rappelons que l'initialisation de celles-ci se fait sur le clic du bouton « btnImprimer »« btnImprimer » 
Private Sub btnImprimer_Click()
    ' Première partie du IF : gère le formulaire mode réduit
    If boolEtendue = False Then
        ….
        ….
    Else
        ' Variable publique initialisée sur le choix d'une fréquence
    Select Case octFrequence
        ' Représente la fréquence quotidienne
        Case Is = 1
            ' Création de la clause WHERE
            strEtendue = "WHERE R_StatProductionRealisee.DateProduction BETWEEN #" _
                         & format(CDate(txtDebutPeriode),"mm/dd/yy") & "# AND #" _
                         & format(CDate(txtFinPeriode),"mm/dd/yy)) & "#"
        ' Représente la fréquence hebdomadaire
        Case Is = 2
            ' Création de la clause WHERE
            strEtendue = "WHERE DatePart(""ww"",[R_StatProductionRealisee.DateProduction]) BETWEEN " _
                         & octNumSemaineDebut & " AND " & octNumSemaineFin _
                         & " GROUP BY DatePart(""ww"",[R_StatProductionRealisee.DateProduction])"
        ' Représente la fréquence mensuelle
        Case Is = 3
            intNumAnnee = intAnneeTraitee
            strEtendue = " WHERE R_StatProductionRealisee.AnneeProduction = " & intNumAnnee & _
                                  " GROUP BY T_Mois.LibelMois, R_StatProductionRealisee.MoisProduction " & _
                                  " HAVING R_StatProductionRealisee.MoisProduction BETWEEN " & octMoisDebut & _
                                  " AND " & octMoisFin & " ORDER BY R_StatProductionRealisee.MoisProduction"
    End Select
    End If
    DoCmd.Close
    ' Ouvre l'état des performances.
    DoCmd.OpenReport "E_Performances", acViewPreview
End SubOn retrouvera la même procédure à l'ouverture de l'état que pour le cas du formulaire en Mode réduit.
III-C-1-h. Conclusion sur le mode étendu▲
- En cliquant sur « Définir l'étendue… »
Le Calendrier s'affiche. - En cliquant sur une fréquence
Initialise la variable octFrequence.
Modifie l'affichage des étiquettes en bas du formulaire. - En cliquant sur le bouton « Imprimer »
Récupération de la constante SQL correspondant à la fréquence choisie.
Création de la clause WHERE correspondant à la fréquence choisie.
Ouverture de l'état « E_Performances ». - Sur l'ouverture de l'état
Initialisation de l'étiquette txtFrequence.
Affectation de la nouvelle source de l'état en concaténant la constante SQL et la variable strEtendue 
IV. 3e Cas : Filtrer la source de l'état et changer la source des différents contrôles de la section Détail▲
IV-A. Présentation de l'exemple▲
Une entreprise de fabrique de fauteuils et canapés souhaite imprimer le planning de fabrication des différents ateliers.
IV-B. De quoi avons-nous besoin ?▲
IV-B-1. Les tables▲
La table T_Articles qui contiendra toutes les informations sur l'article. Pour notre exemple nous n'aurons besoin que du CodeArticle (Clé primaire) et de la désignation de l'article.
		La table T_Ateliers qui contiendra deux informations : le CodeAtelier (Clé primaire) et le LibelAtelier.
		La table T_Productions qui contiendra les informations de la fabrication. 
		À remarquer que cette table a une structure différente de notre premier exemple. En effet, on retrouve dans la structure de celle-ci trois champs par atelier (voir ci-dessous). 
IV-B-2. Le formulaire▲
| 
                 
  | 
              
                 De même structure que pour le premier cas étudié, il aura pour rôle de permettre à l'utilisateur de sélectionner un atelier et en cliquant sur le bouton « Imprimer le Planning » de lancer l'impression.  | 
            
IV-B-3. Un état▲
On remarquera que dans cette structure tous les champs sont indépendants (donc par définition reliés à aucune source).
		Néanmoins pour faciliter l'utilisation de ces différents contrôles, on les nommera.
		Pour nommer chaque zone de texte, il faut la sélectionner et appeler la fenêtre des Propriétés.
		Dans l'onglet « Autres » saisir un nom qui sera évocateur (exemple :txtTitreEtat et non ZoneTexte1). 
| 
                 
  | 
              
                 
  | 
            
1 - txtTitreEtat / 2 - txtDatePlanning / 3 - txtNumOrdre / 4 - txtOF / 5 - txtDesignation
IV-B-4. Les requêtes▲
Comme pour le premier exemple, tout le process se déroule sur le clic du bouton « btnImprimer » du formulaire.
		Les requêtes seront stockées dans une variable strSqlImpression qui sera utilisée lors de l'ouverture de l'état. 
' Génération de la requête pour l'atelier coupe
                strSqlImpression = "SELECT [T_Productions].[OF], T_Articles.DesignationArticle, " _
                & [T_Productions].DateCoupe, [T_Productions].CoupeTermine " _
                & " T_Articles INNER JOIN [T_Productions].ON T_Articles.CodeArticle = [T_Productions].CodeArticle " & _
                "WHERE [T_Productions].DateCoupe=#" & varDateImpression & "# AND [T_Productions].CoupeTermine=No"
     ' Génération de la requête de l'atelier Couture pour les articles dont l'atelier COUPE est terminé
                strSqlImpression = "SELECT [T_ Productions].OF, T_Articles.DesignationArticle, " _
                & [T_Productions].DateCouture, [T_ Productions].CoupeTermine " & _
                "FROM T_Articles INNER JOIN T_ Productions ON T_Articles.CodeArticle = ON [T_Productions].OF " & _
                "WHERE T_Productions.CoupeTermine=Yes AND T_Productions.DateCouture)=#" & varDateImpression _
                & "# AND T_Productions.CoutureTermine=No"
     ' Génération de la requête de l'atelier Bois
                strSqlImpression = "SELECT [T_Productions].OF, T_Articles.DesignationArticle, " _
                & T_Productions.DateBois, T_Productions.BoisTermine " & _
                "FROM T_Articles INNER JOIN T_Productions ON T_Articles.CodeArticle = T_Productions.CodeArticle & _
                "WHERE T_Productions.DateBois=#" & varDateImpression & "# AND T_Productions.BoisTermine=No"
     ' Génération de la requête de l'atelier Mousse pour les articles dont l'atelier BOIS est terminé
                strSqlImpression = "SELECT [T_Productions].OF, T_Articles.DesignationArticle,  " _
                & T_Productions.DateMousse, T_Productions.MousseTermine " & _
                "FROM T_Articles INNER JOIN T_Productions ON T_Articles.CodeArticle = T_Productions.CodeArticle) " & _
                "WHERE T_Productions.BoisTermine=Yes AND T_Productions.DateMousse=#" & varDateImpression _
                & "#  AND T_Productions.MousseTermine=No AND T_Productions.ProblemeMousse=No"Ainsi de suite pour les sept ateliers.
		Ces séquences SQL seront récupérées dans la procédure sur Clic du bouton btnImprimer décrite ci-dessous :
    Private Sub cmdImprimer_Click()
        ' Déclaration d'une variable compteur qui permettra de retrouver le nom de l'atelier en cours d'impression
        Dim intCompteurImpression As Integer
        ' cboAtelier est le nom de la liste déroulante du formulaire
        ' Le code 8 correspond au choix "Tout"
        If cboAtelier = 8 Then
            For intCompteurImpression = 1 To 7
                ' La propriété Column permet de récupérer l'info contenue dans une colonne d'une liste déroulante,
                ' il faut indiquer la position de cette colonne -1 parce que l'indexation de colonnes commence à 0
                strNomAtelier = cboAtelier.Column(intCompteurImpression - 1)
               ' Récupération des Séquences SQL définies ci-dessus en fonction du compteur de boucle
                CreationRequeteImpression (intCompteurImpression)
            Next
            Else
                ' Un atelier spécifique a été choisi
                strNomAtelier = cboAtelier.Column(intCompteurImpression - 1)
               ' Récupération de la  Séquence SQL définie ci-dessus par rapport à l'atelier choisi
                CreationRequeteImpression (cboAtelier)
        End If
                ' Ouverture de l'état
                DoCmd.OpenReport "E_PlanningLancementFab", acPreview
    End SubIV-C. Lancer l'impression▲
Il nous reste donc à découvrir les procédures qui vont s'exécuter à l'ouverture de l'état.
IV-C-1. La section Entête d'état▲
On créera une petite procédure sur le formatage de la section entête. 
		On passera donc par la fenêtre des « Propriétés » puis onglet « Événements » :
    Private Sub EntêteÉtat_Format(Cancel As Integer, FormatCount As Integer)
        txtTitreEtat = "PLANNING ATELIER : " & strNomAtelier
        txtDatePlanning = DateTraitee
    End SubIV-C-2. La section Détail▲
Pour la création de l'état, il nous faudra écrire deux procédures. 
IV-C-2-a. Affectation de la source aux contrôles▲
Cette affectation se fait sur l’événement « À l'ouverture de l'état ».
		On procédera comme à l'accoutumée :
- affichez l'état en mode création ;
 - cliquez droit dans la section « Détail » ;
 - cliquez « Propriétés » ;
 - activez l'onglet « Événement » ;
 - cliquez dans l’événement « À l'ouverture ».
 
Private Sub Report_Open(Cancel As Integer)
        ' Déclaration des variables
        Dim rstImpression As DAO.Recordset
        ' Initialisation du jeu d'enregistrements en fonction de la séquence récupérée
        Set rstImpression = CurrentDb.OpenRecordset(strSqlImpression)
        ' Traitement du jeu d'enregistrements
        With rstImpression
            ' Contrôle du contenu
            If .BOF = True And .EOF = True Then
                MsgBox "Il n'y a rien à imprimer sur le planning de : " & strNomAtelier
                ' Annulation de l'événement Ouverture de l'état
                Cancel = True
               Exit Sub
            End If
            ' Affectation de la source à l'état
            Reports("E_PlanningFabrication").RecordSource = strSqlImpression
            ' Affectation des champs de la source aux contrôles de la zone Détail - Voir remarque
            Me.txtOF.ControlSource = .Fields(1).Name
            Me.txtDesignationArticle.ControlSource = .Fields(2).Name
        End With
    End SubOn utilise l'objet Fields(index) pour affecter le nom du champ aux contrôles de la section Détail.
Les requêtes étant bâties toutes sur la même structure, cela nous permet d'utiliser une procédure générale.
IV-C-2-b. Formatage de la section Détail▲
Afin d'assurer une meilleure présentation de l'état, nous souhaitons mettre une ligne sur deux avec un fond coloré. Cette procédure est attachée à l'événement Sur Formatage de la section détail :
Private Sub Détail_Format(Cancel As Integer, FormatCount As Integer)
        ' Déclaration d'une variable statique (la valeur est préservée durant le traitement)
        Static NumLigne
        NumLigne = NumLigne + 1
        Me.txtNumOrdre = NumLigne
        ' affecte un fond grisé pour les lignes paires
        If NumLigne Mod 2 = 0 Then
            Me.Détail.BackColor = 14869218
        Else
        ' Affecte un fond blanc pour les lignes impaires
            Me.Détail.BackColor = 16777215
        End If
    End SubIV-D. Conclusion sur l'affectation de la source à l'état et aux contrôles▲
- Après avoir choisi un atelier, en cliquant sur le bouton btnImprimer :
Création de la séquence SQL en fonction de l'atelier. - Impression de l'état
Affectation de la source de l'état.
Affectation de la source aux contrôles de la zone de Détail.
Formatage de la section Entête d'état.
Formatage de la section Détail. 
V. Bibliographie▲
« Access en Action » de Ken Getz, Paul Litwin et Andy Baron aux éditions O'REILLY
		Excellent ouvrage dans lequel j'ai trouvé l'exemple de l'utilisation du formulaire étendu. 
VI. Remerciements▲
Dolphy35 pour son incitation à la rédaction de cet article, son aide pour la prise en main de l'outil de Nono40.
Heureux-oli pour son soutien et ses explications lors de la première mise en place dans mon domaine.
Loufab pour ses précieux conseils de présentation. Starec, RideKick, Claude LELOUP pour leur relecture attentive. SQLPro pour sa permission d'accéder à son site. 
 




 
 
 
 
 
 
 



 
 
 
 
 
 
 
 
 
