Gérer du personnel - Novembre 2005
But : Nous allons développer progressivement une application qui devra nous permettre de gérer des personnes en suivant leurs activités au jour le jour, et effectuer un contrôle sur celles-ci. Par exemple, décompter des congés de leur quota, comptabiliser les heures supplémentaires, retirer les heures récupérées, additionner des services particuliers de manière à être capable de décider qui participera à la prochaine prestation, etc...Tout ceci sous MS Access
Les tables
En tout premier, il faut déterminer une clé primaire qui sera LA référence de la base de données, car il est important d'identifier avec certitude la personne concernée. Le nom, même groupé au prénom n'est pas suffisant à cause des homonymes. Il faut plutôt choisir une information comme un numéro national, un matricule, un numéro de sécurité sociale, ou une classification propre à l'entreprise. Cette information doit revêtir un caractère unique.
Quand ceci est déterminé, on crée une première table qui contiendra des informations comme LA fameuse référence, noms, prénoms, date de naissance, nationalité, rue, n° , ville, code postal, etc... Dans mon exemple, c'est T_Noms, avec les champs Identifications, Noms et Fonctions
Pour imposer une mise en forme d'encodage pour le champ Fonctions, nous utiliserons une seconde table : T_Fonctions, on édite alors la T_Noms et l'on redéfinit le champ T_Noms.Fonctions en liste déroulante... en utilisant l'assistant on définit l'instruction SQL suivante: SELECT T_Fonctions.Fonctions FROM T_Fonctions ORDER BY T_Fonctions.Fonctions;
Etant donné que l'on gérera entre autres choses les jours de congés, on doit stocker dans une table le nombre de jours de congés alloués par année et par Identifications (clé primaire)
On crée ensuite une table qui contiendra les noms des 31 jours d'un mois, 31 champs Commentaires et d'autres champs utiles pour la tenue de la comptabilité des différentes situations quotidiennes que le personnel peut rencontrer. Nous nous contenterons d'examiner 3 situations :
- Les congés (jours entiers: C , demi jours : C/2)
- Les récupérations en temps (de -16 à +16)
- Les exemptions médicales à domicile (code EXDOM)
Les requêtes
Première requête, simplement une reproduction de T_Noms (dans un souci de maintenance de la BD, il est toujours préférable de créer des requêtes, même si dans un premier temps, elles peuvent paraître inutiles)
On crée ensuite une requête qui regroupe 2 tables. On utilise les champs T_Noms.Noms, T_Noms.Fonctions et tous les champs de la seconde table T_Details. Une liaison de un à plusieurs les relie
On finit par créer une dernière requête basée sur la T_InitialisationAnnees
Les formulaires
SF_Details : Ce formulaire est basé sur la requête R_Appel, on y place les 31 jours du mois, l'intitulé du mois, les champs concernant le décompte des congés, récupérations et exemptions, on l'affiche en mode "Feuille de données"
Pour les champs reprenant les journées (1,2,3...31) on inclut une procédure VBA sur l'événement "Sur sortie"
Private Sub Ctl1_Exit(Cancel As Integer)
Me.Refresh
End Sub
et sur l'événement "Après mise à jour", le code suivant :
Private Sub Form_AfterUpdate()
Call CalculRecupConges
End Sub
Ceci pour provoquer le lancement de la procédure "CalculRecupConges" que l'on détaille plus bas sur cette feuille. Il est indispensable de l'initier très souvent pour obtenir des informations correctes au niveau des décomptes des situations que l'on souhaite surveiller (ici, congés, récupérations, exemptions)
F_Appel : pour réaliser ce formulaire, on commence par en créer un premier, automatiquement en mode "formulaire" en nous basant sur la requête R_Noms, on incorpore ensuite par un "glisser" le SF_Details, et on règle la liaison "père-fils" qui doit exister entre eux
Au niveau VBA, on incluera sur l'événement "Sur Activation", le code suivant
Private Sub Form_Current()
DoCmd.Maximize
Call CalculRecupConges
End Sub
On peut ensuite construire différents formulaires pour présenter les informations de manière plus conviviale pour remplir l'une ou l'autre tâche... Parfois, ce sera un formulaire pour afficher les infos individuellement, parfois de manière plus groupées etc... c'est le rôle dans mon exemple, des formulaires F_Mois, F_MoisTabulaire
Nous aurons également besoin d'un formulaire pour initier le nombre de congés alloués par année et par personne (voir F_InitConge dans l'exemple. Cette donnée est essentielle pour effectuer un décompte correct des jours de congé
Les rapports
Ici, je n'en ai composé qu'un seul, il reprend les prestations de chacun sur un mois. Il est destiné à une impression éventuelle pour être archivé sur une feuille de papier. Chacun évaluera s'il est nécessaire ou non
Les modules
Enfin, la partie la plus importante... Comment effectuer un calcul des différentes situations administratives du personnel que l'on souhaite comptabiliser ? Tout d'abord, ces situations seront toujours encodées de la même manière. Des sigles bien déterminés seront employés, un commentaire éventuel peut être utilisé dans le champ ad hoc, mais le sigle ne sera pris en compte que si sa syntaxe est respectée... Aussi, dans mon exemple, un jour de congé sera représenté par la lettre "C" , un demi jour de congé sera représenté par "C\2" , des heures supplémentaires par +1, +2, etc... les heures récupérées par -1, -2, etc ...ces heures seront entrées pour une raison de facilité sous un format décimal, donc +2,25 signifie deux heures un quart et -3,50 correspond à trois heures et demie. Les exemptions à domicile correspondront au sigle "EXDOM".
Si vous souhaitez ajouter un code en surveillance, je place dans une couleur différente les lignes que vous devez copier-coller et adapter au nouveau code...Je prend ici en exemple le code "EXDOM"
Sub CalculRecupConges()
On Error Resume Next
'initialise les tables temporaires en recordsets
Dim db As DAO.Database
Dim rs As DAO.Recordset, rs2 As DAO.Recordset
Dim strSQL As String, strSQL2 As String
Set db = CurrentDb
strSQL = "Select * from T_Details ORDER BY Identification, Mois"
Set rs = db.OpenRecordset(strSQL)
strSQL2 = "Select * from T_InitialisationAnnees order by Annee"
Set rs2 = db.OpenRecordset(strSQL2)
'déclaration des variables
Dim vRecup As Double, vConges As Double, vDemiConges As Double
Dim vIdentification As String, vIdentificationSuivant As String, vConge As Double, vRecups As Double
Dim vExemptions As Double
Dim vQuotaCongeAnnuel As Double, vAnnee As String, test As String, vMoisSuivant As String
'Traitement des enregistrements
Do
'position obligatoire des ces variables, on récupère les valeurs de l'enregistrement en cours de traitement
vIdentification = rs("Identifications")
vRecups = rs("SoldeRecup")
vConge = rs("SoldeConge")
vAnnee = Year(CDate(rs("Mois")))
vExemptions = Abs(rs("Exdom"))
'Récupérer le quota de congé de l'année. En effet, on doit connaître pour chaque personne
'le nombre de congé avec lequel il débute l'année.
'Ce renseignement est dans la T_InitialisationAnnees
rs2.MoveFirst
Do
If rs2("Identifications") = vIdentification And rs2("Annee") = vAnnee Then
vQuotaCongeAnnuel = rs2("NombreJoursDeConges")
End If
rs2.MoveNext
Loop Until rs2.EOF = True
'Récupération du contenu de chaque champs et somme avec situation du mois précédent
vRecup = rs("Sit_Recup_Mois_Precedent") + Val(rs("1")) _
+ Val(rs("2")) + Val(rs("3")) + Val(rs("4")) + Val(rs("5")) _
+ Val(rs("6")) + Val(rs("7")) + Val(rs("8")) + Val(rs("9")) _
+ Val(rs("10")) + Val(rs("11")) + Val(rs("12")) + Val(rs("13")) _
+ Val(rs("14")) + Val(rs("15")) + Val(rs("16")) + Val(rs("17")) _
+ Val(rs("18")) + Val(rs("19")) + Val(rs("20")) + Val(rs("21")) _
+ Val(rs("22")) + Val(rs("23")) + Val(rs("24")) + Val(rs("25")) _
+ Val(rs("26")) + Val(rs("27")) + Val(rs("28")) + Val(rs("29")) _
+ Val(rs("30")) + Val(rs("31"))
vConges = ((rs![1] = "C") + (rs![2] = "C") + (rs![3] = "C") _
+ (rs![4] = "C") + (rs![5] = "C") + (rs![6] = "C") _
+ (rs![7] = "C") + (rs![8] = "C") + (rs![9] = "C") _
+ (rs![10] = "C") + (rs![11] = "C") + (rs![12] = "C") _
+ (rs![13] = "C") + (rs![14] = "C") + (rs![15] = "C") _
+ (rs![16] = "C") + (rs![17] = "C") + (rs![18] = "C") _
+ (rs![19] = "C") + (rs![20] = "C") + (rs![21] = "C") _
+ (rs![22] = "C") + (rs![23] = "C") + (rs![24] = "C") _
+ (rs![25] = "C") + (rs![26] = "C") + (rs![27] = "C") _
+ (rs![28] = "C") + (rs![29] = "C") + (rs![30] = "C") + (rs![31] = "C"))
vDemiConges = ((rs![1] = "C/2") + (rs![2] = "C/2") _
+ (rs![3] = "C/2") + (rs![4] = "C/2") + (rs![5] = "C/2") _
+ (rs![6] = "C/2") + (rs![7] = "C/2") + (rs![8] = "C/2") _
+ (rs![9] = "C/2") + (rs![10] = "C/2") + (rs![11] = "C/2") _
+ (rs![12] = "C/2") + (rs![13] = "C/2") + (rs![14] = "C/2") _
+ (rs![15] = "C/2") + (rs![16] = "C/2") + (rs![17] = "C/2") _
+ (rs![18] = "C/2") + (rs![19] = "C/2") + (rs![20] = "C/2") _
+ (rs![21] = "C/2") + (rs![22] = "C/2") + (rs![23] = "C/2") _
+ (rs![24] = "C/2") + (rs![25] = "C/2") + (rs![26] = "C/2") _
+ (rs![27] = "C/2") + (rs![28] = "C/2") + (rs![29] = "C/2") _
+ (rs![30] = "C/2") + (rs![31] = "C/2"))
vExemptions = Abs(((rs![1] = "EXDOM") + (rs![2] = "EXDOM") _
+ (rs![3] = "EXDOM") + (rs![4] = "EXDOM") + (rs![5] = "EXDOM") _
+ (rs![6] = "EXDOM") + (rs![7] = "EXDOM") + (rs![8] = "EXDOM") _
+ (rs![9] = "EXDOM") + (rs![10] = "EXDOM") + (rs![11] = "EXDOM") _
+ (rs![12] = "EXDOM") + (rs![13] = "EXDOM") + (rs![14] = "EXDOM") _
+ (rs![15] = "EXDOM") + (rs![16] = "EXDOM") + (rs![17] = "EXDOM") _
+ (rs![18] = "EXDOM") + (rs![19] = "EXDOM") + (rs![20] = "EXDOM") _
+ (rs![21] = "EXDOM") + (rs![22] = "EXDOM") + (rs![23] = "EXDOM") _
+ (rs![24] = "EXDOM") + (rs![25] = "EXDOM") + (rs![26] = "EXDOM") _
+ (rs![27] = "EXDOM") + (rs![28] = "EXDOM") + (rs![29] = "EXDOM") _
+ (rs![30] = "EXDOM") + (rs![31] = "EXDOM")))
'Mise à jour de ce qui reste en récup et en congé
rs.Edit
rs("SoldeRecup") = vRecup
If rs("Sit_Conge_Mois_Precedent") = 0 Then
rs("Sit_Conge_Mois_Precedent") = vQuotaCongeAnnuel
End If
rs("SoldeConge") = rs("Sit_Conge_Mois_Precedent") - (Abs(vConges) + ((Abs(vDemiConges)) / 2))
rs("Exdom") = rs("Sit_EXDOM_Mois_Precedent") + vExemptions
rs.Update
vRecups = rs("SoldeRecup")
vConge = rs("SoldeConge")
vExemptions = rs("Exdom")
rs.MoveNext
vIdentificationSuivant = rs("Identifications")
vMoisSuivant = Year(CDate(rs("Mois")))
'Premier test, on remplit les situations des mois précédents
If vIdentificationSuivant = vIdentification Then
rs.Edit
rs("Sit_Conge_Mois_Precedent") = vConge
rs("Sit_Recup_Mois_Precedent") = vRecups
rs("Sit_EXDOM_Mois_Precedent") = vExemptions
rs.Update
End If
'Second test doit être dissocié du premier, on réinitialise les compteurs si on change d'année
If vMoisSuivant <> vAnnee Then
rs.Edit
rs("Sit_Conge_Mois_Precedent") = 0
rs("Sit_Recup_Mois_Precedent") = 0
rs("Sit_EXDOM_Mois_Precedent") = 0
rs.Update
End If
rs.MovePrevious
'idem, quand on saute d'individu
If vIdentificationSuivant <> vIdentification Then
vRecup = 0
vConges = 0
vDemiConges = 0
vExemptions = 0
End If
rs.MoveNext
Loop Until rs.EOF = True
rs.Close
rs2.Close
Set db = Nothing
End Sub
Cliquez ici pour télécharger le fichier zip : GestionPersonnel (Sous Access 2013, il faut supprimer la référence vers le fichier utility.mda. Pour faire cela, faire ALT+F11, dans le VBE, aller dans le menu Outils - Références et enlever la coche devant ce fichier signalé manquant)