DOCXの作成、編集、解析
.docxファイルはXMLファイルをZIP圧縮したものです。タスクに応じたアプローチを選んでください:
| タスク | アプローチ |
|---|---|
| 新規作成 | docx(npm)のスクリプトを作成 — 下記の注意点を参照 |
| 既存文書の編集 | unzip → word/document.xmlを編集 → zip(docx-jsは既存ファイルを開けません) |
| 内容の読み取り | pandoc -t markdown file.docx |
以下のスクリプトパスはこのスキルのディレクトリからの相対パスです。
docx-jsで作成する際の注意点
docxはプリインストールされています — npm installを実行せず、直接スクリプトを書いてrequire('docx')してください。もしrequireが失敗した場合のみnpm install docxを実行します。モデルはAPIを熟知していますが、以下の落とし穴に注意:
- 用紙サイズはデフォルトでA4です。 USレターの場合は
page: { size: { width: 12240, height: 15840 } }と設定します(DXA単位で1440=1インチ)。 - 横向き: 縦置きの寸法を指定し、
orientation: PageOrientation.LANDSCAPEを設定 — docx-jsが内部で幅と高さを入れ替えます。 - 表は二重の幅設定が必要: 表自体に
columnWidthsを、さらにすべてのセルにwidthを、両方ともWidthType.DXAで設定します(PERCENTAGEはGoogle Docsで壊れます)。列幅の合計が表の幅と一致する必要があります。 - 表の網掛け:
ShadingType.CLEARを使用し、SOLIDは絶対に使わないでください(黒く表示されます)。 - リスト:
•を直接挿入せず、LevelFormat.BULLETを指定したnumbering設定を使用します。 ImageRunにはtype:が必要("png"、"jpg"など)。PageBreakはParagraphの内部に置く必要があります。\nは絶対に使わない — 代わりに別々のParagraph要素を使用します。- 目次(TOC): 見出しは組み込みの
HeadingLevel.*を使用する必要があります。カスタム見出しスタイルはoutlineLevelが設定されていないと目次に表示されません。 - 表を水平線の代わりに使わない — 代わりに段落の下部境界線を使用します。
- ドットリーダー/同一行右揃え:
TextRun内でPositionalTab(alignment: PositionalTabAlignment.RIGHT、leader: PositionalTabLeader.DOT)を使用し、リテラルの.やスペースパディングは使わないでください。
出力の確認
.docxを書き込んだら、レンダリングして確認します:
python scripts/office/soffice.py --headless --convert-to pdf output.docx
pdftoppm -jpeg -r 100 output.pdf page
ls page-*.jpg # その後画像を読み取る
pdftoppmはページ番号をページ数の桁数でゼロ埋めします(page-01.jpg…page-12.jpg)。
既存文書の編集
古い.docファイルは最初に変換する必要があります:python scripts/office/soffice.py --headless --convert-to docx file.doc
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete # シンボリックリンクエントリを削除 — 外部からのdocxは信頼できない
python scripts/merge_runs.py unpacked/ # 断片化したランを結合してテキストを検索可能にする
# unpacked/word/document.xmlをその場で編集 — フォーマットやプリティプリントはしない
(cd unpacked && rm -f ../out.docx && zip -Xr ../out.docx .)
python scripts/office/validate.py out.docx --original doc.docx # XSDチェック; --auto-repairで一般的な問題を修正
# 変更履歴(redlining)? --author "<変更履歴を付けた名前>" を追加して、すべての編集が追跡されているか確認
Wordはテキストを多数の<w:r>ラン(リビジョンID、スペルチェックマーカー)に分割するため、文書上で見えるフレーズがXML上で連続した文字列として存在しないことがよくあります。merge_runs.pyは、word/document.xml内で隣接する同一フォーマットのランを、内容やレンダリングを変更せずに結合します。また、.docxを直接受け取ることもできます(python scripts/merge_runs.py doc.docx -o merged.docx)。
変更履歴(Tracked changes): redlining時には、--author "<変更履歴を付けた名前>"(--originalが必要)を指定して検証します — これにより、誤って変更履歴なしで変更したテキスト(承認ビューでは見えない)を報告します。ランを<w:ins>/<w:del>でラップし、w:id、w:author、w:date属性を付けます。<w:del>内では、テキスト要素は<w:delText>であり、<w:t>ではありません。削除された段落記号(<w:pPr><w:rPr><w:del w:id=".." w:author=".." w:date=".."/></w:rPr></w:pPr>)は「この段落を次の段落に結合する」ことを意味します。したがって、段落を完全に削除するには、これに加えてすべてのランを<w:del>で囲みます。<w:del/>はrPrの他の子要素よりも前に来る必要があります。その順序はスキーマで強制されています。
すべての変更履歴を承認したクリーンなコピーを作成するには:python scripts/accept_changes.py in.docx out.docx
削除された段落記号を承認すると、その段落が次の段落に結合されるはずです。そのため、すべてのランが削除された段落は消えることになります。Wordはこれを行いますが、accept_changes.pyおよびpandoc --track-changes=acceptは常にそうとは限りません。両方とも同じように失敗します — 削除されたテキストは取り除かれますが、空になった段落は残り、自動番号が付いている場合は余分な空の箇条書きとして表示されます。
pandoc --track-changes=acceptは段落を結合しません。accept_changes.py(LibreOffice)は、削除された段落の後に空のスペーサー段落が続く場合を除き、正しく結合します。
どちらのビューでも空の箇条書きはそのビューのアーティファクトであり、文書自体の欠陥ではありません。段落の削除はXMLで確認してください。
コメント
コメントには6つの相互リンクされたファイルが必要です。ヘルパーを使用 — document.xmlも編集する場合はディレクトリモード(unzip/rezipサイクルを節約)、それ以外の場合は.docx直接モードを使用します:
# 既に展開されたディレクトリに対して(マーカーも配置する場合に推奨)
python scripts/comment.py unpacked/ "手数料・経費の上限が低すぎる"
python scripts/comment.py unpacked/ "同意" --parent 0
# .docxに直接
python scripts/comment.py contract.docx "この上限は低すぎる" -o annotated.docx
スクリプトはcomments.xml、commentsExtended.xml、commentsIds.xml、commentsExtensible.xml、関連付け、およびコンテンツタイプのオーバーライドを書き込みます。コメントIDは自動的に割り当てられます。その後、word/document.xmlに追加する<w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference>スニペットを出力します。これによりコメントが特定のテキストにアンカーされます。これらのマーカーを配置しない限り、コメントは存在しますが表示されません。
依存関係
docx(npm、プリインストール済み — require('docx')が失敗した場合のみインストール) · pandoc · LibreOffice(soffice) · pdftoppm(Poppler)