Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

[![PyPI version](https://badge.fury.io/py/exstruct.svg)](https://pypi.org/project/exstruct/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/exstruct?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/exstruct) ![Licence: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-blue?style=flat-square) [![pytest](https://github.com/harumiWeb/exstruct/actions/workflows/pytest.yml/badge.svg)](https://github.com/harumiWeb/exstruct/actions/workflows/pytest.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/e081cb4f634e4175b259eb7c34f54f60)](https://app.codacy.com/gh/harumiWeb/exstruct/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![codecov](https://codecov.io/gh/harumiWeb/exstruct/graph/badge.svg?token=2XI1O8TTA9)](https://codecov.io/gh/harumiWeb/exstruct)

![ExStruct Image](/assets/icon.webp)
![ExStruct Image](docs/assets/icon.webp)

ExStruct は Excel ワークブックを読み取り、構造化データ(セル・テーブル候補・図形・チャート・SmartArt・印刷範囲ビュー)をデフォルトで JSON に出力します。必要に応じて YAML/TOON も選択でき、COM/Excel 環境ではリッチ抽出、非 COM 環境ではセル+テーブル候補+印刷範囲へのフォールバックで安全に動作します。LLM/RAG 向けに検出ヒューリスティックや出力モードを調整可能です。

## 主な特徴

- **Excel → 構造化 JSON**: セル、図形、チャート、SmartArt、テーブル候補、セル結合範囲、印刷範囲/自動改ページ範囲(PrintArea/PrintAreaView)をシート単位・範囲単位で出力。
- **出力モード**: `light`(セル+テーブル候補のみ)、`standard`(テキスト付き図形+矢印、チャート、SmartArt、セル結合範囲)、`verbose`(全図形を幅高さ付きで出力、セルのハイパーリンクも出力)。
- **数式取得**: `formulas_map`(数式文字列 → セル座標)を openpyxl/COM で取得。`verbose` 既定、`include_formulas_map` で制御。
- **フォーマット**: JSON(デフォルトはコンパクト、`--pretty` で整形)、YAML、TOON(任意依存)。
- **テーブル検出のチューニング**: API でヒューリスティックを動的に変更可能。
- **ハイパーリンク抽出**: `verbose` モード(または `include_cell_links=True` 指定)でセルのリンクを `links` に出力。
Expand Down Expand Up @@ -160,7 +161,7 @@ exstruct input.xlsx --pdf --image --dpi 144
- 図形のみで作成したフローチャート

(下画像が実際のサンプル Excel シート)
![Sample Excel](/assets/demo_sheet.png)
![Sample Excel](docs/assets/demo_sheet.png)
サンプル Excel: `sample/sample.xlsx`

### 1. Input: Excel Sheet Overview
Expand Down Expand Up @@ -339,7 +340,7 @@ flowchart TD

### Excel データ

![一般的な申請書Excel](/assets/demo_form.ja.png)
![一般的な申請書Excel](docs/assets/demo_form.ja.png)

### ExStruct JSON

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ExStruct reads Excel workbooks and outputs structured data (cells, table candida

- **Excel → Structured JSON**: cells, shapes, charts, smartart, table candidates, print areas/views, and auto page-break areas per sheet.
- **Output modes**: `light` (cells + table candidates + print areas; no COM, shapes/charts empty), `standard` (texted shapes + arrows, charts, smartart, merged cell ranges, print areas), `verbose` (all shapes with width/height, charts with size, merged cell ranges, print areas). Verbose also emits cell hyperlinks and `colors_map`. Size output is flag-controlled.
- **Formula map extraction**: emits `formulas_map` (formula string -> cell coordinates) via openpyxl/COM; enabled by default in `verbose` or via `include_formulas_map`.
- **Auto page-break export (COM only)**: capture Excel-computed auto page breaks and write per-area JSON/YAML/TOON when requested (CLI option appears only when COM is available).
- **Formats**: JSON (compact by default, `--pretty` available), YAML, TOON (optional dependencies).
- **Table detection tuning**: adjust heuristics at runtime via API.
Expand Down
5 changes: 3 additions & 2 deletions docs/README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ ExStruct reads Excel workbooks and outputs structured data (cells, table candida
## Features

- **Excel → Structured JSON**: cells, shapes, charts, smartart, table candidates, print areas/views, and auto page-break areas per sheet.
- **Output modes**: `light` (cells + table candidates + print areas; no COM, shapes/charts empty), `standard` (texted shapes + arrows, charts, smartart, merged cell ranges, print areas), `verbose` (all shapes with width/height, charts with size, merged cell ranges, print areas). Verbose also emits cell hyperlinks and `colors_map`. Size output is flag-controlled.
- **Output modes**: `light` (cells + table candidates + print areas; no COM, shapes/charts empty), `standard` (texted shapes + arrows, charts, smartart, merged cell ranges, print areas), `verbose` (all shapes with width/height, charts with size, merged cell ranges, print areas). Verbose also emits cell hyperlinks, `colors_map`, and `formulas_map`. Size output is flag-controlled.
- **Formula map extraction**: emits `formulas_map` (formula string -> cell coordinates) via openpyxl/COM; enabled by default in `verbose` or via `include_formulas_map`.
- **Auto page-break export (COM only)**: capture Excel-computed auto page breaks and write per-area JSON/YAML/TOON when requested (CLI option appears only when COM is available).
- **Formats**: JSON (compact by default, `--pretty` available), YAML, TOON (optional dependencies).
- **Table detection tuning**: adjust heuristics at runtime via API.
Expand Down Expand Up @@ -134,7 +135,7 @@ Use higher thresholds to reduce false positives; lower them if true tables are m

- **light**: cells + table candidates (no COM needed).
- **standard**: texted shapes + arrows, charts (COM if available), merged cell ranges, table candidates. Hyperlinks are off unless `include_cell_links=True`.
- **verbose**: all shapes (with width/height), charts, merged cell ranges, table candidates, cell hyperlinks, and `colors_map`.
- **verbose**: all shapes (with width/height), charts, merged cell ranges, table candidates, cell hyperlinks, `colors_map`, and `formulas_map`.

## Error Handling / Fallbacks

Expand Down
5 changes: 3 additions & 2 deletions docs/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ ExStruct は Excel ワークブックを読み取り、構造化データ(セ
## 主な特徴

- **Excel → 構造化 JSON**: セル、図形、チャート、SmartArt、テーブル候補、セル結合範囲、印刷範囲/自動改ページ範囲(PrintArea/PrintAreaView)をシート単位・範囲単位で出力。
- **出力モード**: `light`(セル+テーブル候補のみ)、`standard`(テキスト付き図形+矢印、チャート、SmartArt、セル結合範囲)、`verbose`(全図形を幅高さ付きで出力、セルのハイパーリンクも出力)。
- **出力モード**: `light`(セル+テーブル候補のみ)、`standard`(テキスト付き図形+矢印、チャート、SmartArt、セル結合範囲)、`verbose`(全図形を幅高さ付きで出力、セルのハイパーリンク/`colors_map`/`formulas_map`も出力)。
- **数式取得**: `formulas_map`(数式文字列 → セル座標)を openpyxl/COM で取得。`verbose` 既定、`include_formulas_map` で制御。
- **フォーマット**: JSON(デフォルトはコンパクト、`--pretty` で整形)、YAML、TOON(任意依存)。
- **テーブル検出のチューニング**: API でヒューリスティックを動的に変更可能。
- **ハイパーリンク抽出**: `verbose` モード(または `include_cell_links=True` 指定)でセルのリンクを `links` に出力。
Expand Down Expand Up @@ -131,7 +132,7 @@ set_table_detection_params(

- **light**: セル+テーブル候補のみ(COM 不要)。
- **standard**: テキスト付き図形+矢印、チャート(COM ありで取得)、テーブル候補。セルのハイパーリンクは `include_cell_links=True` を指定したときのみ出力。
- **verbose**: all shapes, charts, table_candidates, hyperlinks, and `colors_map`.
- **verbose**: 全図形(幅高さ付き)、チャート、`table_candidates`、ハイパーリンク、`colors_map`、`formulas_map` を出力。

## エラーハンドリング / フォールバック

Expand Down
4 changes: 3 additions & 1 deletion docs/agents/DATA_MODEL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ExStruct データモデル仕様

**Version**: 0.15
**Version**: 0.16
**Status**: Authoritative

本ドキュメントは ExStruct が返す全モデルの唯一の正準ソースです。
Expand Down Expand Up @@ -175,6 +175,7 @@ SheetData {
table_candidates: [str]
print_areas: [PrintArea]
auto_print_areas: [PrintArea] // 自動改ページ矩形 (COM 前提、デフォルト無効)
formulas_map: {[formula: str]: [[int, int]]} // (row=1-based, col=0-based)
colors_map: {[colorHex: str]: [[int, int]]} // (row=1-based, col=0-based)
merged_cells: MergedCells | null
}
Expand Down Expand Up @@ -251,3 +252,4 @@ WorkbookData {
- 0.13: Shape を `Shape` / `Arrow` / `SmartArt` に分割し、`SmartArtNode` のネスト構造を追加
- 0.14: `MergedCell` / `SheetData.merged_cells` を追加
- 0.15: `MergedCells` を schema + items 形式に変更し圧縮形式を導入
- 0.16: `SheetData.formulas_map` を追加
20 changes: 20 additions & 0 deletions docs/agents/FEATURE_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@

---

## 数式取得機能追加

- 新たに数式文字列をそのまま取得する機能を追加
- `SheetData`モデルに`formulas_map`を新設予定`formulas_map: dict[str, list[tuple[int,int]]]`
- 数式の値は定義されている数式をそのまま取得する
- セル座標はcolors_mapと同じようにr,cの数値で表記
- デフォルトはverboseモード以上で出力、もしくはオプションからONにする
- 定義されている数式文字列をシンプルに取得する実装
- 数式の表記形式は「=A1」のようにユーザーが見るままの数式文字列にする
- 共有数式や配列数式は一旦は展開しない実装にする
- 空文字は除外、=だけのセルも数式文字として取得
- formulas_mapのキーは「式文字列(先頭=を含む)」で固定する
- 既存の値はSheetData.rowsにあり、数式はSheetData.formulas_mapにあることで共存する
- データ取得時はformulas_map が ON のときだけ data_only=False で再読込
- オプションは`StructOptions`にて`include_formulas_map: bool = False`で設定を受け付ける
- `.xls`形式かつ数式取得ONの時は処理が遅くなるという警告を出しつつ、COMで取得処理をする。
- cell.value が ArrayFormula の場合に value.text(実際の式文字列)を使う

---

## 今後のオプション検討メモ

- 表検知スコアリングの閾値を CLI/環境変数で調整可能にする
Expand Down
39 changes: 35 additions & 4 deletions docs/agents/TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,38 @@

未完了 [ ], 完了 [x]

- [x] 仕様確認: 画像出力は DPI を維持しつつ、メモリリーク/クラッシュ回避のためサブプロセス化で処理する方針を明記
- [x] 実装方針: シートごとに PDF を分割 → サブプロセスで PDF ページを PNG へ変換 → 終了時にメモリを解放する設計(親は進捗/結果を集約)
- [x] 実装方針: 子プロセスは `pypdfium2` をロードしてページごとにレンダリングし、書き込み済みパスを親に返す
- [x] 実装方針: 例外時は子プロセスでエラーを返し、親が RenderError として集約して返す
## 数式取得機能追加

- [x] `SheetData`に`formulas_map`フィールドを追加し、シリアライズ対象に含める
- [x] `StructOptions`に`include_formulas_map: bool = False`を追加し、verbose時の既定挙動と整合させる
- [x] openpyxlで`data_only=False`の読み取りパスを追加し、`formulas_map`用の走査処理を実装する
- [x] `.xls`かつ数式取得ONの場合はCOM経由で`formulas_map`を取得し、遅延警告を出す
- [x] `formulas_map`の仕様(=付きの式文字列、空文字除外、=のみ許可、共有/配列は未展開)に沿った抽出ロジックを追加
- [x] openpyxlの配列数式(`ArrayFormula`)は`value.text`から式文字列を取得する分岐を追加
- [x] CLI/ドキュメント/READMEの出力モード説明に`formulas_map`の条件を追記する
- [x] テスト要件に`formulas_map`関連(ON/OFF、verbose既定、.xls COM分岐)を追加する

## PR #44 指摘対応

- [x] `src/exstruct/render/__init__.py` の `_page_index_from_suffix` を2桁固定ではなく可変桁の数値サフィックスに対応させ、`_rename_pages_for_print_area` の上書きリスクを解消する
- [x] `src/exstruct/render/__init__.py` の `_export_sheet_pdf` の `finally` 内 `return` を削除し、PrintArea 復元失敗はログに残して例外を握りつぶさない
- [x] `src/exstruct/core/pipeline.py` の `step_extract_formulas_map_*` の挙動を docstring に合わせる(失敗時にログしてスキップ)か、docstring を実装に合わせて修正する
- [x] `docs/README.ja.md` の `**verbose**` 説明行を日本語に統一する

## PR #44 コメント/Codecov 対応

- [x] Codecov パッチカバレッジ低下(60.53%)の指摘に対応し、対象ファイルの不足分テストを追加する(`src/exstruct/render/__init__.py`, `src/exstruct/core/cells.py`, `src/exstruct/core/backends/com_backend.py`, `src/exstruct/core/pipeline.py`, `src/exstruct/core/backends/openpyxl_backend.py`)
- [x] Codecov の「Files with missing lines」で具体的な未カバー行を確認し、テスト観点を整理する
- [x] Codacy 警告対応: `src/exstruct/render/__init__.py:274` の finally 内 return により例外が握りつぶされる可能性(`PyLintPython3_W0150`)を解消する

## PR #44 CodeRabbit 再レビュー対応

- [ ] `scripts/codacy_issues.py`: トークン未設定時の `sys.exit(1)` をモジュールトップから排除し、`get_token()` または `main()` で検証する
- [ ] `scripts/codacy_issues.py`: `format_for_ai` の `sys.exit` を `ValueError` に置換し、呼び出し側でバリデーションする
- [ ] `scripts/codacy_issues.py`: `urlopen` の非2xxチェック(到達不能)を削除または `HTTPError` 側へ寄せる
- [ ] `scripts/codacy_issues.py`: `status` の固定値バリデーションを廃止する(固定なら直代入/必要なら CLI 引数化)
- [ ] `tests/backends/test_print_areas_openpyxl.py`: `PrintAreaData` 型に合わせる+関連テストに Google スタイル docstring を付与
- [ ] `tests/core/test_pipeline.py`: 無効な `MergedCellRange` を有効な非重複レンジに修正する
- [ ] `tests/backends/test_backends.py`: `sheets` のクラス属性共有を避け、インスタンス属性に変更する
- [ ] `tests/render/test_render_init.py` / `tests/utils.py` / `tests/models/test_models_export.py`: docstring/コメントの指摘を反映する
- [ ] `src/exstruct/render/__init__.py`: Protocol クラスに Google スタイル docstring を追加する
19 changes: 19 additions & 0 deletions docs/release-notes/v0.3.7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# v0.3.7 Release Notes

This release adds formula extraction to the structured output, expanding the
pipeline, models, and backends while keeping the existing modes and fallbacks.

## Highlights

- Added `formulas_map` extraction (formula string -> cell coordinates) via
openpyxl for .xlsx/.xlsm and COM for .xls, with `include_formulas_map` option
and verbose default behavior.
- Pipeline, engine, and models now propagate `formulas_map` end-to-end, with
updated samples and documentation.
- Rendering robustness improved for print-area exports (safer page numbering
and error handling during PrintArea restoration).

## Notes

- `formulas_map` is emitted in `verbose` by default; use `include_formulas_map`
to enable/disable explicitly.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nav:
- CLI Guide: cli.md
- Concept / Why ExStruct?: concept.md
- Release Notes:
- v0.3.7: release-notes/v0.3.7.md
- v0.3.6: release-notes/v0.3.6.md
- v0.3.5: release-notes/v0.3.5.md
- v0.3.2: release-notes/v0.3.2.md
Expand Down
36 changes: 16 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "exstruct"
version = "0.3.6"
version = "0.3.7"
description = "Excel to structured JSON (tables, shapes, charts) for LLM/RAG pipelines"
readme = "README.md"
license = { file = "LICENSE" }
Expand Down Expand Up @@ -60,7 +60,10 @@ omit = [
[tool.ruff]
target-version = "py311"
src = ["exstruct"]
fix = true

# 静的解析ルール
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
Expand All @@ -75,43 +78,36 @@ select = [
]

ignore = [
"E501", # 行長は許容(Excel JSON は長くなりがち)
"B008", # Pydantic の default_factory を誤検知するため
"ANN101", # self に型を要求されてしまうため
"ANN102", # cls も同様
"E501", # 長い行は許容(Excel JSON は長くなりがち)
"B008", # Pydantic の default_factory を使用するため
"ANN101", # self の型注釈は省略可能
"ANN102", # cls の型注釈は省略可能
]

fix = true

# 型ヒントのスタイル
[tool.ruff.lint]
extend-select = ["ANN"]

# import の並び替え設定
[tool.ruff.isort]
# import の並び順
[tool.ruff.lint.isort]
combine-as-imports = true
known-first-party = ["exstruct"]
force-sort-within-sections = true

# 複雑度チェック(関数の最大複雑度)
[tool.ruff.mccabe]
# 複雑度の最大値
[tool.ruff.lint.mccabe]
max-complexity = 12

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["N802", "N803", "N806"]


[tool.mypy]
packages = ["exstruct"]
python_version = "3.11"

# 外部ライブラリは一切チェックしない
# 外部ライブラリの型情報がない場合は無視
ignore_missing_imports = true

# 自作コードは厳密にチェックする
# 厳格モードを有効化
strict = true

# Pydantic v2 向け
# Pydantic v2 対応
plugins = ["pydantic.mypy"]

[tool.pytest.ini_options]
Expand Down
Loading
Loading