Création, édition et analyse de documents DOCX
Un fichier .docx est une archive ZIP de 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 |
| Modifier un document existant | unzip → modifier word/document.xml → zip (docx-js ne peut pas ouvrir les fichiers existants) |
| Lire le contenu | pandoc -t markdown file.docx |
Les chemins de scripts ci-dessous sont relatifs au répertoire de cette compétence.
Création avec docx-js — pièges
docx est préinstallé — n'exécutez pas npm install d'abord ; écrivez le script et utilisez require('docx') directement. Ce n'est qu'en cas d'échec de require : npm install docx. Le modèle connaît l'API ; voici les pièges à éviter :
- La taille de page par défaut est A4. Pour le 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/hauteur en interne. - Les tableaux nécessitent deux largeurs : définissez
columnWidthssur le tableau ETwidthsur chaque cellule, les deux enWidthType.DXA(POURCENTAGE casse dans Google Docs). Les largeurs de colonnes doivent totaliser la largeur du tableau. - Fond de tableau : utilisez
ShadingType.CLEAR, jamaisSOLID(rendu en 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. - TOC : les titres doivent utiliser les
HeadingLevel.*intégrés ; les styles de titre personnalisés nécessitentoutlineLeveldéfini ou ils n'apparaîtront 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.littéral ou d'espacement.
Vérifier le résultat
Après avoir écrit un .docx, convertissez-le et regardez-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 de pages (page-01.jpg…page-12.jpg).
Modifier 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 externes ne sont pas fiables
python scripts/merge_runs.py unpacked/ # fusionner les fragments de runs pour que le texte soit trouvable
# modifier unpacked/word/document.xml sur place — NE PAS reformater ou 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 suivi>" pour vérifier que chaque modification est suivie
Word divise le texte en de nombreux runs <w:r> (identifiants de révision, marqueurs de vérification orthographique), donc une phrase que vous voyez dans le document n'existe souvent pas en tant que chaîne contiguë dans le XML. merge_runs.py fusionne les runs adjacents de même format dans word/document.xml sans modifier le contenu ni le rendu ; il accepte également un .docx directement (python scripts/merge_runs.py doc.docx -o merged.docx).
Modifications suivies : lors du suivi des modifications, validez avec --author "<le nom sous lequel vous avez suivi>" (nécessite --original) — il signale tout texte que vous avez modifié sans <w:ins>/<w:del> l'entourant, ce qui est facile à faire accidentellement et invisible dans la vue acceptée. Encapsulez les runs dans <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 directement est cela plus un <w:del> autour de chaque run. Le <w:del/> doit venir avant les autres enfants de rPr ; leur ordre est imposé par le schéma.
Pour produire une copie propre avec toutes les modifications suivies acceptées : 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 tous 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 vidé derrière, 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 lorsque le paragraphe supprimé est suivi d'un paragraphe d'espacement 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 paragraphe dans le XML.
Commentaires
Les commentaires nécessitent six fichiers liés entre eux. Utilisez l'assistant — mode répertoire lorsque vous modifierez également document.xml (économise un cycle unzip/rezip), mode .docx direct sinon :
# Contre un répertoire déjà décompressé (préféré lorsque vous placez également 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
# Contre 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 remplacements de type de contenu. Les ID de commentaires sont attribués automatiquement. Il imprime 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é — installer seulement si require('docx') échoue) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)