Création, édition et analyse PPTX
Un .pptx est une archive ZIP de fichiers XML. Choisissez votre approche selon la tâche :
| Tâche | Approche |
|---|---|
| Créer un nouveau diaporama | Écrire un script pptxgenjs — voir les pièges ci-dessous |
| Modifier un diaporama existant, ou créer à partir d'un modèle | Décompresser → modifier ppt/slides/slideN.xml → recompresser |
| Lire le contenu | markitdown deck.pptx (un bloc par diapositive sous les marqueurs <!-- Slide number: N -->) ; grille visuelle : python scripts/thumbnail.py deck.pptx |
Scripts
Les chemins sont relatifs au répertoire de cette compétence. Tout le reste est en Python pur, Node ou shell.
| Script | Fonction |
|---|---|
scripts/thumbnail.py deck.pptx [prefix] | Grille annotée de chaque diapositive, pour choisir les mises en page. .pptx uniquement. Passez un prefix — par défaut thumbnails, ce qui écrase les grilles d'autres diaporamas dans le même répertoire |
scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml] | Duplique une diapositive (ou un slideLayoutN.xml) avec toute la comptabilité de package. Accepte aussi un .pptx directement avec -o out.pptx |
scripts/clean.py unpacked/ | Supprime les diapositives, médias et relations qui ne sont plus référencés. Exécutez après avoir finalisé <p:sldIdLst> |
scripts/office/validate.py deck.pptx [--original src.pptx] | Vérifications de schéma, relations, type de contenu, graphiques et diapositives ; chaque échec nomme sa correction. Passez --original pour tout diaporama dérivé d'un modèle — il compare les vérifications de schéma au modèle, afin que les erreurs XSD du modèle ne soient pas comptées comme vôtres |
scripts/office/soffice.py --headless --convert-to pdf deck.pptx | Wrapper LibreOffice — soffice brut bloque dans ce sandbox |
Création avec pptxgenjs — pièges
pptxgenjs est préinstallé — n'exécutez pas npm install d'abord ; écrivez le script et utilisez require('pptxgenjs') directement. Si ce require échoue seulement alors exécutez npm install pptxgenjs. Le modèle connaît l'API ; voici les pièges :
- Définissez
pres.layoutavant d'ajouter des diapositives. Le canevas par défaut estLAYOUT_16x9= 10" × 5,625", pas 13,3" de large. Les coordonnées au-delà du bord sont écrites, pas bloquées — la forme n'est simplement pas sur la diapositive. (LAYOUT_WIDEfait 13,3" × 7,5".) - Couleurs hexadécimales : jamais
#, jamais 8 chiffres.color: "FF0000"."#FF0000"et l'alpha intégré dans le hex ("00000020") corrompent le fichier. Pour la translucidité :transparency: 0-100sur les remplissages et images,opacity: 0.0-1.0sur les ombres — chacun est ignoré silencieusement sur l'autre. - pptxgenjs mute les objets d'options sur place (convertit les valeurs en EMU lors de la première utilisation). Ne partagez jamais un objet
shadow/options entre deux appelsadd*— construisez un nouvel objet à chaque fois. - L'
offsetd'une ombre doit être ≥ 0 — un offset négatif corrompt le fichier. Pour projeter une ombre vers le haut, utilisezangle: 270avec un offset positif. letterSpacingest ignoré silencieusement — la vraie option estcharSpacing.- Listes :
bullet: truesur chaque élément, jamais un•littéral (rend des doubles puces). DéfinissezbreakLine: truesur chaque élément de tableau sauf le dernier. Espacez les paragraphes à puces avecparaSpaceAfter, paslineSpacing(grands écarts). - Un
new pptxgen()par fichier de sortie — ne réutilisez jamais une instance. rectRadiusfonctionne uniquement surROUNDED_RECTANGLE, pas surRECTANGLE.- Les dégradés de remplissage ne sont pas pris en charge — utilisez une image dégradée comme arrière-plan à la place.
- Les zones de texte ont un rembourrage interne intégré — définissez
margin: 0lorsque le texte doit s'aligner avec une forme, une ligne ou une icône au même x. - Les notes du présentateur vont dans
slide.addNotes("...")(texte brut, une fois par diapositive), jamais dans une zone de texte sur la diapositive. - Gardez les graphiques natifs. Utilisez
addChart()pour tout ce que PowerPoint peut graphiquer (passez un tableau de{type, data, options}pour les combos). Pour les fonctionnalités natives de PowerPoint que la bibliothèque n'expose pas (lignes de tendance, barres d'erreur), calculez vous-même la série supplémentaire ou post-traitez le OOXML généré — ne recourez pas à une image rendue. Seuls les types de graphiques pour lesquels PowerPoint n'a pas de forme native (Sankey, réseau, corde) passent sous forme d'images. - Les graphiques par défaut sont rendus nus — pas de titre, pas d'étiquettes de données, palette datée. Définissez
showTitle+title,showValue: true+dataLabelPosition,chartColors: [...]depuis votre palette, et rendez le cadre discret (catAxisLabelColor/valAxisLabelColor,valGridLine: { color, size },catGridLine: { style: "none" },showLegend: falsepour une seule série). - Sur un histogramme ou un graphique à barres empilées,
dataLabelPositiondoit êtrectr,inEndouinBase.outEndcorrompt le fichier. - Une série combinée utilisant
secondaryValAxis/secondaryCatAxisnécessite à la foisvalAxesetcatAxesdans les options du graphique, deux entrées chacun. Sans eux, pptxgenjs écrit des ids d'axe qu'il ne déclare jamais, et PowerPoint rejette ce graphique et signale le fichier comme corrompu. Fournir uniquementvalAxesne suffit pas. - Après
writeFile(), exécutezpython scripts/office/validate.py deck.pptx. Il signale les deux défauts de graphique ci-dessus et les défauts de slide-XML que PowerPoint refuse, et nomme la correction pour chacun. Corrigez-les dans votre générateur, pas en éditant manuellement le XML compressé. - Ne réorganisez jamais les enfants de
<p:presentation>. pptxgenjs écrit<p:notesMasterIdLst>juste après<p:sldIdLst>et pointe les deux maîtres vers une même partie de thème. PowerPoint le lit joyeusement — déplacez l'élément et le même diaporama devient impossible à ouvrir. - Icônes : rendez les
react-iconsen SVG (ReactDOMServer.renderToStaticMarkup), pixellisez avecsharpà ≥256px, et insérez viaaddImage({ data: "image/png;base64," + buf.toString("base64") })— le préfixeimage/png;base64,est requis (react-icons,react,react-dometsharpsont préinstallés —npm install react-icons react react-dom sharpseulement si unrequireéchoue).
Modification de diaporamas et modèles existants
Choisissez d'abord les mises en page : python scripts/thumbnail.py template.pptx template-thumbs écrit une grille annotée de chaque diapositive et affiche le ou les fichiers créés — template-thumbs.jpg, divisé en template-thumbs-N.jpg au-delà de 12 diapositives. Passez toujours ce deuxième argument, nommé d'après le diaporama. Par défaut, il est thumbnails, donc deux diaporamas avec vignettes dans un même répertoire écrasent silencieusement les grilles l'un de l'autre — les grilles du premier diaporama sont simplement perdues (analyse de modèle uniquement — le contrôle visuel a besoin des rendus pleine résolution de Conversion en images ; il n'accepte que les .pptx, donc copiez d'abord un .potx sous un nom .pptx). Utilisez-le avec markitdown pour mapper chaque section de contenu sur une diapositive de modèle, et variez les mises en page — ne mettez pas chaque section sur la même diapositive titre-et-puces.
python3 -c "import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall('unpacked')" deck.pptx
python scripts/add_slide.py unpacked/ slide2.xml --after slide2.xml # duplique une diapositive (ou slideLayoutN.xml) ; affiche le chemin de la nouvelle diapositive
# réorganiser / supprimer des diapositives = modifier <p:sldIdLst> dans ppt/presentation.xml
python scripts/clean.py unpacked/ # après suppressions : supprime les diapositives, médias, relations orphelins
# modifier le contenu des diapositives dans ppt/slides/slideN.xml
(cd unpacked && rm -f ../out.pptx && zip -Xr ../out.pptx .) # compresser DEPUIS l'intérieur du répertoire ; rm d'abord ou les parties supprimées survivent
python scripts/office/validate.py out.pptx --original deck.pptx
- Effectuez tout le travail structurel — ajouter, supprimer, réorganiser — avant de modifier le contenu d'une diapositive.
add_slide.pycopie un fichier de diapositive textuellement, donc dupliquer après modification clone le contenu modifié ; etclean.pysupprime toute diapositive manquante dans<p:sldIdLst>, y compris celle que vous venez d'écrire. - Ne copiez jamais un fichier de diapositive à la main —
add_slide.pyeffectue tous les enregistrements nécessaires pour une nouvelle diapositive et indique ce qu'il a créé (Created ppt/slides/slide17.xml from slide2.xml). Il fonctionne aussi directement sur un fichier :add_slide.py deck.pptx slide2.xml -o out.pptx— passez-o, sinon il réécrit le diaporama d'entrée sur place. Une diapositive dupliquée référence toujours les parties du graphique/SmartArt/objet intégré de sa source au lieu de les cloner, donc modifier le graphique d'une diapositive modifie celui de l'autre. - Si vous utilisez
python-pptx, trois choses qu'il ne fera pas : dupliquer une diapositive (son seul point d'entrée estadd_slide(layout)), préserver le formatage viatext_frame.text = "..."(cela réduit le paragraphe à une seule exécution non stylisée — assignezrun.textà la place), ou lire le SVG/EMF utilisé par la plupart des graphismes de modèles (add_picturelèveUnidentifiedImageError). - Les
.ppthérités doivent d'abord être convertis :python scripts/office/soffice.py --headless --convert-to pptx file.ppt. Les modèles.potxse décompressent et se recompressent à l'identique — conservez l'extension.potxsur la sortie. - Pour réutiliser une icône ou une image d'un modèle, dupliquez une diapositive ou une mise en page qui la contient déjà.
Lors du remplissage d'un modèle :
- Si vous scriptez une transformation XML, analysez avec
defusedxml.minidom— faire un aller-retour du OOXML viaxml.etree.ElementTreeréécrit les préfixes d'espace de noms et corrompt le diaporama. - Les emplacements du modèle ≠ les éléments source. Si le modèle montre 4 membres d'équipe et que vous en avez 3, supprimez le groupe entier du 4ème membre (image + zones de texte), pas seulement son texte — puis vérifiez les éléments visuels orphelins dans le contrôle qualité.
- Un
<a:p>par élément de liste — ne concaténez jamais les éléments en un seul paragraphe. Copiez le frère<a:pPr>pour préserver l'espacement, et mettezb="1"sur le<a:rPr>des titres, en-têtes de section et étiquettes en ligne (Status:,Owner:). - Laissez les puces hériter de la mise en page ; ajoutez
<a:buChar>,<a:buAutoNum>(numéroté), ou<a:buNone>uniquement pour remplacer — jamais un•littéral dans le texte. - Le texte avec des espaces de début ou de fin a besoin de
xml:space="preserve"sur son<a:t>.
Idées de conception
Ne créez pas de diapositives ennuyeuses. Des puces simples sur fond blanc n'impressionneront personne. Considérez les idées de cette liste pour chaque diapositive.
Avant de commencer
- Choisissez une palette de couleurs audacieuse et adaptée au contenu : La palette doit sembler conçue POUR ce sujet. Si échanger vos couleurs dans une présentation complètement différente "fonctionne" encore, vous n'avez pas fait de choix suffisamment spécifiques.
- Domination sur égalité : Une couleur doit dominer (60-70% du poids visuel), avec 1-2 tons de soutien et un accent vif. Ne donnez jamais à toutes les couleurs un poids égal.
- Contraste clair/sombre : Arrière-plans sombres pour les diapositives de titre + conclusion, clairs pour le contenu (structure "sandwich"). Ou optez pour le sombre partout pour un aspect premium.
- Adoptez un motif visuel : Choisissez UN élément distinctif et répétez-le — cadres d'image arrondis, icônes dans des cercles colorés. Portez-le sur chaque diapositive. N'utilisez pas de barre de couleur ou de bande d'accent comme motif (voir liste À éviter).
Palettes de couleurs
Choisissez des couleurs qui correspondent à votre sujet — ne recourez pas par défaut au bleu générique. Utilisez ces palettes comme inspiration :
| Thème | Primaire | Secondaire | Accent |
|---|---|---|---|
| Midnight Executive | 1E2761 (marine) | CADCFC (bleu glacier) | FFFFFF (blanc) |
| Forest & Moss | 2C5F2D (forêt) | 97BC62 (mousse) | F5F5F5 (crème) |
| Coral Energy | F96167 (corail) | F9E795 (or) | 2F3C7E (marine) |
| Warm Terracotta | B85042 (terre cuite) | E7E8D1 (sable) | A7BEAE (sauge) |
| Ocean Gradient | 065A82 (bleu profond) | 1C7293 (sarcelle) | 21295C (minuit) |
| Charcoal Minimal | 36454F (charbon) | F2F2F2 (blanc cassé) | 212121 (noir) |
| Teal Trust | 028090 (sarcelle) | 00A896 (écume) | 02C39A (menthe) |
| Berry & Cream | 6D2E46 (baie) | A26769 (rose poussiéreux) | ECE2D0 (crème) |
| Sage Calm | 84B59F (sauge) | 69A297 (eucalyptus) | 50808E (ardoise) |
| Cherry Bold | 990011 (cerise) | FCF6F5 (blanc cassé) | 2F3C7E (marine) |
Pour chaque diapositive
Chaque diapositive a besoin d'un élément visuel — image, graphique, icône ou forme. Les diapositives textuelles uniquement sont oubliables.
Options de mise en page :
- Deux colonnes (texte à gauche, illustration à droite)
- Icône + lignes de texte (icône dans un cercle coloré, en-tête en gras, description en dessous)
- Grille 2x2 ou 2x3 (image d'un côté, grille de blocs de contenu de l'autre)
- Image à demi-débordement (côté gauche ou droit entier) avec superposition de contenu
Affichage des données :
- Appels de statistiques larges (grands nombres 60-72pt avec petites étiquettes en dessous)
- Colonnes de comparaison (avant/après, pour/contre, options côte à côte)
- Chronologie ou flux de processus (étapes numérotées, flèches)
Polissage visuel :
- Icônes dans de petits cercles colorés à côté des en-têtes de section
- Texte d'accent en italique pour les statistiques clés ou les slogans
Typographie
Les noms de polices que vous écrivez dans le .pptx sont rendus par le PowerPoint de l'utilisateur, pas par cet environnement. Votre contrôle visuel se fait via LibreOffice, qui substitue les polices qu'il n'a pas — et pour certaines polices, le substitut a des largeurs différentes, donc votre aperçu de contrôle peut montrer un débordement de texte (ou un ajustement) que le diaporama réel n'aura pas. Pour garder votre contrôle fiable :
- Polices sûres (rendu à largeur réelle dans le contrôle et livrées avec Office) : Arial, Calibri, Cambria, Times New Roman, Courier New, Bookman Old Style, Century Schoolbook. Utilisez-les pour le corps du texte et tout ce qui nécessite un ajustement précis.
- En-têtes avec personnalité sans risque de contrôle : associez un en-tête serif de la liste sûre (Cambria, Bookman Old Style, Century Schoolbook) avec un corps sans serif de la liste sûre (Calibri ou Arial). Vous obtenez un contraste visuel sans renoncer à des vérifications de débordement fiables.
- Si l'utilisateur demande une police hors de la liste sûre (par ex. Georgia ou Trebuchet MS) : utilisez-la là où l'utilisateur l'a demandé, mais dimensionnez ces conteneurs avec une marge supplémentaire (~10%) et ne faites pas confiance à l'ajustement du texte de contrôle sur ces éléments — l'aperçu de cette police est approximatif. Si l'utilisateur n'a pas spécifié, préférez les polices de la liste sûre pour le corps du texte.
- Polices non fiables pour le contrôle (le substitut a des largeurs différentes — les vérifications de débordement peuvent être erronées) : Georgia, Trebuchet MS, Impact, Arial Black, Garamond, Consolas, Palatino Linotype. Calibri Light varie selon l'environnement ; traitez-la comme non fiable pour le contrôle. Convient aux titres/accentuations avec marge ; ne faites pas confiance à l'ajustement du texte de contrôle sur ces polices.
- Ne recourez jamais par défaut à Aptos — le défaut d'Office post-2023 n'a pas de substitut compatible métrique ici et est absent des installations Office plus anciennes, donc il est non fiable des deux côtés.
| Élément | Taille |
|---|---|
| Titre de diapositive | 36-44pt gras |
| En-tête de section | 20-24pt gras |
| Corps du texte | 14-16pt |
| Légendes | 10-12pt atténué |
…
[le contenu a été tronqué pour la traduction]
Conversion en images
markitdown extrait le texte. Pour des images de diapositives entières : python scripts/office/soffice.py --headless --convert-to pdf deck.pptx puis convertissez le PDF en images avec pdf2image (préinstallé) : python3 -c "from pdf2image import convert_from_path; [img.save(f'slide{i}.png') for i, img in enumerate(convert_from_path('deck.pdf'))]".
Validation
Exécutez toujours python scripts/office/validate.py deck.pptx [--original modèle.pptx] après toute opération d'écriture. Cela vérifie :
- Intégrité du schéma : Le XML se valide-t-il par rapport aux XSD d'Office ?
- Relations : Chaque partie référencée a-t-elle une relation déclarée ?
- Types de contenu : Chaque partie a-t-elle un type de contenu dans
[Content_Types].xml? - Graphiques : Les axes secondaires sont-ils correctement déclarés ?
- Diapositives :
<p:sldIdLst>dans presentation.xml correspond-il aux fichiers de diapositives présents ?
Chaque échec affiche :
❌ [chemin/vers/la/partie] problème détecté → correction : [instructions]
Optimisation de la taille des fichiers
Si le fichier résultant est trop volumineux : les images non compressées sont la cause principale. pptxgenjs n'optimise pas les images. Avant d'insérer des images, réduisez leur résolution à la dimension d'affichage (typiquement 1920×1080 px pour une diapositive 16:9 à 96 DPI) et compressez-les avec sharp avant l'insertion. Pour les images déjà présentes dans un diaporama décompressé, exécutez mogrify -resize 1920x1080 -quality 85% unpacked/ppt/media/*.png (installez ImageMagick si nécessaire).
Dépannage
"Impossible d'ouvrir le fichier" / "Fichier corrompu"
- Exécutez
python scripts/office/validate.py out.pptx— la plupart des causes sont signalées avec une correction - Si le problème persiste : décompressez et comparez la structure avec un fichier sain (
diff -r unpacked_bon unpacked_mauvais) - Problème courant : les couleurs hexadécimales avec
#ou 8 chiffres dans pptxgenjs — ne le faites pas. - Problème courant :
dataLabelPosition: 'outEnd'sur un graphique empilé — ne le faites pas. - Problème courant : ombre avec offset négatif — ne le faites pas.
"L'image ne s'affiche pas"
- Vérifiez que le chemin de l'image est absolu ou relatif correctement à l'exécution
- Pour pptxgenjs : utilisez
addImage({ path: "chemin/vers/image.png" })ouaddImage({ data: "image/png;base64,..." }) add_picturede python-pptx échoue sur SVG/EMF — utilisez PNG ou JPG à la place
"Les polices sont différentes"
Voir la section Typographie ci-dessus. Les polices dans la liste "sûre" sont fiables. Pour les autres, acceptez que l'aperçu du contrôle ne corresponde pas parfaitement.