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 Letter,請設定
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元素。 - **目錄:**標題必須使用內建的
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 可修復常見問題
# 修訂標記?加上 --author "<您的名稱>" 以檢查每項編輯是否都已追蹤
Word 會將文字分割到多個 <w:r> 區塊中(因修訂 ID、拼字檢查標記等),因此你在文件中看到的片語,在 XML 中往往不是連續的字串。merge_runs.py 會合併 word/document.xml 中相鄰且格式相同的區塊,而不會改變內容或顯示效果;它也能直接接受 .docx 檔案(python scripts/merge_runs.py doc.docx -o merged.docx)。
**追蹤修訂:**當使用修訂標記時,請使用 --author "<您的名稱>"(需搭配 --original)進行驗證 — 它會報告任何您修改但未以 <w:ins>/<w:del> 包裹的文字,這種情況很容易不小心發生,且在已接受檢視中看不到。請使用包含 w:id、w:author、w:date 屬性的 <w:ins>/<w:del> 來包裹區塊。在 <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 中檢查段落刪除。
註解
註解需要六個相互關聯的檔案。使用輔助腳本 — 若您同時要編輯 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 會自動指派。接著它會輸出 <w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference> 程式碼片段,供您加入 word/document.xml,以便將註解錨定到特定文字 — 在放置這些標記之前,註解雖已存在但不可見。
相依項目
docx (npm,已預先安裝 — 僅在 require('docx') 失敗時才安裝) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)