{"id":34510159,"url":"https://github.com/f-y/md-spreadsheet-parser","last_synced_at":"2026-01-23T02:59:00.949Z","repository":{"id":328813697,"uuid":"1101180249","full_name":"f-y/md-spreadsheet-parser","owner":"f-y","description":"A robust, zero-dependency Python library for parsing, validating, and manipulating Markdown tables, including conversion from Excel to Markdown.","archived":false,"fork":false,"pushed_at":"2026-01-22T12:46:53.000Z","size":1388,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-22T23:13:41.346Z","etag":null,"topics":["data-conversion","excel","library","markdown","pandas","parser","python","spreadsheet","table-parser","type-safe","zero-dependency"],"latest_commit_sha":null,"homepage":"https://f-y.github.io/md-spreadsheet-parser/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/f-y.png","metadata":{"files":{"readme":"README.ja.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-21T10:01:36.000Z","updated_at":"2026-01-22T12:46:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/f-y/md-spreadsheet-parser","commit_stats":null,"previous_names":["f-y/md-spreadsheet-parser"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/f-y/md-spreadsheet-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f-y%2Fmd-spreadsheet-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f-y%2Fmd-spreadsheet-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f-y%2Fmd-spreadsheet-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f-y%2Fmd-spreadsheet-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/f-y","download_url":"https://codeload.github.com/f-y/md-spreadsheet-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f-y%2Fmd-spreadsheet-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28679139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T01:00:35.747Z","status":"online","status_checked_at":"2026-01-23T02:00:08.296Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-conversion","excel","library","markdown","pandas","parser","python","spreadsheet","table-parser","type-safe","zero-dependency"],"created_at":"2025-12-24T03:55:56.521Z","updated_at":"2026-01-23T02:59:00.943Z","avatar_url":"https://github.com/f-y.png","language":"Python","readme":"# Markdown Spreadsheet Parser\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/f-y/md-spreadsheet-parser/blob/main/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/md-spreadsheet-parser/\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/md-spreadsheet-parser.svg\" alt=\"PyPI\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pepy.tech/projects/md-spreadsheet-parser\"\u003e\u003cimg src=\"https://static.pepy.tech/personalized-badge/md-spreadsheet-parser?period=total\u0026units=INTERNATIONAL_SYSTEM\u0026left_color=GREY\u0026right_color=BLUE\u0026left_text=downloads\" alt=\"PyPI Downloads\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/md-spreadsheet-parser\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/md-spreadsheet-parser.svg\" alt=\"npm\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/f-y/md-spreadsheet-parser\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/repository-github-blue.svg\" alt=\"Repository\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/f-y/md-spreadsheet-parser/actions?query=workflow%3ATests\"\u003e\n    \u003cimg src=\"https://github.com/f-y/md-spreadsheet-parser/workflows/Tests/badge.svg\" alt=\"Build Status\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eMarkdownテーブル操作に特化したPythonライブラリ。ExcelからMarkdownへの変換、テーブルの解析、型安全な検証など。堅牢で依存関係ゼロ\u003c/strong\u003e\n\u003c/p\u003e\n\n---\n\n**md-spreadsheet-parser** は、Markdownのテーブルを単なるテキストからファーストクラスのデータ構造へと昇華させます。スプレッドシートの手軽さとPythonの強力さを兼ね備え、正確かつ依存関係ゼロのエンジンでテーブルの解析、検証、操作を実現します。\n\n\u003e **🎉 公式GUIエディタが登場: [PengSheets](https://marketplace.visualstudio.com/items?itemName=f-y.peng-sheets)**\n\u003e\n\u003e このライブラリのパワーをそのままに、VS Code上でExcelライクな操作感を実現しました。ソート、フィルタ、快適なナビゲーションなどをGUIで直感的に扱えます。\n\u003e\n\u003e [![Get it on VS Code Marketplace](https://img.shields.io/badge/VS%20Code%20Marketplace-%E3%81%A7%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89-007ACC?style=for-the-badge\u0026logo=visual-studio-code\u0026logoColor=white)](https://marketplace.visualstudio.com/items?itemName=f-y.peng-sheets)\n\n🚀 **すぐに使いたいですか？** [Cookbook](https://github.com/f-y/md-spreadsheet-parser/blob/main/COOKBOOK.ja.md) には、コピー＆ペーストで使えるレシピ（Excel変換、Pandas連携、Markdownテーブル操作など）が満載です。\n\n## 目次\n\n- [機能](#機能)\n- [インストール](#インストール)\n- [使い方](#使い方)\n    - [1. 基本的な解析](#1-基本的な解析)\n    - [GFM機能のサポート](#gfm機能のサポート)\n    - [2. 型安全な検証](#2-型安全な検証-推奨)\n        - [Pydantic連携](#pydantic連携)\n    - [3. JSONと辞書への変換](#3-jsonと辞書への変換)\n    - [4. Pandas連携とエクスポート](#4-pandas連携とエクスポート)\n    - [5. Excelインポート](#5-excelインポート)\n    - [6. Markdown生成](#6-markdown生成-ラウンドトリップ)\n    - [7. 高度な機能](#7-高度な機能)\n    - [8. 高度な型変換](#8-高度な型変換)\n    - [9. 堅牢性](#9-堅牢性-不正なテーブルの処理)\n    - [10. セル内改行のサポート](#10-セル内改行のサポート)\n    - [11. パフォーマンスとスケーラビリティ](#11-パフォーマンスとスケーラビリティ-ストリーミングapi)\n    - [12. プログラムによる操作](#12-プログラムによる操作)\n    - [13. ビジュアルメタデータの永続化](#13-ビジュアルメタデータの永続化)\n    - [コマンドラインインターフェース (CLI)](#コマンドラインインターフェース-cli)\n- [設定](#設定)\n- [エコシステム](#エコシステム-ecosystem)\n- [ライセンス](#ライセンス)\n\n## 機能\n\n- **純粋なPythonと依存関係ゼロ**: 軽量でポータブルです。**AWS Lambda Layers** や制約のある環境に最適です。**WebAssembly (Pyodide)** を含む、Pythonが動作する場所ならどこでも動作します。\n- **型安全な検証**: ルーズなMarkdownテーブルを、自動型変換を含む強力に型付けされたPythonの `dataclasses` に変換します。カスタマイズ可能なブール値ロジック (I18N) やカスタム型コンバータもサポートします。\n- **データベースとしてのMarkdown**: MarkdownファイルをGit管理された設定やマスターデータとして扱えます。スキーマと型を自動的に検証し、手書きテーブルの人為的ミスを防ぎます。\n- **ラウンドトリップサポート**: オブジェクトへの解析、データの変更、Markdownへの再生成が可能です。エディタの実装に最適です。\n- **GFM準拠**: 列の配置 (`:--`, `:--:`, `--:`) やインラインコード内のパイプ (`` `|` ``) の正しい処理など、GitHub Flavored Markdown (GFM) 仕様をサポートしています。\n- **堅牢な解析**: 不正なテーブル（列の欠落や過剰）やエスケープ文字を適切に処理します。\n- **マルチテーブル・ワークブック**: 単一ファイルからの複数のシートやテーブルの解析、およびメタデータをサポートします。\n- **JSONとDictのサポート**: 列レベルのJSON解析と、`dict`/`TypedDict` への直接変換をサポートします。\n- **Pandas連携**: MarkdownテーブルからDataFrameをシームレスに作成できます。\n- **Excelインポートとデータクリーニング**: Excel/TSV/CSVをMarkdownに変換し、結合セルをインテリジェントに処理します。階層ヘッダーのフラット化やギャップの埋め合わせを自動的に行い、「汚い」スプレッドシートをきれいな構造化データに変換します。\n- **JSONフレンドリー**: 辞書/JSONへのエクスポートが容易で、他のツールとの連携も簡単です。\n\n## インストール\n\n```bash\npip install md-spreadsheet-parser\n```\n\n## 使い方\n\n### 1. 基本的な解析\n\n**単一のテーブル**\n標準的なMarkdownテーブルを構造化オブジェクトに解析します。\n\n```python\nfrom md_spreadsheet_parser import parse_table\n\nmarkdown = \"\"\"\n| Name | Age |\n| --- | --- |\n| Alice | 30 |\n| Bob | 25 |\n\"\"\"\n\nresult = parse_table(markdown)\n\nprint(result.headers)\n# ['Name', 'Age']\n\nprint(result.rows)\n# [['Alice', '30'], ['Bob', '25']]\n```\n\n**複数のテーブル (ワークブック)**\n複数のシート（セクション）を含むファイルを解析します。デフォルトでは、ルートマーカーとして `# Tables`、シート用には `## Sheet Name` を探します。\n\n```python\nfrom md_spreadsheet_parser import parse_workbook, MultiTableParsingSchema\n\nmarkdown = \"\"\"\n# Tables\n\n## Users\n| ID | Name |\n| -- | ---- |\n| 1  | Alice|\n\n## Products\n| ID | Item |\n| -- | ---- |\n| A  | Apple|\n\"\"\"\n\n# デフォルトスキーマを使用\nschema = MultiTableParsingSchema()\nworkbook = parse_workbook(markdown, schema)\n\nfor sheet in workbook.sheets:\n    print(f\"Sheet: {sheet.name}\")\n    for table in sheet.tables:\n        print(table.rows)\n```\n\n**ルックアップAPIとメタデータ**\nシートやテーブルを名前で直接取得し、説明などの解析されたメタデータにアクセスできます。\n\n```python\nfrom md_spreadsheet_parser import parse_workbook\n\nmarkdown = \"\"\"\n# Tables\n\n## Sales Data\n\n### Q1 Results\nFinancial performance for the first quarter.\n\n| Year | Revenue |\n| ---- | ------- |\n| 2023 | 1000    |\n\"\"\"\n\nworkbook = parse_workbook(markdown)\n\n# 名前でアクセス\nsheet = workbook.get_sheet(\"Sales Data\")\nif sheet:\n    # 名前でテーブルを取得 (### Header から)\n    table = sheet.get_table(\"Q1 Results\")\n    \n    print(table.description)\n    # \"Financial performance for the first quarter.\"\n    \n    print(table.rows)\n    # [['2023', '1000']]\n```\n\n**シンプルなスキャンインターフェース**\nドキュメントの構造（シートやヘッダー）を無視して、ファイル内の *すべての* テーブルを抽出したい場合は、`scan_tables` を使用します。\n\n```python\nfrom md_spreadsheet_parser import scan_tables\n\nmarkdown = \"\"\"\n| ID | Name |\n| -- | ---- |\n| 1  | Alice|\n\n... text ...\n\n| ID | Item |\n| -- | ---- |\n| A  | Apple|\n\"\"\"\n\n# 見つかったすべてのテーブルのフラットリストを返す\ntables = scan_tables(markdown)\nprint(len(tables)) # 2\n```\n\n**ファイル読み込みヘルパー**\n\n利便性のため、`_from_file` バリアントを使用して、ファイルパス (`str` または `Path`) やファイルライクオブジェクトから直接解析できます：\n\n```python\nfrom md_spreadsheet_parser import parse_workbook_from_file\n\n# 簡単でクリーン\nworkbook = parse_workbook_from_file(\"data.md\")\n```\n\n利用可能なヘルパー:\n- `parse_table_from_file(path_or_file)`\n- `parse_workbook_from_file(path_or_file)`\n- `scan_tables_from_file(path_or_file)`\n\n### GFM機能のサポート\n\nパーサーは、テーブルに関するGitHub Flavored Markdown (GFM) 仕様に厳密に準拠しています。\n\n**列の配置**\n区切り行の配置マーカーは解析され、保持されます。\n\n```python\nmarkdown = \"\"\"\n| Left | Center | Right |\n| :--- | :----: | ----: |\n| 1    | 2      | 3     |\n\"\"\"\ntable = parse_table(markdown)\nprint(table.alignments)\n# [\"left\", \"center\", \"right\"]\n```\n\n**コード内のパイプとエスケープ**\nインラインコードブロック（バッククォート）内のパイプ `|` や、`\\` でエスケープされたパイプは、列区切りではなくコンテンツとして正しく扱われます。\n\n```python\nmarkdown = \"\"\"\n| Code  | Escaped |\n| ----- | ------- |\n| `a|b` | \\|      |\n\"\"\"\ntable = parse_table(markdown)\n# table.rows[0] == [\"`a|b`\", \"|\"]\n```\n\n### 2. 型安全な検証 (推奨)\n\nこのライブラリの最も強力な機能は、`dataclasses` を使用して、ルーズなMarkdownテーブルを強く型付けされたPythonオブジェクトに変換することです。これにより、データの妥当性が保証され、扱いやすくなります。\n\n```python\nfrom dataclasses import dataclass\nfrom md_spreadsheet_parser import parse_table, TableValidationError\n\n@dataclass\nclass User:\n    name: str\n    age: int\n    is_active: bool = True\n\nmarkdown = \"\"\"\n| Name | Age | Is Active |\n|---|---|---|\n| Alice | 30 | yes |\n| Bob | 25 | no |\n\"\"\"\n\ntry:\n    # ワンステップで解析と検証\n    users = parse_table(markdown).to_models(User)\n    \n    for user in users:\n        print(f\"{user.name} is {user.age} years old.\")\n        # Alice is 30 years old.\n        # Bob is 25 years old.\n\nexcept TableValidationError as e:\n    print(e)\n```\n\n**機能:**\n*   **型変換**: 文字列を標準的なルールで自動的に `int`, `float`, `bool` に変換します。\n*   **ブール値の処理 (デフォルト)**: 標準的なペア `true/false`, `yes/no`, `on/off`, `1/0` を即座にサポートします。（カスタマイズについては [高度な型変換](#8-高度な型変換) を参照）。\n*   **オプションフィールド**: 空文字列を `None` に変換することで `Optional[T]` を処理します。\n*   **検証**: データがスキーマに一致しない場合、詳細なエラーを発生させます。\n\n### Pydantic連携\n\nより高度な検証（メール形式、範囲、正規表現）を行うには、dataclassesの代わりに [Pydantic](https://docs.pydantic.dev/) モデルを使用できます。`pydantic` がインストールされている場合、この機能は自動的に有効になります。\n\n```python\nfrom pydantic import BaseModel, Field, EmailStr\n\nclass User(BaseModel):\n    name: str = Field(alias=\"User Name\")\n    age: int = Field(gt=0)\n    email: EmailStr\n\n# 自動的にPydanticモデルを検出し、検証に使用します\nusers = parse_table(markdown).to_models(User)\n```\n\nパーサーはPydanticの `alias` と `Field` 制約を尊重します。\n\n### 3. JSONと辞書への変換\n\n完全なDataclassやPydanticモデルを定義したくない場合や、JSON文字列を含む列がある場合の対応です。\n\n**シンプルな辞書出力**\nテーブルを辞書のリストに直接変換します。キーはヘッダーから派生します。\n\n```python\n# list[dict[str, Any]] を返します (値は生の文字列です)\nrows = parse_table(markdown).to_models(dict)\nprint(rows[0])\n# {'Name': 'Alice', 'Age': '30'}\n```\n\n**TypedDict サポート**\n軽量な型安全性のために `TypedDict` を使用します。パーサーは型アノテーションを使用して値を自動的に変換します。\n\n```python\nfrom typing import TypedDict\n\nclass User(TypedDict):\n    name: str\n    age: int\n    active: bool\n\nrows = parse_table(markdown).to_models(User)\nprint(rows[0])\n# {'name': 'Alice', 'age': 30, 'active': True}\n```\n\n**列レベルのJSON解析**\nフィールドが `dict` または `list` として型付けされている場合（DataclassまたはPydanticモデル内）、パーサーは **セルの値を自動的にJSONとして解析** します。\n\n```python\n@dataclass\nclass Config:\n    id: int\n    metadata: dict  # セル: '{\"debug\": true}' -\u003e dictに解析\n    tags: list      # セル: '[\"a\", \"b\"]'      -\u003e listに解析\n\n# PydanticモデルもJson[]ラッパーなしで動作します\nclass ConfigModel(BaseModel):\n    metadata: dict\n```\n\n**制限事項:**\n*   **JSON構文**: セルの内容は有効なJSONである必要があります（例: ダブルクォート `{\"a\": 1}`）。不正なJSONは `ValueError` を発生させます。\n*   **単純な辞書解析**: `to_models(dict)` は、カスタムスキーマを使用しない限り、内部のJSON文字列を自動的には解析 *しません*。文字列の浅い辞書を作成するだけです。\n\n### 4. Pandas連携とエクスポート\n\nこのライブラリは、Markdownと **Pandas** などのデータサイエンスツールの架け橋となるように設計されています。\n\n**DataFrameへの変換 (最も簡単な方法)**\nDataFrameを作成する最もきれいな方法は、`to_models(dict)` を使用することです。これはPandasが直接取り込める辞書のリストを返します。\n\n```python\nimport pandas as pd\nfrom md_spreadsheet_parser import parse_table\n\nmarkdown = \"\"\"\n| Date       | Sales | Region |\n|------------|-------|--------|\n| 2023-01-01 | 100   | US     |\n| 2023-01-02 | 150   | EU     |\n\"\"\"\n\ntable = parse_table(markdown)\n\n# 1. 辞書のリストに変換\ndata = table.to_models(dict)\n\n# 2. DataFrameの作成\ndf = pd.DataFrame(data)\n\n# 3. 後処理: 型変換 (Pandasは通常、最初は文字列として推論します)\ndf[\"Sales\"] = pd.to_numeric(df[\"Sales\"])\ndf[\"Date\"] = pd.to_datetime(df[\"Date\"])\n\nprint(df.dtypes)\n# Date      datetime64[ns]\n# Sales              int64\n# Region            object\n```\n\n**型安全なオブジェクトからの変換**\nDataFrameを作成する **前** にデータを検証したい場合（例: 解析中に \"Sales\" が整数であることを保証する）は、`dataclass` を使用してからPandasに変換します。\n\n```python\nfrom dataclasses import dataclass, asdict\n\n@dataclass\nclass SalesRecord:\n    date: str\n    amount: int\n    region: str\n\n# 1. 解析と検証 (無効な場合はTableValidationErrorが発生)\nrecords = parse_table(markdown).to_models(SalesRecord)\n\n# 2. asdict()を使用してDataFrameに変換\ndf = pd.DataFrame([asdict(r) for r in records])\n\n# 'amount' 列は検証時に変換されているため、すでにint64です\nprint(df[\"amount\"].dtype) # int64\n```\n\n**JSONエクスポート**\nすべての結果オブジェクト (`Workbook`, `Sheet`, `Table`) には、シリアライズに適した辞書構造を返す `.json` プロパティがあります。\n\n```python\nimport json\n\n# ワークブック構造全体をエクスポート\nprint(json.dumps(workbook.json, indent=2))\n```\n\n\n### 5. Excelインポート\n\n結合セルや階層ヘッダーをインテリジェントに処理して、Excelデータ（TSV/CSVまたは `openpyxl` 経由）をインポートします。\n\n\u003e [!NOTE]\n\u003e TSV/CSVテキストからのインポートは **依存関係ゼロ** で動作します。`.xlsx` ファイルの直接読み込みには `openpyxl`（ユーザー管理のオプション依存関係）が必要です。\n\n**基本的な使い方**\n\n🚀 **より包括的なレシピについては [Cookbook](https://github.com/f-y/md-spreadsheet-parser/blob/main/COOKBOOK.ja.md) をご覧ください。**\n\n```python\nfrom md_spreadsheet_parser import parse_excel\n\n# TSV/CSVから (依存関係ゼロ)\ntable = parse_excel(\"Name\\tAge\\nAlice\\t30\")\n\n# .xlsxから (openpyxlが必要)\nimport openpyxl\nwb = openpyxl.load_workbook(\"data.xlsx\")\ntable = parse_excel(wb.active)\n```\n\n**結合ヘッダーの処理**\n\nExcelが結合セルをエクスポートすると、それらは空のセルとして表示されます。パーサーはこれらのギャップを自動的に前方埋めします：\n\n```text\nExcel (結合ヘッダー):\n┌─────────────────────────────┬────────┐\n│      Category (3 cols)      │  Info  │\n├─────────┬─────────┬─────────┼────────┤\n│    A    │    B    │    C    │   D    │\n└─────────┴─────────┴─────────┴────────┘\n\n          ↓ parse_excel()\n\nMarkdown:\n| Category | Category | Category | Info |\n|----------|----------|----------|------|\n| A        | B        | C        | D    |\n```\n\n**2行階層ヘッダー**\n\n親子関係のある複雑なヘッダーには、`ExcelParsingSchema(header_rows=2)` を使用します：\n\n```text\nExcel (2行ヘッダー):\n┌───────────────────┬───────────────────┐\n│       Info        │      Metrics      │  ← Row 1 (Parent)\n├─────────┬─────────┼─────────┬─────────┤\n│  Name   │   ID    │  Score  │  Rank   │  ← Row 2 (Child)\n├─────────┼─────────┼─────────┼─────────┤\n│  Alice  │   001   │   95    │    1    │\n└─────────┴─────────┴─────────┴─────────┘\n\n          ↓ parse_excel(schema=ExcelParsingSchema(header_rows=2))\n\nMarkdown:\n| Info - Name | Info - ID | Metrics - Score | Metrics - Rank |\n|-------------|-----------|-----------------|----------------|\n| Alice       | 001       | 95              | 1              |\n```\n\n\u003e **注:** 現在、最大2行のヘッダー行をサポートしています。より深い階層の場合は、解析前にデータを前処理してください。\n\n**Excelから構造化オブジェクトへ（「キラー」機能）**\n\n単にテキストに変換するだけでなく、Excelをワンステップで有効で型安全なPythonオブジェクトに直接変換します。\n\n```python\n@dataclass\nclass SalesRecord:\n    category: str\n    item: str\n    amount: int  # 文字列からintへの自動変換\n\n# 1. Excelを解析 (結合セルを自動的に処理)\n# 2. 検証とオブジェクトへの変換\nrecords = parse_excel(ws).to_models(SalesRecord)\n\n# これできれいな型付きデータが得られます\nassert records[0].amount == 1000\n```\n\n**設定**\n\n解析動作をカスタマイズするには `ExcelParsingSchema` を使用します：\n\n```python\nfrom md_spreadsheet_parser import parse_excel, ExcelParsingSchema\n\nschema = ExcelParsingSchema(\n    header_rows=2,\n    fill_merged_headers=True,\n    header_separator=\" / \"\n)\n\ntable = parse_excel(source, schema)\n```\n\n| オプション | デフォルト | 説明 |\n|--------|---------|-------------|\n| `header_rows` | `1` | ヘッダー行の数 (1 or 2)。 |\n| `fill_merged_headers` | `True` | 空のヘッダーセルを前方埋めします。 |\n| `header_separator` | `\" - \"` | フラット化された2行ヘッダーの区切り文字。 |\n| `delimiter` | `\"\\t\"` | TSV/CSVの列区切り文字。 |\n\n\n### 6. Markdown生成 (ラウンドトリップ)\n\n解析されたオブジェクトを変更し、`to_markdown()` を使用してMarkdown文字列に戻すことができます。これにより、完全な「解析 -\u003e 変更 -\u003e 生成」のワークフローが可能になります。\n\n```python\nfrom md_spreadsheet_parser import parse_table, ParsingSchema\n\nmarkdown = \"| A | B |\\n|---|---| \\n| 1 | 2 |\"\ntable = parse_table(markdown)\n\n# データの変更\ntable.rows.append([\"3\", \"4\"])\n\n# Markdownの生成\n# スキーマを使用して出力形式をカスタマイズできます\nschema = ParsingSchema(require_outer_pipes=True)\nprint(table.to_markdown(schema))\n# | A | B |\n# | --- | --- |\n# | 1 | 2 |\n# | 3 | 4 |\n```\n\n### 7. 高度な機能\n\n**メタデータ抽出の設定**\nデフォルトでは、パーサーはテーブル名（レベル3ヘッダー）と説明をキャプチャします。`MultiTableParsingSchema` でこの動作をカスタマイズできます。\n\n```python\nfrom md_spreadsheet_parser import MultiTableParsingSchema\n\nschema = MultiTableParsingSchema(\n    table_header_level=3,     # ### Header をテーブル名として扱う\n    capture_description=True  # ヘッダーとテーブルの間のテキストをキャプチャ\n)\n# parse_workbook にスキーマを渡す...\n```\n\n### 8. 高度な型変換\n\n`to_models()` に `ConversionSchema` を渡すことで、文字列値がPythonオブジェクトに変換される方法をカスタマイズできます。これは国際化 (I18N) やカスタム型の処理に役立ちます。\n\n**国際化 (I18N): カスタムブール値ペア**\n\nどの文字列ペアを `True`/`False` にマッピングするかを設定します（大文字小文字を区別しません）。\n\n```python\nfrom md_spreadsheet_parser import parse_table, ConversionSchema\n\nmarkdown = \"\"\"\n| User | Active? |\n| --- | --- |\n| Tanaka | はい |\n| Suzuki | いいえ |\n\"\"\"\n\n# \"はい\" -\u003e True, \"いいえ\" -\u003e False を設定\nschema = ConversionSchema(\n    boolean_pairs=((\"はい\", \"いいえ\"),)\n)\n\nusers = parse_table(markdown).to_models(User, conversion_schema=schema)\n# Tanaka.active is True\n```\n\n**カスタム型コンバータ**\n\n特定の型のカスタム変換関数を登録します。以下を含む **任意のPython型** をキーとして使用できます：\n\n- **組み込み**: `int`, `float`, `bool` (デフォルト動作の上書き)\n- **標準ライブラリ**: `Decimal`, `datetime`, `date`, `ZoneInfo`, `UUID`\n- **カスタムクラス**: 独自のデータクラスやオブジェクト\n\n標準ライブラリの型とカスタムクラスを使用した例：\n\n```python\nfrom dataclasses import dataclass\nfrom uuid import UUID\nfrom zoneinfo import ZoneInfo\nfrom md_spreadsheet_parser import ConversionSchema, parse_table\n\n@dataclass\nclass Color:\n    r: int\n    g: int\n    b: int\n\n@dataclass\nclass Config:\n    timezone: ZoneInfo\n    session_id: UUID\n    theme_color: Color\n\nmarkdown = \"\"\"\n| Timezone | Session ID | Theme Color |\n| --- | --- | --- |\n| Asia/Tokyo | 12345678-1234-5678-1234-567812345678 | 255,0,0 |\n\"\"\"\n\nschema = ConversionSchema(\n    custom_converters={\n        # 標準ライブラリ型\n        ZoneInfo: lambda v: ZoneInfo(v),\n        UUID: lambda v: UUID(v),\n        # カスタムクラス\n        Color: lambda v: Color(*map(int, v.split(\",\")))\n    }\n)\n\ndata = parse_table(markdown).to_models(Config, conversion_schema=schema)\n# data[0].timezone is ZoneInfo(\"Asia/Tokyo\")\n# data[0].theme_color is Color(255, 0, 0)\n```\n\n**フィールド固有のコンバータ**\n\n詳細な制御のために、特定のフィールド名に対するコンバータを定義でき、これらは型ベースのコンバータよりも優先されます。\n\n```python\ndef parse_usd(val): ...\ndef parse_jpy(val): ...\n\nschema = ConversionSchema(\n    # 型ベースのデフォルト (低優先度)\n    custom_converters={\n        Decimal: parse_usd \n    },\n    # フィールド名のオーバーライド (高優先度)\n    field_converters={\n        \"price_jpy\": parse_jpy,\n        \"created_at\": lambda x: datetime.strptime(x, \"%Y/%m/%d\")\n    }\n)\n\n# price_usd (オーバーライドなし) -\u003e custom_converters (parse_usd)\n# price_jpy (オーバーライド)    -\u003e field_converters (parse_jpy)\ndata = parse_table(markdown).to_models(Product, conversion_schema=schema)\n```\n\n**標準コンバータライブラリ**\n\n一般的なパターン（通貨、リスト）については、独自に記述する代わりに、`md_spreadsheet_parser.converters` にある組み込みヘルパー関数を使用できます。\n\n```python\nfrom md_spreadsheet_parser.converters import (\n    to_decimal_clean,        # \"$1,000\", \"¥500\" -\u003e Decimal\n    make_datetime_converter, # 解析/TZロジックのファクトリ\n    make_list_converter,     # \"a,b,c\" -\u003e [\"a\", \"b\", \"c\"]\n    make_bool_converter      # カスタムの厳密なブール値セット\n)\n\nschema = ConversionSchema(\n    custom_converters={\n        # 通貨: $, ¥, €, £, カンマ, スペースを削除\n        Decimal: to_decimal_clean,\n        # DateTime: ISO形式デフォルト, ナイーブな場合はTokyo TZを付与\n        datetime: make_datetime_converter(tz=ZoneInfo(\"Asia/Tokyo\")),\n        # リスト: カンマで分割, 空白を除去\n        list: make_list_converter(separator=\",\")\n    },\n    field_converters={\n        # 特定のフィールドに対するカスタムブール値\n        \"is_valid\": make_bool_converter(true_values=[\"OK\"], false_values=[\"NG\"])\n    }\n)\n```\n\n### 9. 堅牢性 (不正なテーブルの処理)\n\nパーサーは、不完全なMarkdownテーブルを適切に処理するように設計されています。\n\n*   **列の欠落**: ヘッダーよりも列が少ない行は、自動的に空文字列で **パディング** されます。\n*   **余分な列**: ヘッダーよりも列が多い行は、自動的に **切り捨て** られます。\n\n```python\nfrom md_spreadsheet_parser import parse_table\n\nmarkdown = \"\"\"\n| A | B |\n|---|---|\n| 1 |       \u003c-- 列の欠落\n| 1 | 2 | 3 \u003c-- 余分な列\n\"\"\"\n\ntable = parse_table(markdown)\n\nprint(table.rows)\n# [['1', ''], ['1', '2']]\n```\n\nこれにより、`table.rows` は常に `table.headers` の構造と一致することが保証され、反復や検証中のクラッシュを防ぎます。\n\n### 10. セル内改行のサポート\n\nパーサーは、HTMLの改行タグを自動的にPythonの改行 (`\\n`) に変換します。これにより、複数行のセルを自然に扱うことができます。\n\n**サポートされているタグ (大文字小文字区別なし):**\n- `\u003cbr\u003e`\n- `\u003cbr/\u003e`\n- `\u003cbr /\u003e`\n\n```python\nmarkdown = \"| Line1\u003cbr\u003eLine2 |\"\ntable = parse_table(markdown)\n# table.rows[0][0] == \"Line1\\nLine2\"\n```\n\n**ラウンドトリップサポート:**\nMarkdownを生成する場合（例: `table.to_markdown()`）、Pythonの改行 (`\\n`) は、テーブル構造を維持するために自動的に `\u003cbr\u003e` タグに変換されます。\n\nこれを無効にするには、`ParsingSchema` で `convert_br_to_newline=False` を設定します。\n\n### 11. パフォーマンスとスケーラビリティ (ストリーミングAPI)\n\n**本当に10GBのMarkdownファイルがありますか？**\n\nおそらくないでしょう。そうでないことを心から願っています。Markdownはそのために作られたものではありません。\n\nしかし *万が一ある場合* —たとえば、膨大なログを生成していたり、標準コンバータの監査を行っている場合—このライブラリはあなたをサポートします。Excelが1,048,576行で諦める一方で、`md-spreadsheet-parser` は **無制限のサイズ** のファイルに対するストリーミング処理をサポートし、メモリ使用量を一定に保ちます。\n\n**scan_tables_iter**:\nこの関数はファイルを行ごとに読み込み、`Table` オブジェクトが見つかるたびにyieldします。ファイル全体をメモリに読み込むことは **ありません**。\n\n```python\nfrom md_spreadsheet_parser import scan_tables_iter\n\n# 巨大なログファイルを処理 (例: 10GB)\n# メモリ使用量は低いまま (単一のテーブルブロックのサイズのみ)\nfor table in scan_tables_iter(\"huge_server_log.md\"):\n    print(f\"Found table with {len(table.rows)} rows\")\n    \n    # 行の処理...\n    for row in table.rows:\n        pass\n```\n\nこれは、データパイプライン、ログ分析、および標準的なスプレッドシートエディタで開くには大きすぎるエクスポートの処理に最適です。\n\n### 12. プログラムによる操作\n\nこのライブラリは、データ構造を変更するための不変メソッドを提供します。これらのメソッドは、変更が適用された **新しいインスタンス** を返し、元のオブジェクトは変更しません。\n\n**ワークブック操作**\n```python\n# 新しいシートの追加 (ヘッダーA, B, Cを持つデフォルトテーブルを作成)\nnew_wb = workbook.add_sheet(\"New Sheet\")\n\n# シート名の変更\nnew_wb = workbook.rename_sheet(sheet_index=0, new_name(\"Budget 2024\"))\n\n# シートの削除\nnew_wb = workbook.delete_sheet(sheet_index=1)\n```\n\n**シート操作**\n```python\n# シート名の変更 (直接メソッド)\nnew_sheet = sheet.rename(\"Q1 Data\")\n\n# テーブルメタデータの更新\nnew_sheet = sheet.update_table_metadata(\n    table_index=0, \n    name=\"Expenses\", \n    description=\"Monthly expense report\"\n)\n```\n\n**テーブル操作**\n```python\n# セルの更新 (インデックスが範囲外の場合、自動的にテーブルを拡張)\nnew_table = table.update_cell(row_idx=5, col_idx=2, value=\"Updated\")\n\n# 行の削除 (構造的な削除)\nnew_table = table.delete_row(row_idx=2)\n\n# 列データのクリア (ヘッダーと行構造は保持し、セルを空にする)\nnew_table = table.clear_column_data(col_idx=3)\n```\n\n### 13. ビジュアルメタデータの永続化\n\nこのライブラリは、Markdownテーブルの構造自体を変更することなく、ビジュアル状態（列幅やフィルタ設定など）を永続化することをサポートしています。これは、テーブルの後に追加される隠しHTMLコメントによって実現されます。\n\n```markdown\n| A | B |\n|---|---|\n| 1 | 2 |\n\n\u003c!-- md-spreadsheet-table-metadata: {\"columnWidths\": [100, 200]} --\u003e\n```\n\nこれにより、以下のことが保証されます：\n1.  **クリーンなデータ**: テーブルは標準的なMarkdownのままであり、どのレンダラーでも読み取ることができます。\n2.  **リッチな状態**: 互換性のあるツール（私たちが提供するVS Code拡張機能など）は、このコメントを読み取ってUIの状態（列幅、非表示列など）を復元できます。\n3.  **堅牢性**: パーサーは、空行で区切られていても、このメタデータを直前のテーブルに自動的に関連付けます。\n\n### コマンドラインインターフェース (CLI)\n\n`md-spreadsheet-parser` コマンドを使用してMarkdownファイルを解析し、JSONを出力できます。これは、データを他のツールにパイプ処理する場合に便利です。\n\n```bash\n# ファイルから読み込む\nmd-spreadsheet-parser input.md\n\n# 標準入力（パイプ）から読み込む\ncat input.md | md-spreadsheet-parser\n```\n\n**オプション:**\n- `--scan`: ワークブック構造を無視してすべてのテーブルをスキャンします（テーブルのリストを返します）。\n- `--root-marker`: ルートマーカーを設定します（デフォルト: `# Tables`）。\n- `--sheet-header-level`: シートのヘッダーレベルを設定します（デフォルト: 2）。\n- `--table-header-level`: テーブルのヘッダーレベルを設定します（デフォルト: 3）。\n- `--capture-description`: テーブルの説明をキャプチャします（デフォルト: True）。\n- `--column-separator`: 列の区切りに使用する文字（デフォルト: `|`）。\n- `--header-separator-char`: 区切り行で使用する文字（デフォルト: `-`）。\n- `--no-outer-pipes`: 外側のパイプがないテーブルを許可します（デフォルト: False）。\n- `--no-strip-whitespace`: セルの値から空白を除去しません（デフォルト: False）。\n- `--no-br-conversion`: `\u003cbr\u003e` タグの改行への自動変換を無効にします（デフォルト: False）。\n\n## 設定 (Configuration)\n\n`ParsingSchema` と `MultiTableParsingSchema` を使用して、解析動作をカスタマイズできます。\n\n| オプション | デフォルト | 説明 |\n| :--- | :--- | :--- |\n| `column_separator` | `\\|` | 列の区切りに使用する文字。 |\n| `header_separator_char` | `-` | 区切り行で使用する文字。 |\n| `require_outer_pipes` | `True` | `True` の場合、生成されるMarkdownテーブルに外側のパイプが含まれます。 |\n| `strip_whitespace` | `True` | `True` の場合、セルの値から空白が除去されます。 |\n| `convert_br_to_newline` | `True` | `True` の場合、`\u003cbr\u003e` タグは `\\n` に変換されます（逆も同様）。 |\n| `root_marker` | `# Tables` | (MultiTable) データセクションの開始を示すマーカー。 |\n| `sheet_header_level` | `2` | (MultiTable) シートのヘッダーレベル。 |\n| `table_header_level` | `3` | (MultiTable) テーブルのヘッダーレベル。 |\n| `capture_description` | `True` | (MultiTable) ヘッダーとテーブルの間のテキストをキャプチャします。 |\n\n## エコシステム (Ecosystem)\n \nこのパーサーは、新しいエコシステムである **テキストベースの表計算管理** の中核となる基盤です。\n\nMarkdownファイルの完全なGUIスプレッドシートエディタとして機能する **[PengSheets](https://marketplace.visualstudio.com/items?itemName=f-y.peng-sheets)** を提供しています。\n\n**ビジョン: \"ExcelのようなUX、Gitネイティブなデータ\"**\n高パフォーマンスなエディタとこの堅牢なパーサーを組み合わせることで、ソフトウェアプロジェクトにおけるバイナリスプレッドシートファイルの管理という長年の問題を解決することを目指しています。\n*   **人間のために**: 快適で馴染みのあるUI（セルの書式設定、改善されたナビゲーション、視覚的なフィードバック）でデータを編集できます。\n*   **マシンのために**: データはクリーンで差分可能なMarkdownとして保存され、このライブラリが瞬時に解析、検証、Pythonオブジェクトへの変換を行います。\n\n## ライセンス\n\nこのプロジェクトは [MIT License](https://github.com/f-y/md-spreadsheet-parser/blob/main/LICENSE) の下でライセンスされています。\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff-y%2Fmd-spreadsheet-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ff-y%2Fmd-spreadsheet-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff-y%2Fmd-spreadsheet-parser/lists"}