Convert XLSX workbooks to single styled HTML file with support for conditional formatting and in-cell images.
Project description
xx2html
xx2html converts Excel workbooks (.xlsx) into a single HTML file while preserving:
- Cell formatting and styles
- Conditional formatting classes (via
condif2css) - Worksheet link behavior
- Embedded worksheet images and in-cell rich-value images
Repository: https://github.com/gocova/xx2html
Issues: https://github.com/gocova/xx2html/issues
Installation
pip install xx2html
Usage
from xx2html import apply_openpyxl_patches, create_xlsx_transform
# Explicit entrypoint. Patches are also applied automatically on import.
apply_openpyxl_patches()
transform = create_xlsx_transform(
sheet_html=(
'<section id="{enc_sheet_name}" data-sheet-name="{sheet_name}">'
"{table_generated_html}"
"</section>"
),
sheetname_html='<a class="sheet-nav" href="#{enc_sheet_name}">{sheet_name}</a>',
index_html=(
"<!doctype html><html><head>"
"{fonts_html}{core_css_html}{user_css_html}{generated_css_html}"
"{generated_incell_css_html}{conditional_css_html}"
'</head><body data-source="{source_filename}">{sheets_names_generated_html}{sheets_generated_html}'
"{safari_js}</body></html>"
),
fonts_html="",
core_css="",
user_css="",
safari_js="",
apply_cf=True,
max_sheets=3, # optional preview limit
max_rows=200, # optional preview limit per sheet
max_cols=20, # optional preview limit per sheet
raise_on_error=False,
)
ok, err = transform("input.xlsx", "output.html", "en_US")
if not ok:
raise RuntimeError(err)
API Map
Public API (xx2html):
apply_openpyxl_patches() -> None- Applies required openpyxl monkey patches (idempotent).
create_xlsx_transform(...) -> Callable[[str, str, str], tuple[bool, str | None]]- Returns a transformer callable with signature
(source_xlsx, dest_html, locale). - Returns
(True, None)on success,(False, "<error repr>")on failure. - Optional preview controls:
max_sheets: convert only the first N visible sheets.max_rows: convert only the first N rows per included sheet.max_cols: convert only the first N columns per included sheet.
- Optional error mode:
raise_on_error=Trueraises the original exception instead of returning(False, ...).
- Returns a transformer callable with signature
Core helpers (xx2html.core, useful for advanced integrations):
get_worksheet_contents(...) -> WorksheetContentscova_render_table(worksheet_contents) -> strget_incell_images_refs(archive) -> tuple[dict[str, str], Exception | None]get_incell_css(...) -> strapply_cf_styles(html, cf_style_relations) -> strupdate_links(html, encoded_sheet_names, ...) -> str
Template Placeholders
sheet_html requires:
{enc_sheet_name}{sheet_name}{table_generated_html}
sheetname_html requires:
{enc_sheet_name}{sheet_name}
index_html requires:
{sheets_generated_html}{sheets_names_generated_html}{source_filename}{fonts_html}{core_css_html}{user_css_html}{generated_css_html}{generated_incell_css_html}{conditional_css_html}
index_html optional:
{safari_js}- If omitted while
safari_jsis non-empty, xx2html logs a warning and skips injection.
- If omitted while
Generated output also includes:
<meta name="generator" content="xx2html {version}">in<head><!-- Generated by xx2html {version} -->as the first node in<body>
Monkey Patching Behavior
xx2html relies on an openpyxl monkey patch to carry rich-value metadata used for in-cell images.
- The patch is applied automatically when
xx2html.coreis imported. - The explicit API entrypoint is
apply_openpyxl_patches(). xx2htmlvalidates theopenpyxlmajor/minor version before patching.- Set
XX2HTML_ALLOW_UNSUPPORTED_OPENPYXL=1to bypass the guard.
- Set
Development
pdm sync --group dev --frozen-lockfile
python3 tests/scripts/generate_fixtures.py
pdm run python -m compileall src tests
ruff check src tests
mypy src/xx2html
pdm run pytest
Release
- Stable releases are tag-driven and use SemVer tags:
vMAJOR.MINOR.PATCH(for examplev1.2.3). - Push the tag to GitHub; the
publishworkflow builds from SCM metadata and publishes with PyPI Trusted Publishing.
License
xx2html is dual-licensed under MIT or Apache-2.0.
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 xx2html-0.18.0rc1.tar.gz.
File metadata
- Download URL: xx2html-0.18.0rc1.tar.gz
- Upload date:
- Size: 139.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
380e835bbe2061529bbf6a881805e84d45304292cab85ade25947b2ea5066ae1
|
|
| MD5 |
bb7a1cd2f0b606697fa05f38821d12a7
|
|
| BLAKE2b-256 |
a22a8f8ffae78b2d3ef4c21630345e1297387ddde2a4b75c9e4e327d4d6187d9
|
Provenance
The following attestation bundles were made for xx2html-0.18.0rc1.tar.gz:
Publisher:
publish.yml on gocova/xx2html
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xx2html-0.18.0rc1.tar.gz -
Subject digest:
380e835bbe2061529bbf6a881805e84d45304292cab85ade25947b2ea5066ae1 - Sigstore transparency entry: 970336715
- Sigstore integration time:
-
Permalink:
gocova/xx2html@2baf5ad1e6e51dc215b702defd880d833178d8ec -
Branch / Tag:
refs/tags/v0.18.0rc1 - Owner: https://github.com/gocova
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2baf5ad1e6e51dc215b702defd880d833178d8ec -
Trigger Event:
push
-
Statement type:
File details
Details for the file xx2html-0.18.0rc1-py3-none-any.whl.
File metadata
- Download URL: xx2html-0.18.0rc1-py3-none-any.whl
- Upload date:
- Size: 29.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f529b18ce89458fa48c182ec513795f898bd9317669ce2df539d8c0f8c1554f4
|
|
| MD5 |
d13ba48e242ad4d9a2f981ccc8205ace
|
|
| BLAKE2b-256 |
7c0b43914d706cfef612d68a4ef45e5d2b6b161ae616470f5dbb236ee7480c57
|
Provenance
The following attestation bundles were made for xx2html-0.18.0rc1-py3-none-any.whl:
Publisher:
publish.yml on gocova/xx2html
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xx2html-0.18.0rc1-py3-none-any.whl -
Subject digest:
f529b18ce89458fa48c182ec513795f898bd9317669ce2df539d8c0f8c1554f4 - Sigstore transparency entry: 970336739
- Sigstore integration time:
-
Permalink:
gocova/xx2html@2baf5ad1e6e51dc215b702defd880d833178d8ec -
Branch / Tag:
refs/tags/v0.18.0rc1 - Owner: https://github.com/gocova
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2baf5ad1e6e51dc215b702defd880d833178d8ec -
Trigger Event:
push
-
Statement type: