Skip to main content

Composable framework for building styled Excel reports with openpyxl and matplotlib.

Project description

xllayout

Composable framework to build styled Excel reports with openpyxl and matplotlib.

Philosophy

xllayout is split into three layers:

  1. Theme: centralized visual tokens (fonts, fills, borders, number formats, spacing).
  2. Components: reusable blocks (TitleBlock, KpiCard, TableBlock, MatplotlibChart, etc.).
  3. Layouts: sheet composition using absolute canvas coordinates or Grid12.

This lets you place components at any coordinate without relying on cursor-based writing.

Structure

xllayout/
  pyproject.toml
  xllayout/
    __init__.py
    core/
      canvas.py
      cell_style.py
      grid.py
      style_sheet.py
      style_engine.py
      theme.py
      formats.py
      utils.py
    components/
      title.py
      text.py
      section.py
      kpi.py
      table.py
      chart.py
    layouts/
      summary.py
    writer/
      workbook.py
  examples/
    build_summary.py

Install

Editable (recommended for development):

pip install -e ".[charts]"

Standard install:

pip install ".[charts]"
  • Base dependency: openpyxl
  • Optional extra charts: matplotlib, Pillow

Quick API

from xllayout.core.theme import LightTheme
from xllayout.core.style_sheet import StyleSheet
from xllayout.layouts.summary import ExecutiveSummaryData
from xllayout.writer.workbook import ReportWriter

style_sheet = StyleSheet(
    styles={
        "title-block.subtitle": {"font_color": "#5B6570", "font_size": 9},
        "section-block.text": {"fill_color": "#E8EEF5", "bold": True},
        "kpi-card.value": {"font_size": 20, "bold": True, "font_color": "#0F4C81"},
        "table-block.header": {"align_horizontal": "center", "wrap_text": True},
    }
)

writer = ReportWriter(
    theme=LightTheme(style_sheet=style_sheet),
    detect_collisions=True,
)
wb = writer.new_workbook()
writer.build_summary_sheet(wb, data)  # data: ExecutiveSummaryData
wb.save("report.xlsx")

Style Tag + Local Override (v1.2.0)

Each component supports:

  • style="...": global style tags (like CSS classes)
  • style_props={...}: local overrides for that instance

style_props supports either:

  • flat dict for the container ({"fill_color": "...", "border_style": "thin"})
  • per-part dict ({"header": {...}, "body": {...}, "value": {...}})

Example:

from xllayout.components.table import TableBlock
from xllayout.core.cell_style import CellStyleSpec

table = TableBlock(
    headers=["id", "descripcion", "valor"],
    rows=[[1, "Texto largo que debe envolver en varias lineas", 1200]],
    col_widths=[10, 34, 14],
    number_formats_by_col={3: "#,##0"},
    style="table-block compact",
    style_props={
        "header": {"fill_color": "#E2EAF3"},
        "body": {"align_vertical": "center"},
    },
    body_style_by_col={
        1: CellStyleSpec(align_horizontal="center", bold=True),
        2: CellStyleSpec(wrap_text=True, align_vertical="top"),
        3: CellStyleSpec(align_horizontal="right", font_color="#1B4D8A"),
    },
    header_style=CellStyleSpec(
        bold=True,
        align_horizontal="center",
        fill_color="#E2EAF3",
        border_style="thin",
        border_color="#D0D7DE",
    ),
    header_row_height=24,
    default_row_height=32,
)

Supported style attributes (CellStyleSpec):

  • font: font_name, font_size, bold, italic, underline, font_color
  • cell: fill_color, border_style, border_color
  • alignment: align_horizontal, align_vertical, wrap_text, shrink_to_fit, text_rotation
  • format: number_format

Canvas vs Grid12

Absolute placement:

from xllayout.core.canvas import SheetCanvas

canvas = SheetCanvas(ws, theme, detect_collisions=True)
canvas.put(component, row=5, col=3)

Grid placement:

from xllayout.core.grid import Grid12

grid = Grid12(canvas)  # 12 tracks
grid.put(component, y=4, x=1, w=6, h=5)

If detect_collisions=True, overlapping components raise ValueError.

Build a New Layout

  1. Create a typed input dataclass under layouts/.
  2. In build(ws), initialize SheetCanvas and optionally Grid12.
  3. Place components with canvas.put(...) or grid.put(...).
  4. Expose a facade method in ReportWriter.

Run the example

python examples/build_summary.py

Output:

examples/output/summary_report_example.xlsx

Versioning and publishing

  • Uses SemVer (1.0.0, 1.0.1, 1.1.0, 1.2.0, ...).
  • Recommended for teams: publish to a private PyPI-compatible registry.

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

xllayout-1.2.1.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

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

xllayout-1.2.1-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

File details

Details for the file xllayout-1.2.1.tar.gz.

File metadata

  • Download URL: xllayout-1.2.1.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for xllayout-1.2.1.tar.gz
Algorithm Hash digest
SHA256 5e13be8128a4004877e560746cb41e500983b9f553dcde065066b3118c02f3dd
MD5 e363c62df2b37f9301995ab3c8c6903b
BLAKE2b-256 a361594dd659bc2bf6376c898b2150b2cda6dfd60f75fc9330caed8f753e7ba1

See more details on using hashes here.

File details

Details for the file xllayout-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: xllayout-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 24.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for xllayout-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d264d0d2f39b5636cf54dd6a70f73a6f1d81b41e4f4e675246531c97ee7ffa2e
MD5 adbe6d52b63aebb5a854171db3eef95b
BLAKE2b-256 c83e424111fd7e46916d8f110e88f3bac1aa3873d68a8c279161d558ea43db03

See more details on using hashes here.

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