Excel Structured Extraction Engine
[](https://pypi.org/project/exstruct/) [](https://pepy.tech/projects/exstruct)  [](https://github.com/harumiWeb/exstruct/actions/workflows/pytest.yml) [](https://app.codacy.com/gh/harumiWeb/exstruct/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [](https://codecov.io/gh/harumiWeb/exstruct) [](https://deepwiki.com/harumiWeb/exstruct)  [](https://github.com/sponsors/harumiWeb)
# ExStruct — Excel 構造化抽出エンジン
ExStruct は Excel ワークブックを構造化データへ抽出し、shared core を通じて
patch-based な編集フローも扱えます。抽出 API、JSON-first editing CLI、
host-managed integration 向けの MCP サーバーを提供し、LLM/RAG 向け前処理、
レビューしやすい編集フロー、ローカル自動化に使える設計になっています。
- COM/Excel 環境 ではリッチ抽出
- 非 COM 環境 では
- OOXML を直接解析してセル・図形・グラフ・テーブル候補・印刷範囲を抽出 (best-effort)
- LibreOffice runtime があればセル・テーブル候補・図形・グラフ(best-effort)
LLM/RAG 向けに検出ヒューリスティックや出力モードを調整でき、編集ワーク
フローも同じ責務分離で扱えます。
## 主な特徴
- **Excel → 構造化 JSON**
- セル、図形、チャート、SmartArt、テーブル候補、セル結合範囲、印刷範囲/自動改ページ範囲をシート単位・範囲単位で出力。
- **出力モード**
- `light`: `.xlsx` / `.xlsm` のセル・テーブル候補・印刷範囲・図形/グラフをOOXML直接解析で抽出(rich artifactはbest-effort)
- `libreoffice`: `.xlsx/.xlsm` 向けの best-effort 非 COM モード。LibreOffice runtime があれば結合セル・図形・コネクタ・チャートを追加
- `standard`: Excel COM でテキスト付き図形+矢印、チャート、SmartArt、セル結合範囲
- `verbose`: 全図形を幅高さ付きで出力、セルのハイパーリンクも出力。
- **数式取得**
- `formulas_map`(数式文字列 → セル座標)を OOXML または選択された openpyxl/COM 経路で取得。`verbose` 既定、`include_formulas_map` で制御。
- **フォーマット**
- JSON(デフォルトはコンパクト、`--pretty` で整形)、YAML、TOON(任意依存)。
- **ワークブック編集インターフェース**
- ExStruct の主な編集導線は editing CLI、host 側制御が必要な場合は MCP tools、Python から `exstruct.edit` を使うのは同じ patch contract を再利用したい場合に限ります。
- **テーブル検出のチューニング**
- API でヒューリスティックを動的に変更可能。
- **ハイパーリンク抽出**
- `verbose` モード(または `include_cell_links=True` 指定)でセルのリンクを `links` に出力。
- **安全なフォールバック**
- `.xlsx` / `.xlsm` の `light` はOOXMLを直接解析します。未対応OOXMLまたは `colors_map` 指定時はpartial結果を破棄し、openpyxl互換パイプライン全体を最初から実行して `ooxml_compatibility` warningを記録します。1シートのdrawing失敗は従来どおりそのシートだけbest-effortで処理します。
## インストール
```bash
pip install exstruct
```
オプション依存:
- YAML: `pip install pyyaml`
- 罫線クラスタリングの高速化: `pip install exstruct[fast]`(SciPy)。通常の直接OOXML light抽出ではPythonの罫線検出を使います。SciPyによる高速化と `EXSTRUCT_BORDER_CLUSTER_BACKEND` の選択は、他モードと互換抽出経路で利用できます。NumPy は引き続き必須依存です。
- TOON: `pip install python-toon`
- レンダリング(PDF/PNG): Excel + `pip install pypdfium2 pillow`(`mode=libreoffice` では非対応)
- まとめて導入: `pip install exstruct[yaml,toon,render,fast]`
プラットフォーム注意:
- Debian/Ubuntu/WSL で `mode=libreoffice` を使う場合、 LibreOffice と `python3-uno` を一緒に導入してください。`mode=libreoffice` は互換な system Python を自動検出し、必要なら `EXSTRUCT_LIBREOFFICE_PYTHON_PATH=/usr/bin/python3` で明示指定できます。
- LibreOffice 用 Python の検出では、候補 interpreter に対して bundled bridge の `--probe` を実行してから採用します。互換性のない `EXSTRUCT_LIBREOFFICE_PYTHON_PATH` は、抽出中の遅延 `SyntaxError` ではなく早期の互換性エラーとして失敗します。
- 一時的な孤立 LibreOffice profile で UNO socket の起動に失敗した場合、ExStruct は互換性 fallback として shared/default profile で 1 回だけ再試行し、両方失敗したときは各試行の起動詳細をエラーに含めます。
## クイックスタート CLI
```bash
exstruct input.xlsx > output.json # デフォルトは標準出力のコンパクト JSON
exstruct input.xlsx -o out.json --pretty # 整形 JSON をファイルへ
exstruct input.xlsx --format yaml # YAML(pyyaml が必要)
exstruct input.xlsx --format toon # TOON(python-toon が必要)
exstruct input.xlsx --sheets-dir sheets/ # シートごとに分割出力
exstruct input.xlsx --auto-page-breaks-dir auto_areas/ # 常時表示。実行には standard/verbose + Excel COM が必要
exstruct input.xlsx --alpha-col # 列キーを A, B, ..., AA 形式で出力
exstruct input.xlsx --include-backend-metadata # shape/chart の backend metadata を含める
exstruct input.xlsx --mode light # セル+テーブル候補+OOXML ベースの best-effort shape/chart
exstruct input.xlsx --mode libreoffice # COM なしで図形/コネクタ/チャートを best-effort 抽出
exstruct input.xlsx --pdf --image # PDF と PNG(Excel COM 必須)
```
- 自動改ページ範囲の書き出しは API/CLI 両方に対応(Excel/COM が必要)し、CLI では `--auto-page-breaks-dir` を常時表示したうえで実行時に検証します。
- `mode=libreoffice` では `--pdf` / `--image` / `--auto-page-breaks-dir` を早期エラーにし、`mode=light` でも `--auto-page-breaks-dir` を拒否します。これらの機能は `standard` または `verbose` + Excel COM を前提にします。
- CLI の既定では列キーは従来どおり 0 始まりの数値文字列(`"0"`, `"1"`, ...)です。Excel 形式(`"A"`, `"B"`, ...)が必要な場合は `--alpha-col` を指定してください。
- CLI の既定では shape/chart の `provenance` / `approximation_level` / `confidence` も出力しません。必要な場合は `--include-backend-metadata` を指定してください。
## クイックスタート Editing CLI
```bash
exstruct patch --input book.xlsx --ops ops.json --backend openpyxl
exstruct patch --input book.xlsx --ops - --dry-run --pretty < ops.json
exstruct make --output new.xlsx --ops ops.json --backend openpyxl
exstruct ops list
exstruct ops describe create_chart --pretty
exstruct validate --input book.xlsx --pretty
```
- `patch` / `make` は JSON の `PatchResult` を標準出力に出します。
- `ops list` / `ops describe` で public patch-op schema を確認できます。
- `validate` はワークブックの読取可否(`is_readable`, `warnings`, `errors`)を返します。
推奨フロー:
1. patch ops を組み立てる。
2. `exstruct patch --dry-run` を実行し、`PatchResult`・warnings・diff を確認する。
3. dry run と実適用で同じ engine を使いたい場合は `--backend openpyxl` を固定する。
4. `--backend auto` を使う場合は `PatchResult.engine` を確認する。Windows/Excel 環境では実適用時に COM へ切り替わることがある。
5. 問題がなければ `--dry-run` なしで再実行する。
## ExStruct CLI Skill
ExStruct には、editing CLI を安全に使うための repo 管理 Skill も 1 つ含めています。
repo 上の正本:
- `.agents/skills/exstruct-cli/`
次の 1 コマンドでインストールできます。
```bash
npx skills add harumiWeb/exstruct/.agents/skills --skill exstruct-cli
```
`npx skills add` を使えない実行環境では、従来どおり `SKILL.md` ベースの Skill が
検出されるローカルディレクトリへ同じフォルダを手動配置してください。
この Skill は、`patch` / `make` / `validate` / `ops list` /
`ops describe` の使い分けや、安全な
`validate -> dry-run -> PatchResult/diff を確認 -> apply -> verify`
フローが必要なときに使います。
エージェント向けの最小プロンプト例:
> `$exstruct-cli` を使って適切な ExStruct editing CLI コマンドを選び、PatchResult/diff の確認を含む validate/dry-run の安全なフローと、このワークブック作業に関係する backend 制約を説明してください。
## MCPサーバー (標準入出力)
MCP は同じ editing core を包む integration / compatibility layer です。
path restriction、transport mapping、artifact mirroring、approval-aware な
agent 実行が必要なときに使ってください。通常の Python workbook editing には
`openpyxl` / `xlwings` の方が合っています。ローカル shell / agent workflow
では editing CLI を優先します。
### uvx を使ったクイックスタート(推奨)
インストール不要で直接実行できます:
```bash
uvx --from 'exstruct[mcp]' exstruct-mcp --root C:\data --log-file C:\logs\exstruct-mcp.log --on-conflict rename
```
利点:
- `pip install` が不要
- 依存関係の自動管理
- 環境の分離
- バージョン指定が簡単: `uvx --from 'exstruct[mcp]==0.4.4' exstruct-mcp`
### 従来のインストール方法
pip でインストールすることもできます:
```bash
pip install exstruct[mcp]
exstruct-mcp --root C:\data --log-file C:\logs\exstruct-mcp.log --on-conflict rename
```
利用可能なツール:
| ツール名 | 説明 |
| ------------------------------- | -------------------------------------- |
| `exstruct_extract` | ワークブックからデータを抽出します。 |
| `exstruct_capture_sheet_images` | シートの画像をキャプチャします。 |
| `exstruct_make` | ワークブックを新規作成します。 |
| `exstruct_patch` | ワークブックに編集パッチを適用します。 |
| `exstruct_read_json_chunk` | 抽出した JSON チャンクを読み取ります。 |
| `exstruct_read_range` | 指定範囲のセルを読み取ります。 |
| `exstruct_read_cells` | セル単位でデータを読み取ります。 |
| `exstruct_read_formulas` | セルの数式を読み取ります。 |
| `exstruct_validate_input` | 入力データの検証を行います。 |
その他、詳しい使用方法や API についてはドキュメントサイトを参照してください:
[MCPサーバー](https://harumiweb.github.io/exstruct/mcp/)
## クイックスタート Python Extraction
```python
from pathlib import Path
from exstruct import extract, export, set_table_detection_params
# テーブル検出を調整(任意)
set_table_detection_params(table_score_threshold=0.3, density_min=0.04)
# モード: "light" / "standard" / "verbose"
wb = extract("input.xlsx", mode="standard") # standard ではリンクはデフォルト非出力
export(wb, Path("out.json"), pretty=False) # コンパクト JSON
export(wb, Path("out.json"), include_backend_metadata=True) # backend metadata も含める
# モデルの便利メソッド: 反復・インデックス・直列化
first_sheet = wb["Sheet1"] # __getitem__ でシート取得
for name, sheet in wb: # __iter__ で (name, SheetData) を列挙
print(name, len(sheet.rows))
wb.save("out.json", pretty=True) # WorkbookData を拡張子に応じて保存
first_sheet.save("sheet.json") # SheetData も同様に保存
print(first_sheet.to_yaml()) # YAML 文字列(pyyaml 必須)
print(first_sheet.to_json(include_backend_metadata=True)) # 必要なときだけ backend metadata を含める
# ExStructEngine: インスタンスごとの設定(ネスト構造)
from exstruct import (
DestinationOptions,
ExStructEngine,
FilterOptions,
FormatOptions,
OutputOptions,
StructOptions,
export_auto_page_breaks,
)
engine = ExStructEngine(
options=StructOptions(mode="verbose"), # verbose ではハイパーリンクがデフォルトで含まれる
output=OutputOptions(
format=FormatOptions(pretty=True),
filters=FilterOptions(
include_shapes=False,
include_backend_metadata=True,
), # 図形を除外しつつ backend metadata は保持
destinations=DestinationOptions(sheets_dir=Path("out_sheets")), # シートごとに保存
),
)
wb2 = engine.extract("input.xlsx")
engine.export(wb2, Path("out_filtered.json")) # フィルタ適用後の出力
# standard でハイパーリンクを有効化
engine_links = ExStructEngine(options=StructOptions(mode="standard", include_cell_links=True))
with_links = engine_links.extract("input.xlsx")
# 印刷範囲ごとに書き出す
from exstruct import export_print_areas_as
export_print_areas_as(wb, "areas", fmt="json", pretty=True) # 印刷範囲がある場合のみファイル生成
# 自動改ページ範囲の抽出/出力(COM 限定。自動改ページが無い場合は例外を送出)
engine_auto = ExStructEngine(
output=OutputOptions(
destinations=DestinationOptions(auto_page_breaks_dir=Path("auto_areas"))
)
)
wb_auto = engine_auto.extract("input.xlsx") # SheetData.auto_print_areas を含む
engine_auto.export(wb_auto, Path("out_with_auto.json")) # 自動改ページごとのファイルも auto_areas/* に保存
export_auto_page_breaks(wb_auto, "auto_areas", fmt="json", pretty=True)
```
**備考 (COM 非対応環境):** Excel COM が使えない場合でもセル+`table_candidates` は返り、`.xlsx` / `.xlsm` では利用可能な範囲で OOXML ベースの `shapes` / `charts` も best-effort で保持されます。
## テーブル検出パラメータ
```python
from exstruct import set_table_detection_params
set_table_detection_params(
table_score_threshold=0.35, # 厳しくするなら上げる
density_min=0.05,
coverage_min=0.2,
min_nonempty_cells=3,
)
```
値を上げると誤検知が減り、下げると検出漏れが減ります。
## 出力モード
- **light**: `.xlsx` / `.xlsm` のセル・テーブル候補・印刷範囲・図形/コネクタ/チャートを直接OOXMLで抽出します。通常経路はopenpyxl、pandas、SciPy、xlwingsをimportしません。
- **standard**: テキスト付き図形+矢印、チャート(COM ありで取得)、テーブル候補。セルのハイパーリンクは `include_cell_links=True` を指定したときのみ出力。
- **verbose**: すべての図形、チャート、`table_candidates`、ハイパーリンク、`colors_map`。
## エラーハンドリング / フォールバック
- Excel COM 不在時はセル+テーブル候補に自動フォールバックし、`.xlsx` / `.xlsm` では利用可能な OOXML 図形/チャートも best-effort で保持します。
- 1シートのdrawing失敗はそのシートの対象artifactだけを省き、健全なシートは維持します。未対応OOXMLまたは他のdirect pipeline stageの失敗時はpartial結果を破棄し、openpyxl互換pipeline全体を最初から実行して `ooxml_compatibility` を記録します。
- CLI はエラーを stdout/stderr に出し、失敗時は非ゼロ終了コード。
## 任意レンダリング
Excel と `pypdfium2` が必要です:
```bash
exstruct input.xlsx --pdf --image --dpi 144
```
`