Creación, edición y análisis de DOCX
Un .docx es un archivo ZIP de archivos XML. Elige tu enfoque según la tarea:
| Tarea | Enfoque |
|---|---|
| Crear un documento nuevo | Escribe un script docx (npm) — consulta las advertencias a continuación |
| Editar un documento existente | unzip → editar word/document.xml → zip (docx-js no puede abrir archivos existentes) |
| Leer contenido | pandoc -t markdown file.docx |
Las rutas de los scripts a continuación son relativas al directorio de esta habilidad.
Crear con docx-js — advertencias
docx está preinstalado — no ejecutes npm install primero; escribe el script y usa require('docx') directamente. Solo si ese require falla: npm install docx. El modelo conoce la API; estos son los errores comunes:
- El tamaño de página predeterminado es A4. Para Carta EE. UU., establece
page: { size: { width: 12240, height: 15840 } }(DXA; 1440 = 1″). - Apaisado: pasa las dimensiones en vertical y
orientation: PageOrientation.LANDSCAPE— docx-js intercambia ancho/alto internamente. - Las tablas necesitan anchos dobles: establece
columnWidthsen la tabla Ywidthen cada celda, ambos enWidthType.DXA(PORCENTAJE falla en Google Docs). Los anchos de columna deben sumar el ancho de la tabla. - Sombreado de tabla: usa
ShadingType.CLEAR, nuncaSOLID(se renderiza en negro). - Listas: nunca insertes
•literalmente; usa una configuración denumberingconLevelFormat.BULLET. ImageRunrequieretype:("png","jpg", …).PageBreakdebe estar dentro de unParagraph.- Nunca uses
\n— usa elementosParagraphseparados. - TOC: los encabezados deben usar
HeadingLevel.*incorporados; los estilos de encabezado personalizados necesitanoutlineLevelconfigurado o no aparecerán. - No uses una tabla como una regla horizontal — usa un borde inferior de párrafo en su lugar.
- Guiones de relleno / alineado a la derecha en la misma línea: usa
PositionalTab(alignment: PositionalTabAlignment.RIGHT,leader: PositionalTabLeader.DOT) dentro de unTextRun, no puntos literales ni relleno con espacios.
Verificar la salida
Después de escribir un .docx, conviértelo a PDF y visualízalo:
python scripts/office/soffice.py --headless --convert-to pdf output.docx
pdftoppm -jpeg -r 100 output.pdf page
ls page-*.jpg # luego lee las imágenes
pdftoppm rellena con ceros los números de página hasta el ancho del número total de páginas (page-01.jpg…page-12.jpg).
Editar documentos existentes
Los archivos .doc heredados deben convertirse primero: python scripts/office/soffice.py --headless --convert-to docx file.doc.
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete # eliminar entradas de enlaces simbólicos — los docx de terceros no son confiables
python scripts/merge_runs.py unpacked/ # fusionar fragmentos para que el texto sea localizable
# editar unpacked/word/document.xml in place — NO reformatear ni embellecer
(cd unpacked && rm -f ../out.docx && zip -Xr ../out.docx .)
python scripts/office/validate.py out.docx --original doc.docx # comprobaciones XSD; --auto-repair corrige problemas comunes
# ¿control de cambios? añade --author "<nombre bajo el que controlaste cambios>" para verificar que cada edición esté registrada
Word divide el texto en muchos fragmentos <w:r> (ids de revisión, marcas de revisión ortográfica), por lo que una frase que ves en el documento a menudo no existe como una cadena contigua en el XML. merge_runs.py fusiona fragmentos adyacentes con formato idéntico en word/document.xml sin cambiar el contenido ni el renderizado; también acepta un .docx directamente (python scripts/merge_runs.py doc.docx -o merged.docx).
Cambios controlados: al hacer «redlining» (control de cambios), valida con --author "<nombre bajo el que controlaste cambios>" (necesita --original) — reporta cualquier texto que hayas modificado sin un <w:ins>/<w:del> alrededor, algo fácil de hacer por accidente e invisible en la vista aceptada. Envuelve los fragmentos en <w:ins>/<w:del> con atributos w:id, w:author, w:date. Dentro de <w:del>, el elemento de texto es <w:delText>, no <w:t>. Una marca de párrafo eliminada (<w:pPr><w:rPr><w:del w:id=".." w:author=".." w:date=".."/></w:rPr></w:pPr>) significa "fusiona este párrafo con el siguiente", por lo que eliminar un párrafo por completo es eso más un <w:del> alrededor de cada fragmento. <w:del/> debe ir antes de los otros hijos de rPr; su orden está impuesto por el esquema.
Para producir una copia limpia con todos los cambios controlados aceptados: python scripts/accept_changes.py in.docx out.docx.
Aceptar una marca de párrafo eliminada debería unir ese párrafo con el de abajo, por lo que un párrafo cuyos fragmentos estén todos eliminados desaparece. Word hace esto; accept_changes.py y pandoc --track-changes=accept no siempre lo hacen. Ambos fallan de la misma manera: eliminan el texto eliminado pero dejan el párrafo vacío, que se lee como una viñeta vacía extraviada cuando estaba numerada automáticamente:
pandoc --track-changes=acceptnunca une los párrafos.accept_changes.py(LibreOffice) los une correctamente, excepto cuando el párrafo eliminado va seguido de un párrafo espaciador vacío.
Una viñeta vacía en cualquiera de las vistas es un artefacto de esa vista, no un defecto en el documento. Verifica las eliminaciones de párrafos en el XML.
Comentarios
Los comentarios requieren seis archivos vinculados entre sí. Usa el asistente — modo directorio cuando también vayas a editar document.xml (ahorra un ciclo de descompresión/recompresión), modo .docx directo en caso contrario:
# Contra un directorio ya descomprimido (preferido cuando también se colocan marcadores)
python scripts/comment.py unpacked/ "El límite de honorarios y gastos es demasiado bajo"
python scripts/comment.py unpacked/ "De acuerdo" --parent 0
# Contra un .docx directamente
python scripts/comment.py contract.docx "Este límite es demasiado bajo" -o annotated.docx
El script escribe comments.xml, commentsExtended.xml, commentsIds.xml, commentsExtensible.xml, las relaciones y las anulaciones de tipo de contenido. Los IDs de comentarios se asignan automáticamente. Luego imprime el fragmento <w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference> para agregar a word/document.xml y que el comentario se ancle a un texto específico — hasta que coloques esos marcadores, el comentario existe pero no es visible.
Dependencias
docx (npm, preinstalado — instalar solo si require('docx') falla) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)