I. Contexte▲
Cette petite application est une extraction d'une base plus globale qui gère le personnel et les chiffres d'une petite entreprise familiale. Les tables, utilisées ici, ne reprennent que les informations utiles à la génération du planning. Je n'aborderai pas la validation du planning qui avait pour but de modifier directement les données de la table T_TempsTravail qui contient les temps de travail des employés. Par contre, en lieu et place du bouton de validation du planning, j'ai ajouté dans le formulaire un bouton qui donnera la possibilité d'ajouter un salarié afin de voir comment la table T_PlanningPreparation est alimentée.
II. Les tables▲
Pour bien appréhender la base, je vais vous présenter les différentes tables qui entrent en jeu.
II-A. T_Employes▲
Reprend les informations basiques du salarié.
| Nom du Champ | Type | Description |
|---|---|---|
| Matricule | NuméroAuto | Clé Primaire |
| NomEmploye | Texte | Reprend le patronyme de l'employé |
| PrenomEmploye | Texte | Reprend le prénom de l'employé |
Pour les débutants : on pourra remarquer que dans les noms de champs, je n'utilise ni accent, ni espace.
II-B. T_Activite▲
Reprend les informations des différents types d'activités ou de situations pouvant être affectées à l'employé dans l'entreprise.
| Nom du Champ | Type de Données | Description |
|---|---|---|
| CodeActivite | NuméroAuto | Clé Primaire |
| LibelActivite | Texte | Intitulé de l'activité ou de la situation |
| ImageActivite | Texte | Contient le chemin des images liées à l'activité ou à la situation d'un employé |
II-C. T_Contrats▲
Reprend les informations relatives au contrat du salarié. Cette table a été très simplifiée par rapport à l'application originale.
| Nom du Champ | Type de Données | Description |
|---|---|---|
| CodeContrat | NuméroAuto | Clé Primaire |
| Matricule | Numérique | En relation avec la table T_Employes |
| TypeContrat | Texte | Indique s'il s'agit d'un CDI, CDD, Extra, Apprenti |
| DebutContrat | Date | Date du Début du Contrat |
| FinContrat | Date | Date de Fin de Contrat |
| DebutAmContractuel | Numérique | Heure de début de travail service du Midi (Théorique) |
| FinAmContractuel | Numérique | Heure de fin de travail service du Midi (Théorique) |
| DebutPmContractuel | Numérique | Heure de début de travail service du soir (Théorique) |
| FinPmContractuel | Numérique | Heure de fin de travail service du soir (Théorique) |
Afin de faciliter la saisie, des valeurs par défaut seront implantées :
- DebutAmContractuel = 10.00 ;
- FinAmContractuel = 14.30 ;
- DebutPmContractuel = 18.30 ;
- FinPmContractuel = 22.00 ;
- CodeActivite = 1 (Travail).
II-D. T_PlanningPreparation▲
C'est la table qui reprend toute l'activité du salarié.
| Nom du Champ | Type de Données | Description |
|---|---|---|
| CodeContrat | Numérique | Est en relation avec la table des contrats |
| MoisPlanning | Numérique | Contient le quantième du mois. Il y aura autant d'enregistrements dans la table que de mois correspondant à la durée du contrat |
| AnneePlanning | Numérique | Contient l'année |
| Activite1 | Numérique | Contient le code d'activité du salarié (1 = Travail (par défaut)) pour le 1er jour du mois |
| .... | ||
| Activite31 | Numérique | Contient le code d'activité du salarié (1 = Travail (par défaut)) |
Il y a 31 champs "Activité". Chaque champ représente un jour du mois. On considère que tous les mois ont 31 jours.
Le traitement en arrière-plan ne fera apparaître, dans le planning, que les jours correspondant au mois en cours.
Ne pas oublier que cette table ne sert que pour la préparation des plannings et que les données seront ensuite stockées dans la table T_TempsTravail.
II-E. T_TempsTravail▲
Je vous présente cette table par rapport à la modélisation de l'application. En effet, la table T_PlanningPréparation, de par sa structure,
ne répond pas aux règles de normalisation d'une base de données (cf : la suite des champs Activite1 à Activite31).
Cette table contient toutes les données de travail des employés. Elle est modifiée :
1. lors de la validation du planning ;
2. lors de la saisie des temps de travail des employés ;
3. lors de la saisie d'une observation pour une date donnée et un salarié particulier.
Ces traitements ne seront pas abordés car ils débordent du sujet de ce tutoriel.
| Nom du Champ | Type de Données | Description |
|---|---|---|
| CodeContrat | Numérique | Contient le Numéro de contrat du salarié |
| JourTravail | Date/Heure | Contient la date du jour de travail |
| CodeActivite | Numérique | Contient le Code de l'activité assurée par l'employé |
| HeureDebutAm | Numérique | Contient l'heure de début du service du midi (Format : Fixe) |
| HeureFinAm | Numérique | Contient l'heure de fin du service du midi (Format : Fixe) |
| HeureDebutPm | Numérique | Contient l'heure de début du service du soir (Format : Fixe) |
| HeureFinPm | Numérique | Contient l'heure de fin du service du soir (Format : Fixe) |
| Observation | Texte | Contient toute remarque afférente à la journée de travail du salarié |
II-F. T_Mois▲
Petite table d'information permettant d'avoir les libellés des mois dans différentes situations (Liste déroulante, Impression ...).
| Nom du Champ | Type de Données | Description |
|---|---|---|
| CodeMois | Numérique | Contient le Quantième du mois de l'année |
| LibelleMois | Texte | Continent le nom du mois |
II-G. Le modèle relationnel▲
III. Présentation du Planning▲
Dans l'image ci-dessus, nous avons une vue d'ensemble du formulaire servant à la préparation du planning.
1. Les différents boutons de gestion (navigation par semaine, nouvelle saisie, impression).
2. Les étiquettes et les dates à mettre à jour pour chaque changement de semaine.
3. La liste des situations ou activités liées à une image.
IV. Les différents formulaires▲
IV-A. Le choix du Planning▲
IV-A-1. Implantation de la liste et de la zone de texte▲
|
Petit formulaire simple permettant à l'utilisateur de sélectionner le mois sur lequel il souhaite intervenir : - soit pour la préparation ; - soit pour imprimer le planning. Ce formulaire contient une liste déroulante basée sur la table T_Mois et une zone de texte pour y saisir l'année concernée. Nous modifierons les propriétés Nom des deux objets : - pour la liste déroulante : cboMois ; - pour la zone de texte : txtAnneeConcernee. |
IV-A-2. Implantation du bouton "Ouvrir Planning"▲
|
Avant d'implanter les boutons, désactivez l'assistant contrôle comme indiqué dans l'image ci-contre. Cliquez sur l'outil Bouton puis cliquez sur le formulaire pour déposer l'objet. Dans le volet des propriétés du bouton : - onglet Autres : changez le nom de l'objet (btnOuvrirPlanning) ; - onglet Format : saisissez la légende (Ouvrir le planning) ; - onglet Évènements : sur clic, choisissez Procédure évènementielle. |
IV-A-3. Le code dans ce formulaire▲
|
Nous aurons besoin de passer des informations d'un formulaire à un autre (le mois et l'année du planning). Pour faciliter le transit de celles-ci, nous allons utiliser des Variables Publiques. Il faut les déclarer dans un module spécial. 1. Ouvrez la fenêtre de l'éditeur VBA (Alt F11). 2. Cliquez sur l'outil Ajouter un module. 3. Dans le volet des propriétés, changez le nom du module en saisissant : Déclaration Globale. |
Nous allons déclarer les deux variables nécessaires :
' Récupèrera le mois choisi dans la liste déroulante : cboMois
Public p_intMoisPlanning As Integer
' Récupèrera l'année saisie dans la zone de texte : txtAnneeConcernee
Public p_intAnneePlanning As IntegerIV-B. Création du Formulaire du Planning▲
IV-B-1. Section Détail▲
Cette première phase permettra de créer les différents objets du planning c'est-à-dire :
- une zone de texte pour afficher le n° de contrat ;
- une zone de texte pour afficher le nom du salarié ;
- sept contrôles "Image" pour afficher les images des différentes situations ou activités ;
- sept listes déroulantes qui afficheront les choix possibles issus de la table T_Activite.
Ces différents éléments seront alimentés par une requête affectée au formulaire :
- soit à l'ouverture du formulaire ;
- soit à l'utilisation des boutons de navigation.
C'est dans cet objectif que nous affecterons une Source contrôle à chaque objet dont le nom sera repris dans chaque requête.
IV-B-1-a. Les deux zones de texte▲
|
Pour ces deux contrôles, pas de difficultés particulières. Dans un formulaire indépendant en mode création : 1. Cliquez sur l'outil "ab" ; 2. Placez vos contrôles ; 3. Affichez les propriétés ; 4. Dans l'onglet : Données, propriété : Source conctrôle, saisissez les intitulés suivants : - CodeContrat ; - idEmploye. |
IV-B-1-b. Les contrôles "Image"▲
|
Pour cette série de sept contrôles, plusieurs propriétés seront à modifier. Nous allons créer totalement un objet avec toutes ses propriétés et nous allons ensuite le recopier six fois. 1. Cliquez sur l'outil : Cadre d'objet indépendant. 2. Placez le contrôle sur le formulaire. |
|
La fenêtre des Propriétés étant affichée, il nous faut maintenant modifier les propriétés suivantes (après avoir
cliqué sur l'onglet Toutes) : - Nom : imgAct1 ; - Source contrôle : srcImage1 ; - Mode affichage : Echelle ; - Largeur : 2,152cm ; - Hauteur : 1,201cm. |
Vous allez maintenant recopier ce contrôle six fois puis modifier les propriétés Nom et Source Contrôle des nouveaux objets
en respectant bien l'ordre :
- Nom : imgAct2, imgAct3, [...], imgAct7
- Source contrôle : srcImage2, srcImage3, [...], srcImage7
IV-B-1-c. Les listes déroulantes▲
|
Comme précédemment, nous allons créer une liste déroulante et la recopier six fois. Cliquez sur l'outil : Liste Déroulante : - Étape 1 : les données sont issues d'une table ; - Étape 2 : choisissez la table T_Activite ; - Étape 3 : sélectionnez les deux premiers champs ; - Étape 4 : comme bon vous semble, vous pouvez trier les données de la liste ; - Étape 5 : vous ajusterez la largeur de la colonne (même principe que dans Excel) ; - Étape 6 : vous pouvez laisser l'intitulé de l'étiquette par défaut, celle-ci sera supprimée. |
|
Il nous faut maintenant modifier l'identité, la source et les dimensions de notre contrôle. Affichez les propriétés de la liste déroulante et cliquez sur l'onglet : Toutes - Nom : cboActivite1 ; - Source contrôle : cboActivite1 ; - Largeur : 0,451cm ; - Hauteur : 0,423cm. |
Après avoir supprimé l'étiquette, il nous suffit de recopier ce contrôle six fois puis de modifier les propriétés Nom et Source contrôle des nouveaux objets
en respectant bien l'ordre :
- Nom : cboActivite2, cboActivite3, [...], cboActivite7 ;
- Source contrôle : cboActivite2, cboActivite3, [...], cboActivite7.
Positionnez les contrôles pour obtenir la disposition du modèle.
IV-B-1-d. Le code attaché aux listes déroulantes▲
Le code placé sur l'évènement Après MAJ concerne le statut de l'apprenti. En effet, celui-ci suit sa formation au CFA.
J'ai donc pensé qu'en affectant l'activité "CFA", il était intéressant d'agir sur l'ensemble de la semaine. La procédure permet donc à
l'utilisateur du planning d'implanter l'activité automatiquement à partir de n'importe quel jour avec mise en place
de la récupération le samedi et le dimanche qui suivent la semaine de formation.
Le principe est de rechercher la position du lundi par rapport à la position du jour de la semaine modifié.
Voici le code :
l_intJourModif = Weekday(l_dteDateModif)
Select Case l_intJourModif
' Cas du Lundi
Case Is = 2
l_sngCompteurJourSem = 0
' Cas du Mardi
Case Is = 3
l_sngCompteurJourSem = -1
' Cas du Mercredi
Case Is = 4
l_sngCompteurJourSem = -2
' Cas du Jeudi
Case Is = 5
l_sngCompteurJourSem = -3
' Cas du Vendredi
Case Is = 6
l_sngCompteurJourSem = -4
' Cas du Samedi ou du Dimanche
Case Else
Me.ActiveControl = 1
MsgBox "Impossibilité de placer des journées de CFA un Week-End." & vbCrLf & "Opération annulée", vbInformation, "Préparation du Planning - DVP"
Exit Sub
End Select
Dans un second temps, par une boucle il faut réécrire les nouvelles valeurs dans l'enregistrement correspondant.
La boucle s'interrompt si la fin de mois est atteinte.
Voici le code :
' Récupération des données du planning de l'employé afin de modifier les CodeActivité sur toute la semaine
strSqlPlanning = "SELECT * FROM T_PlanningPreparation WHERE CodeContrat = " & Me.CodeContrat & " AND MoisPlanning = " _
& p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
Set m_rsPlanning = CurrentDb.OpenRecordset(strSqlPlanning)
With m_rsPlanning
For l_intBoucleCfa = 0 To 6
' Contrôle de la fin de mois
If intChampActiviteConcerne + (sngCompteurJourSem + intBoucleCfa) > m_intFinMois Then
Exit For
Else
.Edit
If l_intBoucleCfa <= 4 Then
' Implantation du code CFA sur tous les jours du Lundi au Vendredi
.Fields("Activite" & l_intChampActiviteConcerne + (l_sngCompteurJourSem + l_intBoucleCfa)) = 5
Else
' Implantation du code ReposJournée pour les Samedi et Dimanche de la semaine
.Fields("Activite" & l_intChampActiviteConcerne + (l_sngCompteurJourSem + l_intBoucleCfa)) = 4
End If
.Update
End If
Next
End With
Une procédure est affectée à l'ensemble des listes déroulantes du formulaire.
Private Sub cboActivite1_AfterUpdate()
Call SauvegardeEnregistrement
End Sub
On remarquera dans cette procédure l'appel à la routine SauvegardeEnregistrement.
' Déclaration des variables locales
' utilisables uniquement dans cette procédure
Dim l_rsContrat As DAO.Recordset
Dim l_intJourModif As Integer, l_intBoucleCfa As Integer, l_intChampActiviteConcerne As Integer
Dim l_strSqlContrat As String
Dim l_dteDateModif As Date
Dim l_sngCompteurJourSem As Single
' Sauvegarde de l'enregistrement modifé
DoCmd.RunCommand acCmdSaveRecord
' Automatisation de la gestion de l'indicatif CFA
If Me.ActiveControl = 5 Then
' Contrôle du type de Contrat du salarié
l_strSqlContrat = "SELECT TypeContrat FROM T_Contrats WHERE CodeContrat = " & Me.CodeContrat
Set l_rsContrat = CurrentDb.OpenRecordset(l_strSqlContrat)
If l_rsContrat.Fields(0) <> "Apprentissage" Then
'Repositionnement sur la valeur par défaut (travail)
Me.ActiveControl = 1
MsgBox "L'employé modifié n'est pas un apprenti !!!" & vbCrLf & "La modification du planning a été annulée.", vbExclamation, "Préparation du Planning - Forum DVP"
Exit Sub
End If
' Récupération de la date concernée
l_dteDateModif = CDate(Me.Controls("lblJour" & Right(Me.ActiveControl.Name, 1)).Caption)
l_intChampActiviteConcerne = Day(l_dteDateModif)
' Recherche du jour concernant la modif
l_intJourModif = Weekday(l_dteDateModif)
Select Case l_intJourModif
' Cas du Lundi
Case Is = 2
l_sngCompteurJourSem = 0
' Cas du Mardi
Case Is = 3
l_sngCompteurJourSem = -1
' Cas du Mercredi
Case Is = 4
l_sngCompteurJourSem = -2
' Cas du Jeudi
Case Is = 5
l_sngCompteurJourSem = -3
' Cas du Vendredi
Case Is = 6
l_sngCompteurJourSem = -4
Case Else
Me.ActiveControl = 1
MsgBox "Impossibilité de placer des journées de CFA un Week-End." & vbCrLf & "Opération annulée", vbInformation, "Préparation du Planning - DVP"
Exit Sub
End Select
' Récupération des données du planning de l'employé afin de modifier les CodeActivité sur toute la semaine
strSqlPlanning = "SELECT * FROM T_PlanningPreparation WHERE CodeContrat = " & Me.CodeContrat & " AND MoisPlanning = " _
& p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
Set m_rsPlanning = CurrentDb.OpenRecordset(strSqlPlanning)
With m_rsPlanning
For l_intBoucleCfa = 0 To 6
' Contrôle de la fin de mois
If intChampActiviteConcerne + (sngCompteurJourSem + intBoucleCfa) > m_intFinMois Then
Exit For
Else
.Edit
If l_intBoucleCfa <= 4 Then
' Implantation du code CFA sur tous les jours du Lundi au Vendredi
.Fields("Activite" & l_intChampActiviteConcerne + (l_sngCompteurJourSem + l_intBoucleCfa)) = 5
Else
' Implantation du code ReposJournée pour les Samedi et Dimanche de la Semaine
.Fields("Activite" & l_intChampActiviteConcerne + (l_sngCompteurJourSem + l_intBoucleCfa)) = 4
End If
.Update
End If
Next
End With
End If
End SubIV-B-2. Section En-tête de Formulaire▲
Durant cette phase, nous allons implanter les étiquettes affichant les dates et les jours de la semaine puis les différents boutons (Navigation, Ajout de salarié, Impression).
IV-B-2-a. Les étiquettes du planning▲
|
Pour afficher l'en-tête et le pied de formulaire : 1. cliquez droit dans la section Détail ; 2. cliquez sur la commande En-tête et Pied de Formulaire ; 3. réduisez la section Pied de Formulaire qui ne sera pas utilisée. |
|
Nous allons préparer les deux premières étiquettes puis comme précédemment faire une recopie
des deux éléments : 1. cliquez sur l'outil "Aa" (étiquette) ; 2. cliquez dans la section En-tête de Formulaire ; 3. saisissez un espace pour "valider" l'objet dessiné. |
|
Nous allons maintenant modifier les propriétés de l'étiquette : 1. cliquez sur l'onglet Toutes de la fenêtre des propriétés ; 2. modifiez les deux propriétés suivantes : - Nom : lblJourSem1, - Largeur : 2,619cm. |
Il nous suffit de recopier cette étiquette treize fois en renommant :
- les six premières : lblJourSem2, lblJourSem3..., lblJourSem7 ;
- les sept suivantes : lblJour1, lblJour2..., lblJour7.
Il nous reste à les disposer comme sur le modèle.
IV-B-2-b. Le Code du Formulaire▲
IV-B-2-b-i. Une petite fonction pour la requête▲
Notre formulaire étant indépendant, il nous faudra lui amener une source de données lors de l'ouverture afin que celui-ci affiche
des informations.
Nous utiliserons pour cela un jeu de requêtes paramétrées.
Dans notre formulaire, le N° de contrat, l'identité du salarié concaténée, le mois et l'année du planning ainsi que deux informations, répétées sept fois, sont affichées :
- une valeur dans la liste déroulante représentant le code de l'activité ou de la situation du salarié ;
- une image associée à la valeur de la liste déroulante.
Ce qui nous donne l'image de la requête ci-dessous :
Remarquez la répétition de la table T_Activite pour chaque champ Activite de la table T_PreparationPlanning.
Il nous faut maintenant associer l'image d'une activité à chaque CodeActivite de T_PreparationPlanning.
Or, le champ ImageActivite contient une partie du chemin de stockage du fichier image (exemple : images\imgTravail.jpg).
L'accès complet à l'image étant tributaire de l'organisation des fichiers de chacun, il nous faudra écrire une petite fonction qui nous permettra de récupérer
le chemin complet de l'image par rapport à son emplacement sur votre disque :
1. ouvrez la fenêtre VBA (Alt F11) ;
2. insérez un nouveau Module ;
3. renommez ce module : Fonctions Globales ;
4. saisissez ou copiez le code ci-dessous.
Public Function fncCheminImage(pRelativePath As String) As String
'Concaténation du chemin de la base et de l'image
fncCheminImage = CurrentProject.Path & "\" & pRelativePath
End FunctionIV-B-2-b-ii. La structure de la requête▲
Cette requête, que nous avons dessinée précédemment, devra être évolutive puisqu'elle n'affichera que sept jours à la fois.
Nous serons donc amené à la manipuler via le Code VBA.
Reprenons la requête précédente et ajoutons les champs nécessaires :
- CodeContrat ;
- IdSalarie représentant l'identité du salarié par concaténation des deux champs NomEmploye et PrenomEmploye ;
- MoisPlanning ;
- AnneePlanning ;
- Activite1 ;
- srcImage1 représentant le chemin de l'image (utilisation de la fonction personnalisée créée ci-dessus) ;
- Ces deux derniers champs seront répétés sept fois (avec les champs Activite2 à Activite7).
Nous obtenons l'image suivante :
Cette requête devra alimenter notre formulaire dès son ouverture. Cliquez dans le volet des propriétés du formulaire sur l'onglet Évènements et
recherchez l'évènement sur Ouverture puis choisissez Procédure évènementielle.
Comme nous devrons paramétrer notre requête, nous allons commencer par déclarer des variables de portée Module, ainsi
elles seront reconnues de toutes les procédures du module attaché à notre formulaire.
1. ouvrez la fenêtre de VBA (Alt F11).
1. Dans la zone de Déclarations, Access affiche la ligne Option Compare Database,
2. saisissez : Option explicit. Cette option a pour but d'obliger la déclaration des variables avant utilisation. Le code en sera plus performant.
Voici les variables à déclarer :
' Déclaration des variables de portée Module
' Ces variables ne sont utilisables que dans ce module
' Variable qui récupère les enregistrements sélectionnés
Dim m_rsPlanning As DAO.Recordset
' Variable qui contient la syntaxe SQL source du formulaire
Dim m_strSqlPrepaPlanning As String
' Variable contenant la partie de la syntaxe SQL contenant les critères de sélection
Dim m_strSqlWHERE As String
' Divers compteurs
Dim m_intCompteurSemaine As Integer, m_intCompteurJour As Integer
' Variable de gestion de la fin de mois
Dim m_boolFinMois As BooleanIV-B-2-b-iii. Le code à l'ouverture du formulaire▲
Lors de l'ouverture de la fenêtre VBA, une procédure était déjà prête à être complétée.
Access l'a préparée lorsque nous avons demandé une procédure évènementielle sur ouverture du formulaire.
Positionnez-vous avant l'instruction End Sub et saisissez votre code :
' Variable pour gérer la boucle de création des étiquettes de planning
Dim l_intCompteur As Integer
' Variable pour gérer les dates des étiquettes de planning
Dim l_dteDatePlanning As Date
' initialisation des variables de portée Module
m_intCompteurSemaine = 1
m_intCompteurJour = 0
' Appel de la routine de création de la source du formulaire
Call ChangementSourcePlanning
' Création des étiquettes calendrier
For l_intCompteur = 1 To 7
l_dteDatePlanning = CDate(Format(l_intCompteur, "00") & "/" & Format(p_intMoisPlanning, "00") & "/" & Format(p_intAnneePlanning, "00"))
Me.Controls("lblJourSem" & l_intCompteur).Caption = Format(l_dteDatePlanning, "dddd")
Me.Controls("lblJour" & l_intCompteur).Caption = Format(l_dteDatePlanning, "dd/mm/yyyy")
Next
End Sub
Remarquez l'appel à la routine ChangementSourcePlanning. C'est dans cette procédure que nous sélectionnerons
la syntaxe SQL qui servira de source à notre planning.
Quelques remarques sur le code :
m_strSqlPrepaPlanning =
"SELECT T_PlanningPreparation.CodeContrat, [PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye, " _
& "T_PlanningPreparation.Activite" & 1 + m_intCompteurJour & " AS cboActivite1, T_PlanningPreparation.Activite" & 2 + m_intCompteurJour & " AS cboActivite2, " _
& "T_PlanningPreparation.Activite" & 3 + m_intCompteurJour & " AS cboActivite3, T_PlanningPreparation.Activite" & 4 + m_intCompteurJour & " AS cboActivite4, " _
& "T_PlanningPreparation.Activite" & 5 + m_intCompteurJour & " AS cboActivite5, T_PlanningPreparation.Activite" & 6 + m_intCompteurJour & " AS cboActivite6, " _
& "T_PlanningPreparation.Activite" & 7 + m_intCompteurJour & " AS cboActivite7, T_PlanningPreparation.MoisPlanning, T_PlanningPreparation.AnneePlanning, " _
& "fncCheminImage([T_Activite].[ImageActivite]) AS srcImage1, fncCheminImage([T_Activite_1].[ImageActivite]) AS srcImage2, " _
& "fncCheminImage([T_Activite_2].[ImageActivite]) AS srcImage3, fncCheminImage([T_Activite_3].[ImageActivite]) AS srcImage4, " _
& "fncCheminImage([T_Activite_4].[ImageActivite]) AS srcImage5, fncCheminImage([T_Activite_5].[ImageActivite]) AS srcImage6, " _
& "fncCheminImage([T_Activite_6].[ImageActivite]) AS srcImage7 " _
& "FROM T_Activite AS T_Activite_6 " _
& "INNER JOIN (T_Activite AS T_Activite_5 " _
& "INNER JOIN (T_Activite AS T_Activite_4 " _
& "INNER JOIN (T_Activite AS T_Activite_3 " _
& "INNER JOIN (T_Activite AS T_Activite_2 " _
& "INNER JOIN (T_Activite AS T_Activite_1 " _
& "INNER JOIN (T_Activite INNER JOIN ((T_PlanningPreparation INNER JOIN T_Contrats " _
& "ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) " _
& "INNER JOIN T_Employes ON T_Contrats.Matricule = T_Employes.Matricule) " _
& "ON T_Activite.CodeActivite = T_PlanningPreparation.Activite" & 1 + m_intCompteurJour & ") " _
& "ON T_Activite_1.CodeActivite = T_PlanningPreparation.Activite" & 2 + m_intCompteurJour & ") " _
& "ON T_Activite_2.CodeActivite = T_PlanningPreparation.Activite" & 3 + m_intCompteurJour & ") " _
& "ON T_Activite_3.CodeActivite = T_PlanningPreparation.Activite" & 4 + m_intCompteurJour & ") " _
& "ON T_Activite_4.CodeActivite = T_PlanningPreparation.Activite" & 5 + m_intCompteurJour & ") " _
& "ON T_Activite_5.CodeActivite = T_PlanningPreparation.Activite" & 6 + m_intCompteurJour & ") " _
& "ON T_Activite_6.CodeActivite = T_PlanningPreparation.Activite" & 7 + m_intCompteurJour
J'ai géré la modularité du planning en utilisant le compteur m_intCompteurJour :
"T_PlanningPreparation.Activite" & 1 + m_intCompteurJour & " AS cboActivite1Dans la concaténation du nom et du prénom de l'employé, j'ai remplacé les "" par de simples quotes, cela facilite la gestion des "".
"...[PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye,..."
Il nous faut maintenant récupérer dans la clause WHERE les critères saisis dans le formulaire F_ChoixPlanning. Je rappelle qu'ils "transitent" par des variables publiques.
' Création de la clause WHERE
m_strSqlWHERE = " WHERE MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning _
& " ORDER BY T_Employes.NomEmploye, T_Employes.PrenomEmploye "
Pour terminer, il faut affecter notre nouvelle source à notre formulaire :
' Initialisation de la Source du formulaire
Me.RecordSource = m_strSqlPrepaPlanning & m_strSqlWHERE
Dans le reste de la procédure, on retrouvera le même type de syntaxe pour la gestion des fins de mois.
Voici ci-dessous la procédure complète :
Sub ChangementSourcePlanning(Optional intFinMois As Integer)
' Récupération de la syntaxe SQL pour les jours de la semaine
If m_boolFinMois = False Then
m_strSqlPrepaPlanning = "SELECT T_PlanningPreparation.CodeContrat, [PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye, " _
& "T_PlanningPreparation.Activite" & 1 + m_intCompteurJour & " AS cboActivite1, T_PlanningPreparation.Activite" & 2 + m_intCompteurJour & " AS cboActivite2, " _
& "T_PlanningPreparation.Activite" & 3 + m_intCompteurJour & " AS cboActivite3, T_PlanningPreparation.Activite" & 4 + m_intCompteurJour & " AS cboActivite4, " _
& "T_PlanningPreparation.Activite" & 5 + m_intCompteurJour & " AS cboActivite5, T_PlanningPreparation.Activite" & 6 + m_intCompteurJour & " AS cboActivite6, " _
& "T_PlanningPreparation.Activite" & 7 + m_intCompteurJour & " AS cboActivite7, T_PlanningPreparation.MoisPlanning, T_PlanningPreparation.AnneePlanning, " _
& "fncCheminImage([T_Activite].[ImageActivite]) AS srcImage1, fncCheminImage([T_Activite_1].[ImageActivite]) AS srcImage2, " _
& "fncCheminImage([T_Activite_2].[ImageActivite]) AS srcImage3, fncCheminImage([T_Activite_3].[ImageActivite]) AS srcImage4, " _
& "fncCheminImage([T_Activite_4].[ImageActivite]) AS srcImage5, fncCheminImage([T_Activite_5].[ImageActivite]) AS srcImage6, " _
& "fncCheminImage([T_Activite_6].[ImageActivite]) AS srcImage7 " _
& "FROM T_Activite AS T_Activite_6 " _
& "INNER JOIN (T_Activite AS T_Activite_5 " _
& "INNER JOIN (T_Activite AS T_Activite_4 " _
& "INNER JOIN (T_Activite AS T_Activite_3 " _
& "INNER JOIN (T_Activite AS T_Activite_2 " _
& "INNER JOIN (T_Activite AS T_Activite_1 " _
& "INNER JOIN (T_Activite INNER JOIN ((T_PlanningPreparation INNER JOIN T_Contrats " _
& "ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) " _
& "INNER JOIN T_Employes ON T_Contrats.Matricule = T_Employes.Matricule) " _
& "ON T_Activite.CodeActivite = T_PlanningPreparation.Activite" & 1 + m_intCompteurJour & ") " _
& "ON T_Activite_1.CodeActivite = T_PlanningPreparation.Activite" & 2 + m_intCompteurJour & ") " _
& "ON T_Activite_2.CodeActivite = T_PlanningPreparation.Activite" & 3 + m_intCompteurJour & ") " _
& "ON T_Activite_3.CodeActivite = T_PlanningPreparation.Activite" & 4 + m_intCompteurJour & ") " _
& "ON T_Activite_4.CodeActivite = T_PlanningPreparation.Activite" & 5 + m_intCompteurJour & ") " _
& "ON T_Activite_5.CodeActivite = T_PlanningPreparation.Activite" & 6 + m_intCompteurJour & ") " _
& "ON T_Activite_6.CodeActivite = T_PlanningPreparation.Activite" & 7 + m_intCompteurJour
Else
Select Case intFinMois
' Récupération de la syntaxe SQL pour la fin de mois
' Année bissextile
Case Is = 29
m_strSqlPrepaPlanning = "SELECT T_PlanningPreparation.CodeContrat, [PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye, " & _
"T_PlanningPreparation.Activite29 AS cboActivite1, T_PlanningPreparation.MoisPlanning, T_PlanningPreparation.AnneePlanning, " & _
"fncCheminImage([T_Activite].[ImageActivite]) AS srcImage1 " & _
"FROM T_Activite INNER JOIN (T_Employes INNER JOIN (T_PlanningPreparation INNER JOIN T_Contrats " & _
"ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) ON T_Employes.Matricule = T_Contrats.Matricule) " & _
"ON T_Activite.CodeActivite = T_PlanningPreparation.Activite29 "
' Mois à 30 jours
Case Is = 30
m_strSqlPrepaPlanning = "SELECT T_PlanningPreparation.CodeContrat, [PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye, " & _
"T_PlanningPreparation.Activite29 AS cboActivite1,T_PlanningPreparation.Activite30 AS cboActivite2, T_PlanningPreparation.MoisPlanning, T_PlanningPreparation.AnneePlanning, " & _
"fncCheminImage([T_Activite].[ImageActivite]) AS srcImage1, fncCheminImage([T_Activite1].[ImageActivite]) AS srcImage2 " & _
"FROM (T_Activite INNER JOIN (T_Employes " & _
"INNER JOIN (T_PlanningPreparation INNER JOIN T_Contrats " & _
"ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) ON T_Employes.Matricule = T_Contrats.Matricule) " & _
"ON T_Activite.CodeActivite = T_PlanningPreparation.Activite29) INNER JOIN T_Activite AS T_Activite1 ON T_PlanningPreparation.Activite30 = T_Activite1.CodeActivite "
' Mois à 31 jours
Case Is = 31
m_strSqlPrepaPlanning = "SELECT T_PlanningPreparation.CodeContrat, [PrenomEmploye] & ' ' & [NomEmploye] AS IdEmploye, " & _
"T_PlanningPreparation.Activite29 AS cboActivite1, T_PlanningPreparation.Activite30 AS cboActivite2, T_PlanningPreparation.Activite31 AS cboActivite3, " & _
"T_PlanningPreparation.MoisPlanning, T_PlanningPreparation.AnneePlanning, " & _
"fncCheminImage([T_Activite].[ImageActivite]) AS srcImage1, fncCheminImage([T_Activite1].[ImageActivite]) AS srcImage2, " & _
"fncCheminImage([T_Activite2].[ImageActivite]) AS srcImage3 " & _
"FROM T_Activite AS T_Activite2 " & _
"INNER JOIN (T_Activite AS T_Activite1 " & _
"INNER JOIN (T_Activite INNER JOIN ((T_PlanningPreparation INNER JOIN T_Contrats " & _
"ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) INNER JOIN T_Employes " & _
"ON T_Contrats.Matricule = T_Employes.Matricule) " & _
"ON T_Activite.CodeActivite = T_PlanningPreparation.Activite29) " & _
"ON T_Activite1.CodeActivite = T_PlanningPreparation.Activite30) " & _
"ON T_Activite2.CodeActivite = T_PlanningPreparation.Activite31"
End Select
End If
' Création de la clause WHERE
m_strSqlWHERE = " WHERE MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning _
& " ORDER BY T_Employes.NomEmploye, T_Employes.PrenomEmploye "
' Initialisation de la Source du formulaire
Me.RecordSource = m_strSqlPrepaPlanning & m_strSqlWHERE
End SubIV-B-2-c. Les boutons de commande▲
IV-B-2-c-i. Le bouton "Semaine Précédente"▲
L'assistant étant inactif, cliquez sur l'outil Bouton et implantez celui-ci sur le formulaire.
Nous allons dans un premier temps modifier ses propriétés :
- onglet Format :
Image : cliquez sur l'outil à droite de la propriété et allez rechercher une image représentant une flèche gauche.
- onglet Données :
Activé : choisissez Non.
- onglet Autres :
Nom : saisissez btnSemainePrecedente.
Texte info-bulle : tapez Semaine précédente.
Pour ajouter le code du bouton, cliquez dans l'onglet Évènements puis sur l'évènement sur clic, choisissez Procédure évènementielle.
' Variable locale de comptage de la boucle
Dim l_intCompteur As Integer
m_intCompteurSemaine = m_intCompteurSemaine - 1
If m_intCompteurSemaine = 0 Then
m_intCompteurSemaine = 1
Else
' Récupération de la requête source
Select Case m_intCompteurSemaine
Case Is = 1
m_intCompteurJour = 0
' Atteindre le bouton Semaine Suivante pour...
DoCmd.GoToControl "btnSemaineSuivante"
' ... Désactivation du bouton Semaine Précedente.
Me.btnSemainePrecedente.Enabled = False
Case Is = 2
m_intCompteurJour = 7
Case Is = 3
m_intCompteurJour = 14
' Réactivation du bouton Semaine Suivante si le mois à 28 jours
Me.btnSemaineSuivante.Enabled = True
m_boolFinMois = False
Case Is = 4
m_intCompteurJour = 21
' Réactivation du bouton Semaine Suivante si le mois à + de 28 jours
Me.btnSemaineSuivante.Enabled = True
m_boolFinMois = False
Case Is = 5
m_intCompteurJour = 28
End Select
' Récupération de la source
Call ChangementSourcePlanning
' Boucle de génération des différentes étiquettes de la zone En-tête de Formulaire
For l_intCompteur = 1 To 7
Me.Controls("lblJour" & l_intCompteur).Caption = Format(m_intCompteurJour + l_intCompteur, "00") & "/" & Format(p_intMoisPlanning, "00") & "/" & Format(p_intAnneePlanning, "00")
Me.Controls("lblJourSem" & l_intCompteur).Caption = Format(CDate(Me.Controls("lblJour" & l_intCompteur).Caption), "dddd")
Next
End If
End SubIV-B-2-c-ii. Le bouton "Semaine Suivante"▲
Procédez comme ci-dessus pour implanter le nouveau bouton et modifiez les mêmes propriétés :
- onglet Format :
Image : cliquez sur l'outil à droite de la propriété et allez rechercher une image représentant une flèche droite.
- onglet Autres :
Nom : saisissez btnSemaineSuivante.
Texte info-bulle : tapez Semaine suivante.
Pour ajouter le code du bouton, cliquez dans l'onglet Évènements puis sur l'évènement sur clic, choisissez Procédure évènementielle.
' Variable pour calculer le quantième du jour
Dim l_intCompteur As Integer
' Variable qui récupère le quantième correspondant à la fin de mois
Dim l_intFinMois As Integer
' Compteur du page du planning (1semaine = 1 page)
m_intCompteurSemaine = m_intCompteurSemaine + 1
' Récupération de la requête source
Select Case m_intCompteurSemaine
Case Is = 1
m_intCompteurJour = 0
Case Is = 2
m_intCompteurJour = 7
' Réactivation du bouton semaine précédente (nous sommes en semaine 2)
Me.btnSemainePrecedente.Enabled = True
Case Is = 3
m_intCompteurJour = 14
Case Is = 4
m_intCompteurJour = 21
' Cas du mois de février à 28 jours
If l_intFinMois = 28 Then
' Atteindre le bouton Semaine Précédente pour...
DoCmd.GoToControl "btnSemainePrecedente"
' ... Désactivation du bouton Semaine Suivante.
Me.btnSemaineSuivante.Enabled = False
End If
Case Is = 5
' Semaine 5 : Semaine de toutes les fins de mois (à 29 j, 30 j ou 31 j)
m_intCompteurJour = 28
' Activation de la variable booléenne qui permettra de retrouver la structure Sql correspondant au nombre de jours du mois
m_boolFinMois = True
' Atteindre le bouton Semaine Suivante pour...
DoCmd.GoToControl "btnSemainePrecedente"
' ... Désactivation du bouton Semaine Suivante.
Me.btnSemaineSuivante.Enabled = False
End Select
' Récupération de la source
Call ChangementSourcePlanning(l_intFinMois)
' Boucle d'initialisation
For l_intCompteur = 1 To 7
' Contrôle la fin de mois
If m_intCompteurJour + l_intCompteur > l_intFinMois Then
' Mise à Blanc des contrôles supérieurs à la date de fin de mois
Me.Controls("lblJour" & l_intCompteur).Caption = " "
Me.Controls("lblJourSem" & l_intCompteur).Caption = " "
Else
' Génération des étiquettes des dates du jour
Me.Controls("lblJour" & l_intCompteur).Caption = Format(m_intCompteurJour + l_intCompteur, "00") & "/" & Format(p_intMoisPlanning, "00") & "/" & Format(p_intAnneePlanning, "00")
Me.Controls("lblJourSem" & l_intCompteur).Caption = Format(CDate(Me.Controls("lblJour" & l_intCompteur).Caption), "dddd")
End If
Next
End SubIV-B-2-c-iii. Le bouton "Imprimer le Planning"▲
Implantez le bouton comme nous l'avons fait précédemment et modifiez les propriétés suivantes :
- onglet Autres :
- Nom : btnImprimerLePlanning.
- onglet Format :
- Image : recherchez une image évocatrice de l'impression.
Pour ajouter le code du bouton, cliquez dans l'onglet Évènements puis sur l'évènement sur clic, choisissez Procédure évènementielle.
Private Sub btnImprimerLePlanning_Click()
DoCmd.OpenForm "F_ChoixEtendueImpression"
End SubPour lire la partie concernant l'impression, cliquez ici : Détail de l'impression
IV-B-2-c-iv. Le bouton "Nouveau Salarié"▲
Bien que ne faisant pas partie de l'objet de l'article, j'ai voulu détailler ce chapitre pour montrer comment la table
T_PlanningPreparation est alimentée.
Cela suppose donc la création d'un formulaire. Pour lire la partie concernant la création du formulaire, cliquez ici :
Création du formulaire de saisie d'un nouveau salarié
IV-C-3. Les propriétés du formulaire F_PreparationPlanning▲
IV-C. Création d'un nouveau salarié▲
IV-C-1. Le formulaire de saisie▲
Ce formulaire a été simplifié au strict minimum. Il contient :
- une liste déroulante basée sur la table T_Employes ;
- celle-ci représente le champ Père du formulaire.
- J'en ai profité pour rappeler comment alimenter une liste déroulante (Voir la FAQ) ;
- un sous-formulaire qui reprend l'essentiel du contrat.
IV-C-1-a. La liste déroulante et son code▲
Dans un formulaire indépendant en mode création (indépendant = rattaché à aucune source de données), implantez une liste déroulante en suivant
les diverses étapes de la création :
Étape 1 : la source est une table ou une requête ;
Étape 2 : sélectionnez la table T_Employes ;
Étape 3 : choisissez les premiers champs (Matricule, NomEmploye).
Étape 3 : Le prénom sera ajouté par concaténation lors de la modification de la requête source ;
Étape 4 : positionnez un tri sur le NomEmploye ;
Étape 5 : ne changez rien à la largeur de la colonne ;
Étape 6 : saisissez l'étiquette : Choisir dans la liste.
|
Nous allons maintenant modifier les propriétés de la liste. Dans le volet des propriétés : - cliquez sur l'onglet Données Contenu : Ouvrez la requête en cliquant sur l'outil à droite du volet ; Contenu : Modifiez le champ NomEmploye en créant un champ calculé (idEmploye) ; Contenu : Ajoutez une seconde fois le champ NomEmploye et placez-y le tri en désactivant l'option d'affichage ; Contenu : Fermer la fenêtre du générateur de requête et validez. - cliquez sur l'onglet Format Nbre Colonnes : 2 ; Largeurs colonnes : 0cm, 5cm. - cliquez sur l'onglet Autres Nom : cboEmploye. - cliquez onglet Évènements Sur absence dans liste : Choisir procédure évènementielle. |
En cliquant sur l'outil à droite de la procédure évènementielle, on entre dans l'environnement du code.
Au préalable quelques remarques sur le code :
Utilisation de la fonction Split(expression,séparateur) qui permet d'éclater la chaîne de caractères saisie dans un tableau :
- L'argument "Expression" représente la chaîne à traiter ;
- L'argument "Séparateur" représente le caractère séparant les éléments de la chaîne à éclater.
' Eclatement de la chaîne saisie dans un tableau
l_tabTrav = Split(NewData, " ")
' Récupération des données dans les variables
l_strNom = l_tabTrav(1)
l_strPrenom = l_tabTrav(0)Exécution d'une requête Ajout pour implanter les valeurs dans la table source de la liste
' Génération et exécution de la chaine SQL pour ajouter les infos à la table
l_strSqlEmploye = "INSERT INTO T_Employes ( NomEmploye, PrenomEmploye)" _
& " SELECT '" & l_strNom & "','" & l_strPrenom & "' ;"
With DoCmd
' Désactivation Message système
.SetWarnings False
' Exécution de la requête Ajout
.RunSQL l_strSqlEmploye
' Réactivation des messages système
.SetWarnings True
End WithVoici, ci-dessous, le code complet de la procédure :
Private Sub cboEmploye_NotInList(NewData As String, Response As Integer)
Dim l_strSqlEmploye As String
Dim l_strNom As String, l_strPrenom As String
Dim l_tabTrav() As String
' Eclatement de la chaine saisie dans un tableau
l_tabTrav = Split(NewData, " ")
' Récupération des données dans les variables
l_strNom = l_tabTrav(1)
l_strPrenom = l_tabTrav(0)
' Génération et exécution de la chaine SQL pour ajouter les infos à la table
l_strSqlEmploye = "INSERT INTO T_Employes ( NomEmploye, PrenomEmploye)" _
& " SELECT '" & l_strNom & "','" & l_strPrenom & "' ;"
With DoCmd
' Désactivation Message système
.SetWarnings False
' Exécution de la requête Ajout
.RunSQL l_strSqlEmploye
' Réactivation des messages système
.SetWarnings True
End With
' Mise à jour du contenu de la liste
Response = acDataErrAdded
End SubIV-C-1-b. Le sous-formulaire ▲
Pour en terminer avec le sous formulaire, il faut implanter une procédure sur les deux zones de texte
DebutContrat et FinContrat. Ce code sera placé sur l'évènement "après mise à jour" du contrôle.
Son objectif : récupérer les valeurs du formulaire nécessaires à la création des enregistrements de T_PlanningPréparation
Private Sub DebutContrat_AfterUpdate()
p_dteDebutContrat = Me.DebutContrat
End SubPrivate Sub FinContrat_AfterUpdate()
p_dteFinContrat = Me.FinContrat
p_lngCodeContrat = Me.CodeContrat
DoCmd.GoToControl "btnFermer"
End SubJe n'ai pas fait de contrôle de saisie pour vérifier la cohérence des dates, ce n'est pas l'objet du tuto.
IV-C-1-c. Implanter le sous-formulaire▲
IV-C-2. Le code de génération des enregistrements▲
Lors de la création d'un contrat, la table T_PlanningPreparation est alimentée d'un enregistrement par mois de contrat et la table T_TempsTravail est alimentée d'un enregistrement par jour de travail.
Le code s'exécute sur la fermeture du formulaire de saisie du contrat.
Dans un premier temps, on alimente la table T_PreparationPlanning :
Private Sub btnFermer_Click()
' Déclaration des variables locales
Dim l_rsPrepaPlanning As DAO.Recordset
Dim l_strSqlPrepaPlanning As String
Dim l_intCompteur As Integer
' Initialisation des variables de travail
l_strSqlPrepaPlanning = "SELECT * FROM T_PlanningPreparation"
Set l_rsPrepaPlanning = CurrentDb.OpenRecordset(l_strSqlPrepaPlanning)
'Ajout des enregistrements pour les mois du contrat
For l_intCompteur = Month(p_dteDebutContrat) To Month(p_dteFinContrat)
With l_rsPrepaPlanning
.AddNew
.Fields!CodeContrat = p_lngCodeContrat
.Fields!MoisPlanning = l_intCompteur
' Remarque : le planning est régénéré tous les ans,
' si un employé est embauché lors de la génération du premier planning,
' l'année planning correspond à l'année de la date d'embauche.
.Fields!AnneePlanning = Year(p_dteDebutContrat)
.Update
End With
NextDans un second temps, on alimente T_TempsTravail :
' Initialisation des variables de travail
l_strSqlPrepaPlanning = "SELECT * FROM T_TempsTravail"
Set l_rsPrepaPlanning = CurrentDb.OpenRecordset(l_strSqlPrepaPlanning)
'Ajout des enregistrements pour les jours travaillés du contrat
For l_intCompteur = p_dteDebutContrat To p_dteFinContrat
With l_rsPrepaPlanning
.AddNew
.Fields!CodeContrat = p_lngCodeContrat
.Fields!JourTravail = l_intCompteur
.Update
End With
NextVoici donc le code complet de la procédure évènementielle "sur Clic" du bouton de fermeture du formulaire :
Private Sub btnFermer_Click()
Dim l_rsPrepaPlanning As DAO.Recordset
Dim l_strSqlPrepaPlanning As String
Dim l_varCompteur As Variant
If Me.cboEmploye > "" Then
' Alimentation de T_PreparationPlanning
'-----------------------------------------------
' Initialisation des variables de travail
l_strSqlPrepaPlanning = "SELECT * FROM T_PlanningPreparation"
Set l_rsPrepaPlanning = CurrentDb.OpenRecordset(l_strSqlPrepaPlanning)
'Ajout des enregistrements pour les mois du contrat
For l_varCompteur = Month(p_dteDebutContrat) To Month(p_dteFinContrat)
With l_rsPrepaPlanning
.AddNew
.Fields!CodeContrat = p_lngCodeContrat
.Fields!MoisPlanning = l_varCompteur
' Remarque : le planning est régénéré tous les ans,
' si un employé est embauché lors de la génération du premier planning,
' l'année planning correspond à l'année de la date d'embauche.
.Fields!AnneePlanning = Year(p_dteDebutContrat)
.Update
End With
Next
' Alimentation de T_TempsTravail
' --------------------------------------
' Initialisation des variables de travail
l_strSqlPrepaPlanning = "SELECT * FROM T_TempsTravail"
Set l_rsPrepaPlanning = CurrentDb.OpenRecordset(l_strSqlPrepaPlanning)
'Ajout des enregistrements pour les jours travaillés du contrat
For l_varCompteur = p_dteDebutContrat To p_dteFinContrat
With l_rsPrepaPlanning
.AddNew
.Fields!CodeContrat = p_lngCodeContrat
.Fields!jourtravail = l_varCompteur
.Update
End With
Next
' Réactualisation du Planning
Forms!F_PreparationPlanning.Requery
End If
DoCmd.Close acForm, "F_SaisieContrats"
End SubIV-D. L'impression▲
L'impression est lancée à partir du bouton btnImprimerLePlanning. L'ouverture du formulaire ci-dessus à gauche permettra
de choisir l'étendue de l'impression tandis que l'image de droite nous montre le résultat obtenu.
On remarquera que les intitulés des Week-End sont affichés en rouge.
IV-D-1. Le formulaire du choix de l'impression▲
IV-D-1-a. La liste déroulante▲
|
Dans un nouveau formulaire indépendant, implantez une liste déroulante et suivez les diverses
étapes de l'assistant : Étape 1 : choisissez l'option "Je taperai les valeurs souhaitées" ; Étape 2 : choisissez le nombre de colonne : 2 ; Étape 2 : saisissez les valeurs à afficher dans la liste : 1ère Quinzaine, 2ème Quinzaine, Le mois complet ; Étape 3 : saisissez l'étiquette à associer à la liste. |
IV-D-1-b. Le bouton d'impression et son code▲
Il ne reste plus qu'à implanter un bouton qui lancera le processus d'impression.
Private Sub btnImprimerPlanning_Click()
' Selection de l'impression
Select Case Me.cboChoixImprimer
Case Is = 1
' Impression Quinzaine 1
p_intCompteurImpressDeb = 1
DoCmd.OpenReport "E_ImpressionPlanning", acViewNormal, , "MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
Case Is = 2
' Impression Quinzaine 2
p_intCompteurImpressDeb = 17
DoCmd.OpenReport "E_ImpressionPlanning", acViewNormal, , "MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
Case Else
' Impression Quinzaine 1
p_intCompteurImpressDeb = 1
DoCmd.OpenReport "E_ImpressionPlanning", acViewNormal, , "MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
' Impression Quinzaine 2
p_intCompteurImpressDeb = 17
DoCmd.OpenReport "E_ImpressionPlanning", acViewNormal, , "MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
End Select
' Fermeture du formulaire de lancement
DoCmd.Close acForm, "F_ChoixEtendueImpression"
End SubIV-D-2. Le Planning▲
IV-D-2-a. Le structure de l'état▲
IV-D-2-a-i. La section En-tête d'état▲
Cette section contient une étiquette qui affichera le titre de l'état :
1. cliquez sur l'outil Aa ;
2. tapez un espace pour mettre un contenu à l'étiquette ;
3. changez les propriétés :
- Nom : lblTitre,
- Largeur : 18.794cm.
On implantera également quinze étiquettes pour les jours de planning. Comme plus haut, on créera une étiquette que l'on
recopiera quinze fois.
1. cliquez sur l'outil Aa ;
2. tapez Date1 pour mettre un contenu à l'étiquette ;
3. changez les propriétés :
- Nom : lblDate1,
- Largeur : 1.492cm,
- Hauteur : 0.503cm ;
Recopiez cette étiquette quinze fois en prenant soin de modifier la propriété Nom (onglet : Autres) comme ci-dessous :
lblDate2, lblDate3, [...], lblDate16.
IV-D-2-a-ii. La section Détail▲
Nous positionnerons dans cette section, une zone de texte et seize contrôles Image indépendants. Ceux-ci seront alimentés par le code.
Pour la zone de texte :
1. cliquez sur l'outil ab puis cliquez dans la section Détail ;
2. changez les propriétés :
- Nom : Employe,
- Source Contrôle : Employe,
- Largeur : 3cm.
Pour les contrôle image, nous agirons comme ci-dessus en créant un contrôle et en le recopiant.
1. cliquez sur l'outil : Cadre d'objet indépendant ;
2. modifiez les propriétés :
- Nom : img1,
- Largeur : 1.492cm,
- Hauteur : 0.804cm,
- Mode d'affichage : Echelle.
Recopiez cette étiquette quinze fois en prenant soin de modifier la propriété Nom (onglet : Autres) comme ci-dessous :
img2, img3, [...], img16.
IV-D-2-b. Le code attaché à l'état▲
IV-D-2-b-i. À l'ouverture de l'état▲
Durant cette procédure, nous allons :
1. générer la source de l'état :
' Déclaration de la variable
Dim strSqlPrepaImpress As String
' Création de la requête source
strSqlPrepaImpress = "SELECT [PrenomEmploye] & ' ' & [NomEmploye] AS Employe, T_PlanningPreparation.CodeContrat, T_Mois.LibelleMois, MoisPlanning, AnneePlanning, " _
& "Activite1, Activite2, Activite3, Activite4, Activite5, Activite6, Activite7, Activite8, Activite9, Activite10, Activite11, " _
& "Activite12, Activite13, Activite14, Activite15, Activite16, " _
& "Activite17, Activite18, Activite19, Activite20, Activite21, Activite22, Activite23, Activite24, Activite25, Activite26, " _
& "Activite27 , Activite28, Activite29, Activite30, Activite31 " _
& "FROM T_Employes INNER JOIN ((T_PlanningPreparation " _
& "INNER JOIN T_Contrats ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) " _
& "INNER JOIN T_Mois ON T_PlanningPreparation.MoisPlanning = T_Mois.CodeMois) ON T_Employes.Matricule = T_Contrats.Matricule " _
& "WHERE MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
' Affectation de la source
Me.RecordSource = strSqlPrepaImpress2. rechercher la fin de mois pour gérer les étiquettes vierges :
' Recherche fin de mois
If p_intMoisPlanning = 12 Then
intFinMois = Day(DateSerial(p_intAnneePlanning + 1, p_intMoisPlanning + 1, 1) - 1)
Else
intFinMois = Day(DateSerial(p_intAnneePlanning, p_intMoisPlanning + 1, 1) - 1)
End If3. générer les étiquettes des dates de planning par rapport à la plage à imprimer :
'Récupération du Jeu d'enregistrements
Set rsImpressPlanning = CurrentDb.OpenRecordset(strSqlPrepaImpress)
' Génération des étiquettes
With rsImpressPlanning
' Génération du titre
Me.lblTitre.Caption = "Planning de l'équipe pour " & .Fields(2) & " " & .Fields(4)
For intCompteur = 0 To 15
' Gestion de la fin de mois
If intCompteur + p_intCompteurImpressDeb > intFinMois Then
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption = ""
Else
' Implantation de la date
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption = Format(DateSerial(.Fields("AnneePlanning"), _
.Fields("MoisPlanning"), intCompteur + p_intCompteurImpressDeb), "dddd dd")
' Modification de la couleur en fonction du jour de la semaine
If Left(Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption, 1) = "S" Or _
Left(Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption, 1) = "D" Then
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).ForeColor = 255
Else
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).ForeColor = 0
End If
End If
Next
End WithVoici donc le code complet à placer dans l'évènement "A l'ouverture" de l'état :
Private Sub Report_Open(Cancel As Integer)
' Déclaration de la variable
Dim strSqlPrepaImpress As String
' Création de la requête source
strSqlPrepaImpress = "SELECT [PrenomEmploye] & ' ' & [NomEmploye] AS Employe, T_PlanningPreparation.CodeContrat, T_Mois.LibelleMois, MoisPlanning, AnneePlanning, " _
& "Activite1, Activite2, Activite3, Activite4, Activite5, Activite6, Activite7, " _
& "Activite8, Activite9, Activite10, Activite11, " _
& "Activite12, Activite13, Activite14, Activite15, Activite16, " _
& "Activite17, Activite18, Activite19, Activite20, Activite21, Activite22, " _
& "Activite23, Activite24, Activite25, Activite26, " _
& "Activite27 , Activite28, Activite29, Activite30, Activite31 " _
& "FROM T_Employes INNER JOIN ((T_PlanningPreparation " _
& "INNER JOIN T_Contrats ON T_PlanningPreparation.CodeContrat = T_Contrats.CodeContrat) " _
& "INNER JOIN T_Mois ON T_PlanningPreparation.MoisPlanning = T_Mois.CodeMois) ON T_Employes.Matricule = T_Contrats.Matricule " _
& "WHERE MoisPlanning = " & p_intMoisPlanning & " AND AnneePlanning = " & p_intAnneePlanning
' Affectation de la source
Me.RecordSource = strSqlPrepaImpress
' Recherche fin de mois
If p_intMoisPlanning = 12 Then
intFinMois = Day(DateSerial(p_intAnneePlanning + 1, p_intMoisPlanning + 1, 1) - 1)
Else
intFinMois = Day(DateSerial(p_intAnneePlanning, p_intMoisPlanning + 1, 1) - 1)
End If
'Récupération du Jeu d'enregistrements
Set rsImpressPlanning = CurrentDb.OpenRecordset(strSqlPrepaImpress)
' Génération des étiquettes
With rsImpressPlanning
' Génération du titre
Me.lblTitre.Caption = "Planning de l'équipe pour " & .Fields(2) & " " & .Fields(4)
For intCompteur = 0 To 15
' Gestion de la fin de mois
If intCompteur + p_intCompteurImpressDeb > intFinMois Then
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption = ""
Else
' Implantation de la date
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption = Format(DateSerial(.Fields("AnneePlanning"), _
.Fields("MoisPlanning"), intCompteur + p_intCompteurImpressDeb), "dddd dd")
' Modification de la couleur en fonction du jour de la semaine
If Left(Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption, 1) = "S" _
Or Left(Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).Caption, 1) = "D" Then
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).ForeColor = 255
Else
Me.ZoneEntêtePage.Controls("lblDate" & intCompteur + 1).ForeColor = 0
End If
End If
Next
End With
End SubIV-D-2-b-ii. Au formatage de la section détail▲
Dans cette procédure, il nous faut gérer les images.
Cette procédure lit le code Activité de chaque champ et recherche le chemin de l'image afin
de créer la source pour chaque objet image de la section Détail.
For intCompteur = 0 To 15
' Gestion de la fin de mois
If intCompteur + p_intCompteurImpressDeb > intFinMois Then
strPathImage = "/Images/imgVierge.jpg"
Else
' Ajout de 4 au compteur d'impression parce qu'il y a 4 champs dans la requête source avant le premier champ Activité
Select Case .Fields(intCompteur + p_intCompteurImpressDeb + 4)
Case Is = 1
strPathImage = "\Images\imgTravail.jpg"
Case Is = 2
strPathImage = "\Images\imgReposM.jpg"
Case Is = 3
strPathImage = "\Images\imgReposS.jpg"
Case Is = 4
strPathImage = "\Images\imgReposJ.jpg"
Case Is = 5
strPathImage = "\Images\imgCFA.jpg"
Case Is = 6
strPathImage = "\Images\imgAbsenceJ.jpg"
Case Is = 7
strPathImage = "\Images\imgAbsenceNJ.jpg"
Case Is = 8
strPathImage = "\Images\imgRecupM.jpg"
Case Is = 9
strPathImage = "\Images\imgRecupS.jpg"
Case Is = 10
strPathImage = "\Images\imgRecupJ.jpg"
Case Is = 11
strPathImage = "\Images\imgRecupMReposS.jpg"
Case Is = 12
strPathImage = "\Images\imgReposMRecupS.jpg"
Case Is = 13
strPathImage = "\Images\imgVacances.jpg"
Case Is = 14
strPathImage = "\Images\imgMaladie.jpg"
Case Is = 15
strPathImage = "\Images\imgRupture.jpg"
End Select
End If
' Implantation de l'image dans le contrôle
Me.Controls("img" & intCompteur + 1).Picture = CurrentProject.Path & strPathImage
NextCette partie de procédure est incluse dans la lecture de tous les enregistrements du jeu sélectionné.
' Boucle de lecture des enregistrements sélectionnés
With rsImpressPlanning
' Boucle pour sélectionner l'image à imprimer
' ...
' Lecture de l'enregistrement suivant
.MoveNext
End WithVoici donc le code complet affecté à l'évènement "Sur Formatage" de la section Détail :
Private Sub Détail_Format(Cancel As Integer, FormatCount As Integer)
' Déclaration de la variable
Dim strPathImage As String
' Boucle de lecture des enregistrements sélectionnés
With rsImpressPlanning
' Boucle pour sélectionner l'image à imprimer
For intCompteur = 0 To 15
' Gestion de la fin de mois
If intCompteur + p_intCompteurImpressDeb > intFinMois Then
strPathImage = "/Images/imgVierge.jpg"
Else
' Ajout de 4 au compteur d'impression parce qu'il y a 4 champs dans la requête source avant le premier champ Activité
Select Case .Fields(intCompteur + p_intCompteurImpressDeb + 4)
Case Is = 1
strPathImage = "\Images\imgTravail.jpg"
Case Is = 2
strPathImage = "\Images\imgReposM.jpg"
Case Is = 3
strPathImage = "\Images\imgReposS.jpg"
Case Is = 4
strPathImage = "\Images\imgReposJ.jpg"
Case Is = 5
strPathImage = "\Images\imgCFA.jpg"
Case Is = 6
strPathImage = "\Images\imgAbsenceJ.jpg"
Case Is = 7
strPathImage = "\Images\imgAbsenceNJ.jpg"
Case Is = 8
strPathImage = "\Images\imgRecupM.jpg"
Case Is = 9
strPathImage = "\Images\imgRecupS.jpg"
Case Is = 10
strPathImage = "\Images\imgRecupJ.jpg"
Case Is = 11
strPathImage = "\Images\imgRecupMReposS.jpg"
Case Is = 12
strPathImage = "\Images\imgReposMRecupS.jpg"
Case Is = 13
strPathImage = "\Images\imgVacances.jpg"
Case Is = 14
strPathImage = "\Images\imgMaladie.jpg"
Case Is = 15
strPathImage = "\Images\imgRupture.jpg"
End Select
End If
' Implantation de l'image dans le contrôle
Me.Controls("img" & intCompteur + 1).Picture = CurrentProject.Path & strPathImage
Next
' Lecture de l'enregistrement suivant
.MoveNext
End With
End SubV. Conclusion▲
Voilà donc comment placer des images dans vos formulaires en mode continu (à partir de la version 2007) ou dans un état. Ceci n'est qu'un exemple, à vous de vous lancer maintenant.
VI. Remerciements▲
Merci à Arkham46 pour ses conseils techniques éclairés.
Merci à blade159 et jacques-jean pour leur relecture et leurs conseils orthographiques.
Je remercie également toute l'équipe Office de DVP qui est toujours présente lors de l'élaboration et la finalisation d'un nouveau projet (en particulier :
Tofalu, Philippe JOCHMANS et
User)
VII. Téléchargement▲
Téléchargement : Préparation d'un planning



















