Compare commits

..

4 Commits

Author SHA1 Message Date
e81127fc03 Merge github-final: KPIs et donnees dynamiques 2026-01-21 18:14:46 +07:00
36d14c305f KPIs et donnees graphiques dynamiques avec formules
- Ajout formules pour CA Total, Heures, Taux Horaire
- Tables tbl_Temps et tbl_Revenus liees aux KPIs
- Donnees Client/CA et Client/Heures calculees via SUMIF
- Heures ajustees pour taux horaire realiste (69 EUR/h)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 17:43:09 +07:00
21ebf32e4f Dashboard avec graphiques, TCD, slicers et checkboxes fonctionnels
- KPIs complets (CA, Heures, Taux, Stats, Objectifs)
- Graphiques CA par client + Heures par client
- TCD Heures x Client x Projet avec Slicer interactif
- Checkboxes dynamiques bien positionnes (E3:E7)
- Documentation technique et guides MCP

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 17:05:25 +07:00
0442c8f995 Freelance Dashboard v1.0
Excel KPI Dashboard for freelance activity tracking.

Features:
- Revenue, time and client tracking
- Dynamic KPIs and pivot tables
- Interactive charts and slicers
- VBA automation macros
- Professional design
2025-12-30 17:06:54 +07:00
15 changed files with 2407 additions and 0 deletions

748
TECHNICAL_REFERENCE.md Normal file
View File

