mcpField
O
office-repair

office-repair

github.com/gasseraneドキュメント3120 回インストール1 週間前に更新
リポジトリ

office-repair について

office-repairは、Excelブックの修復や、手動編集されたOfficeファイルと生成元の整理を行うスキルです。既存機能の保持が必要なチーム向けに、読み取り専用の調査、保護付き編集、書き込み後の検証を行い、編集済みファイルを正本として生成器を退役させることもできます。

主な機能

  1. 01ブック構造とエラーの読み取り専用スキャン
  2. 02変更前の値を検証してセルを編集
  3. 03バックアップと修復後のブック検証
  4. 04生成ファイルと手動編集版の比較
  5. 05生成器のアーカイブと正本の保護

活用シーン

  1. 01スライサーや保護設定のあるブックの修復
  2. 02キャッシュ済みエラーや分断した入力規則の確認
  3. 03手動編集したOfficeファイルを正本に設定
  4. 04古い生成器による正本の上書きを防止

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gasserane/personal-skills --skill office-repair

インストール後、Claude Code で/office-repairを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
officeops-excel-api.md
scripts/
office_repair.py
test_office_repair.py

詳細

/office-repair — ブックをその場で修復する、または生成ファイルをAneに引き渡す

作業は1つです。Aneがすでに所有しているOfficeファイルに手を加える必要があり、ディスク上のバージョンが正となります。

Officeファイルの処理はすべて ane_package.officeops に集約されています。このスキルが担うのは判断であり、処理の仕組みではありません。あるモードでofficeopsにない機能が必要な場合は、officeopsに追加して、そこでテストしてください。office-review-pass はこのルールを適用した実例であり、Wave 3では独自の機能を増やすのではなく、この方法で5つの機能を追加しました。正確な呼び出しシグネチャは references/officeops-excel-api.md に記載されています。コードを書く前に読んでください。

このルールに議論の余地はありません。**Officeファイルを開く処理はすべてofficeopsに置きます。**文字列のリストを2つ比較すること、自動修正による置換を見つけて修正すること、.py ジェネレーターを書き換えることはOfficeファイルの処理ではないため、scripts/office_repair.py に置き、そこでテストします。

モードの振り分け

  • repair — Aneが管理しているExcelブックが壊れている、または変更が必要で、単純に書き込むと失われる機能が含まれています。
  • canonical — 生成されたアーティファクトが手作業で編集され、ジェネレーターが古い状態になっています。

修復したブックの背後にジェネレーターもある場合は、両方のモードを使います。先に repair を実行し、その後 canonical を実行してジェネレーターを廃止します。

共通ルール — 両方のモードに適用

  • Aneのファイルを基準にします。 対象ファイルが存在する場合は、mel_wiki/wiki/concepts/edit-preservation-protocol.md を適用してください。ディスク上の内容を読み、依頼された箇所だけを変更し、それ以外はバイト単位でそのまま残します。このスキルがあるのは、バイナリファイルではこのルールを守るのが最も難しく、損失が発生すると気づかれないまま元に戻せなくなるためです。
  • openpyxlで認識できない機能が含まれるOfficeファイルを、openpyxlで書き込まないでください。 スライサーはopenpyxlではまったく表現できません。読み込みと保存を行うと xl/slicers/ はただ消えます。ブックはそのまま開けるため、何も報告されません。このため、スキャンは安全のためだけでなく、読み取り専用で行います。
  • 書き込んだファイルを、書き込み前の状態と照合して検証します。 書き込み前に workbook_inventory を実行し、書き込み後に assert_inventory_unchanged を実行してください。保存処理が正常に戻っただけでは、何も証明されません。
  • 事実を捏造しないでください。 セルのアドレス、シート名、数値、数式を含みます。スキャン結果や読み込み済みのコンテキストにない場合は、質問してください。
  • EDIT-PRESERVATION DELIVERYの形式で報告してください。 変更した内容、変更せずに残した内容、対象外として確認したものの対応しなかった点を記載します。

修復モード

