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▲
On remarquera l'absence de relation entre T_Activite et T_PlanningPréparation. Celle-ci sera établie lors de la génération des requêtes pour afficher les images dans le planning.
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
Integer
IV-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
Sub
IV-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
Function
IV-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
Boolean
IV-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 cboActivite1
Dans 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
Sub
IV-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
Sub
IV-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
Sub
IV-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
Sub
Pour 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
With
Voici, 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
Sub
IV-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
Sub
Private
Sub
FinContrat_AfterUpdate
(
)
p_dteFinContrat =
Me.FinContrat
p_lngCodeContrat =
Me.CodeContrat
DoCmd.GoToControl
"btnFermer"
End
Sub
Je 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
Next
Dans 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
Next
Voici 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
Sub
IV-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
Sub
IV-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
=
strSqlPrepaImpress
2. 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
If
3. 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
With
Voici 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
Sub
IV-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
Next
Cette 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
With
Voici 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
Sub
V. 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