Création, édition et analyse de documents DOCX
Un fichier .docx est une archive ZIP contenant des fichiers XML. Choisissez votre approche selon la tâche :
| Tâche | Approche |
|---|---|
| Créer un nouveau document | Écrire un script docx (npm) — voir les pièges ci-dessous |
| Éditer un document existant | unzip → éditer word/document.xml → zip (docx-js ne peut pas ouvrir les fichiers existants) |
| Lire le contenu | pandoc -t markdown file.docx |
Les chemins des scripts ci-dessous sont relatifs au répertoire de cette compétence.
Créer avec docx-js — pièges
docx est préinstallé — n'exécutez pas npm install d'abord ; écrivez le script et utilisez directement require('docx'). Ce n'est que si ce require échoue : npm install docx. Le modèle connaît l'API ; voici les pièges courants :
- La taille de page par défaut est A4. Pour du format US Letter, définissez
page: { size: { width: 12240, height: 15840 } }(en DXA ; 1440 = 1 pouce). - Paysage : passez les dimensions portrait et
orientation: PageOrientation.LANDSCAPE— docx-js échange largeur et hauteur en interne. - Les tableaux nécessitent deux largeurs : définissez
columnWidthssur le tableau ETwidthsur chaque cellule, tous deux enWidthType.DXA(le format PERCENTAGE pose problème dans Google Docs). La somme des largeurs de colonnes doit être égale à la largeur du tableau. - Ombrage de tableau : utilisez
ShadingType.CLEAR, jamaisSOLID(affiche du noir). - Listes : n'insérez jamais
•littéralement ; utilisez une configurationnumberingavecLevelFormat.BULLET. ImageRunnécessitetype:("png","jpg", …).PageBreakdoit être à l'intérieur d'unParagraph.- N'utilisez jamais
\n— utilisez des élémentsParagraphséparés. - TDM : les titres doivent utiliser les niveaux prédéfinis
HeadingLevel.*; les styles de titre personnalisés nécessitent de définiroutlineLevelsans quoi ils n'apparaissent pas. - N'utilisez pas un tableau comme filet horizontal — utilisez plutôt une bordure inférieure de paragraphe.
- Points de suite / aligné à droite sur la même ligne : utilisez
PositionalTab(alignment: PositionalTabAlignment.RIGHT,leader: PositionalTabLeader.DOT) à l'intérieur d'unTextRun, pas de points.ou d'espaces littéraux.
Vérifier la sortie
Après avoir écrit un fichier .docx, convertissez-le et examinez-le :
python scripts/office/soffice.py --headless --convert-to pdf output.docx
pdftoppm -jpeg -r 100 output.pdf page
ls page-*.jpg # puis lire les images
pdftoppm remplit les numéros de page avec des zéros sur la largeur du nombre total de pages (page-01.jpg...page-12.jpg).
Éditer des documents existants
Les fichiers .doc hérités doivent d'abord être convertis : python scripts/office/soffice.py --headless --convert-to docx file.doc.
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete # supprimer les entrées de liens symboliques — les docx provenant de tiers ne sont pas fiables
python scripts/merge_runs.py unpacked/ # fusionner les fragments de runs pour que le texte soit trouvable
# éditer unpacked/word/document.xml sur place — NE PAS reformater ni pretty-print
(cd unpacked && rm -f ../out.docx && zip -Xr ../out.docx .)
python scripts/office/validate.py out.docx --original doc.docx # vérifications XSD ; --auto-repair corrige les problèmes courants
# suivi des modifications ? ajoutez --author "<le nom sous lequel vous avez modifié>" pour vérifier que chaque édition est tracée
Word divise le texte en de nombreux fragments <w:r> (identifiants de révision, marqueurs de correction orthographique), donc une phrase que vous voyez dans le document n'existe souvent pas comme chaîne contiguë dans le XML. merge_runs.py fusionne les fragments adjacents de formatage identique dans word/document.xml sans modifier le contenu ni le rendu ; il accepte aussi directement un fichier .docx (python scripts/merge_runs.py doc.docx -o merged.docx).
Suivi des modifications : lorsque vous utilisez le suivi, validez avec --author "<le nom sous lequel vous avez modifié>" (nécessite --original) — il signale tout texte modifié sans balise <w:ins>/<w:del> autour, ce qui arrive facilement par erreur et reste invisible dans la vue acceptée. Entourez les runs avec <w:ins>/<w:del> avec les attributs w:id, w:author, w:date. À l'intérieur de <w:del>, l'élément de texte est <w:delText>, pas <w:t>. Une marque de paragraphe supprimée (<w:pPr><w:rPr><w:del w:id=".." w:author=".." w:date=".."/></w:rPr></w:pPr>) signifie « fusionner ce paragraphe dans le suivant » — donc supprimer un paragraphe entièrement consiste à ajouter cela plus un <w:del> autour de chaque run. <w:del/> doit venir avant les autres enfants de rPr ; leur ordre est imposé par le schéma.
Pour produire une copie propre avec tous les suivis acceptés : python scripts/accept_changes.py in.docx out.docx.
Accepter une marque de paragraphe supprimée devrait joindre ce paragraphe à celui du dessous, donc un paragraphe dont tous les runs sont supprimés disparaît. Word fait cela ; accept_changes.py et pandoc --track-changes=accept ne le font pas toujours. Les deux échouent de la même manière — ils suppriment le texte supprimé mais laissent le paragraphe vide, ce qui apparaît comme une puce vide parasite lorsqu'il était numéroté automatiquement :
pandoc --track-changes=acceptne joint jamais les paragraphes.accept_changes.py(LibreOffice) les joint correctement, sauf si le paragraphe supprimé est suivi d'un paragraphe espaceur vide.
Une puce vide dans l'une ou l'autre vue est un artefact de cette vue, pas un défaut du document. Vérifiez les suppressions de paragraphes dans le XML.
Commentaires
Les commentaires nécessitent six fichiers liés entre eux. Utilisez l'outil d'aide — mode répertoire lorsque vous éditez aussi document.xml (économise un cycle décompression/recompression), mode .docx direct sinon :
# Avec un répertoire déjà décompressé (préféré lorsqu'on place aussi des marqueurs)
python scripts/comment.py unpacked/ "Le plafond des frais et dépenses est trop bas"
python scripts/comment.py unpacked/ "D'accord" --parent 0
# Avec un .docx directement
python scripts/comment.py contract.docx "Ce plafond est trop bas" -o annotated.docx
Le script écrit comments.xml, commentsExtended.xml, commentsIds.xml, commentsExtensible.xml, les relations et les surcharges de type de contenu. Les identifiants de commentaire sont attribués automatiquement. Il affiche ensuite l'extrait <w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference> à ajouter dans word/document.xml pour que le commentaire soit ancré à un texte spécifique — tant que vous n'avez pas placé ces marqueurs, le commentaire existe mais n'est pas visible.
Dépendances
docx (npm, préinstallé — n'installez que si require('docx') échoue) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)