Skip to main content

Create styled excel reports with declarative python.

Project description

xpyxl — Excel in Python

Compose polished spreadsheets with pure Python—no manual coordinates. You assemble rows/columns/cells; xpyxl handles layout, rendering, and styling with utility-style classes.

Core ideas

  • Positionless composition: Build sheets declaratively from row, col, cell, table, vstack, and hstack.
  • Composable styling: Tailwind-inspired utilities (typography, colors, alignment, number formats) applied via style=[...].
  • Deterministic rendering: Pure-data trees compiled into .xlsx files with predictable output—ideal for tests and CI diffing.

Installation

uv add xpyxl
pip install xpyxl

Getting started

import xpyxl as x

report = (
    x.workbook()[
        x.sheet("Summary")[
            x.row(style=[x.text_2xl, x.bold, x.text_blue])["Q3 Sales Overview"],
            x.row(style=[x.text_sm, x.text_gray])["Region", "Units", "Price"],
            x.row(style=[x.bg_primary, x.text_white, x.bold])["EMEA", 1200, 19.0],
            x.row()["APAC", 900, 21.0],
            x.row()["AMER", 1500, 18.5],
        ]
    ]
)

report.save("report.xlsx")

Primitives

x.row(style=[x.bold, x.bg_warning])[1, 2, 3, 4, 5]
x.col(style=[x.italic])["a", "b", "c"]
x.cell(style=[x.text_green, x.number_precision])[42100]
  • row[...] accepts any sequence (numbers, strings, dataclasses…)
  • col[...] stacks values vertically
  • cell[...] wraps a single scalar
  • All primitives accept style=[...]

Component: table

x.table(...) renders a header + body with optional style overrides. Combine with vstack/hstack for dashboards and reports.

sales_table = x.table(
    header_style=[x.text_sm, x.text_gray, x.align_middle],
    style=[x.table_bordered, x.table_compact],
)[
    {"Region": "EMEA", "Units": 1200, "Price": 19.0},
    {"Region": "APAC", "Units": 900, "Price": 21.0},
    {"Region": "AMER", "Units": 1500, "Price": 18.5},
]

layout = x.vstack(
    x.row(style=[x.text_xl, x.bold])["Q3 Sales Overview"],
    x.space(),
    x.hstack(
        sales_table,
        x.cell(style=[x.text_sm, x.text_gray])["Generated with xpyxl"],
        gap=2,
    ),
)

Tables also accept pandas-friendly shapes:

  • records: table()[[{"region": "EMEA", "units": 1200}, ...]] derives the header from dict keys (missing keys are filled with None).
  • dict of lists: table()[{"region": ["EMEA", "APAC"], "units": [1200, 900]}] zips columns together (lengths must match). Headers are inferred from your keys and default to bold text on a muted background; override with header_style=[...] when needed.

Utility styles (non-exhaustive)

  • Typography: text_xs/_sm/_base/_lg/_xl/_2xl/_3xl, bold, italic, mono
  • Text colors: text_red, text_green, text_blue, text_orange, text_purple, text_black, text_gray
  • Backgrounds: bg_red, bg_primary, bg_muted, bg_success, bg_warning, bg_info
  • Layout & alignment: text_left, text_center, text_right, align_top/middle/bottom, wrap, nowrap, wrap_shrink, allow_overflow, row_height(...), row_width(...)
  • Use allow_overflow when you want to keep a column narrow and let the text spill into adjacent empty cells, row_height(32) to force a specific row height, and row_width(12) to pin a column width.
  • Borders: border_all, border_top, border_bottom, border_left, border_right, border_x, border_y, border_red, border_green, border_blue, border_orange, border_purple, border_black, border_gray, border_white, border_muted, border_primary, border_thin, border_medium, border_thick, border_dashed, border_dotted, border_double, border_none
  • Tables: table_bordered, table_banded, table_compact
  • Number/date formats: number_comma, number_precision, percent, currency_usd, currency_eur, date_short, datetime_short, time_short

Border utilities can sit on individual cells or be applied at the row/column level for fast outlines.

Mix and match utilities freely—what you see is what you get.

Layout helpers

  • vstack(a, b, c, gap=1, style=[x.border_all]) vertically stacks components with optional blank rows and shared styles (great for card-like borders).
  • hstack(a, b, gap=1, style=[x.border_all]) arranges components side by side with configurable column gaps and shared wrapper styles.
  • space(rows=1, height=None) inserts empty rows (optionally with a fixed height).

Examples

  • Multi-sheet sales demo: see examples/multi_sheet_sales_demo.py.
    • Run it to generate a showcase workbook:
python examples/multi_sheet_sales_demo.py
  • Output: multi-sheet-sales-demo-output.xlsx with sheets Summary, Raw Data, Pipeline, and Glossary, demonstrating tables, stacks, spacing, and utility styles.
  • Run every demo at once: uv run scripts/run_all_examples.py

Types & ergonomics

  • Modern Python with full type hints.
  • Pure Python stack traces; easy to debug, script, and test.
  • Deterministic rendering for stable diffs in CI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xpyxl-0.4.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xpyxl-0.4.0-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file xpyxl-0.4.0.tar.gz.

File metadata

  • Download URL: xpyxl-0.4.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xpyxl-0.4.0.tar.gz
Algorithm Hash digest
SHA256 c1b2607c06c4ac35ec16a12032b6981b70c58db65d07f7088832df8662139e41
MD5 d399be8ceb925c8b79d4794f495e9fa7
BLAKE2b-256 65436d33045ff9fb372f98c22d7ca9d5ddb7fcf548e7d104af6466a8ed5951e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpyxl-0.4.0.tar.gz:

Publisher: publish.yml on dakixr/xpyxl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xpyxl-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: xpyxl-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xpyxl-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 33f72e2b4b42f8fbcb7a28c951a86a4492585bdaaa10f45cb431c8774751d468
MD5 4694053f954c1f2300647db133bd2336
BLAKE2b-256 4410edff81c652b6ddbfb2e33174afab8514664d577ed26d7a0d55335aa713a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpyxl-0.4.0-py3-none-any.whl:

Publisher: publish.yml on dakixr/xpyxl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page