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 |
| 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 fichier.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 require('docx') directement. Ce n'est qu'en cas d'échec de cette instruction : npm install docx. Le modèle connaît l'API ; voici les pièges à éviter :
- Le format 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 la largeur/hauteur en interne. - Les tableaux nécessitent deux largeurs : définissez
columnWidthssur le tableau ETwidthsur chaque cellule, les deux enWidthType.DXA(POURCENTAGE ne fonctionne pas dans Google Docs). Les largeurs de colonnes doivent totaliser la largeur du tableau. - Ombrer un 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. - TDM : les titres doivent utiliser les
HeadingLevel.*intégrés ; les styles de titre personnalisés nécessitentoutlineLeveldéfini, sinon 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) dans unTextRun, pas de.littéral ou d'espacement.
Vérifier la sortie
Après avoir écrit un fichier .docx, rendez-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 Lisez les images
pdftoppm ajoute des zéros non significatifs aux numéros de page pour correspondre à 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 fichier.doc.
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete # supprimer les entrées de liens symboliques — les docx de sources externes ne sont pas fiables
python scripts/merge_runs.py unpacked/ # fusionner les fragments de texte pour que le texte soit trouvable
# modifier 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
# marquage ? ajoutez --author "<le nom sous lequel vous avez marqué>" pour vérifier que chaque modification est suivie
Word fragmente le texte entre de nombreuses balises <w:r> (identifiants de révision, marqueurs de correction 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 fragments adjacents de même formatage dans word/document.xml sans modifier le contenu ni le rendu ; il accepte également un fichier .docx directement (python scripts/merge_runs.py doc.docx -o merged.docx).
Modifications suivies : lors du marquage, validez avec --author "<le nom sous lequel vous avez marqué>" (nécessite --original) — il signale tout texte modifié sans balise <w:ins>/<w:del> autour, ce qui est facile à faire par accident et invisible dans la vue acceptée. Encadrez les fragments 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" — supprimer carrément un paragraphe revient donc à cela plus un <w:del> autour de chaque fragment. <w:del/> doit précéder 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 fusionner ce paragraphe avec celui du dessous, de sorte qu'un paragraphe dont tous les fragments sont supprimés disparaisse. 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 fusionne jamais les paragraphes.accept_changes.py(LibreOffice) les fusionne correctement, sauf lorsque 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 paragraphe dans le XML.
Commentaires
Les commentaires nécessitent six fichiers liés entre eux. Utilisez l'assistant — mode répertoire lorsque vous allez également modifier document.xml (économise un cycle décompression/recompression), mode .docx direct sinon :
# Contre un répertoire déjà décompressé (préféré si vous placez aussi des marqueurs)
python scripts/comment.py unpacked/ "Le plafond des frais est trop bas"
python scripts/comment.py unpacked/ "D'accord" --parent 0
# Contre un .docx directement
python scripts/comment.py contrat.docx "Ce plafond est trop bas" -o annote.docx
Le script écrit comments.xml, commentsExtended.xml, commentsIds.xml, commentsExtensible.xml, les relations et les substitutions de type de contenu. Les ID de commentaires sont attribués automatiquement. Il imprime ensuite l'extrait <w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference> à ajouter à word/document.xml pour que le commentaire s'ancre à un texte spécifique — jusqu'à ce que vous placiez ces marqueurs, le commentaire existe mais n'est pas visible.
Dépendances
docx (npm, préinstallé — n'installer que si require('docx') échoue) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)