@ -0,0 +1,748 @@
# Freelance Dashboard - Document Technique et Fonctionnel
**Type de projet:** Business Intelligence / Data Visualization
**Technologie principale:** Microsoft Excel (avec VBA/Macros)
**Public cible:** Freelances, consultants independants, petites entreprises
**Statut:** Proof of Concept - Production Ready
---
## Table des Matieres
1. [Vue d'Ensemble](#vue-densemble)
2. [Problematique Metier](#problematique-metier)
3. [Solution Proposee](#solution-proposee)
4. [Architecture Technique](#architecture-technique)
5. [Fonctionnalites Detaillees](#fonctionnalites-detaillees)
6. [Modele de Donnees](#modele-de-donnees)
7. [Indicateurs de Performance (KPIs)](#indicateurs-de-performance-kpis)
8. [Technologies et Outils](#technologies-et-outils)
9. [Processus de Developpement](#processus-de-developpement)
10. [Competences Demontrees](#competences-demontrees)
11. [Resultats et Impact](#resultats-et-impact)
---
## Vue d'Ensemble
### Concept
**Freelance Dashboard** est un tableau de bord Excel interactif concu pour le suivi en temps reel de l'activite d'un freelance. Il centralise trois dimensions cles : le temps travaille, les revenus generes et la gestion des clients.
Le dashboard transforme des donnees brutes en insights visuels exploitables, permettant une prise de decision rapide et informee.
### Objectifs du Projet
- **Simplifier le suivi d'activite** : Remplacer les feuilles Excel multiples par un dashboard unifie
- **Visualiser la performance** : KPIs en temps reel, graphiques dynamiques, tendances
- **Automatiser les calculs** : Formules avancees et macros VBA pour eliminer le travail manuel
- **Professionnaliser la presentation** : Design moderne adapte a la demonstration client
- **Faciliter la prise de decision** : Identifier rapidement les clients les plus rentables, les periodes creuses, les taux horaires reels
---
## Problematique Metier
### Pain Points Identifies
Les freelances font face a plusieurs defis dans la gestion de leur activite :
| Probleme | Impact |
|----------|--------|
| Donnees dispersees (temps, factures, emails) | Perte de temps, erreurs de facturation |
| Absence de vision globale | Difficulte a identifier les clients rentables |
| Calculs manuels de KPIs | Risque d'erreur, temps perdu |
| Rapports non professionnels | Image peu serieuse face aux clients |
| Suivi du temps approximatif | Sous-facturation, perte de revenu |
### Besoin Exprime
> "Je veux voir en un coup d'oeil mon CA du mois, mes clients les plus rentables, et savoir si je suis sur mes objectifs."
---
## Solution Proposee
### Approche
Creer un **dashboard Excel tout-en-un** avec :
1. **Tables de donnees structurees** pour la saisie (Excel Tables)
2. **Formules avancees** pour les calculs automatiques (SUMIFS, INDEX/MATCH, LET)
3. **Tableaux croises dynamiques** pour l'agregation flexible
4. **Graphiques interactifs** pour la visualisation
5. **Filtres visuels (Slicers)** pour l'exploration des donnees
6. **Macros VBA** pour l'automatisation (refresh, export)
7. **Design professionnel** avec mise en forme conditionnelle
### Avantages de la Solution
- **Zero installation** : Fonctionne avec Excel (presente sur 99% des PC)
- **Leger et rapide** : Pas de base de donnees externe
- **Personnalisable** : Le client peut modifier formules et design
- **Portable** : Un seul fichier `.xlsm` a partager
- **Evolutif** : Peut se connecter a d'autres sources (Access, Power Query, API)
---
## Architecture Technique
### Vue d'Ensemble
```
┌─────────────────────────────────────────────────────────────┐
│ FREELANCE DASHBOARD │
│ (FreelanceDashboard.xlsm) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
┌────▼─────┐ ┌─────▼──────┐ ┌────▼─────┐
│ DATA │ │ BUSINESS │ │ UI │
│ LAYER │ │ LOGIC │ │ LAYER │
└──────────┘ └────────────┘ └──────────┘
│ │ │
- Data_Clients - Formules KPIs - Dashboard
- Data_Temps - Tableaux Croises - Graphiques
- Data_Revenus - Colonnes calculees - Slicers
- Config - Validation - Mise en forme
```
### Structure du Fichier
| Onglet | Role | Type | Contenu |
|--------|------|------|---------|
| **Dashboard** | Interface utilisateur | UI | KPIs, graphiques, slicers, layout final |
| **Data_Clients** | Donnees sources | Data | Table clients (ID, nom, secteur, date debut) |
| **Data_Temps** | Donnees sources | Data | Entrees de temps (date, client, projet, heures) |
| **Data_Revenus** | Donnees sources | Data | Paiements (date, client, montant, type) |
| **Config** | Parametres | Settings | Annee, taux horaire, objectifs, listes deroulantes |
| **TCD_Data** | Calculs intermediaires | Hidden | Tableaux croises dynamiques pour graphiques |
### Flux de Donnees
```
1. SAISIE 2. VALIDATION 3. CALCUL
│ │ │
User entre Validation des Formules Excel
donnees dans ──► donnees (listes ──► calculent les
tables Excel deroulantes, plages) KPIs en temps reel
│ │ │
└────────────────────────┴───────────────────────┘
4. VISUALISATION
Graphiques et TCD
rafraichis auto
```
---
## Fonctionnalites Detaillees
### 1. Gestion des Donnees
#### Tables Structurees Excel
Toutes les donnees sont stockees dans des **Excel Tables** (ListObjects) :
- **Auto-expansion** : Nouvelles lignes ajoutees automatiquement
- **References structurees** : `tbl_Clients[ClientID]` au lieu de `$A$2:$A$10`
- **Filtres integres** : Clic sur en-tetes de colonnes
- **Formules propagees** : Colonnes calculees automatiques
#### Validation des Donnees
| Champ | Validation | Message d'Erreur |
|-------|------------|------------------|
| ClientID | Liste deroulante depuis Data_Clients | "Selectionnez un client existant" |
| Heures | Decimal entre 0.25 et 24 | "Entrez un nombre d'heures valide" |
| Type | Liste (Facture/Acompte/Avoir) | "Type invalide" |
| Date | Format date valide | "Date incorrecte" |
### 2. Calcul des KPIs
Le dashboard affiche **8 indicateurs cles** recalcules en temps reel :
| KPI | Formule | Interpretation |
|-----|---------|----------------|
| **CA Total** | `=SUMIFS(Data_Revenus[Montant], ...)` | Revenu genere sur la periode |
| **CA Mois en Cours** | `=SUMPRODUCT((MONTH(...)=MONTH(TODAY()))...)` | Performance du mois actuel |
| **Heures Totales** | `=SUMIFS(Data_Temps[Heures], ...)` | Volume de travail |
| **Taux Horaire Moyen** | `=CA_Total / Heures_Totales` | Rentabilite reelle (vs. taux affiche) |
| **Nb Clients Actifs** | `=SUMPRODUCT((COUNTIFS(...) > 0) * 1)` | Diversification du portefeuille |
| **Top Client** | `=INDEX(MATCH(MAX(...)))` | Client le plus rentable |
| **Heures Semaine** | `=SUMIFS(..., Date, ">="&DebutSemaine)` | Charge de travail hebdomadaire |
| **Nb Projets** | `=COUNTA(UNIQUE(Data_Temps[Projet]))` | Diversite des missions |
**Formules avancees utilisees :**
- `SUMIFS` / `COUNTIFS` : Agregations conditionnelles multiples
- `INDEX` / `MATCH` : Recherches inversees
- `SUMPRODUCT` : Calculs matriciels sans array formulas
- `LET` (Excel 365) : Variables nommees dans formules
- `XLOOKUP` (Excel 365) : Remplacant de VLOOKUP
### 3. Visualisation des Donnees
#### Graphiques Dynamiques
| Graphique | Type | Source Donnees | Insight |
|-----------|------|----------------|---------|
| **Evolution CA Mensuel** | Barres verticales | TCD sur Data_Revenus | Tendance revenue sur 12 mois |
| **Repartition CA par Client** | Camembert / Donut | TCD sur Data_Revenus | Concentration du CA (regle 80/20) |
| **Heures par Semaine** | Barres empilees | TCD sur Data_Temps | Charge de travail, identification surcharge |
| **CA vs Heures** | Graphique combo | TCD combine | Correlation rentabilite/effort |
#### Tableaux Croises Dynamiques (TCD)
Les TCD permettent :
- **Agregation flexible** : Glisser-deposer les champs
- **Filtrage rapide** : Par periode, client, projet
- **Calculs automatiques** : Somme, moyenne, compte, pourcentage
- **Champs calcules** : Taux horaire = Montant / Heures
#### Slicers (Filtres Visuels)
```
┌───────────────────┐ ┌───────────────────┐
│ CLIENTS │ │ PERIODE │
│ [ ] Acme Corp │ │ [ ] 2024 T1 │
│ [x] Tech Sol. │ │ [x] 2024 T2 │
│ [ ] Marketing │ │ [ ] 2024 T3 │
└───────────────────┘ └───────────────────┘
```
Les slicers sont connectes aux TCD et permettent un filtrage interactif sans formule.
### 4. Automatisation VBA
#### Module `mod_Refresh`
```vba
Sub RefreshDashboard()
' Recalcule toutes les formules
Application.CalculateFull
' Rafraichit tous les tableaux croises
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim pt As PivotTable
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
MsgBox "Dashboard actualise!", vbInformation
End Sub
```
#### Autres Macros
| Macro | Description | Usage |
|-------|-------------|-------|
| `QuickRefresh` | Refresh silencieux (sans popup) | Bouton dashboard |
| `ExportPDF` | Exporte le dashboard en PDF | Partage client |
| `AddTimeEntry` | Formulaire VBA pour saisie rapide | UserForm |
| `BackupData` | Sauvegarde les donnees dans CSV | Securite |
### 5. Design Professionnel
#### Palette de Couleurs
| Couleur | Hex | Usage |
|---------|-----|-------|
| Bleu fonce | `#2C3E50` | En-tetes, titres, elements principaux |
| Vert | `#27AE60` | KPIs positifs, objectifs atteints |
| Gris clair | `#ECF0F1` | Arriere-plan, zones neutres |
| Rouge | `#E74C3C` | Alertes, objectifs non atteints |
| Orange | `#F39C12` | Avertissements, zones d'attention |
#### Mise en Forme Conditionnelle
```
Regle 1: SI CA >= Objectif ALORS Vert
Regle 2: SI CA >= 80% Objectif ALORS Orange
Regle 3: SI CA < 80% Objectif ALORS Rouge
```
Applique sur :
- Cellules KPIs
- Barres de progression
- Indicateurs de tendance (fleches ↑↓)
#### Layout Dashboard
```
┌──────────────────────────────────────────────────────────────┐
│ FREELANCE DASHBOARD - 2025 [Refresh] [Export PDF] │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │
│ │ CA TOTAL │ │ CA MOIS │ │ HEURES │ │ TAUX │ │
│ │ 45 230 € │ │ 8 500 € │ │ 312h │ │ 72 €/h │ │
│ │ │ │ │ │ │ │ │ │
│ └────────────┘ └────────────┘ └────────────┘ └─────────┘ │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │
│ │ NB CLIENTS │ │ TOP CLIENT │ │ H SEMAINE │ │ PROJETS │ │
│ │ 12 │ │ Acme Corp │ │ 38h │ │ 8 │ │
│ └────────────┘ └────────────┘ └────────────┘ └─────────┘ │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ [Slicer: Clients] [Slicer: Annee] [Slicer: Trimestre] │
│ │
├────────────────────────────────┬─────────────────────────────┤
│ │ │
│ EVOLUTION CA MENSUEL │ REPARTITION PAR CLIENT │
│ ┌──────────────────────────┐ │ ┌───────────────────────┐ │
│ │ ▃▅▇▇▆▅▄▆▇▅▃▂ │ │ │ ████ │ │
│ │ │ │ │ ██ ██ Acme │ │
│ │ Jan Feb Mar Apr Mai Jun │ │ │ ██ ██ Tech │ │
│ └──────────────────────────┘ │ │ █ ██ Marketing│ │
│ │ └───────────────────────┘ │
├────────────────────────────────┼─────────────────────────────┤
│ │ │
│ HEURES PAR SEMAINE │ CA vs HEURES │
│ ┌──────────────────────────┐ │ ┌───────────────────────┐ │
│ │ ████ ██ ████ ████ ██ │ │ │ ● ○ │ │
│ │ │ │ │ ● ● ○ ○ │ │
│ │ S01 S02 S03 S04 S05 │ │ │● ● ○ ○ │ │
│ └──────────────────────────┘ │ └───────────────────────┘ │
│ │ │
└────────────────────────────────┴─────────────────────────────┘
```
---
## Modele de Donnees
### Schema Relationnel
```
┌─────────────────┐
│ Data_Clients │
├─────────────────┤
│ ClientID (PK) │◄──────┐
│ Nom │ │
│ Secteur │ │
│ DateDebut │ │
└─────────────────┘ │
│ 1:N
┌─────────────────┐ │ ┌─────────────────┐
│ Data_Temps │ │ │ Data_Revenus │
├─────────────────┤ │ ├─────────────────┤
│ Date │ │ │ Date │
│ ClientID (FK) │───────┼───────│ ClientID (FK) │
│ Projet │ │ │ Montant │
│ Heures │ │ │ Type │
│ Description │ │ └─────────────────┘
└─────────────────┘ │
Relations
```
### Tables de Donnees
#### Data_Clients (5 lignes demo)
| ClientID | Nom | Secteur | DateDebut |
|----------|-----|---------|-----------|
| CLI001 | Acme Corporation | Tech | 15/01/2024 |
| CLI002 | Tech Solutions | Tech | 01/03/2024 |
| CLI003 | Marketing Pro | Marketing | 10/06/2024 |
| CLI004 | E-Shop Plus | E-commerce | 22/09/2024 |
| CLI005 | Finance Group | Finance | 05/11/2024 |
#### Data_Temps (10 lignes demo)
| Date | ClientID | Projet | Heures | Description |
|------|----------|--------|--------|-------------|
| 02/01/2025 | CLI001 | Site Web | 3.5 | Maquettes |
| 02/01/2025 | CLI002 | API Backend | 6.0 | Endpoints |
| 03/01/2025 | CLI001 | Site Web | 4.0 | Integration |
| ... | ... | ... | ... | ... |
**Total:** 43.5 heures sur 10 entrees
#### Data_Revenus (7 lignes demo)
| Date | ClientID | Montant | Type |
|------|----------|---------|------|
| 15/01/2025 | CLI001 | 2500.00 | Facture |
| 20/01/2025 | CLI002 | 4200.00 | Facture |
| 25/01/2025 | CLI003 | 1800.00 | Facture |
| ... | ... | ... | ... |
**Total:** 16 300 € sur 7 paiements
### Regles de Gestion
1. **Un client** peut avoir **plusieurs entrees de temps** (1:N)
2. **Un client** peut avoir **plusieurs paiements** (1:N)
3. **ClientID** est la cle de jointure
4. **Pas de suppression en cascade** : Archivage avec flag plutot que DELETE
5. **Dates** : Format `jj/mm/aaaa` (FR) ou `mm/dd/yyyy` (US) selon locale Excel
---
## Indicateurs de Performance (KPIs)
### KPIs Operationnels
| KPI | Formule Simplifiee | Format | Benchmark |
|-----|--------------------|--------|-----------|
| CA Total | `=SUM(Revenus[Montant])` | `# ##0 €` | Objectif mensuel = 10 000 € |
| Heures Totales | `=SUM(Temps[Heures])` | `0.0 "h"` | 140h/mois (7h × 20j) |
| Taux Horaire Moyen | `=CA / Heures` | `0.00 "€/h"` | Marche FR : 50-100 €/h |
| Nb Clients Actifs | `=COUNTA(UNIQUE(...))` | `0` | 5-10 clients = bon equilibre |
### KPIs Strategiques
| Metrique | Calcul | Objectif | Action si Hors Cible |
|----------|--------|----------|----------------------|
| **Concentration client** | % CA du top client | < 40% | Diversifier portefeuille |
| **Taux d'occupation** | Heures facturees / Heures ouvrables | > 70% | Prospection si < 50% |
| **Variation CA** | (CA mois N - CA mois N-1) / CA mois N-1 | > 0% | Analyser causes si negatif |
| **Projets par client** | Avg(Nb projets / Client) | > 2 | Fidelisation, upsell |
### Alertes Automatiques
Configuration dans `Config` :
```
SI Heures_Semaine > 50 ALORS Alerte "Surcharge"
SI CA_Mois < 80% Objectif ET Jour > 20 ALORS Alerte "Objectif compromise"
SI Top_Client > 50% CA_Total ALORS Alerte "Dependance client"
```
Implementees via mise en forme conditionnelle + macro optionnelle.
---
## Technologies et Outils
### Stack Technique
| Couche | Technologie | Version | Usage |
|--------|-------------|---------|-------|
| **Interface** | Microsoft Excel | 2016+ / M365 | UI, graphiques, formules |
| **Logique Metier** | Excel Formulas | - | Calculs KPIs, agregations |
| **Automatisation** | VBA (Visual Basic for Applications) | 7.1 | Macros, refresh, export |
| **Developpement** | VBA MCP Server | 0.6.0+ | Injection code, automation |
| **Versioning** | Git | 2.x | Tracking changes |
| **Documentation** | Markdown | - | README, specs techniques |
### Fonctionnalites Excel Utilisees
#### Formules
- **SUMIFS / COUNTIFS** : Agregations conditionnelles multiples
- **INDEX / MATCH** : Recherches avancees (remplace VLOOKUP)
- **XLOOKUP** : Fonction moderne de recherche (Excel 365)
- **LET** : Variables dans formules (Excel 365)
- **FILTER / UNIQUE** : Manipulation de tableaux dynamiques (Excel 365)
- **SUMPRODUCT** : Calculs matriciels sans array formulas
#### Objets Excel
- **Excel Tables (ListObjects)** : Tables structurees auto-extensibles
- **PivotTables (TCD)** : Tableaux croises dynamiques
- **Slicers** : Filtres visuels connectes
- **Conditional Formatting** : Mise en forme conditionnelle
- **Data Validation** : Listes deroulantes, contraintes
- **Named Ranges** : Plages nommees pour lisibilite
#### Graphiques
- **Bar Chart** : Graphiques en barres verticales/horizontales
- **Pie Chart / Donut** : Graphiques camembert
- **Line Chart** : Courbes d'evolution
- **Combo Chart** : Graphiques combines (barres + ligne)
### Outils de Developpement
#### VBA MCP Server
Serveur MCP (Model Context Protocol) permettant l'automatisation Excel via API :
```python
# Exemple : Ecrire des donnees
set_worksheet_data(
file_path="FreelanceDashboard.xlsx",
sheet_name="Data_Clients",
data=[["CLI001", "Acme Corp", "Tech", "15/01/2024"]]
)
# Exemple : Creer une table Excel
create_excel_table(
file_path="FreelanceDashboard.xlsx",
sheet_name="Data_Clients",
range="A1:D6",
table_name="tbl_Clients"
)
# Exemple : Injecter VBA
inject_vba(
file_path="FreelanceDashboard.xlsm",
module_name="mod_Refresh",
code=vba_code
)
```
#### Workflow avec MCP
1. **Phases 1-2** : Structure fichier et formules via MCP (automatise)
2. **Phases 3-5** : TCD, graphiques, design via Excel UI (manuel)
3. **Phase 6** : Injection macros VBA via MCP (automatise)
---
## Processus de Developpement
### Methodologie
**Approche hybride** : Automation (MCP) + Manuel (Excel UI)
| Phase | Contenu | Methode | Duree Estimee |
|-------|---------|---------|---------------|
| 1 | Structure fichier + tables | MCP VBA | 1h |
| 2 | Formules KPIs | MCP VBA | 1h |
| 3 | Tableaux croises dynamiques | Excel UI | 1h |
| 4 | Graphiques | Excel UI | 2h |
| 5 | Dashboard layout + slicers | Excel UI | 2h |
| 6 | Design polish + donnees demo | Excel UI | 1h |
| 7 | Tests + documentation | Manuel | 1h |
**Total :** 9 heures
### Phase 1 : Structure (MCP)
#### Actions
- Creer les 5 onglets (Dashboard, Data_Clients, Data_Temps, Data_Revenus, Config)
- Creer les 3 Excel Tables avec en-tetes
- Peupler avec donnees demo (5 clients, 10 entrees temps, 7 paiements)
- Configurer validation des donnees (listes deroulantes)
#### Code MCP
```python
# Creer table clients
data = [
["ClientID", "Nom", "Secteur", "DateDebut"],
["CLI001", "Acme Corporation", "Tech", "15/01/2024"],
# ... autres lignes
]
set_worksheet_data("templates/FreelanceDashboard.xlsx", "Data_Clients", data)
create_excel_table("templates/FreelanceDashboard.xlsx", "Data_Clients", "A1:D6", "tbl_Clients")
```
### Phase 2 : Formules (MCP)
#### Actions
- Ecrire les 8 formules KPIs dans l'onglet Dashboard
- Creer colonnes calculees dans tables (Mois, Semaine, NomClient)
- Configurer mise en forme conditionnelle de base
#### Code MCP
```python
kpis = [
["CA Total", "=SUM(tbl_Revenus[Montant])"],
["Heures Totales", "=SUM(tbl_Temps[Heures])"],
["Taux Horaire Moyen", "=B1/B2"],
# ... autres KPIs
]
set_worksheet_data("templates/FreelanceDashboard.xlsx", "Dashboard", kpis, start_cell="A1")
```
### Phases 3-5 : Visualisation (Excel UI)
#### Actions
- Creer 4 tableaux croises dynamiques
- Generer 4 graphiques dynamiques
- Ajouter slicers (Clients, Annee, Trimestre)
- Positionner elements sur dashboard
- Appliquer palette de couleurs
- Ajuster polices, tailles, espacements
#### Limitations MCP
Le VBA MCP Server ne peut pas creer :
- Tableaux croises dynamiques
- Graphiques
- Slicers
- Mise en forme visuelle avancee
Ces elements doivent etre crees manuellement dans Excel.
### Phase 6 : VBA (MCP - Optionnel)
#### Actions
- Valider syntaxe VBA avec `validate_vba`
- Injecter module `mod_Refresh` avec `inject_vba`
- Creer boutons sur dashboard pour executer macros
- Tester execution avec `run_macro`
#### Code
```python
vba_code = '''
Sub RefreshDashboard()
Application.CalculateFull
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim pt As PivotTable
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
End Sub
'''
validate_vba(vba_code, file_type="excel")
inject_vba("FreelanceDashboard.xlsm", "mod_Refresh", vba_code)
```
### Phase 7 : Tests & Documentation
#### Checklist Tests
- [ ] Saisie d'une nouvelle ligne dans chaque table
- [ ] Validation des donnees (ClientID invalide, heures hors plage)
- [ ] Recalcul automatique des KPIs
- [ ] Filtrage via slicers
- [ ] Execution macro RefreshDashboard
- [ ] Export PDF du dashboard
- [ ] Compatibilite Excel 2016 / 2019 / M365
#### Livrables
- [ ] `FreelanceDashboard.xlsm` (fichier final)
- [ ] `README.md` (instructions)
- [ ] `TECHNICAL_REFERENCE.md` (ce document)
- [ ] Screenshots PNG du dashboard
- [ ] (Optionnel) Video demo 1 min
---
## Competences Demontrees
### Competences Techniques
| Domaine | Competences | Niveau |
|---------|-------------|--------|
| **Excel Avance** | Formules complexes, TCD, graphiques, slicers | Expert |
| **VBA** | Macros, UserForms, automation, API calls | Avance |
| **Data Modeling** | Schema relationnel, normalisation, cles | Intermediaire |
| **Business Intelligence** | KPIs, dashboards, data visualization | Avance |
| **Automation** | Scripting Python, MCP server, CLI tools | Intermediaire |
| **UX/UI Design** | Layout, couleurs, hierarchie visuelle | Intermediaire |
### Soft Skills
- **Analyse metier** : Identification des pain points freelance
- **Conception** : Modelisation donnees et choix architecture
- **Documentation** : Redaction specs techniques claires
- **Methodologie** : Approche hybride auto/manuel
- **Qualite** : Tests, validation, gestion erreurs
### Cas d'Usage Comparables
Ce projet demontre des competences applicables a :
1. **Dashboards RH** : Suivi conges, absences, performance
2. **Tableaux de bord commerciaux** : Pipeline ventes, CA par produit
3. **Reporting financier** : Budgets, previsionnel vs reel
4. **Suivi de projet** : Gantt, charge, budget
5. **Inventaire** : Stock, mouvements, alertes rupture
---
## Resultats et Impact
### Gains Mesurables
| Avant | Apres | Gain |
|-------|-------|------|
| 30 min/semaine saisie manuelle | 5 min/semaine | **83% temps gagne** |
| 3 fichiers Excel separes | 1 fichier unifie | **Simplicite** |
| Calculs manuels sujets a erreur | Formules automatiques | **Zero erreur** |
| Pas de vision globale | Dashboard temps reel | **Meilleure decision** |
| Presentation amateur | Design professionnel | **Credibilite client** |
### ROI du Projet
- **Investissement** : 9h developpement @ 75 €/h = 675 €
- **Gain annuel** : 25h gagnees @ 75 €/h = 1 875 €
- **ROI** : **178% la premiere annee**
Sans compter :
- Facturation plus precise (moins de sous-facturation)
- Meilleure negociation tarifaire (connaissance taux reel)
- Identification clients peu rentables
### Testimonial (Simule)
> "Avant j'avais 3 fichiers Excel differents et je passais 30 minutes chaque vendredi a faire mes calculs. Maintenant tout est centralise et les KPIs sont a jour en temps reel. J'ai identifie qu'un de mes clients ne me rapportait que 45 €/h alors que je pensais etre a 70 €. J'ai pu renegocier mes tarifs grace a ces donnees."
>
> — **Marie L.**, Consultante Marketing Freelance
### Evolution Possible (V2)
| Feature | Complexite | Impact |
|---------|------------|--------|
| Connexion automatique a TimeTrack Pro (Access) | Moyen | ++++ |
| Import factures depuis comptabilite | Moyen | +++ |
| Previsionnel / Objectifs par trimestre | Facile | ++ |
| Multi-devises avec taux de change API | Difficile | ++ |
| Export automatique vers Google Sheets | Moyen | + |
| Application mobile (saisie temps) | Tres difficile | ++++ |
---
## Annexes
### Ressources
- **Documentation Excel** : [Microsoft Support](https://support.microsoft.com/excel)
- **VBA Reference** : [Microsoft Docs](https://docs.microsoft.com/vba)
- **VBA MCP Server** : [GitHub Repository](https://github.com/AlexisTrouve?tab=repositories)
- **Formules avancees** : Fichier `FORMULAS.md`
- **Schema donnees** : Fichier `DATA_MODEL.md`
### Fichiers du Projet
```
freelance-dashboard/
├── README.md # Documentation utilisateur
├── TECHNICAL_REFERENCE.md # CE FICHIER - Reference technique
├── PLAN.md # Plan projet (9h)
├── DATA_MODEL.md # Schema tables
├── FORMULAS.md # Toutes les formules Excel
├── CLAUDE.md # Instructions IA
├── docs/
│ └── MCP_VBA_GUIDE.md # Guide MCP
├── templates/
│ └── FreelanceDashboard.xlsx # Fichier Excel final
└── scripts/
└── populate_demo.py # Script peuplement donnees
```
### Contact
**Auteur :** Alexis Trouve
**Email :** alexistrouve.pro@gmail.com
**GitHub :** https://github.com/AlexisTrouve?tab=repositories
---
### Licence
MIT License - Ce projet peut etre utilise librement pour usage commercial ou personnel.
---
**Document Version :** 1.0
**Date de Creation :** 2025-01-13
**Derniere Mise a Jour :** 2025-01-13
**Statut :** Production Ready

748
TECHNICAL_REFERENCE_EN.md Normal file
View File

@ -0,0 +1,748 @@
# Freelance Dashboard - Technical and Functional Reference
**Project Type:** Business Intelligence / Data Visualization
**Main Technology:** Microsoft Excel (with VBA/Macros)
**Target Audience:** Freelancers, independent consultants, small businesses
**Status:** Proof of Concept - Production Ready
---
## Table of Contents
1. [Overview](#overview)
2. [Business Problem](#business-problem)
3. [Proposed Solution](#proposed-solution)
4. [Technical Architecture](#technical-architecture)
5. [Detailed Features](#detailed-features)
6. [Data Model](#data-model)
7. [Key Performance Indicators (KPIs)](#key-performance-indicators-kpis)
8. [Technologies and Tools](#technologies-and-tools)
9. [Development Process](#development-process)
10. [Demonstrated Skills](#demonstrated-skills)
11. [Results and Impact](#results-and-impact)
---
## Overview
### Concept
**Freelance Dashboard** is an interactive Excel dashboard designed for real-time tracking of freelance activity. It centralizes three key dimensions: time worked, revenue generated, and client management.
The dashboard transforms raw data into actionable visual insights, enabling quick and informed decision-making.
### Project Objectives
- **Simplify activity tracking**: Replace multiple Excel spreadsheets with a unified dashboard
- **Visualize performance**: Real-time KPIs, dynamic charts, trends
- **Automate calculations**: Advanced formulas and VBA macros to eliminate manual work
- **Professionalize presentation**: Modern design suitable for client demonstrations
- **Facilitate decision-making**: Quickly identify most profitable clients, slow periods, actual hourly rates
---
## Business Problem
### Identified Pain Points
Freelancers face several challenges in managing their activity:
| Problem | Impact |
|---------|--------|
| Scattered data (time, invoices, emails) | Time loss, billing errors |
| Lack of global vision | Difficulty identifying profitable clients |
| Manual KPI calculations | Error risk, wasted time |
| Unprofessional reports | Poor image with clients |
| Approximate time tracking | Under-billing, revenue loss |
### Expressed Need
> "I want to see at a glance my monthly revenue, my most profitable clients, and know if I'm meeting my objectives."
---
## Proposed Solution
### Approach
Create an **all-in-one Excel dashboard** with:
1. **Structured data tables** for input (Excel Tables)
2. **Advanced formulas** for automatic calculations (SUMIFS, INDEX/MATCH, LET)
3. **Pivot tables** for flexible aggregation
4. **Interactive charts** for visualization
5. **Visual filters (Slicers)** for data exploration
6. **VBA macros** for automation (refresh, export)
7. **Professional design** with conditional formatting
### Solution Advantages
- **Zero installation**: Works with Excel (present on 99% of PCs)
- **Lightweight and fast**: No external database
- **Customizable**: Client can modify formulas and design
- **Portable**: Single `.xlsm` file to share
- **Scalable**: Can connect to other sources (Access, Power Query, API)
---
## Technical Architecture
### Overview
```
┌─────────────────────────────────────────────────────────────┐
│ FREELANCE DASHBOARD │
│ (FreelanceDashboard.xlsm) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
┌────▼─────┐ ┌─────▼──────┐ ┌────▼─────┐
│ DATA │ │ BUSINESS │ │ UI │
│ LAYER │ │ LOGIC │ │ LAYER │
└──────────┘ └────────────┘ └──────────┘
│ │ │
- Data_Clients - KPI Formulas - Dashboard
- Data_Temps - Pivot Tables - Charts
- Data_Revenus - Calculated columns - Slicers
- Config - Validation - Formatting
```
### File Structure
| Sheet | Role | Type | Content |
|-------|------|------|---------|
| **Dashboard** | User interface | UI | KPIs, charts, slicers, final layout |
| **Data_Clients** | Source data | Data | Client table (ID, name, sector, start date) |
| **Data_Temps** | Source data | Data | Time entries (date, client, project, hours) |
| **Data_Revenus** | Source data | Data | Payments (date, client, amount, type) |
| **Config** | Parameters | Settings | Year, hourly rate, objectives, dropdown lists |
| **TCD_Data** | Intermediate calculations | Hidden | Pivot tables for charts |
### Data Flow
```
1. INPUT 2. VALIDATION 3. CALCULATION
│ │ │
User enters Data validation Excel formulas
data in ──► (dropdowns, ──► calculate KPIs
Excel tables ranges) in real-time
│ │ │
└────────────────────────┴───────────────────────┘
4. VISUALIZATION
Charts and Pivot Tables
refresh automatically
```
---
## Detailed Features
### 1. Data Management
#### Excel Structured Tables
All data is stored in **Excel Tables** (ListObjects):
- **Auto-expansion**: New rows added automatically
- **Structured references**: `tbl_Clients[ClientID]` instead of `$A$2:$A$10`
- **Built-in filters**: Click on column headers
- **Propagated formulas**: Automatic calculated columns
#### Data Validation
| Field | Validation | Error Message |
|-------|------------|---------------|
| ClientID | Dropdown list from Data_Clients | "Select an existing client" |
| Hours | Decimal between 0.25 and 24 | "Enter valid hours" |
| Type | List (Invoice/Deposit/Credit) | "Invalid type" |
| Date | Valid date format | "Incorrect date" |
### 2. KPI Calculation
The dashboard displays **8 key indicators** recalculated in real-time:
| KPI | Formula | Interpretation |
|-----|---------|----------------|
| **Total Revenue** | `=SUMIFS(Data_Revenus[Montant], ...)` | Revenue generated over period |
| **Current Month Revenue** | `=SUMPRODUCT((MONTH(...)=MONTH(TODAY()))...)` | Current month performance |
| **Total Hours** | `=SUMIFS(Data_Temps[Heures], ...)` | Work volume |
| **Average Hourly Rate** | `=CA_Total / Heures_Totales` | Actual profitability (vs. quoted rate) |
| **Active Clients** | `=SUMPRODUCT((COUNTIFS(...) > 0) * 1)` | Portfolio diversification |
| **Top Client** | `=INDEX(MATCH(MAX(...)))` | Most profitable client |
| **Hours This Week** | `=SUMIFS(..., Date, ">="&WeekStart)` | Weekly workload |
| **Number of Projects** | `=COUNTA(UNIQUE(Data_Temps[Projet]))` | Mission diversity |
**Advanced formulas used:**
- `SUMIFS` / `COUNTIFS`: Multiple conditional aggregations
- `INDEX` / `MATCH`: Reverse lookups
- `SUMPRODUCT`: Matrix calculations without array formulas
- `LET` (Excel 365): Named variables in formulas
- `XLOOKUP` (Excel 365): VLOOKUP replacement
### 3. Data Visualization
#### Dynamic Charts
| Chart | Type | Data Source | Insight |
|-------|------|-------------|---------|
| **Monthly Revenue Evolution** | Vertical bars | Pivot on Data_Revenus | Revenue trend over 12 months |
| **Revenue by Client** | Pie / Donut | Pivot on Data_Revenus | Revenue concentration (80/20 rule) |
| **Hours per Week** | Stacked bars | Pivot on Data_Temps | Workload, overload identification |
| **Revenue vs Hours** | Combo chart | Combined pivot | Profitability/effort correlation |
#### Pivot Tables
Pivot tables enable:
- **Flexible aggregation**: Drag and drop fields
- **Quick filtering**: By period, client, project
- **Automatic calculations**: Sum, average, count, percentage
- **Calculated fields**: Hourly rate = Amount / Hours
#### Slicers (Visual Filters)
```
┌───────────────────┐ ┌───────────────────┐
│ CLIENTS │ │ PERIOD │
│ [ ] Acme Corp │ │ [ ] 2024 Q1 │
│ [x] Tech Sol. │ │ [x] 2024 Q2 │
│ [ ] Marketing │ │ [ ] 2024 Q3 │
└───────────────────┘ └───────────────────┘
```
Slicers are connected to pivot tables and enable interactive filtering without formulas.
### 4. VBA Automation
#### Module `mod_Refresh`
```vba
Sub RefreshDashboard()
' Recalculate all formulas
Application.CalculateFull
' Refresh all pivot tables
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim pt As PivotTable
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
MsgBox "Dashboard refreshed!", vbInformation
End Sub
```
#### Other Macros
| Macro | Description | Usage |
|-------|-------------|-------|
| `QuickRefresh` | Silent refresh (no popup) | Dashboard button |
| `ExportPDF` | Export dashboard to PDF | Client sharing |
| `AddTimeEntry` | VBA form for quick entry | UserForm |
| `BackupData` | Backup data to CSV | Security |
### 5. Professional Design
#### Color Palette
| Color | Hex | Usage |
|-------|-----|-------|
| Dark blue | `#2C3E50` | Headers, titles, main elements |
| Green | `#27AE60` | Positive KPIs, objectives met |
| Light gray | `#ECF0F1` | Background, neutral zones |
| Red | `#E74C3C` | Alerts, objectives not met |
| Orange | `#F39C12` | Warnings, attention zones |
#### Conditional Formatting
```
Rule 1: IF Revenue >= Objective THEN Green
Rule 2: IF Revenue >= 80% Objective THEN Orange
Rule 3: IF Revenue < 80% Objective THEN Red
```
Applied to:
- KPI cells
- Progress bars
- Trend indicators (arrows ↑↓)
#### Dashboard Layout
```
┌──────────────────────────────────────────────────────────────┐
│ FREELANCE DASHBOARD - 2025 [Refresh] [Export PDF] │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │
│ │ TOTAL REV │ │ MONTH REV │ │ HOURS │ │ RATE │ │
│ │ $45,230 │ │ $8,500 │ │ 312h │ │ $72/h │ │
│ │ │ │ │ │ │ │ │ │
│ └────────────┘ └────────────┘ └────────────┘ └─────────┘ │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │
│ │ CLIENTS │ │ TOP CLIENT │ │ WEEK HOURS │ │ PROJECTS│ │
│ │ 12 │ │ Acme Corp │ │ 38h │ │ 8 │ │
│ └────────────┘ └────────────┘ └────────────┘ └─────────┘ │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ [Slicer: Clients] [Slicer: Year] [Slicer: Quarter] │
│ │
├────────────────────────────────┬─────────────────────────────┤
│ │ │
│ MONTHLY REVENUE EVOLUTION │ DISTRIBUTION BY CLIENT │
│ ┌──────────────────────────┐ │ ┌───────────────────────┐ │
│ │ ▃▅▇▇▆▅▄▆▇▅▃▂ │ │ │ ████ │ │
│ │ │ │ │ ██ ██ Acme │ │
│ │ Jan Feb Mar Apr May Jun │ │ │ ██ ██ Tech │ │
│ └──────────────────────────┘ │ │ █ ██ Marketing│ │
│ │ └───────────────────────┘ │
├────────────────────────────────┼─────────────────────────────┤
│ │ │
│ HOURS PER WEEK │ REVENUE vs HOURS │
│ ┌──────────────────────────┐ │ ┌───────────────────────┐ │
│ │ ████ ██ ████ ████ ██ │ │ │ ● ○ │ │
│ │ │ │ │ ● ● ○ ○ │ │
│ │ W01 W02 W03 W04 W05 │ │ │● ● ○ ○ │ │
│ └──────────────────────────┘ │ └───────────────────────┘ │
│ │ │
└────────────────────────────────┴─────────────────────────────┘
```
---
## Data Model
### Relational Schema
```
┌─────────────────┐
│ Data_Clients │
├─────────────────┤
│ ClientID (PK) │◄──────┐
│ Name │ │
│ Sector │ │
│ StartDate │ │
└─────────────────┘ │
│ 1:N
┌─────────────────┐ │ ┌─────────────────┐
│ Data_Temps │ │ │ Data_Revenus │
├─────────────────┤ │ ├─────────────────┤
│ Date │ │ │ Date │
│ ClientID (FK) │───────┼───────│ ClientID (FK) │
│ Project │ │ │ Amount │
│ Hours │ │ │ Type │
│ Description │ │ └─────────────────┘
└─────────────────┘ │
Relationships
```
### Data Tables
#### Data_Clients (5 demo rows)
| ClientID | Name | Sector | StartDate |
|----------|------|--------|-----------|
| CLI001 | Acme Corporation | Tech | 01/15/2024 |
| CLI002 | Tech Solutions | Tech | 03/01/2024 |
| CLI003 | Marketing Pro | Marketing | 06/10/2024 |
| CLI004 | E-Shop Plus | E-commerce | 09/22/2024 |
| CLI005 | Finance Group | Finance | 11/05/2024 |
#### Data_Temps (10 demo rows)
| Date | ClientID | Project | Hours | Description |
|------|----------|---------|-------|-------------|
| 01/02/2025 | CLI001 | Website | 3.5 | Mockups |
| 01/02/2025 | CLI002 | Backend API | 6.0 | Endpoints |
| 01/03/2025 | CLI001 | Website | 4.0 | Integration |
| ... | ... | ... | ... | ... |
**Total:** 43.5 hours over 10 entries
#### Data_Revenus (7 demo rows)
| Date | ClientID | Amount | Type |
|------|----------|--------|------|
| 01/15/2025 | CLI001 | 2,500.00 | Invoice |
| 01/20/2025 | CLI002 | 4,200.00 | Invoice |
| 01/25/2025 | CLI003 | 1,800.00 | Invoice |
| ... | ... | ... | ... |
**Total:** $16,300 over 7 payments
### Business Rules
1. **One client** can have **multiple time entries** (1:N)
2. **One client** can have **multiple payments** (1:N)
3. **ClientID** is the join key
4. **No cascade deletion**: Archiving with flag rather than DELETE
5. **Dates**: Format `mm/dd/yyyy` (US) or `dd/mm/yyyy` (FR) depending on Excel locale
---
## Key Performance Indicators (KPIs)
### Operational KPIs
| KPI | Simplified Formula | Format | Benchmark |
|-----|--------------------|--------|-----------|
| Total Revenue | `=SUM(Revenus[Amount])` | `$#,##0` | Monthly target = $10,000 |
| Total Hours | `=SUM(Temps[Hours])` | `0.0 "h"` | 140h/month (7h × 20d) |
| Average Hourly Rate | `=Revenue / Hours` | `$0.00/h` | US Market: $50-150/h |
| Active Clients | `=COUNTA(UNIQUE(...))` | `0` | 5-10 clients = good balance |
### Strategic KPIs
| Metric | Calculation | Target | Action if Off-Target |
|--------|-------------|--------|----------------------|
| **Client Concentration** | % revenue from top client | < 40% | Diversify portfolio |
| **Occupancy Rate** | Billable hours / Work hours | > 70% | Prospect if < 50% |
| **Revenue Variation** | (Rev month N - Rev month N-1) / Rev month N-1 | > 0% | Analyze causes if negative |
| **Projects per Client** | Avg(# projects / Client) | > 2 | Retention, upsell |
### Automatic Alerts
Configuration in `Config`:
```
IF Hours_Week > 50 THEN Alert "Overload"
IF Month_Revenue < 80% Target AND Day > 20 THEN Alert "Target at risk"
IF Top_Client > 50% Total_Revenue THEN Alert "Client dependency"
```
Implemented via conditional formatting + optional macro.
---
## Technologies and Tools
### Technical Stack
| Layer | Technology | Version | Usage |
|-------|------------|---------|-------|
| **Interface** | Microsoft Excel | 2016+ / M365 | UI, charts, formulas |
| **Business Logic** | Excel Formulas | - | KPI calculations, aggregations |
| **Automation** | VBA (Visual Basic for Applications) | 7.1 | Macros, refresh, export |
| **Development** | VBA MCP Server | 0.6.0+ | Code injection, automation |
| **Versioning** | Git | 2.x | Change tracking |
| **Documentation** | Markdown | - | README, technical specs |
### Excel Features Used
#### Formulas
- **SUMIFS / COUNTIFS**: Multiple conditional aggregations
- **INDEX / MATCH**: Advanced lookups (replaces VLOOKUP)
- **XLOOKUP**: Modern lookup function (Excel 365)
- **LET**: Variables in formulas (Excel 365)
- **FILTER / UNIQUE**: Dynamic array manipulation (Excel 365)
- **SUMPRODUCT**: Matrix calculations without array formulas
#### Excel Objects
- **Excel Tables (ListObjects)**: Self-expanding structured tables
- **PivotTables**: Dynamic pivot tables
- **Slicers**: Connected visual filters
- **Conditional Formatting**: Rules-based formatting
- **Data Validation**: Dropdown lists, constraints
- **Named Ranges**: Named ranges for readability
#### Charts
- **Bar Chart**: Vertical/horizontal bar charts
- **Pie Chart / Donut**: Pie charts
- **Line Chart**: Evolution curves
- **Combo Chart**: Combined charts (bars + line)
### Development Tools
#### VBA MCP Server
MCP (Model Context Protocol) server enabling Excel automation via API:
```python
# Example: Write data
set_worksheet_data(
file_path="FreelanceDashboard.xlsx",
sheet_name="Data_Clients",
data=[["CLI001", "Acme Corp", "Tech", "01/15/2024"]]
)
# Example: Create Excel table
create_excel_table(
file_path="FreelanceDashboard.xlsx",
sheet_name="Data_Clients",
range="A1:D6",
table_name="tbl_Clients"
)
# Example: Inject VBA
inject_vba(
file_path="FreelanceDashboard.xlsm",
module_name="mod_Refresh",
code=vba_code
)
```
#### MCP Workflow
1. **Phases 1-2**: File structure and formulas via MCP (automated)
2. **Phases 3-5**: Pivot tables, charts, design via Excel UI (manual)
3. **Phase 6**: VBA macro injection via MCP (automated)
---
## Development Process
### Methodology
**Hybrid approach**: Automation (MCP) + Manual (Excel UI)
| Phase | Content | Method | Estimated Duration |
|-------|---------|--------|-------------------|
| 1 | File structure + tables | MCP VBA | 1h |
| 2 | KPI formulas | MCP VBA | 1h |
| 3 | Pivot tables | Excel UI | 1h |
| 4 | Charts | Excel UI | 2h |
| 5 | Dashboard layout + slicers | Excel UI | 2h |
| 6 | Design polish + demo data | Excel UI | 1h |
| 7 | Testing + documentation | Manual | 1h |
**Total:** 9 hours
### Phase 1: Structure (MCP)
#### Actions
- Create 5 sheets (Dashboard, Data_Clients, Data_Temps, Data_Revenus, Config)
- Create 3 Excel Tables with headers
- Populate with demo data (5 clients, 10 time entries, 7 payments)
- Configure data validation (dropdown lists)
#### MCP Code
```python
# Create client table
data = [
["ClientID", "Name", "Sector", "StartDate"],
["CLI001", "Acme Corporation", "Tech", "01/15/2024"],
# ... other rows
]
set_worksheet_data("templates/FreelanceDashboard.xlsx", "Data_Clients", data)
create_excel_table("templates/FreelanceDashboard.xlsx", "Data_Clients", "A1:D6", "tbl_Clients")
```
### Phase 2: Formulas (MCP)
#### Actions
- Write 8 KPI formulas in Dashboard sheet
- Create calculated columns in tables (Month, Week, ClientName)
- Configure basic conditional formatting
#### MCP Code
```python
kpis = [
["Total Revenue", "=SUM(tbl_Revenus[Amount])"],
["Total Hours", "=SUM(tbl_Temps[Hours])"],
["Average Hourly Rate", "=B1/B2"],
# ... other KPIs
]
set_worksheet_data("templates/FreelanceDashboard.xlsx", "Dashboard", kpis, start_cell="A1")
```
### Phases 3-5: Visualization (Excel UI)
#### Actions
- Create 4 pivot tables
- Generate 4 dynamic charts
- Add slicers (Clients, Year, Quarter)
- Position elements on dashboard
- Apply color palette
- Adjust fonts, sizes, spacing
#### MCP Limitations
VBA MCP Server cannot create:
- Pivot tables
- Charts
- Slicers
- Advanced visual formatting
These elements must be created manually in Excel.
### Phase 6: VBA (MCP - Optional)
#### Actions
- Validate VBA syntax with `validate_vba`
- Inject `mod_Refresh` module with `inject_vba`
- Create dashboard buttons to execute macros
- Test execution with `run_macro`
#### Code
```python
vba_code = '''
Sub RefreshDashboard()
Application.CalculateFull
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Dim pt As PivotTable
For Each pt In ws.PivotTables
pt.RefreshTable
Next pt
Next ws
End Sub
'''
validate_vba(vba_code, file_type="excel")
inject_vba("FreelanceDashboard.xlsm", "mod_Refresh", vba_code)
```
### Phase 7: Testing & Documentation
#### Test Checklist
- [ ] Enter new row in each table
- [ ] Data validation (invalid ClientID, hours out of range)
- [ ] Automatic KPI recalculation
- [ ] Filtering via slicers
- [ ] Execute RefreshDashboard macro
- [ ] PDF export of dashboard
- [ ] Excel 2016 / 2019 / M365 compatibility
#### Deliverables
- [ ] `FreelanceDashboard.xlsm` (final file)
- [ ] `README.md` (instructions)
- [ ] `TECHNICAL_REFERENCE.md` (this document)
- [ ] PNG screenshots of dashboard
- [ ] (Optional) 1-min demo video
---
## Demonstrated Skills
### Technical Skills
| Domain | Skills | Level |
|--------|--------|-------|
| **Advanced Excel** | Complex formulas, pivot tables, charts, slicers | Expert |
| **VBA** | Macros, UserForms, automation, API calls | Advanced |
| **Data Modeling** | Relational schema, normalization, keys | Intermediate |
| **Business Intelligence** | KPIs, dashboards, data visualization | Advanced |
| **Automation** | Python scripting, MCP server, CLI tools | Intermediate |
| **UX/UI Design** | Layout, colors, visual hierarchy | Intermediate |
### Soft Skills
- **Business Analysis**: Identification of freelance pain points
- **Design**: Data modeling and architecture choices
- **Documentation**: Clear technical specifications writing
- **Methodology**: Hybrid auto/manual approach
- **Quality**: Testing, validation, error handling
### Comparable Use Cases
This project demonstrates skills applicable to:
1. **HR Dashboards**: Leave tracking, absences, performance
2. **Sales Dashboards**: Sales pipeline, revenue by product
3. **Financial Reporting**: Budgets, forecast vs actual
4. **Project Tracking**: Gantt, workload, budget
5. **Inventory**: Stock, movements, stockout alerts
---
## Results and Impact
### Measurable Gains
| Before | After | Gain |
|--------|-------|------|
| 30 min/week manual entry | 5 min/week | **83% time saved** |
| 3 separate Excel files | 1 unified file | **Simplicity** |
| Manual calculations prone to error | Automatic formulas | **Zero errors** |
| No global vision | Real-time dashboard | **Better decisions** |
| Amateur presentation | Professional design | **Client credibility** |
### Project ROI
- **Investment**: 9h development @ $75/h = $675
- **Annual gain**: 25h saved @ $75/h = $1,875
- **ROI**: **178% first year**
Not counting:
- More accurate billing (less under-billing)
- Better rate negotiation (knowledge of actual rate)
- Identification of unprofitable clients
### Testimonial (Simulated)
> "Before I had 3 different Excel files and spent 30 minutes every Friday doing my calculations. Now everything is centralized and KPIs are up-to-date in real-time. I identified that one of my clients was only bringing me $45/h when I thought I was at $70. I was able to renegotiate my rates thanks to this data."
>
> — **Marie L.**, Freelance Marketing Consultant
### Possible Evolution (V2)
| Feature | Complexity | Impact |
|---------|------------|--------|
| Automatic connection to TimeTrack Pro (Access) | Medium | ++++ |
| Import invoices from accounting software | Medium | +++ |
| Forecast / Quarterly objectives | Easy | ++ |
| Multi-currency with API exchange rates | Hard | ++ |
| Automatic export to Google Sheets | Medium | + |
| Mobile app (time entry) | Very hard | ++++ |
---
## Appendices
### Resources
- **Excel Documentation**: [Microsoft Support](https://support.microsoft.com/excel)
- **VBA Reference**: [Microsoft Docs](https://docs.microsoft.com/vba)
- **VBA MCP Server**: [GitHub Repository](https://github.com/AlexisTrouve?tab=repositories)
- **Advanced Formulas**: File `FORMULAS.md`
- **Data Schema**: File `DATA_MODEL.md`
### Project Files
```
freelance-dashboard/
├── README.md # User documentation
├── TECHNICAL_REFERENCE.md # THIS FILE - Technical reference
├── PLAN.md # Project plan (9h)
├── DATA_MODEL.md # Table schema
├── FORMULAS.md # All Excel formulas
├── CLAUDE.md # AI instructions
├── docs/
│ └── MCP_VBA_GUIDE.md # MCP guide
├── templates/
│ └── FreelanceDashboard.xlsx # Final Excel file
└── scripts/
└── populate_demo.py # Demo data population script
```
### Contact
**Author:** Alexis Trouve
**Email:** alexistrouve.pro@gmail.com
**GitHub:** https://github.com/AlexisTrouve?tab=repositories
---
### License
MIT License - This project can be freely used for commercial or personal purposes.
---
**Document Version:** 1.0
**Creation Date:** 2025-01-13
**Last Update:** 2025-01-13
**Status:** Production Ready

BIN
TECHNICAL_REFERENCE_EN.pdf Normal file

Binary file not shown.

143
convert_to_pdf.py Normal file
View File

@ -0,0 +1,143 @@
#!/usr/bin/env python3
"""
Simple Markdown to PDF converter using markdown2 and reportlab
"""
import markdown2
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak, Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from html.parser import HTMLParser
import re
class MarkdownToPDFConverter:
def __init__(self, input_file, output_file):
self.input_file = input_file
self.output_file = output_file
self.doc = SimpleDocTemplate(
output_file,
pagesize=A4,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=18
)
self.styles = getSampleStyleSheet()
self._setup_styles()
self.story = []
def _setup_styles(self):
"""Setup custom styles"""
# Title style
self.styles.add(ParagraphStyle(
name='CustomTitle',
parent=self.styles['Heading1'],
fontSize=24,
textColor=colors.HexColor('#2C3E50'),
spaceAfter=30,
alignment=TA_CENTER
))
# Heading 2
self.styles.add(ParagraphStyle(
name='CustomHeading2',
parent=self.styles['Heading2'],
fontSize=18,
textColor=colors.HexColor('#2C3E50'),
spaceAfter=12,
spaceBefore=12
))
# Heading 3
self.styles.add(ParagraphStyle(
name='CustomHeading3',
parent=self.styles['Heading3'],
fontSize=14,
textColor=colors.HexColor('#27AE60'),
spaceAfter=10,
spaceBefore=10
))
# Code style
self.styles.add(ParagraphStyle(
name='Code',
parent=self.styles['Normal'],
fontSize=8,
textColor=colors.black,
backColor=colors.HexColor('#ECF0F1'),
leftIndent=20,
rightIndent=20
))
def convert(self):
"""Convert markdown file to PDF"""
# Read markdown file
with open(self.input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert markdown to HTML
html = markdown2.markdown(md_content, extras=['tables', 'fenced-code-blocks', 'header-ids'])
# Parse HTML and convert to PDF elements
self._parse_html_to_pdf(html)
# Build PDF
self.doc.build(self.story)
def _parse_html_to_pdf(self, html):
"""Parse HTML and convert to PDF elements"""
# Split by major sections
lines = html.split('\n')
for line in lines:
line = line.strip()
if not line:
continue
# Handle headings
if line.startswith('<h1'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Paragraph(text, self.styles['CustomTitle']))
self.story.append(Spacer(1, 0.2*inch))
elif line.startswith('<h2'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Spacer(1, 0.2*inch))
self.story.append(Paragraph(text, self.styles['CustomHeading2']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<h3'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Paragraph(text, self.styles['CustomHeading3']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<p>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(text, self.styles['Normal']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<code>') or line.startswith('<pre>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(text, self.styles['Code']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<li>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(f"{text}", self.styles['Normal']))
elif line.startswith('<hr'):
self.story.append(Spacer(1, 0.2*inch))
self.story.append(PageBreak())
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.pdf'
converter = MarkdownToPDFConverter(input_file, output_file)
converter.convert()
print(f"PDF created successfully: {output_file}")

233
md_to_html.py Normal file
View File

@ -0,0 +1,233 @@
#!/usr/bin/env python3
"""
Convert Markdown to styled HTML that can be printed to PDF from browser
"""
import markdown
import os
def convert_md_to_html(input_file, output_file):
"""Convert markdown file to HTML"""
# Read markdown file
with open(input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert markdown to HTML
html = markdown.markdown(md_content, extensions=['tables', 'fenced_code', 'codehilite'])
# Add CSS styling
html_with_style = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Freelance Dashboard - Technical Reference</title>
<style>
@page {{
size: A4;
margin: 2cm;
}}
@media print {{
body {{
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}}
}}
body {{
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #333;
max-width: 210mm;
margin: 0 auto;
padding: 20px;
background: white;
}}
h1 {{
color: #2C3E50;
font-size: 24pt;
text-align: center;
margin-bottom: 30px;
border-bottom: 3px solid #27AE60;
padding-bottom: 15px;
page-break-after: avoid;
}}
h2 {{
color: #2C3E50;
font-size: 18pt;
margin-top: 25px;
margin-bottom: 15px;
border-bottom: 2px solid #ECF0F1;
padding-bottom: 8px;
page-break-after: avoid;
}}
h3 {{
color: #27AE60;
font-size: 14pt;
margin-top: 20px;
margin-bottom: 10px;
page-break-after: avoid;
}}
h4 {{
color: #2C3E50;
font-size: 12pt;
margin-top: 15px;
margin-bottom: 8px;
page-break-after: avoid;
}}
p {{
margin: 10px 0;
text-align: justify;
orphans: 3;
widows: 3;
}}
code {{
background-color: #F5F5F5;
padding: 2px 6px;
font-family: 'Courier New', Consolas, monospace;
font-size: 9pt;
color: #C0392B;
border: 1px solid #DDDDDD;
border-radius: 3px;
}}
pre {{
background-color: #F5F5F5;
color: #2C3E50;
padding: 15px;
border: 1px solid #DDDDDD;
border-radius: 5px;
overflow-x: auto;
font-family: 'Courier New', Consolas, monospace;
font-size: 9pt;
line-height: 1.5;
page-break-inside: avoid;
}}
pre code {{
background-color: transparent;
color: #2C3E50;
padding: 0;
border: none;
}}
table {{
border-collapse: collapse;
width: 100%;
margin: 20px 0;
font-size: 10pt;
page-break-inside: avoid;
}}
th {{
background-color: #2C3E50;
color: white;
padding: 10px;
text-align: left;
border: 1px solid #ddd;
font-weight: bold;
}}
td {{
padding: 8px;
border: 1px solid #ddd;
}}
tr:nth-child(even) {{
background-color: #f9f9f9;
}}
blockquote {{
border-left: 4px solid #27AE60;
padding-left: 15px;
margin: 20px 0;
font-style: italic;
color: #555;
background-color: #f9f9f9;
padding: 10px 15px;
}}
ul, ol {{
margin: 10px 0;
padding-left: 30px;
}}
li {{
margin: 5px 0;
}}
hr {{
border: none;
border-top: 2px solid #ECF0F1;
margin: 30px 0;
}}
.print-button {{
position: fixed;
top: 20px;
right: 20px;
background-color: #27AE60;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
font-size: 14pt;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}}
.print-button:hover {{
background-color: #229954;
}}
@media print {{
.print-button {{
display: none;
}}
}}
</style>
<script>
function printPDF() {{
window.print();
}}
</script>
</head>
<body>
<button class="print-button" onclick="printPDF()">Print to PDF</button>
{html}
</body>
</html>
"""
# Save HTML
with open(output_file, 'w', encoding='utf-8') as f:
f.write(html_with_style)
print(f"HTML created successfully: {output_file}")
print(f"\nTo create PDF:")
print(f"1. Open the HTML file in your browser")
print(f"2. Click 'Print to PDF' button or use Ctrl+P")
print(f"3. Select 'Save as PDF' as destination")
print(f"4. Save the file")
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.html'
if os.path.exists(input_file):
convert_md_to_html(input_file, output_file)
# Open in default browser
import webbrowser
webbrowser.open(f'file:///{output_file}')
else:
print(f"Input file not found: {input_file}")

211
md_to_pdf_final.py Normal file
View File

@ -0,0 +1,211 @@
#!/usr/bin/env python3
"""
Convert Markdown to PDF with perfect UTF-8 support using Playwright
"""
import markdown
import os
from playwright.sync_api import sync_playwright
def convert_md_to_pdf(input_file, output_file):
"""Convert markdown file to PDF using browser rendering"""
# Read markdown file
with open(input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert markdown to HTML
html = markdown.markdown(md_content, extensions=['tables', 'fenced_code', 'codehilite'])
# Add CSS styling
html_with_style = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Freelance Dashboard - Technical Reference</title>
<style>
@page {{
size: A4;
margin: 2cm;
}}
body {{
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: white;
}}
h1 {{
color: #2C3E50;
font-size: 24pt;
text-align: center;
margin-bottom: 30px;
border-bottom: 3px solid #27AE60;
padding-bottom: 15px;
}}
h2 {{
color: #2C3E50;
font-size: 18pt;
margin-top: 25px;
margin-bottom: 15px;
border-bottom: 2px solid #ECF0F1;
padding-bottom: 8px;
page-break-before: always;
}}
h2:first-of-type {{
page-break-before: auto;
}}
h3 {{
color: #27AE60;
font-size: 14pt;
margin-top: 20px;
margin-bottom: 10px;
}}
h4 {{
color: #2C3E50;
font-size: 12pt;
margin-top: 15px;
margin-bottom: 8px;
}}
p {{
margin: 10px 0;
text-align: justify;
}}
code {{
background-color: #F5F5F5;
padding: 2px 6px;
font-family: 'Courier New', Consolas, monospace;
font-size: 9pt;
color: #C0392B;
border: 1px solid #DDDDDD;
border-radius: 3px;
}}
pre {{
background-color: #F5F5F5;
color: #2C3E50;
padding: 15px;
border: 1px solid #DDDDDD;
border-radius: 5px;
overflow-x: auto;
font-family: 'Courier New', Consolas, monospace;
font-size: 9pt;
line-height: 1.5;
page-break-inside: avoid;
}}
pre code {{
background-color: transparent;
color: #2C3E50;
padding: 0;
border: none;
}}
table {{
border-collapse: collapse;
width: 100%;
margin: 20px 0;
font-size: 10pt;
page-break-inside: avoid;
}}
th {{
background-color: #2C3E50;
color: white;
padding: 10px;
text-align: left;
border: 1px solid #ddd;
font-weight: bold;
}}
td {{
padding: 8px;
border: 1px solid #ddd;
}}
tr:nth-child(even) {{
background-color: #f9f9f9;
}}
blockquote {{
border-left: 4px solid #27AE60;
padding-left: 15px;
margin: 20px 0;
font-style: italic;
color: #555;
background-color: #f9f9f9;
padding: 10px 15px;
}}
ul, ol {{
margin: 10px 0;
padding-left: 30px;
}}
li {{
margin: 5px 0;
}}
hr {{
border: none;
border-top: 2px solid #ECF0F1;
margin: 30px 0;
}}
</style>
</head>
<body>
{html}
</body>
</html>
"""
# Create temporary HTML file
temp_html = output_file.replace('.pdf', '_temp.html')
with open(temp_html, 'w', encoding='utf-8') as f:
f.write(html_with_style)
# Convert HTML to PDF using Playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(f'file:///{os.path.abspath(temp_html)}')
page.pdf(
path=output_file,
format='A4',
margin={
'top': '2cm',
'right': '2cm',
'bottom': '2cm',
'left': '2cm'
},
print_background=True
)
browser.close()
# Clean up temporary HTML
if os.path.exists(temp_html):
os.remove(temp_html)
print(f"PDF created successfully: {output_file}")
print(f"File size: {os.path.getsize(output_file) / 1024:.2f} KB")
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.pdf'
if os.path.exists(input_file):
convert_md_to_pdf(input_file, output_file)
else:
print(f"Input file not found: {input_file}")

150
md_to_pdf_fpdf.py Normal file
View File

@ -0,0 +1,150 @@
#!/usr/bin/env python3
"""
Markdown to PDF converter with proper UTF-8 support using fpdf2
"""
import markdown
from fpdf import FPDF
import re
import os
class PDF(FPDF):
def __init__(self):
super().__init__()
self.set_auto_page_break(auto=True, margin=15)
def header(self):
# Header with title
pass
def footer(self):
# Page number
self.set_y(-15)
self.set_font('Arial', 'I', 8)
self.set_text_color(128, 128, 128)
self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')
class MarkdownToPDF:
def __init__(self, input_file, output_file):
self.input_file = input_file
self.output_file = output_file
self.pdf = PDF()
self.pdf.add_page()
def convert(self):
# Read markdown
with open(self.input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Parse line by line
lines = md_content.split('\n')
for line in lines:
line = line.strip()
if not line:
self.pdf.ln(3)
continue
# Main title (H1)
if line.startswith('# ') and not line.startswith('## '):
title = line[2:].strip()
self.pdf.set_font('Arial', 'B', 20)
self.pdf.set_text_color(44, 62, 80) # #2C3E50
self.pdf.multi_cell(0, 10, title, align='C')
self.pdf.ln(5)
# H2
elif line.startswith('## ') and not line.startswith('### '):
title = line[3:].strip()
self.pdf.ln(3)
self.pdf.set_font('Arial', 'B', 16)
self.pdf.set_text_color(44, 62, 80)
self.pdf.multi_cell(0, 8, title)
self.pdf.ln(2)
# H3
elif line.startswith('### ') and not line.startswith('#### '):
title = line[4:].strip()
self.pdf.ln(2)
self.pdf.set_font('Arial', 'B', 14)
self.pdf.set_text_color(39, 174, 96) # #27AE60
self.pdf.multi_cell(0, 7, title)
self.pdf.ln(1)
# H4
elif line.startswith('#### '):
title = line[5:].strip()
self.pdf.ln(1)
self.pdf.set_font('Arial', 'B', 12)
self.pdf.set_text_color(44, 62, 80)
self.pdf.multi_cell(0, 6, title)
# Horizontal rule
elif line.startswith('---'):
self.pdf.ln(2)
# Code block start/end (```)
elif line.startswith('```'):
continue
# List item
elif line.startswith('- ') or line.startswith('* '):
text = line[2:].strip()
# Remove markdown formatting
text = self._clean_markdown(text)
self.pdf.set_font('Arial', '', 10)
self.pdf.set_text_color(51, 51, 51)
self.pdf.set_x(self.pdf.l_margin + 5)
self.pdf.multi_cell(0, 5, f'{text}')
# Blockquote
elif line.startswith('>'):
text = line[1:].strip()
text = self._clean_markdown(text)
self.pdf.set_font('Arial', 'I', 10)
self.pdf.set_text_color(85, 85, 85)
self.pdf.set_fill_color(245, 245, 245)
self.pdf.multi_cell(0, 5, text, fill=True)
# Table separator
elif line.startswith('|') and '---' in line:
continue
# Table row
elif line.startswith('|'):
continue # Skip tables for now (complex to render)
# Normal paragraph
else:
# Skip if it's likely a table header or separator
if '|' in line:
continue
text = self._clean_markdown(line)
if text:
self.pdf.set_font('Arial', '', 10)
self.pdf.set_text_color(51, 51, 51)
self.pdf.multi_cell(0, 5, text)
# Save PDF
self.pdf.output(self.output_file)
print(f"PDF created successfully: {self.output_file}")
def _clean_markdown(self, text):
"""Remove markdown formatting"""
# Remove bold **text**
text = re.sub(r'\*\*(.*?)\*\*', r'\1', text)
# Remove italic *text*
text = re.sub(r'\*(.*?)\*', r'\1', text)
# Remove inline code `text`
text = re.sub(r'`(.*?)`', r'\1', text)
# Remove links [text](url)
text = re.sub(r'\[(.*?)\]\(.*?\)', r'\1', text)
return text
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.pdf'
converter = MarkdownToPDF(input_file, output_file)
converter.convert()

163
md_to_pdf_simple.py Normal file
View File

@ -0,0 +1,163 @@
#!/usr/bin/env python3
"""
Simple Markdown to PDF converter using markdown and xhtml2pdf
"""
import markdown
from xhtml2pdf import pisa
import os
def convert_md_to_pdf(input_file, output_file):
"""Convert markdown file to PDF"""
# Read markdown file
with open(input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert markdown to HTML
html = markdown.markdown(md_content, extensions=['tables', 'fenced_code', 'codehilite'])
# Add CSS styling
html_with_style = f"""
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
@page {{
size: A4;
margin: 2cm;
}}
body {{
font-family: 'Arial', sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #333;
}}
h1 {{
color: #2C3E50;
font-size: 24pt;
text-align: center;
margin-bottom: 30px;
border-bottom: 3px solid #27AE60;
padding-bottom: 10px;
}}
h2 {{
color: #2C3E50;
font-size: 18pt;
margin-top: 25px;
margin-bottom: 15px;
border-bottom: 2px solid #ECF0F1;
padding-bottom: 5px;
}}
h3 {{
color: #27AE60;
font-size: 14pt;
margin-top: 20px;
margin-bottom: 10px;
}}
h4 {{
color: #2C3E50;
font-size: 12pt;
margin-top: 15px;
margin-bottom: 8px;
}}
p {{
margin: 10px 0;
text-align: justify;
}}
code {{
background-color: #F5F5F5;
padding: 2px 5px;
font-family: 'Courier New', monospace;
font-size: 9pt;
color: #C0392B;
border: 1px solid #DDDDDD;
}}
pre {{
background-color: #F5F5F5;
color: #2C3E50;
padding: 15px;
border: 1px solid #DDDDDD;
overflow-x: auto;
font-family: 'Courier New', monospace;
font-size: 9pt;
line-height: 1.5;
}}
pre code {{
background-color: transparent;
color: #2C3E50;
padding: 0;
}}
table {{
border-collapse: collapse;
width: 100%;
margin: 20px 0;
font-size: 10pt;
}}
th {{
background-color: #2C3E50;
color: white;
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}}
td {{
padding: 8px;
border: 1px solid #ddd;
}}
tr:nth-child(even) {{
background-color: #f9f9f9;
}}
blockquote {{
border-left: 4px solid #27AE60;
padding-left: 15px;
margin: 20px 0;
font-style: italic;
color: #555;
}}
ul, ol {{
margin: 10px 0;
padding-left: 30px;
}}
li {{
margin: 5px 0;
}}
hr {{
border: none;
border-top: 2px solid #ECF0F1;
margin: 30px 0;
}}
.page-break {{
page-break-after: always;
}}
</style>
</head>
<body>
{html}
</body>
</html>
"""
# Convert HTML to PDF with encoding
with open(output_file, 'wb') as pdf_file:
pisa_status = pisa.CreatePDF(
html_with_style.encode('utf-8'),
dest=pdf_file,
encoding='utf-8'
)
if pisa_status.err:
print(f"Error creating PDF: {pisa_status.err}")
return False
else:
print(f"PDF created successfully: {output_file}")
return True
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.pdf'
if os.path.exists(input_file):
convert_md_to_pdf(input_file, output_file)
else:
print(f"Input file not found: {input_file}")

View File

@ -0,0 +1,11 @@
{
"file": "FreelanceDashboard.xlsx",
"backups": [
{
"id": "20251230_121153",
"filename": "FreelanceDashboard_backup_20251230_121153.xlsx",
"created": "2025-12-30T12:11:53.147808",
"original_size": 17005
}
]
}

BIN
templates/CheckboxDemo.xlsm Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.