このブックには、スライサー、グラフ、保護、構造化参照、スピル数式が含まれています。最も手早く使えるツールでは、これらをすべて確認できないため、このモードは単一の呼び出しではなく、一連の手順になっています。

  1. まず読み取り専用で診断します。 python scripts/office_repair.py scan <workbook> 構造、ListObject のカバー範囲、各セルの数式とともにキャッシュされたエラーセル、断片化したデータ検証範囲、機能の一覧が報告されます。何も書き込まれず、実行中に Excel でブックを開いていてもかまいません。

    --com を追加すると、Excel に循環参照も確認させます。この処理には Excel が必要で、ファイルを読み取り専用で開きます。Ane が開いたときに警告ダイアログが表示される、または数値が入るはずの場所がゼロになっていると報告した場合は、必ず実行する価値があります。循環参照は計算時に Excel が構築する依存関係グラフに存在し、保存された XML には含まれないため、ファイルをどれだけ読み込んでも見つかりません。

  2. スキャン結果を正しく読み取ります。 良い知らせのように見えて、実際にはそうでない結果が2つあります。

    • Excel で一度も開かれていないブックに、キャッシュされたエラーがない場合。 ファイルには最後に計算した結果がキャッシュされるため、ライブラリで書き込まれたブックには何もキャッシュされていません。空欄は「キャッシュされたものがない」という意味で、「問題がない」という意味ではありません。
    • 断片化した検証範囲。 列に適用されたドロップダウンは、1つの範囲として設定されます。行を挿入すると1行ずつの範囲に分断され、ルールが適用される行と適用されない行が出てきます。ドロップダウンがない場合は空のセルとして表示されるため、エラーは発生しません。
  3. 書き込む前に、Ane と修正項目の一覧を確認します。 各セル、その現在の値、新しい値を明記してください。現在の値はスキャン結果で確認できます。現在の状態を読まずに変更内容を説明してはいけません。

  4. ペイロードを作成して適用します。 {sheet, cell, old, new} の JSON リストを書き、次を実行します。 python scripts/office_repair.py repair <workbook> --edits edits.json old は記録用ではなく、照合条件です。まず現在の数式を読み取り、一致しない場合は編集をスキップします。さらに、タイムスタンプ付きのバックアップ、セルごとの照合条件、シートの保護状態を取得して見つかったとおりに再適用すること、最後に一度だけ保存すること、そして保存前に例外を発生させることで部分的な修復が書き込まれないようにすること、という5つの安全策が含まれています。

  5. セルがスキップされた場合は、何もしなかったのではなく失敗です。 ペイロードが古いか、アドレスが間違っています。コマンドはゼロ以外の終了コードを返し、その旨を示します。一致した内容だけを書き込み、残りをそのままにする --no-strict を付けて再実行するのではなく、再スキャンしてください。--no-strict が役立つのは、意図的に2回目の処理を行う場合だけです。

  6. バックアップと照合して検証します。 python scripts/office_repair.py verify <workbook> --baseline <workbook>.backup-1.xlsx 変更前のブックの状態を正確に記録しているのはバックアップだけです。そのため、検証では記憶している件数ではなく、バックアップと比較します。

なぜ openpyxl ではなく COM なのか。 好みの問題ではありません。スライサー、シートの保護、ListObject のジオメトリには openpyxl の同等機能がなく、Excel で正しく機能しません。COM を使うと Excel の起動に約1分かかりますが、openpyxl で書き込むとブックが壊れることがあります。

COM 経由で日付を書き込む場合は、日付オブジェクトではなくシリアル値を代入します。 COM は datetime.date をそのまま受け付けず(TypeError: must be a pywintypes time object)、一見妥当な回避策である datetime の受け渡しは、気づかないままデータを破損させます。値が UTC 経由で変換されるため、UTC+2 のマシンでは 16.09.2026 00:00 が 15.09.2026 22:00 として保存され、dd.mm.yyyy セルには前日の日付が表示されます。エラーは発生せず、書き込みは成功と報告され、列の値も一見もっともらしく見えます。代わりに Excel の日付シリアル値を .Value2 に書き込み、その後セルの NumberFormat を復元してください。数値だけを代入すると日付形式が失われるためです。

