timetrack-pro/docs/FORMS_GUIDE.md
StillHammer 317ca0904a Phase 6: Documentation + Guide formulaires
Documentation:
- CHANGELOG.md: v0.1.0 Initial Release
- README.md: Stats, installation, utilisation mise a jour
- PLAN.md: Status phases actualise (85% complete)
- docs/TEST_CHECKLIST.md: 61 tests manuels

Guide Formulaires:
- docs/FORMS_GUIDE.md: Guide complet creation formulaires Access
  - 5 formulaires principaux (Accueil, Clients, Projets, SaisieTemps, Historique)
  - 2 formulaires popup (ProjetDetail, TempsDetail)
  - Code VBA complet pour chaque formulaire
  - 800+ lignes de documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:34:14 +07:00

1356 lines
43 KiB
Markdown

# TimeTrack Pro - Guide de Creation des Formulaires Access
## Vue d'ensemble
Ce guide detaille la creation des 5 formulaires principaux de TimeTrack Pro dans Microsoft Access. Les formulaires utilisent les 6 modules VBA documentes dans `VBA_MODULES.md` (43 macros disponibles).
---
## Architecture des Formulaires
```
frm_Accueil
|
+----------------+----------------+
| | |
frm_Clients frm_Projets frm_SaisieTemps
| | |
+----------------+----------------+
|
frm_Historique
```
### Modules VBA utilises
| Module | Formulaires qui l'utilisent |
|--------|----------------------------|
| mod_Navigation | Tous (navigation entre formulaires) |
| mod_DataAccess | frm_Clients, frm_Projets, frm_SaisieTemps, frm_Historique |
| mod_Calculs | frm_Accueil, frm_Historique |
| mod_Config | Tous (constantes, messages) |
| mod_Utils | Tous (formatage, validation) |
| mod_Export | frm_Historique |
---
## 1. frm_Accueil - Menu Principal
### Description
Formulaire d'accueil avec navigation vers les autres formulaires et affichage des statistiques rapides.
### Proprietes du Formulaire
| Propriete | Valeur |
|-----------|--------|
| Record Source | (aucune - formulaire non lie) |
| Caption | TimeTrack Pro - Accueil |
| Navigation Buttons | Non |
| Record Selectors | Non |
| Dividing Lines | Non |
| Scroll Bars | Neither |
| Border Style | Dialog |
| Auto Center | Oui |
| Width | 10 cm |
| Detail Height | 12 cm |
### Controles a ajouter
#### Section En-tete (Header)
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTitre | Caption: "TimeTrack Pro", Font Size: 24, Font Weight: Bold, Fore Color: #2C3E50 |
| Label | lblVersion | Caption: (lie a GetAppTitle), Font Size: 10 |
#### Section Detail
**Zone Statistiques (Frame)**
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Frame | fraStats | Caption: "Statistiques" |
| Label | lblNbClients | Caption: "Clients:" |
| TextBox | txtNbClients | Enabled: Non, Locked: Oui, Back Color: Blanc |
| Label | lblNbProjets | Caption: "Projets actifs:" |
| TextBox | txtNbProjets | Enabled: Non, Locked: Oui |
| Label | lblHeuresMois | Caption: "Heures ce mois:" |
| TextBox | txtHeuresMois | Enabled: Non, Locked: Oui, Format: "0.00 h" |
**Boutons de Navigation**
| Controle | Nom | Caption | Width |
|----------|-----|---------|-------|
| Button | btnClients | Gestion Clients | 4 cm |
| Button | btnProjets | Gestion Projets | 4 cm |
| Button | btnSaisie | Saisie Temps | 4 cm |
| Button | btnHistorique | Historique | 4 cm |
| Button | btnQuitter | Quitter | 4 cm |
### Code VBA des Evenements
```vba
'===============================================================================
' Formulaire: frm_Accueil
' Description: Menu principal et statistiques
'===============================================================================
Option Compare Database
Option Explicit
'-------------------------------------------------------------------------------
' Evenement: Form_Load
' Description: Initialise le formulaire au chargement
'-------------------------------------------------------------------------------
Private Sub Form_Load()
' Titre de la fenetre
Me.Caption = GetAppTitle()
' Charger les statistiques
Call RefreshStats
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_Activate
' Description: Rafraichit les stats quand on revient sur ce formulaire
'-------------------------------------------------------------------------------
Private Sub Form_Activate()
Call RefreshStats
End Sub
'-------------------------------------------------------------------------------
' Sub: RefreshStats
' Description: Met a jour les statistiques affichees
'-------------------------------------------------------------------------------
Private Sub RefreshStats()
Me.txtNbClients = GetNbClients()
Me.txtNbProjets = GetNbProjetsActifs()
Me.txtHeuresMois = FormatDuree(GetHeuresMoisCourant())
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnClients_Click
' Description: Ouvre le formulaire de gestion des clients
'-------------------------------------------------------------------------------
Private Sub btnClients_Click()
Call OpenFormClients
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnProjets_Click
' Description: Ouvre le formulaire de gestion des projets
'-------------------------------------------------------------------------------
Private Sub btnProjets_Click()
Call OpenFormProjets
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnSaisie_Click
' Description: Ouvre le formulaire de saisie de temps
'-------------------------------------------------------------------------------
Private Sub btnSaisie_Click()
Call OpenFormSaisieTemps
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnHistorique_Click
' Description: Ouvre le formulaire d'historique
'-------------------------------------------------------------------------------
Private Sub btnHistorique_Click()
Call OpenFormHistorique
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnQuitter_Click
' Description: Ferme l'application
'-------------------------------------------------------------------------------
Private Sub btnQuitter_Click()
If Confirm("Voulez-vous vraiment quitter TimeTrack Pro ?") Then
DoCmd.Quit
End If
End Sub
```
### Etapes de Creation dans Access
1. **Creer le formulaire**
- Onglet "Creer" > "Creation de formulaire"
- Enregistrer sous "frm_Accueil"
2. **Configurer les proprietes**
- Feuille de proprietes (F4) > Onglet "Format"
- Appliquer les proprietes du tableau ci-dessus
3. **Ajouter l'en-tete**
- Clic droit sur la section Detail > "En-tete/Pied de formulaire"
- Ajouter les labels dans l'en-tete
4. **Creer le cadre des statistiques**
- Onglet "Conception" > "Controles" > Rectangle (ou Frame)
- Ajouter les TextBox pour les stats
5. **Ajouter les boutons**
- Onglet "Conception" > "Bouton"
- Nommer chaque bouton selon le tableau
- Annuler l'assistant de bouton si propose
6. **Ajouter le code VBA**
- Clic droit sur le formulaire > "Generer le code"
- Coller le code dans le module de classe
---
## 2. frm_Clients - Gestion des Clients
### Description
Formulaire de type liste continue (Continuous Form) pour afficher, ajouter, modifier et supprimer des clients.
### Proprietes du Formulaire
| Propriete | Valeur |
|-----------|--------|
| Record Source | tbl_Clients |
| Default View | Continuous Forms |
| Caption | Gestion des Clients |
| Allow Additions | Oui |
| Allow Deletions | Non (gere par bouton) |
| Allow Edits | Oui |
| Navigation Buttons | Non |
| Record Selectors | Oui |
### Controles a ajouter
#### Section En-tete
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTitre | Caption: "Gestion des Clients", Font Size: 18 |
| Button | btnNouveau | Caption: "Nouveau Client" |
| Button | btnSupprimer | Caption: "Supprimer" |
| Button | btnRetour | Caption: "Retour" |
#### Section Detail (controles lies)
| Controle | Nom | Control Source | Width | Proprietes |
|----------|-----|----------------|-------|------------|
| TextBox | txtClientID | ClientID | 1.5 cm | Enabled: Non, Tab Stop: Non |
| TextBox | txtNom | Nom | 4 cm | |
| TextBox | txtEmail | Email | 4 cm | |
| TextBox | txtTelephone | Telephone | 2.5 cm | |
| TextBox | txtNotes | Notes | 5 cm | |
#### Section Pied
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTotal | Caption: "Total:" |
| TextBox | txtTotal | Control Source: =Count([ClientID]) |
### Code VBA des Evenements
```vba
'===============================================================================
' Formulaire: frm_Clients
' Description: Gestion CRUD des clients
'===============================================================================
Option Compare Database
Option Explicit
'-------------------------------------------------------------------------------
' Evenement: Form_Load
' Description: Initialise le formulaire
'-------------------------------------------------------------------------------
Private Sub Form_Load()
Me.Caption = "Gestion des Clients - " & APP_NAME
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnNouveau_Click
' Description: Ajoute un nouveau client (va a un nouvel enregistrement)
'-------------------------------------------------------------------------------
Private Sub btnNouveau_Click()
DoCmd.GoToRecord , , acNewRec
Me.txtNom.SetFocus
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnSupprimer_Click
' Description: Supprime le client selectionne
'-------------------------------------------------------------------------------
Private Sub btnSupprimer_Click()
If IsNull(Me.txtClientID) Or Me.txtClientID = 0 Then
ShowError "Veuillez selectionner un client a supprimer."
Exit Sub
End If
If Confirm(MSG_CONFIRM_DELETE & vbCrLf & vbCrLf & _
"Client: " & Me.txtNom & vbCrLf & _
"Attention: Les projets et temps associes seront egalement supprimes.") Then
' Utiliser la fonction du module mod_DataAccess
Call DeleteClient(Me.txtClientID)
' Rafraichir le formulaire
Me.Requery
ShowInfo "Client supprime avec succes."
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnRetour_Click
' Description: Retourne au menu principal
'-------------------------------------------------------------------------------
Private Sub btnRetour_Click()
DoCmd.Close acForm, Me.Name
Call OpenFormAccueil
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_BeforeUpdate
' Description: Valide les donnees avant sauvegarde
'-------------------------------------------------------------------------------
Private Sub Form_BeforeUpdate(Cancel As Integer)
' Verifier que le nom est renseigne
If IsNull(Me.txtNom) Or Trim(Me.txtNom & "") = "" Then
ShowError "Le nom du client est obligatoire."
Me.txtNom.SetFocus
Cancel = True
Exit Sub
End If
' Valider l'email si renseigne
If Not IsValidEmail(Nz(Me.txtEmail, "")) Then
ShowError "Le format de l'email n'est pas valide."
Me.txtEmail.SetFocus
Cancel = True
Exit Sub
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_AfterUpdate
' Description: Confirmation apres sauvegarde
'-------------------------------------------------------------------------------
Private Sub Form_AfterUpdate()
LogAction "Client sauvegarde: " & Me.txtNom
End Sub
'-------------------------------------------------------------------------------
' Evenement: txtNom_DblClick
' Description: Double-clic pour voir les projets du client
'-------------------------------------------------------------------------------
Private Sub txtNom_DblClick(Cancel As Integer)
If Not IsNull(Me.txtClientID) Then
Call OpenFormProjets(Me.txtClientID)
End If
End Sub
```
### Etapes de Creation dans Access
1. **Creer le formulaire avec l'assistant**
- Onglet "Creer" > "Assistant Formulaire"
- Selectionner tbl_Clients
- Choisir les champs: ClientID, Nom, Email, Telephone, Notes
- Disposition: Tabulaire
- Style: selon preference
2. **Convertir en Continuous Form**
- Mode Creation > Proprietes > Default View: Continuous Forms
3. **Ajouter l'en-tete avec boutons**
- Afficher l'en-tete de formulaire
- Ajouter le titre et les boutons
4. **Ajouter le pied avec compteur**
- Afficher le pied de formulaire
- Ajouter TextBox avec =Count([ClientID])
5. **Configurer les controles**
- Definir txtClientID comme non editable
- Ajuster les largeurs
6. **Ajouter le code VBA**
- Mode VBA > Coller le code
---
## 3. frm_Projets - Gestion des Projets
### Description
Formulaire liste des projets avec filtre par client (ComboBox).
### Proprietes du Formulaire
| Propriete | Valeur |
|-----------|--------|
| Record Source | qry_ProjetsComplet (voir ci-dessous) |
| Default View | Continuous Forms |
| Caption | Gestion des Projets |
| Allow Additions | Non (via sous-formulaire popup) |
| Allow Deletions | Non (via bouton) |
| Allow Edits | Oui |
### Requete Source (a creer)
```sql
-- qry_ProjetsComplet
SELECT
p.ProjetID,
p.ClientID,
c.Nom AS ClientNom,
p.Nom,
p.Description,
p.TauxHoraire,
p.Actif,
p.DateCreation
FROM tbl_Clients c
INNER JOIN tbl_Projets p ON c.ClientID = p.ClientID
ORDER BY c.Nom, p.Nom;
```
### Controles a ajouter
#### Section En-tete
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTitre | Caption: "Gestion des Projets", Font Size: 18 |
| Label | lblFiltre | Caption: "Filtrer par client:" |
| ComboBox | cboFiltreClient | Row Source: voir ci-dessous |
| Button | btnNouveau | Caption: "Nouveau Projet" |
| Button | btnSupprimer | Caption: "Supprimer" |
| Button | btnRetour | Caption: "Retour" |
**Row Source pour cboFiltreClient:**
```sql
SELECT 0, "(Tous les clients)" FROM tbl_Clients
UNION
SELECT ClientID, Nom FROM tbl_Clients ORDER BY 2;
```
Proprietes ComboBox:
- Column Count: 2
- Column Widths: 0;4cm
- Bound Column: 1
- Default Value: 0
#### Section Detail
| Controle | Nom | Control Source | Width |
|----------|-----|----------------|-------|
| TextBox | txtProjetID | ProjetID | 1 cm |
| TextBox | txtClientNom | ClientNom | 3 cm |
| TextBox | txtNom | Nom | 4 cm |
| TextBox | txtDescription | Description | 4 cm |
| TextBox | txtTauxHoraire | TauxHoraire | 2 cm |
| CheckBox | chkActif | Actif | 1 cm |
### Code VBA des Evenements
```vba
'===============================================================================
' Formulaire: frm_Projets
' Description: Gestion CRUD des projets avec filtre client
'===============================================================================
Option Compare Database
Option Explicit
'-------------------------------------------------------------------------------
' Evenement: Form_Load
' Description: Initialise le formulaire
'-------------------------------------------------------------------------------
Private Sub Form_Load()
Me.Caption = "Gestion des Projets - " & APP_NAME
Me.cboFiltreClient = 0 ' Tous les clients par defaut
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_Open
' Description: Applique un filtre si passe en OpenArgs
'-------------------------------------------------------------------------------
Private Sub Form_Open(Cancel As Integer)
' Si un ClientID est passe via OpenArgs
If Not IsNull(Me.OpenArgs) And IsNumeric(Me.OpenArgs) Then
Me.cboFiltreClient = CLng(Me.OpenArgs)
Call ApplyFilter
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: cboFiltreClient_AfterUpdate
' Description: Filtre les projets par client
'-------------------------------------------------------------------------------
Private Sub cboFiltreClient_AfterUpdate()
Call ApplyFilter
End Sub
'-------------------------------------------------------------------------------
' Sub: ApplyFilter
' Description: Applique le filtre client
'-------------------------------------------------------------------------------
Private Sub ApplyFilter()
If IsNull(Me.cboFiltreClient) Or Me.cboFiltreClient = 0 Then
Me.Filter = ""
Me.FilterOn = False
Else
Me.Filter = "ClientID = " & Me.cboFiltreClient
Me.FilterOn = True
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnNouveau_Click
' Description: Ouvre le formulaire popup pour nouveau projet
'-------------------------------------------------------------------------------
Private Sub btnNouveau_Click()
' Ouvrir un formulaire popup pour ajouter un projet
DoCmd.OpenForm "frm_ProjetDetail", , , , acFormAdd, acDialog
' Rafraichir apres fermeture
Me.Requery
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnSupprimer_Click
' Description: Supprime le projet selectionne
'-------------------------------------------------------------------------------
Private Sub btnSupprimer_Click()
If IsNull(Me.txtProjetID) Or Me.txtProjetID = 0 Then
ShowError "Veuillez selectionner un projet a supprimer."
Exit Sub
End If
If Confirm(MSG_CONFIRM_DELETE & vbCrLf & vbCrLf & _
"Projet: " & Me.txtNom & vbCrLf & _
"Attention: Les entrees de temps associees seront egalement supprimees.") Then
Call DeleteProjet(Me.txtProjetID)
Me.Requery
ShowInfo "Projet supprime avec succes."
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnRetour_Click
' Description: Retourne au menu principal
'-------------------------------------------------------------------------------
Private Sub btnRetour_Click()
DoCmd.Close acForm, Me.Name
Call OpenFormAccueil
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_BeforeUpdate
' Description: Valide les donnees avant sauvegarde
'-------------------------------------------------------------------------------
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me.txtNom) Or Trim(Me.txtNom & "") = "" Then
ShowError "Le nom du projet est obligatoire."
Me.txtNom.SetFocus
Cancel = True
Exit Sub
End If
If IsNull(Me.txtTauxHoraire) Then
Me.txtTauxHoraire = DEFAULT_TAUX_HORAIRE
End If
End Sub
'-------------------------------------------------------------------------------
' Evenement: txtNom_DblClick
' Description: Double-clic pour saisir du temps sur ce projet
'-------------------------------------------------------------------------------
Private Sub txtNom_DblClick(Cancel As Integer)
If Not IsNull(Me.txtProjetID) Then
Call OpenFormSaisieTemps(Me.txtProjetID)
End If
End Sub
```
### Formulaire Popup: frm_ProjetDetail
Pour la creation de nouveaux projets, creer un formulaire popup supplementaire:
**Proprietes:**
- Record Source: tbl_Projets
- Default View: Single Form
- Pop Up: Oui
- Modal: Oui
- Border Style: Dialog
**Controles:**
| Controle | Nom | Control Source |
|----------|-----|----------------|
| ComboBox | cboClient | ClientID |
| TextBox | txtNom | Nom |
| TextBox | txtDescription | Description |
| TextBox | txtTauxHoraire | TauxHoraire |
| CheckBox | chkActif | Actif |
| Button | btnSauver | Caption: "Sauvegarder" |
| Button | btnAnnuler | Caption: "Annuler" |
**Row Source cboClient:**
```sql
SELECT ClientID, Nom FROM tbl_Clients ORDER BY Nom;
```
---
## 4. frm_SaisieTemps - Saisie Rapide de Temps
### Description
Formulaire de saisie rapide avec selection du projet, date, duree et description.
### Proprietes du Formulaire
| Propriete | Valeur |
|-----------|--------|
| Record Source | (aucune - formulaire non lie) |
| Default View | Single Form |
| Caption | Saisie de Temps |
| Pop Up | Non |
| Modal | Non |
| Border Style | Sizable |
| Navigation Buttons | Non |
### Controles a ajouter
#### Section En-tete
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTitre | Caption: "Nouvelle Entree de Temps", Font Size: 18 |
#### Section Detail
| Controle | Nom | Type | Proprietes |
|----------|-----|------|------------|
| Label | lblProjet | Label | Caption: "Projet *" |
| ComboBox | cboProjet | ComboBox | Row Source: voir ci-dessous |
| Label | lblDate | Label | Caption: "Date *" |
| TextBox | txtDate | TextBox | Format: Short Date, Default: =Date() |
| Label | lblDuree | Label | Caption: "Duree (heures) *" |
| TextBox | txtDuree | TextBox | Format: 0.00, Default: 1.00 |
| Label | lblDescription | Label | Caption: "Description" |
| TextBox | txtDescription | TextBox | Height: 2 cm (multilignes) |
| Button | btnSauver | Button | Caption: "Enregistrer" |
| Button | btnSauverNouveau | Button | Caption: "Enregistrer et Nouveau" |
| Button | btnAnnuler | Button | Caption: "Annuler" |
**Row Source pour cboProjet:**
```sql
SELECT p.ProjetID, c.Nom & " - " & p.Nom AS ProjetComplet, p.TauxHoraire
FROM tbl_Clients c
INNER JOIN tbl_Projets p ON c.ClientID = p.ClientID
WHERE p.Actif = True
ORDER BY c.Nom, p.Nom;
```
Proprietes ComboBox:
- Column Count: 3
- Column Widths: 0;6cm;2cm
- Bound Column: 1
#### Section Pied
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblRecent | Caption: "Derniere saisie:" |
| TextBox | txtRecent | Enabled: Non |
| Button | btnRetour | Caption: "Retour au menu" |
### Code VBA des Evenements
```vba
'===============================================================================
' Formulaire: frm_SaisieTemps
' Description: Saisie rapide d'entrees de temps
'===============================================================================
Option Compare Database
Option Explicit
Private m_LastProjetID As Long ' Memorise le dernier projet utilise
'-------------------------------------------------------------------------------
' Evenement: Form_Load
' Description: Initialise le formulaire
'-------------------------------------------------------------------------------
Private Sub Form_Load()
Me.Caption = "Saisie de Temps - " & APP_NAME
' Valeurs par defaut
Me.txtDate = Date
Me.txtDuree = DEFAULT_DUREE
' Afficher la derniere saisie
Call UpdateLastEntry
End Sub
'-------------------------------------------------------------------------------
' Evenement: Form_Open
' Description: Pre-selectionne un projet si passe en OpenArgs
'-------------------------------------------------------------------------------
Private Sub Form_Open(Cancel As Integer)
If Not IsNull(Me.OpenArgs) And IsNumeric(Me.OpenArgs) Then
Me.cboProjet = CLng(Me.OpenArgs)
m_LastProjetID = CLng(Me.OpenArgs)
End If
End Sub
'-------------------------------------------------------------------------------
' Sub: UpdateLastEntry
' Description: Affiche la derniere entree de temps
'-------------------------------------------------------------------------------
Private Sub UpdateLastEntry()
Dim rs As DAO.Recordset
Dim sql As String
sql = "SELECT TOP 1 t.Date, p.Nom, t.Duree " & _
"FROM tbl_Temps t INNER JOIN tbl_Projets p ON t.ProjetID = p.ProjetID " & _
"ORDER BY t.DateCreation DESC"
Set rs = CurrentDb.OpenRecordset(sql)
If Not rs.EOF Then
Me.txtRecent = FormatDateFR(rs!Date) & " - " & rs!Nom & " - " & FormatDuree(rs!Duree)
Else
Me.txtRecent = "(aucune saisie)"
End If
rs.Close
End Sub
'-------------------------------------------------------------------------------
' Sub: ClearForm
' Description: Reinitialise le formulaire
'-------------------------------------------------------------------------------
Private Sub ClearForm()
Me.txtDate = Date
Me.txtDuree = DEFAULT_DUREE
Me.txtDescription = ""
' Garder le dernier projet selectionne
If m_LastProjetID > 0 Then
Me.cboProjet = m_LastProjetID
Else
Me.cboProjet = Null
End If
Me.cboProjet.SetFocus
End Sub
'-------------------------------------------------------------------------------
' Function: ValidateForm
' Description: Valide les donnees du formulaire
'-------------------------------------------------------------------------------
Private Function ValidateForm() As Boolean
ValidateForm = False
' Projet obligatoire
If IsNull(Me.cboProjet) Then
ShowError "Veuillez selectionner un projet."
Me.cboProjet.SetFocus
Exit Function
End If
' Date obligatoire
If IsNull(Me.txtDate) Then
ShowError "Veuillez saisir une date."
Me.txtDate.SetFocus
Exit Function
End If
' Date ne peut pas etre dans le futur
If Me.txtDate > Date Then
ShowError "La date ne peut pas etre dans le futur."
Me.txtDate.SetFocus
Exit Function
End If
' Duree obligatoire et positive
If IsNull(Me.txtDuree) Or Me.txtDuree <= 0 Then
ShowError "Veuillez saisir une duree valide (> 0)."
Me.txtDuree.SetFocus
Exit Function
End If
' Duree raisonnable (max 24h)
If Me.txtDuree > 24 Then
ShowError "La duree ne peut pas depasser 24 heures."
Me.txtDuree.SetFocus
Exit Function
End If
ValidateForm = True
End Function
'-------------------------------------------------------------------------------
' Sub: SaveEntry
' Description: Sauvegarde l'entree de temps
'-------------------------------------------------------------------------------
Private Sub SaveEntry()
Dim tempsID As Long
If Not ValidateForm() Then Exit Sub
' Memoriser le projet pour la prochaine saisie
m_LastProjetID = Me.cboProjet
' Sauvegarder via mod_DataAccess
tempsID = SaveTemps( _
projetID:=Me.cboProjet, _
dateEntree:=Me.txtDate, _
duree:=Me.txtDuree, _
description:=Nz(Me.txtDescription, "") _
)
LogAction "Temps sauvegarde: ID=" & tempsID & ", Projet=" & Me.cboProjet & ", Duree=" & Me.txtDuree
Call UpdateLastEntry
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnSauver_Click
' Description: Sauvegarde et ferme
'-------------------------------------------------------------------------------
Private Sub btnSauver_Click()
Call SaveEntry
ShowInfo MSG_SAVE_SUCCESS
DoCmd.Close acForm, Me.Name
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnSauverNouveau_Click
' Description: Sauvegarde et prepare nouvelle saisie
'-------------------------------------------------------------------------------
Private Sub btnSauverNouveau_Click()
Call SaveEntry
ShowInfo MSG_SAVE_SUCCESS
Call ClearForm
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnAnnuler_Click
' Description: Annule et ferme
'-------------------------------------------------------------------------------
Private Sub btnAnnuler_Click()
DoCmd.Close acForm, Me.Name
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnRetour_Click
' Description: Retourne au menu principal
'-------------------------------------------------------------------------------
Private Sub btnRetour_Click()
DoCmd.Close acForm, Me.Name
Call OpenFormAccueil
End Sub
'-------------------------------------------------------------------------------
' Evenement: cboProjet_AfterUpdate
' Description: Affiche le taux horaire du projet selectionne
'-------------------------------------------------------------------------------
Private Sub cboProjet_AfterUpdate()
If Not IsNull(Me.cboProjet) Then
' La 3e colonne contient le taux horaire
Dim taux As Currency
taux = Nz(Me.cboProjet.Column(2), 0)
Me.Caption = "Saisie de Temps - Taux: " & FormatMontant(taux) & "/h"
End If
End Sub
```
### Etapes de Creation dans Access
1. **Creer le formulaire vierge**
- Onglet "Creer" > "Creation de formulaire"
- Ne pas lier a une table (Record Source vide)
2. **Ajouter les controles**
- Disposer les labels et champs selon le design
- Utiliser l'assistant ComboBox pour cboProjet
3. **Configurer le ComboBox cboProjet**
- Row Source Type: Table/Query
- Row Source: la requete SQL ci-dessus
- Bound Column: 1
- Column Count: 3
- Column Widths: 0;6cm;2cm
4. **Configurer les valeurs par defaut**
- txtDate: =Date()
- txtDuree: 1.00
5. **Ajouter le code VBA**
---
## 5. frm_Historique - Historique des Temps
### Description
Formulaire d'affichage de l'historique avec filtres multiples (dates, client, projet).
### Proprietes du Formulaire
| Propriete | Valeur |
|-----------|--------|
| Record Source | (dynamique via VBA) |
| Default View | Datasheet |
| Caption | Historique des Temps |
| Allow Additions | Non |
| Allow Deletions | Non |
| Allow Edits | Non |
### Controles a ajouter
#### Section En-tete (importante car Datasheet)
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Label | lblTitre | Caption: "Historique des Temps" |
| Label | lblDateDebut | Caption: "Du:" |
| TextBox | txtDateDebut | Format: Short Date |
| Label | lblDateFin | Caption: "Au:" |
| TextBox | txtDateFin | Format: Short Date |
| Label | lblClient | Caption: "Client:" |
| ComboBox | cboClient | Row Source: clients avec option "Tous" |
| Label | lblProjet | Caption: "Projet:" |
| ComboBox | cboProjet | Row Source: dynamique selon client |
| Button | btnFiltrer | Caption: "Filtrer" |
| Button | btnReset | Caption: "Reset" |
| Button | btnExport | Caption: "Exporter Excel" |
| Button | btnRetour | Caption: "Retour" |
**Frame pour totaux:**
| Controle | Nom | Proprietes |
|----------|-----|------------|
| Frame | fraTotaux | Caption: "Totaux" |
| Label | lblTotalHeures | Caption: "Heures:" |
| TextBox | txtTotalHeures | Format: 0.00 h |
| Label | lblTotalMontant | Caption: "Montant:" |
| TextBox | txtTotalMontant | Format: Currency |
#### Section Detail (colonnes Datasheet)
Les colonnes sont definies par la requete source:
- Date
- Client
- Projet
- Duree
- Description
- Montant
### Code VBA des Evenements
```vba
'===============================================================================
' Formulaire: frm_Historique
' Description: Historique des temps avec filtres
'===============================================================================
Option Compare Database
Option Explicit
'-------------------------------------------------------------------------------
' Evenement: Form_Load
' Description: Initialise le formulaire avec le mois en cours
'-------------------------------------------------------------------------------
Private Sub Form_Load()
Me.Caption = "Historique des Temps - " & APP_NAME
' Par defaut: mois en cours
Me.txtDateDebut = GetFirstDayOfMonth()
Me.txtDateFin = GetLastDayOfMonth()
' Initialiser les combos
Call InitCombos
' Charger les donnees
Call LoadData
End Sub
'-------------------------------------------------------------------------------
' Sub: InitCombos
' Description: Initialise les ComboBox de filtres
'-------------------------------------------------------------------------------
Private Sub InitCombos()
' Combo Clients avec option "Tous"
Me.cboClient.RowSource = "SELECT 0, '(Tous les clients)' FROM tbl_Clients " & _
"UNION SELECT ClientID, Nom FROM tbl_Clients ORDER BY 2"
Me.cboClient = 0
' Combo Projets vide au depart
Me.cboProjet.RowSource = ""
Me.cboProjet = Null
End Sub
'-------------------------------------------------------------------------------
' Evenement: cboClient_AfterUpdate
' Description: Met a jour la liste des projets selon le client
'-------------------------------------------------------------------------------
Private Sub cboClient_AfterUpdate()
If IsNull(Me.cboClient) Or Me.cboClient = 0 Then
' Tous les projets
Me.cboProjet.RowSource = "SELECT 0, '(Tous les projets)' FROM tbl_Projets " & _
"UNION SELECT ProjetID, Nom FROM tbl_Projets ORDER BY 2"
Else
' Projets du client selectionne
Me.cboProjet.RowSource = "SELECT 0, '(Tous les projets)' FROM tbl_Projets " & _
"UNION SELECT ProjetID, Nom FROM tbl_Projets " & _
"WHERE ClientID = " & Me.cboClient & " ORDER BY 2"
End If
Me.cboProjet = 0
End Sub
'-------------------------------------------------------------------------------
' Sub: LoadData
' Description: Charge les donnees selon les filtres
'-------------------------------------------------------------------------------
Private Sub LoadData()
Dim sql As String
Dim whereClause As String
' Construction de la requete
sql = "SELECT t.TempsID, t.Date, c.Nom AS Client, p.Nom AS Projet, " & _
"t.Duree, t.Description, t.Duree * p.TauxHoraire AS Montant " & _
"FROM (tbl_Temps t " & _
"INNER JOIN tbl_Projets p ON t.ProjetID = p.ProjetID) " & _
"INNER JOIN tbl_Clients c ON p.ClientID = c.ClientID"
' Construction du WHERE
whereClause = " WHERE 1=1"
' Filtre dates
If Not IsNull(Me.txtDateDebut) Then
whereClause = whereClause & " AND t.Date >= #" & Format(Me.txtDateDebut, "yyyy-mm-dd") & "#"
End If
If Not IsNull(Me.txtDateFin) Then
whereClause = whereClause & " AND t.Date <= #" & Format(Me.txtDateFin, "yyyy-mm-dd") & "#"
End If
' Filtre client
If Not IsNull(Me.cboClient) And Me.cboClient > 0 Then
whereClause = whereClause & " AND p.ClientID = " & Me.cboClient
End If
' Filtre projet
If Not IsNull(Me.cboProjet) And Me.cboProjet > 0 Then
whereClause = whereClause & " AND t.ProjetID = " & Me.cboProjet
End If
' Requete complete
sql = sql & whereClause & " ORDER BY t.Date DESC"
' Appliquer comme source
Me.RecordSource = sql
' Calculer les totaux
Call CalculateTotals(whereClause)
End Sub
'-------------------------------------------------------------------------------
' Sub: CalculateTotals
' Description: Calcule les totaux pour les filtres actuels
'-------------------------------------------------------------------------------
Private Sub CalculateTotals(ByVal whereClause As String)
Dim sql As String
Dim rs As DAO.Recordset
sql = "SELECT SUM(t.Duree) AS TotalHeures, " & _
"SUM(t.Duree * p.TauxHoraire) AS TotalMontant " & _
"FROM (tbl_Temps t " & _
"INNER JOIN tbl_Projets p ON t.ProjetID = p.ProjetID) " & _
"INNER JOIN tbl_Clients c ON p.ClientID = c.ClientID" & _
whereClause
Set rs = CurrentDb.OpenRecordset(sql)
If Not rs.EOF Then
Me.txtTotalHeures = FormatDuree(Nz(rs!TotalHeures, 0))
Me.txtTotalMontant = FormatMontant(Nz(rs!TotalMontant, 0))
Else
Me.txtTotalHeures = FormatDuree(0)
Me.txtTotalMontant = FormatMontant(0)
End If
rs.Close
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnFiltrer_Click
' Description: Applique les filtres
'-------------------------------------------------------------------------------
Private Sub btnFiltrer_Click()
' Validation des dates
If Not IsNull(Me.txtDateDebut) And Not IsNull(Me.txtDateFin) Then
If Me.txtDateDebut > Me.txtDateFin Then
ShowError "La date de debut doit etre anterieure a la date de fin."
Exit Sub
End If
End If
Call LoadData
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnReset_Click
' Description: Reinitialise les filtres
'-------------------------------------------------------------------------------
Private Sub btnReset_Click()
Me.txtDateDebut = GetFirstDayOfMonth()
Me.txtDateFin = GetLastDayOfMonth()
Me.cboClient = 0
Me.cboProjet = Null
Me.cboProjet.RowSource = ""
Call LoadData
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnExport_Click
' Description: Exporte les donnees filtrees vers Excel
'-------------------------------------------------------------------------------
Private Sub btnExport_Click()
Dim dateDebut As Date
Dim dateFin As Date
Dim clientID As Long
' Recuperer les valeurs des filtres
dateDebut = Nz(Me.txtDateDebut, GetFirstDayOfMonth())
dateFin = Nz(Me.txtDateFin, GetLastDayOfMonth())
clientID = Nz(Me.cboClient, 0)
' Appeler la fonction d'export du module mod_Export
Call ExportTempsPeriodeExcel(dateDebut, dateFin, clientID)
End Sub
'-------------------------------------------------------------------------------
' Evenement: btnRetour_Click
' Description: Retourne au menu principal
'-------------------------------------------------------------------------------
Private Sub btnRetour_Click()
DoCmd.Close acForm, Me.Name
Call OpenFormAccueil
End Sub
'-------------------------------------------------------------------------------
' Evenement: Detail_DblClick
' Description: Double-clic sur une ligne pour modifier
'-------------------------------------------------------------------------------
Private Sub Detail_DblClick(Cancel As Integer)
' Option: ouvrir un formulaire de modification
If Not IsNull(Me!TempsID) Then
DoCmd.OpenForm "frm_TempsDetail", , , "TempsID = " & Me!TempsID, , acDialog
Call LoadData ' Rafraichir apres modification
End If
End Sub
```
### Etapes de Creation dans Access
1. **Creer le formulaire**
- Onglet "Creer" > "Creation de formulaire"
- Definir Default View: Datasheet
2. **Important: En-tete de formulaire en mode Datasheet**
- En mode Creation, afficher l'en-tete
- Les controles de l'en-tete apparaitront au-dessus de la grille
3. **Ajouter les filtres dans l'en-tete**
- Placer les TextBox pour les dates
- Placer les ComboBox pour client/projet
- Ajouter les boutons
4. **Zone de totaux**
- Ajouter un cadre avec les TextBox de totaux
- Ces TextBox sont remplis par le code VBA
5. **Configurer l'affichage Datasheet**
- Les colonnes sont definies par le RecordSource (via VBA)
- Ajuster les largeurs de colonnes si necessaire
6. **Ajouter le code VBA**
---
## Annexe A: Formulaire Popup frm_TempsDetail
Pour modifier une entree de temps existante, creer un formulaire popup:
### Proprietes
| Propriete | Valeur |
|-----------|--------|
| Record Source | tbl_Temps |
| Default View | Single Form |
| Pop Up | Oui |
| Modal | Oui |
| Border Style | Dialog |
### Controles
| Controle | Nom | Control Source |
|----------|-----|----------------|
| TextBox | txtTempsID | TempsID (Locked: Oui) |
| ComboBox | cboProjet | ProjetID |
| TextBox | txtDate | Date |
| TextBox | txtDuree | Duree |
| TextBox | txtDescription | Description |
| Button | btnSauver | Caption: "Sauvegarder" |
| Button | btnSupprimer | Caption: "Supprimer" |
| Button | btnAnnuler | Caption: "Annuler" |
### Code VBA
```vba
Private Sub btnSauver_Click()
If Me.Dirty Then Me.Dirty = False
ShowInfo MSG_SAVE_SUCCESS
DoCmd.Close acForm, Me.Name
End Sub
Private Sub btnSupprimer_Click()
If Confirm(MSG_CONFIRM_DELETE) Then
Call DeleteTemps(Me.txtTempsID)
DoCmd.Close acForm, Me.Name
End If
End Sub
Private Sub btnAnnuler_Click()
DoCmd.Close acForm, Me.Name
End Sub
```
---
## Annexe B: Formulaire Popup frm_ProjetDetail
### Proprietes
| Propriete | Valeur |
|-----------|--------|
| Record Source | tbl_Projets |
| Default View | Single Form |
| Pop Up | Oui |
| Modal | Oui |
| Data Entry | Oui (pour nouveau) |
### Controles
| Controle | Nom | Control Source | Proprietes |
|----------|-----|----------------|------------|
| ComboBox | cboClient | ClientID | Row Source: SELECT ClientID, Nom FROM tbl_Clients ORDER BY Nom |
| TextBox | txtNom | Nom | |
| TextBox | txtDescription | Description | Height: 2 cm |
| TextBox | txtTauxHoraire | TauxHoraire | Default: 50, Format: Currency |
| CheckBox | chkActif | Actif | Default: True |
| Button | btnSauver | | Caption: "Sauvegarder" |
| Button | btnAnnuler | | Caption: "Annuler" |
### Code VBA
```vba
Private Sub Form_Load()
Me.Caption = "Nouveau Projet - " & APP_NAME
Me.txtTauxHoraire = DEFAULT_TAUX_HORAIRE
Me.chkActif = True
End Sub
Private Sub btnSauver_Click()
' Validation
If IsNull(Me.cboClient) Then
ShowError "Veuillez selectionner un client."
Me.cboClient.SetFocus
Exit Sub
End If
If IsNull(Me.txtNom) Or Trim(Me.txtNom & "") = "" Then
ShowError "Le nom du projet est obligatoire."
Me.txtNom.SetFocus
Exit Sub
End If
' Sauvegarder
If Me.Dirty Then Me.Dirty = False
ShowInfo MSG_SAVE_SUCCESS
DoCmd.Close acForm, Me.Name
End Sub
Private Sub btnAnnuler_Click()
DoCmd.Close acForm, Me.Name
End Sub
```
---
## Annexe C: Checklist de Creation
### Pour chaque formulaire:
- [ ] Creer le formulaire dans Access
- [ ] Definir les proprietes du formulaire
- [ ] Ajouter tous les controles avec les bons noms
- [ ] Configurer les proprietes de chaque controle
- [ ] Ajouter le code VBA des evenements
- [ ] Tester la navigation (boutons Retour)
- [ ] Tester les operations CRUD
- [ ] Tester les validations
- [ ] Verifier l'affichage (taille, couleurs)
### Ordre de creation recommande:
1. **frm_Accueil** (point d'entree)
2. **frm_Clients** (base, pas de dependances)
3. **frm_ProjetDetail** (popup pour creation)
4. **frm_Projets** (depend de frm_ProjetDetail)
5. **frm_SaisieTemps** (depend des projets)
6. **frm_TempsDetail** (popup pour modification)
7. **frm_Historique** (depend de frm_TempsDetail)
---
## Annexe D: Themes et Styles Access
### Couleurs recommandees
| Element | Couleur | Code |
|---------|---------|------|
| Fond en-tete | Bleu fonce | #2C3E50 |
| Texte en-tete | Blanc | #FFFFFF |
| Boutons principaux | Bleu | #3498DB |
| Boutons danger | Rouge | #E74C3C |
| Fond formulaire | Gris clair | #ECF0F1 |
### Application des styles
```vba
' Dans mod_Config, ajouter:
Public Const COLOR_HEADER As Long = &H503E2C ' RGB inverse en VBA
Public Const COLOR_BUTTON As Long = &HDB9834
Public Const COLOR_DANGER As Long = &H3C4CE7
```
---
## Annexe E: Recapitulatif des Modules VBA Utilises
| Formulaire | Modules utilises | Fonctions appelees |
|------------|------------------|-------------------|
| frm_Accueil | mod_Config, mod_Calculs, mod_Navigation, mod_Utils | GetAppTitle, GetNbClients, GetNbProjetsActifs, GetHeuresMoisCourant, FormatDuree, OpenForm*, Confirm |
| frm_Clients | mod_Config, mod_DataAccess, mod_Navigation, mod_Utils | MSG_CONFIRM_DELETE, DeleteClient, OpenFormAccueil, OpenFormProjets, ShowError, ShowInfo, IsValidEmail, LogAction |
| frm_Projets | mod_Config, mod_DataAccess, mod_Navigation, mod_Utils | MSG_CONFIRM_DELETE, DEFAULT_TAUX_HORAIRE, DeleteProjet, OpenFormAccueil, OpenFormSaisieTemps, ShowError, ShowInfo |
| frm_SaisieTemps | mod_Config, mod_DataAccess, mod_Navigation, mod_Utils | DEFAULT_DUREE, MSG_SAVE_SUCCESS, SaveTemps, FormatDateFR, FormatDuree, FormatMontant, ShowError, ShowInfo, LogAction |
| frm_Historique | mod_Config, mod_Calculs, mod_DataAccess, mod_Export, mod_Navigation, mod_Utils | GetFirstDayOfMonth, GetLastDayOfMonth, FormatDuree, FormatMontant, ExportTempsPeriodeExcel, ShowError, DeleteTemps |
---
**Version:** 1.0
**Date:** 2025-12-30
**Auteur:** Documentation generee pour TimeTrack Pro