Claude docxスキルの使い方 — Word文書の作成・編集・変更履歴
docxスキルの作成・編集・読み取りの使い分けと、変更履歴・コメント・検証スクリプトの手順、docx-jsで踏みやすい落とし穴を、SKILL.mdに沿って示します。
docxスキルは、Wordの.docxと.dotxを作る・直す・読むための手順書です。中心はSKILL.md1枚で、作成にはnpmのdocxライブラリ、編集にはXMLの直接編集、読み取りにはpandocを使い分けます。変更履歴を残した編集と、コメントを付ける作業には専用のPythonスクリプトが用意されています。
この記事では、SKILL.mdが定める分岐と、各工程で手が止まりやすい箇所を順にたどります。
作業の種類で手段が3つに分かれる
.docxの実体はXMLファイルを束ねたZIPです。SKILL.mdはこの前提から、作業ごとに別々の手段を割り当てています。
| 作業 | 手段 |
|---|---|
| 新規作成 | 手段docx(npm)のスクリプトを書く |
| 既存ファイルの編集 | 手段unzipしてword/document.xmlを直し、zipし直す |
| 内容の読み取り | 手段pandoc -t markdown file.docx |
既存文書の編集でdocx-jsを使えない点が、最初の分かれ目です。SKILL.mdは「docx-jsは既存ファイルを開けない」と明記しています。「元の文書を少し直して」という依頼は、作成ではなくXML編集の経路に入ります。
Claudeに頼むときも、依頼文で経路が決まります。
- 「議事録のWord版を新しく作って」は新規作成なので、docx-jsのスクリプトが書かれる
- 「添付の契約書の第3条を直して」は編集なので、展開してXMLを直す
- 「この報告書の要点を教えて」は読み取りなので、pandocでテキスト化する
使える場所とインストール
docxスキルはAnthropicのリポジトリanthropics/skillsのskills/docxにあります。リポジトリのREADMEは、docx・pdf・pptx・xlsxの4つを「Claudeの文書機能を裏で支えるスキル」と説明し、オープンソースではなくソース公開(source-available)だと断っています。複雑なスキルの参考実装として公開されている位置づけです。
利用経路は3つあります。
- Claude API:
containerにskill_idとしてdocxを指定する。呼び出しの骨格はAPI標準スキル一覧とAPIクイックスタートにある - claude.ai: 文書作成機能の内部で使われる
- Claude Code: リポジトリをプラグインのマーケットプレイスとして登録して入れる
Claude Codeには、PowerPoint・Excel・Word・PDFの既製スキルが標準では含まれていません。プラグイン経由なら入れられます。READMEの手順は次のとおりです。
/plugin marketplace add anthropics/skills
/plugin install document-skills@anthropic-agent-skillsdocument-skillsプラグインには、docxのほかpdf・pptx・xlsxが入ります。入れた後は、スキル名を依頼文に書くだけで呼び出せます。READMEの例は「PDFスキルでフォーム項目を取り出して」という言い方です。
新規作成: docx-jsの落とし穴
SKILL.mdは、docx-jsのAPIそのものは説明しません。Claudeが知っている前提で、「踏むと壊れる」箇所だけを列挙しています。
docx-jsで壊れやすい設定
用紙サイズはA4が既定
US Letterにするなら、
width: 12240・height: 15840をDXA単位(1440で1インチ)で渡します。横向きは縦向きの寸法のままorientation: PageOrientation.LANDSCAPEを指定します。幅と高さの入れ替えはdocx-jsが内部でやります。表の幅は二重に指定
表に
columnWidths、全セルにwidthを、どちらもWidthType.DXAで書きます。PERCENTAGEはGoogleドキュメントで崩れます。列幅の合計は表の幅と一致させます。網掛けはCLEARを使う
ShadingType.SOLIDだと黒く塗りつぶされます。ShadingType.CLEARにfill色を添えます。箇条書きは番号設定から作る
「•」を本文に直接書かず、
numbering設定のLevelFormat.BULLETを使います。
ほかにも、次の決まりがあります。
ImageRunにはtype:("png"や"jpg")が必須PageBreakはParagraphの中に置く- 改行に
\nを使わず、Paragraphを分ける - 目次に載せたい見出しは組み込みの
HeadingLevel.*で作る。独自の見出しスタイルはoutlineLevelが要る - 水平線を表で作らず、段落の下罫線にする
- 右端揃えやリーダー点線は、空白や
.を並べずPositionalTabを使う
これらを踏まえた最小のスクリプトを示します。SKILL.mdの規則をひとまとめに適用した形の例で、スキルが出力する固定のコードではありません。
const fs = require('fs');
const {
Document, Packer, Paragraph, TextRun, HeadingLevel, AlignmentType,
Table, TableRow, TableCell, WidthType, ShadingType, LevelFormat,
} = require('docx');
const widths = [3000, 6360]; // 合計 9360 = 12240 - 左右余白 1440 x 2
const cell = (text, w, fill) => new TableCell({
width: { size: w, type: WidthType.DXA },
shading: fill ? { type: ShadingType.CLEAR, fill } : undefined,
children: [new Paragraph({ children: [new TextRun(text)] })],
});
const doc = new Document({
numbering: { config: [{
reference: 'bullets',
levels: [{ level: 0, format: LevelFormat.BULLET, text: '•',
alignment: AlignmentType.LEFT }],
}] },
sections: [{
properties: { page: {
size: { width: 12240, height: 15840 },
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 },
} },
children: [
new Paragraph({ heading: HeadingLevel.HEADING_1,
children: [new TextRun('議事録')] }),
new Paragraph({ numbering: { reference: 'bullets', level: 0 },
children: [new TextRun('決定事項を先頭に置く')] }),
new Table({
width: { size: 9360, type: WidthType.DXA },
columnWidths: widths,
rows: [new TableRow({ children: [
cell('項目', widths[0], 'D9E2F3'), cell('内容', widths[1], 'D9E2F3'),
] })],
}),
],
}],
});
Packer.toBuffer(doc).then((buf) => fs.writeFileSync('minutes.docx', buf));出力を目で確かめる
SKILL.mdは、書き出した.docxを必ず描画して見るよう求めています。LibreOfficeでPDFにし、pdftoppmで画像に変えてから読み込ませる流れです。
python scripts/office/soffice.py --headless --convert-to pdf output.docx
pdftoppm -jpeg -r 100 output.pdf page
ls page-*.jpgpdftoppmのファイル名は、ページ数の桁に合わせてゼロ埋めされます。12ページならpage-01.jpgからpage-12.jpgです。lsで実際の名前を確かめてから読み込む理由はここにあります。
soffice.pyは、通常のsoffice呼び出しの代わりに使うラッパーです。UNIXソケットが塞がれたサンドボックスでも動くよう、必要なときだけ回避用の仕掛けを差し込みます。スクリプトの注記は、自前のsubprocessでsofficeを起動するとユーザープロファイルを作れずに失敗することがあるとも書いています。
既存文書を編集する手順
既存の.docxには、展開・マージ・編集・再圧縮・検証の順で進みます。旧形式の.docは、先にsoffice.py --convert-to docxで変換します。
既存の.docxを直す流れ
- 1
展開してシンボリックリンクを消す
unzipした後、find unpacked -type l -deleteでシンボリックリンクを削除します。外部から届いた.docxは信頼できない入力として扱う、という注記が付いています。 - 2
分断された文字列をつなぐ
python scripts/merge_runs.py unpacked/を実行します。 - 3
document.xmlを直接編集する
整形し直さず、そのまま書き換えます。
- 4
zipし直して検証する
zip -Xrで戻し、validate.pyでXSD検査を通します。
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete
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なぜmerge_runsが要るのか
Wordは1つの文を、書式の違いがなくても複数の<w:r>(ラン)に切り分けて保存します。リビジョンIDや校正マーカーが理由です。画面で見えている語句が、XMLでは連続した文字列として存在しない場合があります。
merge_runs.pyは、隣り合って書式が同じランを1つにまとめます。rsid属性とproofErrマーカーも取り除きます。描画結果は変わりません。
仕様の細部が3つあります。
- 対象は
word/document.xmlだけで、ヘッダー・フッター・脚注は処理しません - 別々の
<w:ins>や<w:del>に入ったランは、リビジョンが1つに潰れるので結合されません - 空白の扱いは見た目基準です。
xml:space="preserve"のない<w:t>Hello </w:t>は端の空白が落ちて描画されるため、次のランと結合するとHelloworldになります
.docxを直接渡すこともできます。python scripts/merge_runs.py doc.docx -o merged.docxです。
validate.pyの検査
validate.pyは、展開済みのディレクトリでも、梱包済みの.docx・.dotxでも受け取ります。--originalで元ファイルを渡すと、変更履歴の整合まで調べます。省くと、XSDエラーがすべて出力され、変更履歴の検査は飛ばされます。
--auto-repairは、上限を超えたparaId・durableIdと、空白を含む<w:t>で抜けたxml:space="preserve"を直します。入力ファイルを直接書き換えるので、元を残したいときはコピーに対して実行します。
変更履歴を残して直す
契約書や社内文書の修正では、直した箇所を追跡変更として残したい場面が多くあります。SKILL.mdは、追跡変更のXMLを手で書く前提で、守るべき構造を4つ挙げています。
- 挿入と削除は
<w:ins>・<w:del>で包み、w:id・w:author・w:dateを付ける <w:del>の中の本文要素は<w:t>ではなく<w:delText>にする- 段落記号の削除は
<w:pPr><w:rPr><w:del .../></w:rPr></w:pPr>で書く。「この段落を次の段落に結合する」という意味になる - 段落を丸ごと消すには、段落記号の削除に加え、すべてのランを
<w:del>で包む
四つ目の<w:del/>は、rPrの中で他の子要素より前に置きます。順序はスキーマで決まっているため、前後を入れ替えるとバリデーションが落ちます。
変更履歴に載せ忘れた編集を見つける
追跡変更の事故で多いのは、<w:ins>・<w:del>で包み忘れた書き換えです。承認後の見た目では差が出ないので、目では気づけません。
validate.pyの--authorはこの検出用です。
python scripts/office/validate.py out.docx --original doc.docx \
--author "Claude"--authorに指定する名前は、変更履歴に書いた作成者名と同じにします。ただし、ヘルプの説明によれば、この名前は検索の絞り込みには使われません。「この実行は変更履歴の作業である」という目印として働き、元ファイルと本文が違うのに<w:ins>・<w:del>の記録がない箇所を、誰が直したかにかかわらず報告します。--originalが必須で、docx専用です。
変更を全部承認したきれいなコピーを作る
python scripts/accept_changes.py in.docx out.docxaccept_changes.pyはLibreOfficeのマクロでAcceptAllTrackedChangesを実行します。LibreOfficeが入っていることが条件です。
空の箇条書きが残る件
削除された段落記号を承認すると、その段落は下の段落に結合され、全ランが削除済みの段落は消えるはずです。Wordはそのとおりに動きます。
accept_changes.pyとpandoc --track-changes=acceptは、動きが少し違います。
| ツール | 削除段落の扱い |
|---|---|
pandoc --track-changes=accept | 削除段落の扱い段落を結合せず、空の段落が残る |
accept_changes.py | 削除段落の扱い結合する。ただし削除段落の直後に空の段落があると、結合されない |
自動番号の付いた段落だと、残った空段落が「中身のない箇条書き」に見えます。SKILL.mdはこれを、その表示経路の副産物であって文書の欠陥ではないと整理し、段落削除の確認はXMLで行うよう指示しています。
コメントを付ける
Wordのコメントは、comments.xml・commentsExtended.xml・commentsIds.xml・commentsExtensible.xmlの4ファイルに加え、リレーション定義とコンテンツタイプの登録が連動して成り立ちます。手で作ると漏れが出るため、comment.pyが担当します。
# 展開済みディレクトリに対して(document.xmlも編集するならこちら)
python scripts/comment.py unpacked/ "手数料の上限が低すぎます"
python scripts/comment.py unpacked/ "同意します" --parent 0
# .docxを直接渡す
python scripts/comment.py contract.docx "上限が低すぎます" -o annotated.docx動作の要点は次のとおりです。
- コメントIDは「既存の最大値+1」で自動採番される。
--idで明示もできる - 本文は自動でXMLエスケープされる。
&のようにエスケープ済みの文字列を渡すときは--rawを付ける - 作成者は既定で
Claude、頭文字はC。--authorと--initialsで変えられる --parentに親コメントのIDを渡すと返信になる
実行すると、document.xmlに足すべき<w:commentRangeStart>・<w:commentRangeEnd>・<w:commentReference>のひな形が表示されます。このマーカーを本文の対象箇所に挿入するまで、コメントは存在していても画面に出ません。「コメントを付けたのに見えない」場合は、まずここを疑います。
つまずきの切り分け
出力がおかしいときの確認順
- Q表が崩れる、または黒塗りになる?答えがいいえのとき答えがはい
columnWidthsと各セルのwidthがDXAで揃っているか、網掛けがShadingType.CLEARかを見ます。 - Q既存文書で置換したい語句が見つからない?答えがいいえのとき答えがはい
merge_runs.pyを通します。語句が複数のランに分かれているのが典型です。 - Qコメントが画面に出ない?答えがいいえのとき答えがはい
document.xmlにコメント範囲のマーカーを入れたかを確認します。 - Q承認後に空の箇条書きが残る?答えがいいえのとき答えがはい
XMLで段落削除の指定を確認します。ツール側の表示の癖の可能性があります。
それでも崩れるとき
validate.pyの出力を読み、元ファイルとの差分で未追跡の編集がないかを調べます。
使えない場面と画像・テンプレートの扱い
SKILL.mdの冒頭は、このスキルを使わない対象を明示しています。PDF、スプレッドシート、Googleドキュメント、文書生成と無関係な一般のコーディングです。PDFはpdfスキル、表計算はxlsxスキルの領分です。
起動条件の説明文には、.dotx(Wordのテンプレート)、画像の挿入と差し替え、検索置換、目次・見出し・ページ番号・レターヘッドを備えた書式付き文書も含まれます。comment.pyとvalidate.pyは.dotxを受け付けます。
一方、SKILL.mdの本文には、画像の差し替えだけを扱う節がありません。画像を足す場面で本文が触れているのは、ImageRunにtype:を渡す点だけです。既存の画像を差し替える依頼は、展開したword/media/とdocument.xmlの参照を直す、XML編集の延長で行うことになります。
Wordの画面上で契約書を点検したい場合は、アドインのClaude for Wordの使い方が別の経路です。Markdownからの変換だけで足りるなら、Claude CodeでPandocを使う手順のほうが軽く済みます。
まとめ
docxスキルを呼び出す前に決めておくと詰まりにくいのは、依頼が「作る」「直す」「読む」のどれかです。作るならdocx-jsの落とし穴、直すならmerge_runs.pyとvalidate.py、変更履歴を残すなら--author付きの検証、コメントなら範囲マーカーの挿入が、それぞれ最初に確かめる場所になります。変更履歴つきの文書を人に渡す前には、--authorの検査を通しておくと、記録されていない書き換えを見逃しません。