EXCEL_EPOCH = datetime.date(1899, 12, 30)    # day 0 of the 1900 date system
fmt = ws.Cells(r, c).NumberFormat
ws.Cells(r, c).Value2 = (the_date - EXCEL_EPOCH).days
ws.Cells(r, c).NumberFormat = fmt

シリアル値にはタイムゾーンがないため、書き込んだ値がそのまま保存されます。書き込みがエラーなく完了したかどうかではなく、保存したファイルを開き直して日付を比較して検証してください。 COM セッション内では日付のずれが見えず、保存して開き直した場合にのみ確認できます(実際の採点用ブックで2026-09-23に確認され、すべての完了日が1日前になっていました)。

COM を使った Excel のテーブルとレイアウト — 注意点

完成済みの結果ブックで範囲をテーブルに変換した際に遭遇した6つの落とし穴です(2026-10-23、証拠は agent-improvements/handoffs/2025-en-results-excel-tables-spec.md の13:53および14:40の更新にあります)。どれもエラーなく処理されました。修正はいずれも1行です。

  1. ListObjects.Add は列幅を自動調整し、ヘッダーの折り返しをオフにします。 修正:呼び出し前に各列の幅を記録し、呼び出し後に復元して、ヘッダー行の WrapText = True を再設定します。
  2. 1文字だけに対するフォントサイズの設定は反映されません。 1文字にサイズを設定しても、読み戻すと11 ptでした。修正:cell.GetCharacters(start, length).Font.Size = 10 を使って、文字列全体の各ランにサイズを設定します。
  3. Font.Size が None を返しても、サイズが混在しているとは限りません。 セル内のランに何らかの違いがあると、セルは None を返しますが、各ランがすべて9 ptの場合もあります。修正:セルからではなく、GetCharacters を使ってランごとにサイズを読み取ります。
  4. AutoFit は結合セルを無視します。 結合されて折り返された元の行は、行の高さが以前のままになります。修正:テキストを、結合セルと同じ幅に設定した予備のヘルパー列にコピーし、その行に AutoFit を適用して高さを取得した後、ヘルパー列をクリアします。
  5. 降順のテーブルの並べ替えでは、テキストがあらゆる数値より上に並びます。 テキストとして保存された数値や、17 of 58 のようなテキスト値が先頭に来ます。修正:範囲をテーブルに変換する前に、数値を実際の数値に変換します(単語はラベルまたは注記に移します)。
  6. 失敗しない検証では、何も証明できません。 修正:PASS を信頼する前に、変更していないファイルに対して各検証スクリプトを1回実行し、FAIL になることを確認します。

canonical mode

