Convert Excel files to Markdown
Project description
xldown
Convert Excel (.xlsx) files to Markdown.
Install
uv pip install -e /path/to/xldown
CLI
xldown input.xlsx # creates input_output/ folder
xldown input.xlsx -o my_report # creates my_report/ folder
xldown --help
Output folder structure:
my_report/
├── output.md # converted markdown with tables and chart links
├── charts/ # rendered chart images (1.png, 2.png, ...)
└── images/ # extracted embedded images (1.png, 2.png, ...)
Python API
from xldown import excel_to_markdown
excel_to_markdown("data.xlsx", "my_report/")
Creates my_report/ with output.md, charts/, and images/ subdirectories.
Dependencies
- pandas
- openpyxl
- matplotlib
- click
- tabulate
- pydantic
Excel Edge Cases Handled
The converter is designed to gracefully handle common Excel edge cases without failing or losing data:
Worksheet and Cell-Level
- Empty worksheets: Worksheets with no cell content are skipped entirely (no output generated)
- Prose cells: Single isolated cells are rendered as plain text paragraphs
- Row length variance: Rows may have different numbers of cells; they are padded to the region's width before table construction
- Merged cells: Merged cell ranges are filled with the top-left cell's value and formatting applied to all cells in the range
- Hidden columns: Columns marked as hidden in the worksheet are detected and labeled with "(hidden)" in the table header
- Cell formatting: Rich text with character-level subscript/superscript (e.g., H₂O) is detected and rendered as
<sub>/<sup>HTML tags; cell-level formatting (bold, italic, strikethrough, superscript, subscript, rotation) is applied as Markdown or HTML annotations - Cell colors and borders: Font colors, background colors, and border styles are extracted and documented in an Annotations section below each table (filtering out default black/white)
- Cell metadata: Comments and hyperlinks are extracted and documented with cell coordinates below each table
Data Organization
- Non-contiguous regions: Adjacent cells are grouped into connected components (4-connected flood-fill), and isolated cells are treated as prose while multi-cell regions become tables
- Annotation grouping: Cells with identical formatting annotations are grouped into connected components; solid rectangles are expressed as ranges (e.g.,
A1:C3), while irregular patterns list individual cells
Chart Edge Cases
- Missing or invalid data: Empty charts, missing sheets, and malformed range references are silently skipped
- Data length mismatches: Series with varying lengths are padded with zeros; missing category labels are replaced with numeric indices
- Missing attributes: Unset or None chart attributes default to sensible values (e.g., "clustered" for bar grouping)
Chart Type-Specific Handling
- Single-series charts (Pie, Doughnut, Radar): Only the first series is plotted
- Stacked charts: Series are stacked correctly, with percent-stacked variants normalized to 100%
- Minimum requirements (Stock, Surface): Charts requiring specific data combinations may be skipped if incomplete
- Coordinate systems: Charts using special projections (3D, polar) are rendered with appropriate matplotlib settings
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xldown-0.1.0.tar.gz.
File metadata
- Download URL: xldown-0.1.0.tar.gz
- Upload date:
- Size: 23.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03a567d876d9f373cd4665ec831c30b6a91c3f40e058d1048889410e57f348d9
|
|
| MD5 |
cfd7c0a5cf323f781b93b988433dda1d
|
|
| BLAKE2b-256 |
1381b6b08b32ce4cb2bea2958d9bd084da58ecef15297fc9ecc264db19947b66
|
Provenance
The following attestation bundles were made for xldown-0.1.0.tar.gz:
Publisher:
publish.yml on clingen-data-model/xldown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xldown-0.1.0.tar.gz -
Subject digest:
03a567d876d9f373cd4665ec831c30b6a91c3f40e058d1048889410e57f348d9 - Sigstore transparency entry: 1487001210
- Sigstore integration time:
-
Permalink:
clingen-data-model/xldown@27f58eacd821c4879eedd3e276a887dbf9941028 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/clingen-data-model
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@27f58eacd821c4879eedd3e276a887dbf9941028 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xldown-0.1.0-py3-none-any.whl.
File metadata
- Download URL: xldown-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43cbe09e03151a40d0a1a588b113b6eed79bc8ddbd23b15aa0f66b86060bff10
|
|
| MD5 |
13de7483a6629567c675ee345f42eb44
|
|
| BLAKE2b-256 |
3d309d90eeb1cdedb44ab6ceb8b1f7e61d002497113e99a7b00bf752fe2427e9
|
Provenance
The following attestation bundles were made for xldown-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on clingen-data-model/xldown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xldown-0.1.0-py3-none-any.whl -
Subject digest:
43cbe09e03151a40d0a1a588b113b6eed79bc8ddbd23b15aa0f66b86060bff10 - Sigstore transparency entry: 1487001237
- Sigstore integration time:
-
Permalink:
clingen-data-model/xldown@27f58eacd821c4879eedd3e276a887dbf9941028 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/clingen-data-model
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@27f58eacd821c4879eedd3e276a887dbf9941028 -
Trigger Event:
push
-
Statement type: