first commit
This commit is contained in:
10
.claude/settings.local.json
Normal file
10
.claude/settings.local.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(pip install:*)",
|
||||
"Bash(pip3 install:*)",
|
||||
"Bash(python3 -m pip install python-docx)",
|
||||
"Bash(python3:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
54
.claude/skills/formation-docx-replacer/SKILL.md
Normal file
54
.claude/skills/formation-docx-replacer/SKILL.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: formation-docx-replacer
|
||||
description: Use when the user asks to create a new formation dossier, replace text in docx files, or apply a YAML config to modify formation documents. Triggers on keywords like formation, dossier, remplacements, docx, yaml config, nouvelle formation.
|
||||
---
|
||||
|
||||
# Formation DOCX Replacer
|
||||
|
||||
## Overview
|
||||
|
||||
Prepare un dossier de formation a partir du template et guide l'utilisateur pour configurer et lancer les remplacements dans les .docx.
|
||||
|
||||
## When to Use
|
||||
|
||||
- L'utilisateur veut creer une nouvelle formation
|
||||
- L'utilisateur mentionne un nouveau dossier de formation
|
||||
- L'utilisateur veut dupliquer le template pour un nouveau client/formation
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Demander le nom de la formation** a l'utilisateur (ex: "Excel Avance Dupont Avril 2026")
|
||||
2. **Creer le dossier** dans `formations/` en slugifiant le nom (ex: `formations/excel_avance_dupont_avril_2026/`)
|
||||
3. **Copier le template YAML** : `template/formation_template.yaml` -> `formations/<nom>/formation.yaml`
|
||||
4. **Indiquer a l'utilisateur** :
|
||||
- Le chemin du fichier YAML a editer
|
||||
- Qu'il doit remplir les paires ancien/nouveau avec ses infos
|
||||
- La commande exacte a lancer une fois le YAML pret :
|
||||
```
|
||||
python3 replace_docx.py formations/<nom>/formation.yaml
|
||||
```
|
||||
|
||||
Ne PAS essayer de remplir le YAML a la place de l'utilisateur. Il connait ses infos.
|
||||
|
||||
## Format YAML
|
||||
|
||||
```yaml
|
||||
dossier_source: template
|
||||
remplacements:
|
||||
- ancien: "texte a chercher"
|
||||
nouveau: "texte de remplacement"
|
||||
- ancien: "autre texte"
|
||||
nouveau: "nouveau texte"
|
||||
fichiers: ["seul_ce_fichier.docx"] # optionnel, par defaut tous
|
||||
```
|
||||
|
||||
## Ce que le script gere
|
||||
|
||||
- Paragraphes, tableaux (imbriques), en-tetes, pieds de page
|
||||
- Texte decoupe sur plusieurs runs Word
|
||||
- Preservation du formatage (police, taille, couleur, gras)
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- **Texte introuvable** : Word fragmente parfois le texte en plusieurs runs. Verifier avec python-docx
|
||||
- **Accents** : YAML en UTF-8
|
||||
10
.idea/.gitignore
generated
vendored
Normal file
10
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
10
.idea/material_theme_project_new.xml
generated
Normal file
10
.idea/material_theme_project_new.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MaterialThemeProjectNewConfig">
|
||||
<option name="metadata">
|
||||
<MTProjectMetadataState>
|
||||
<option name="userId" value="2bbcbe4d:19d1b20fd6b:-65c4" />
|
||||
</MTProjectMetadataState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/qualiopi.iml" filepath="$PROJECT_DIR$/.idea/qualiopi.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
19
.idea/php.xml
generated
Normal file
19
.idea/php.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MessDetectorOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCSFixerOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||
<option name="highlightLevel" value="WARNING" />
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpStanOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PsalmOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/qualiopi.iml
generated
Normal file
8
.idea/qualiopi.iml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
53
CLAUDE.md
Normal file
53
CLAUDE.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# CLAUDE.md - Qualiopi
|
||||
|
||||
## Contexte projet
|
||||
|
||||
Ce depot contient les documents de formation de la SAS MALIO (organisme de formation certifie Qualiopi). L'objectif principal est d'automatiser la creation de nouveaux dossiers de formation a partir de templates existants.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
qualiopi/
|
||||
├── replace_docx.py # Script principal
|
||||
├── template/ # Documents modeles (ne jamais modifier directement)
|
||||
│ ├── *.docx # Documents template
|
||||
│ └── formation_template.yaml # Modele de config
|
||||
└── formations/ # Un sous-dossier par formation generee
|
||||
└── <nom_formation>/
|
||||
├── formation.yaml # Config avec les remplacements
|
||||
├── rapport.md # Rapport des modifications
|
||||
└── *.docx # Documents generes
|
||||
```
|
||||
|
||||
## Outils disponibles
|
||||
|
||||
### replace_docx.py
|
||||
|
||||
Script Python de remplacement de texte dans des fichiers `.docx`.
|
||||
|
||||
- **Commande** : `python3 replace_docx.py <chemin/vers/formation.yaml>`
|
||||
- **Dependances** : python-docx, pyyaml
|
||||
- **Comportement** : copie les .docx du template dans le dossier du YAML, applique les remplacements et genere un `rapport.md`
|
||||
|
||||
## Workflow pour creer une formation
|
||||
|
||||
Via le skill : `/formation-docx-replacer <nom_formation>` (cree le dossier et copie le YAML)
|
||||
|
||||
Ou manuellement :
|
||||
1. `mkdir formations/<nom_formation>`
|
||||
2. `cp template/formation_template.yaml formations/<nom_formation>/formation.yaml`
|
||||
3. Editer le YAML avec les paires ancien/nouveau
|
||||
4. `python3 replace_docx.py formations/<nom_formation>/formation.yaml`
|
||||
5. Verifier `rapport.md` dans le dossier (signaler les remplacements non trouves)
|
||||
|
||||
## Regles importantes
|
||||
|
||||
- **Ne jamais modifier le dossier template/** : le script copie les .docx dans le dossier de la formation
|
||||
- **Chemins relatifs** : dans le YAML, les chemins sont relatifs a la racine du projet
|
||||
- **Encodage** : fichiers YAML en UTF-8
|
||||
- **Verifier le rapport** : apres chaque execution, signaler les remplacements non trouves a l'utilisateur
|
||||
- **Formatage** : le script preserve les polices, tailles, couleurs et styles
|
||||
|
||||
## Skill associe
|
||||
|
||||
Le skill `formation-docx-replacer` dans `.claude/skills/` gere l'utilisation automatique du script.
|
||||
113
README.md
Normal file
113
README.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Qualiopi - Generateur de dossiers de formation
|
||||
|
||||
Outil d'automatisation pour creer des dossiers de formation a partir d'un template existant. Remplace en masse les informations (client, dates, formateur, etc.) dans tous les fichiers `.docx` d'un dossier, en preservant le formatage d'origine.
|
||||
|
||||
## Prerequis
|
||||
|
||||
- Python 3.10+
|
||||
- python-docx (`pip3 install python-docx`)
|
||||
- PyYAML (`pip3 install pyyaml`)
|
||||
|
||||
## Structure du projet
|
||||
|
||||
```
|
||||
qualiopi/
|
||||
├── replace_docx.py # Script de remplacement
|
||||
├── template/ # Dossier template (ne pas modifier)
|
||||
│ ├── CONDITIONS_GENERALES_DE_VENTE.docx
|
||||
│ ├── formation_template.yaml # Modele de config a copier
|
||||
│ └── ... # Autres documents template
|
||||
└── formations/ # Dossiers generes par formation
|
||||
└── excel_dupont_avril2026/
|
||||
├── formation.yaml # Config de la formation
|
||||
├── rapport.md # Rapport des modifications
|
||||
├── CONDITIONS_GENERALES_DE_VENTE.docx # Copie modifiee
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Utilisation
|
||||
|
||||
### 1. Creer le dossier de la formation
|
||||
|
||||
```bash
|
||||
mkdir -p formations/excel_dupont_avril2026
|
||||
```
|
||||
|
||||
### 2. Copier et configurer le YAML
|
||||
|
||||
```bash
|
||||
cp template/formation_template.yaml formations/excel_dupont_avril2026/formation.yaml
|
||||
```
|
||||
|
||||
Editer `formation.yaml` avec les infos de la formation :
|
||||
|
||||
```yaml
|
||||
dossier_source: template
|
||||
|
||||
remplacements:
|
||||
- ancien: "Word - Initiation bureautique"
|
||||
nouveau: "Excel Avance - TCD"
|
||||
|
||||
- ancien: "Societe Martin SARL"
|
||||
nouveau: "Societe Dupont SAS"
|
||||
|
||||
- ancien: "10 et 11 mars 2026"
|
||||
nouveau: "15 et 16 avril 2026"
|
||||
```
|
||||
|
||||
### 3. Lancer le script
|
||||
|
||||
```bash
|
||||
python3 replace_docx.py formations/excel_dupont_avril2026/formation.yaml
|
||||
```
|
||||
|
||||
Le script :
|
||||
1. Copie les `.docx` du template dans le dossier de la formation
|
||||
2. Applique tous les remplacements
|
||||
3. Genere un fichier `rapport.md` dans le dossier de la formation
|
||||
|
||||
### 4. Verifier le rapport
|
||||
|
||||
Ouvrir `formations/excel_dupont_avril2026/rapport.md`. Il contient :
|
||||
- La date d'execution
|
||||
- Un tableau par fichier avec les remplacements effectues et le nombre d'occurrences
|
||||
- La liste des remplacements non trouves (s'il y en a)
|
||||
|
||||
## Options
|
||||
|
||||
### Cibler un fichier specifique
|
||||
|
||||
Par defaut, chaque remplacement s'applique a tous les `.docx`. Pour cibler un fichier :
|
||||
|
||||
```yaml
|
||||
remplacements:
|
||||
- ancien: "Texte specifique"
|
||||
nouveau: "Nouveau texte"
|
||||
fichiers: ["convention.docx"]
|
||||
```
|
||||
|
||||
### Chemins
|
||||
|
||||
Tous les chemins dans le YAML sont relatifs a la racine du projet (dossier contenant `replace_docx.py`).
|
||||
|
||||
## Ce qui est pris en charge
|
||||
|
||||
| Zone du document | Supporte |
|
||||
|---|---|
|
||||
| Paragraphes du corps | Oui |
|
||||
| Cellules de tableaux | Oui |
|
||||
| Tableaux imbriques | Oui |
|
||||
| En-tetes de page | Oui |
|
||||
| Pieds de page | Oui |
|
||||
| Formatage (police, taille, couleur, gras) | Preserve |
|
||||
| Texte decoupe sur plusieurs runs | Gere automatiquement |
|
||||
|
||||
## Utilisation avec Claude
|
||||
|
||||
Le skill `/formation-docx-replacer` permet de preparer un dossier automatiquement :
|
||||
|
||||
```
|
||||
/formation-docx-replacer ma_nouvelle_formation
|
||||
```
|
||||
|
||||
Claude cree le dossier dans `formations/`, copie le template YAML et indique la marche a suivre.
|
||||
272
replace_docx.py
Normal file
272
replace_docx.py
Normal file
@@ -0,0 +1,272 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de remplacement de texte dans des fichiers .docx
|
||||
Lit un fichier YAML de configuration et applique les remplacements
|
||||
dans tous les .docx d'un dossier en préservant le formatage.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import yaml
|
||||
from docx import Document
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
def get_full_text_from_runs(runs):
|
||||
"""Reconstitue le texte complet à partir des runs."""
|
||||
return "".join(r.text for r in runs)
|
||||
|
||||
|
||||
def replace_in_runs(runs, ancien, nouveau):
|
||||
"""
|
||||
Remplace du texte dans une liste de runs en préservant le formatage.
|
||||
Gère le cas où le texte est découpé sur plusieurs runs.
|
||||
Retourne le nombre de remplacements effectués.
|
||||
"""
|
||||
count = 0
|
||||
full_text = get_full_text_from_runs(runs)
|
||||
|
||||
if ancien not in full_text:
|
||||
return 0
|
||||
|
||||
while ancien in full_text:
|
||||
count += 1
|
||||
start_idx = full_text.index(ancien)
|
||||
end_idx = start_idx + len(ancien)
|
||||
|
||||
# Trouver quels runs sont concernés
|
||||
char_pos = 0
|
||||
start_run = None
|
||||
end_run = None
|
||||
|
||||
for i, run in enumerate(runs):
|
||||
run_start = char_pos
|
||||
run_end = char_pos + len(run.text)
|
||||
|
||||
if start_run is None and run_end > start_idx:
|
||||
start_run = i
|
||||
start_offset = start_idx - run_start
|
||||
|
||||
if run_end >= end_idx:
|
||||
end_run = i
|
||||
end_offset = end_idx - run_start
|
||||
break
|
||||
|
||||
char_pos = run_end
|
||||
|
||||
if start_run is None or end_run is None:
|
||||
break
|
||||
|
||||
# Cas simple : tout dans un seul run
|
||||
if start_run == end_run:
|
||||
run = runs[start_run]
|
||||
run.text = run.text[:start_offset] + nouveau + run.text[end_offset:]
|
||||
else:
|
||||
# Multi-run : mettre le nouveau texte dans le premier run,
|
||||
# vider les runs intermédiaires, ajuster le dernier
|
||||
runs[start_run].text = runs[start_run].text[:start_offset] + nouveau
|
||||
|
||||
for i in range(start_run + 1, end_run):
|
||||
runs[i].text = ""
|
||||
|
||||
runs[end_run].text = runs[end_run].text[end_offset:]
|
||||
|
||||
full_text = get_full_text_from_runs(runs)
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def replace_in_paragraph(paragraph, ancien, nouveau):
|
||||
"""Remplace du texte dans un paragraphe."""
|
||||
if not paragraph.runs:
|
||||
return 0
|
||||
return replace_in_runs(paragraph.runs, ancien, nouveau)
|
||||
|
||||
|
||||
def replace_in_table(table, ancien, nouveau):
|
||||
"""Remplace du texte dans toutes les cellules d'un tableau."""
|
||||
count = 0
|
||||
for row in table.rows:
|
||||
for cell in row.cells:
|
||||
for paragraph in cell.paragraphs:
|
||||
count += replace_in_paragraph(paragraph, ancien, nouveau)
|
||||
# Tables imbriquées
|
||||
for nested_table in cell.tables:
|
||||
count += replace_in_table(nested_table, ancien, nouveau)
|
||||
return count
|
||||
|
||||
|
||||
def replace_in_headers_footers(doc, ancien, nouveau):
|
||||
"""Remplace du texte dans les en-têtes et pieds de page."""
|
||||
count = 0
|
||||
for section in doc.sections:
|
||||
for header in [section.header, section.first_page_header, section.even_page_header]:
|
||||
if header and header.is_linked_to_previous is False:
|
||||
for paragraph in header.paragraphs:
|
||||
count += replace_in_paragraph(paragraph, ancien, nouveau)
|
||||
for table in header.tables:
|
||||
count += replace_in_table(table, ancien, nouveau)
|
||||
|
||||
for footer in [section.footer, section.first_page_footer, section.even_page_footer]:
|
||||
if footer and footer.is_linked_to_previous is False:
|
||||
for paragraph in footer.paragraphs:
|
||||
count += replace_in_paragraph(paragraph, ancien, nouveau)
|
||||
for table in footer.tables:
|
||||
count += replace_in_table(table, ancien, nouveau)
|
||||
return count
|
||||
|
||||
|
||||
def process_docx(filepath, remplacements):
|
||||
"""Applique tous les remplacements sur un fichier .docx."""
|
||||
doc = Document(filepath)
|
||||
rapport = {}
|
||||
|
||||
for remp in remplacements:
|
||||
ancien = remp["ancien"]
|
||||
nouveau = remp["nouveau"]
|
||||
fichiers_cibles = remp.get("fichiers", None)
|
||||
|
||||
# Si des fichiers cibles sont spécifiés, vérifier que ce fichier en fait partie
|
||||
if fichiers_cibles:
|
||||
basename = os.path.basename(filepath)
|
||||
if basename not in fichiers_cibles:
|
||||
continue
|
||||
|
||||
count = 0
|
||||
|
||||
# Paragraphes du corps
|
||||
for paragraph in doc.paragraphs:
|
||||
count += replace_in_paragraph(paragraph, ancien, nouveau)
|
||||
|
||||
# Tableaux
|
||||
for table in doc.tables:
|
||||
count += replace_in_table(table, ancien, nouveau)
|
||||
|
||||
# En-têtes et pieds de page
|
||||
count += replace_in_headers_footers(doc, ancien, nouveau)
|
||||
|
||||
if count > 0:
|
||||
rapport[f"'{ancien}' -> '{nouveau}'"] = count
|
||||
|
||||
doc.save(filepath)
|
||||
return rapport
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python3 replace_docx.py <fichier_config.yaml>")
|
||||
sys.exit(1)
|
||||
|
||||
config_path = os.path.abspath(sys.argv[1])
|
||||
config_dir = os.path.dirname(config_path)
|
||||
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# Les chemins sont relatifs à la racine du projet (dossier contenant replace_docx.py)
|
||||
project_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
dossier_source = config["dossier_source"]
|
||||
if not os.path.isabs(dossier_source):
|
||||
dossier_source = os.path.join(project_dir, dossier_source)
|
||||
|
||||
remplacements = config["remplacements"]
|
||||
|
||||
# Le dossier de travail est celui qui contient le fichier YAML
|
||||
dossier_travail = config_dir
|
||||
|
||||
# Copier les .docx du template dans le dossier de travail
|
||||
docx_copies = 0
|
||||
for f in os.listdir(dossier_source):
|
||||
if f.endswith(".docx") and not f.startswith("~$"):
|
||||
src = os.path.join(dossier_source, f)
|
||||
dst = os.path.join(dossier_travail, f)
|
||||
if not os.path.exists(dst):
|
||||
shutil.copy2(src, dst)
|
||||
docx_copies += 1
|
||||
|
||||
if docx_copies > 0:
|
||||
print(f"{docx_copies} fichier(s) .docx copie(s) depuis {dossier_source}")
|
||||
else:
|
||||
print(f"Fichiers .docx deja presents dans {dossier_travail}")
|
||||
|
||||
# Trouver tous les .docx du dossier de travail
|
||||
docx_files = []
|
||||
for f in os.listdir(dossier_travail):
|
||||
if f.endswith(".docx") and not f.startswith("~$"):
|
||||
docx_files.append(os.path.join(dossier_travail, f))
|
||||
|
||||
if not docx_files:
|
||||
print("Aucun fichier .docx trouve.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\n{len(docx_files)} fichier(s) .docx trouve(s)\n")
|
||||
|
||||
# Appliquer les remplacements
|
||||
rapport_global = {}
|
||||
for filepath in sorted(docx_files):
|
||||
rapport = process_docx(filepath, remplacements)
|
||||
rel_path = os.path.relpath(filepath, dossier_travail)
|
||||
rapport_global[rel_path] = rapport
|
||||
|
||||
# Identifier les remplacements non trouves
|
||||
remplacements_non_trouves = set()
|
||||
for remp in remplacements:
|
||||
cle = f"'{remp['ancien']}' -> '{remp['nouveau']}'"
|
||||
trouve = False
|
||||
for fichier, rapport in rapport_global.items():
|
||||
if cle in rapport:
|
||||
trouve = True
|
||||
break
|
||||
if not trouve:
|
||||
remplacements_non_trouves.add(cle)
|
||||
|
||||
# Generer le rapport markdown
|
||||
from datetime import datetime
|
||||
lignes = []
|
||||
lignes.append(f"# Rapport de modifications")
|
||||
lignes.append(f"")
|
||||
lignes.append(f"**Date** : {datetime.now().strftime('%d/%m/%Y %H:%M')}")
|
||||
lignes.append(f"**Template** : `{os.path.relpath(dossier_source, project_dir)}`")
|
||||
lignes.append(f"**Fichiers traites** : {len(docx_files)}")
|
||||
lignes.append(f"")
|
||||
|
||||
lignes.append(f"## Modifications par fichier")
|
||||
lignes.append(f"")
|
||||
for fichier, rapport in sorted(rapport_global.items()):
|
||||
lignes.append(f"### {fichier}")
|
||||
lignes.append(f"")
|
||||
if rapport:
|
||||
lignes.append(f"| Ancien | Nouveau | Occurrences |")
|
||||
lignes.append(f"|---|---|---|")
|
||||
for remp, count in rapport.items():
|
||||
# remp est au format "'ancien' -> 'nouveau'"
|
||||
parties = remp.split("' -> '")
|
||||
ancien_txt = parties[0][1:] # enlever le ' du debut
|
||||
nouveau_txt = parties[1][:-1] # enlever le ' de la fin
|
||||
lignes.append(f"| {ancien_txt} | {nouveau_txt} | {count} |")
|
||||
else:
|
||||
lignes.append(f"Aucun remplacement effectue.")
|
||||
lignes.append(f"")
|
||||
|
||||
if remplacements_non_trouves:
|
||||
lignes.append(f"## Remplacements non trouves")
|
||||
lignes.append(f"")
|
||||
lignes.append(f"Les remplacements suivants n'ont ete trouves dans aucun fichier :")
|
||||
lignes.append(f"")
|
||||
for r in remplacements_non_trouves:
|
||||
lignes.append(f"- {r}")
|
||||
lignes.append(f"")
|
||||
|
||||
# Ecrire le rapport
|
||||
rapport_path = os.path.join(dossier_travail, "rapport.md")
|
||||
with open(rapport_path, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(lignes))
|
||||
|
||||
print(f"Rapport genere : {rapport_path}")
|
||||
print("Termine!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
template/CONDITIONS_GENERALES_DE_VENTE.docx
Normal file
BIN
template/CONDITIONS_GENERALES_DE_VENTE.docx
Normal file
Binary file not shown.
43
template/formation_template.yaml
Normal file
43
template/formation_template.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
# Configuration de remplacement pour dossier de formation
|
||||
# Usage:
|
||||
# 1. Creer un dossier pour la formation : mkdir formations/ma_formation
|
||||
# 2. Copier ce fichier dedans : cp template/formation_template.yaml formations/ma_formation/formation.yaml
|
||||
# 3. Editer le fichier copie avec les bonnes infos
|
||||
# 4. Lancer : python3 replace_docx.py formations/ma_formation/formation.yaml
|
||||
#
|
||||
# Le script copie automatiquement les .docx du template dans le dossier de la formation.
|
||||
# Les chemins sont relatifs a la racine du projet.
|
||||
|
||||
# Dossier contenant les .docx template
|
||||
dossier_source: template
|
||||
|
||||
# Liste des remplacements (appliques a TOUS les .docx copies)
|
||||
remplacements:
|
||||
# Infos formation
|
||||
- ancien: "Word - Initiation bureautique"
|
||||
nouveau: "Excel Avance - Tableaux croises dynamiques"
|
||||
|
||||
# Infos client
|
||||
- ancien: "Societe Martin SARL"
|
||||
nouveau: "Societe Dupont SAS"
|
||||
|
||||
# Dates
|
||||
- ancien: "10 et 11 mars 2026"
|
||||
nouveau: "15 et 16 avril 2026"
|
||||
|
||||
# Formateur
|
||||
- ancien: "Marie Martin"
|
||||
nouveau: "Jean Dupont"
|
||||
|
||||
# Lieu
|
||||
- ancien: "14 allee d'Argenson, Chatellerault"
|
||||
nouveau: "12 rue des Lilas, Poitiers"
|
||||
|
||||
# Duree
|
||||
- ancien: "7 heures (1 jour)"
|
||||
nouveau: "14 heures (2 jours)"
|
||||
|
||||
# Remplacement cible sur un seul fichier (optionnel)
|
||||
# - ancien: "Texte specifique a la convention"
|
||||
# nouveau: "Nouveau texte convention"
|
||||
# fichiers: ["convention.docx"]
|
||||
Reference in New Issue
Block a user