Ane は Word、PowerPoint、または Excel で生成済みファイルを編集しました。今後は、そのファイルが正本であり、ジェネレーター側のファイルは古いコピーです。ここでの作業は、会話の中だけでなく、ファイルシステム上でもそれを正しい状態にすることです。

  1. 抽出して比較します。 python scripts/office_repair.py diff <edited> --against <generated> 抽出処理はグループ化された図形や表のセルも再帰的に調べます。これは見た目以上に重要です。.pptx をフラットに処理すると、python-pptx はグループをテキストのない単一の図形として報告し、箇条書きはその子要素にあるため、すべてのスライドタイトルだけが返され、箇条書きは一つも取得できません。見出しだけのデッキが返ってくる場合、問題はデッキではなく抽出処理にあります。

  2. Ane の編集と Word による変更を切り分けます。 このコマンドは、Ane ではなく Office が行ったと思われる変更を4種類検出します。黙って削除された発音区別符号、スマート引用符やダッシュへの自動修正、URL の途中に入ったスペース、誤入力のように見える、ほぼ同じ意味の言い換えです。いずれも断定ではないため、一つずつ本人に確認します。確認する理由は、この非対称性にあります。自動修正による変更を正本に反映すると、それが恒久的になり、気づけなくなります。一方、意図した編集かどうかを尋ねるだけなら、返信は一行で済みます。

    また、編集済みファイルのテキストブロック数が生成済みファイルの半分未満の場合、構造上の問題として検出します。これは、本文レイヤーが削除され、タイトルだけが残ったデザイン変更を示す、2026-07-22 時点の特徴です。

  3. 変更内容を変更リストとして報告します。 ブロックのインデックスがどう変わったかではなく、文書に現在何が書かれているかを、本人の言葉に沿って分類します。検出された痕跡は、一つずつ確認します。

  4. .md ミラーがある場合は同期し、Office ファイルを正本として指定する注記と日付を追加します。ミラーがない場合は、新たに作成しません。

  5. ジェネレーターを退役させます。 python scripts/office_repair.py archive <generator>.py --canonical <edited file> これにより、--force を指定しないと実行を拒否するガードが先頭に追加されます。また、--force を指定して実行し、正本ファイルに変更が加えられた場合は、正本ファイルをバイト単位で元どおりに復元します。コメントではなくコードにするのは、コメントでは誰も止められないうえ、ここで防ぐべきなのは、今後のセッションで善意から python gen_x.py が実行されてしまうことだからです。この処理を2回実行しても、変更はありません。

Ane の編集をジェネレーターに反映してはいけません。 それは一見もっともらしい方法ですが、間違いです。ジェネレーターはテキストを再現できても、Ane が Word で行った書式レベルの変更は再現できません。そのため、変更を反映すると、最新に見えるスクリプトができあがる一方で、実行時には知らないうちに、より悪いファイルが再生成されます。代わりにアーカイブしてください。別の文書でも今後生成されるため、本当にジェネレーター側で変更すべき内容がある場合は、その旨を伝え、別の作業として対応します。

検証計画

各モードは、処理を始める前に検証項目を明示し、書き込んだファイルを再度開いて検証します。

モード検証内容
scan読み取り専用で、何も書き込みません。機能の一覧と検出数を報告します。
repair各セルでの置換結果を Excel から読み戻し、assert_inventory_unchanged で修復前の機能一覧と照合したうえで、バックアップに対して verify --baseline を実行します。表がそれぞれの行を網羅していること、キャッシュされたエラーがないこと、機能が失われていないことを確認します。
diff読み取り専用です。両方のブロック数と、Ane が意図的だと確認したものも含め、検出された痕跡をすべて明示的に報告します。
archiveアーカイブしたジェネレーターを実行します。終了コードは0以外で、正本ファイルはバイト単位で完全に同一のままでなければなりません。ガードのソーステキストを確認するのは誤りです。docstring にしか存在しない拒否処理こそ、このモードで防ぐべき失敗だからです。

python scripts/test_office_repair.py は変更内容の一覧、痕跡のヒューリスティクス、サブプロセスとしてジェネレーターのガードが実際に実行を拒否することを確認し、ドライバー自体をテストします。Office の動作は、作業フォルダーにある tests/test_officeops.py で検証します。

対象範囲

  • コメント、変更履歴、用語集、出典付録を確認する Word のレビューサイクルは office-review-pass が担当します。このスキルは Excel の修復と、正式な引き継ぎを担当します。
  • 新しいブランドファイルの作成は ane_package.reporting、ToR の作成は tor-procurement、文章に対する読み取り専用の QA 判定は check-deliverable が担当します。
  • どちらの COM パスも Windows、Excel のインストール、PowerShell 5.1 が必要です。Excel のパスで null メソッドの処理が破綻するため、pwsh 7 は使用しないでください。この Python には win32com がインストールされておらず、この方法も使用しません。
  • PackageNotFoundError は Excel でファイルが開かれたままであることを意味し、ファイルの破損ではありません。Ane にワークブックが破損していると伝える前に、zipfile で確認してください。
  • Web コンテナーでは diff と archive のパスは引き続き機能しますが、scan --com と repair は機能しません。

コメント