Wrapper around xlsxwriter to improve usability
Project description
Excelipy
Installation
You can install the package using pip:
pip install excelipy
Or add it as a dependency in your pyproject.toml:
uv add excelipy
Appeal
This was created with less than 100 lines of code, in a declarative, clean, and easy to understand style:
Usage
Detailed Model Overview
Excelipy is built on top of Pydantic models, making it easy to define your Excel structure programmatically.
Excel
The top-level container for your workbook.
path: Path to the output file (string,Path, orBytesIO).sheets: A list ofSheetobjects.nan_inf_to_errors: IfTrue(default), convertsNaNandInfvalues to Excel errors.
Sheet
Represents a single worksheet.
name: The name of the sheet.components: A list of components (Tables, Text, etc.) to be rendered sequentially.grid_lines: Boolean to show or hide grid lines.style: AStyleobject to apply to the entire sheet (e.g., padding).
Table
The main component for rendering data.
data: Apandas.DataFrame.header_style: A dictionary mapping column names toStyleobjects.body_style: A defaultStylefor the table body.column_style: Styles for specific columns. Can be aStyleobject or a function that returns aStylebased on cell value.row_style: Styles for specific rows.header_filters: Boolean to enable/disable Excel header filters.merge_equal_headers: Boolean. IfTrue, adjacent columns with the same name will have their headers merged.
Style
Defines how cells look. Supports most common Excel formatting:
- Font:
bold,font_color,font_family,font_size,underline. - Alignment:
align(left, center, right, etc.),valign(top, vcenter, bottom),text_wrap. - Border:
border(sets all sides) or individualborder_top,border_bottom, etc.border_color. - Background:
background(hex color). - Format:
numeric_format(e.g.,"0.00%","#,##0.00").
Other Components
Text: A simple text cell or merged range. Supportswidth,height, andstyle.Link: A clickable hyperlink (This can be nested inside aTablecomponent).Image: Embeds an image from apath.Fill: Empty space component to push other components down or across.
Examples
Displaying a table
The most basic usage is to display a pandas.DataFrame as a table.
import excelipy as ep
df = ... # your pandas DataFrame
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[ep.Sheet(name="Sheet1", components=[ep.Table(data=df)])],
)
)
By default, ep.Table renders a pandas.DataFrame with standard formatting, including header filters and automatic
column width adjustment.
Basic column formatting
You can apply styles to headers and specific columns. Here, we use header_style to bold and center the headers, and
column_style to format the "Value" column with two decimal places.
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[
ep.Sheet(
name="Sheet1",
components=[
ep.Table(
data=df,
header_style={
col: ep.Style(
bold=True, align="center", valign="vcenter"
)
for col in df.columns
},
column_style={"Value": ep.Style(numeric_format=",.2f")},
)
],
)
],
)
)
The output shows bold, centered headers and a formatted numeric column.
Adding a title
You can add text components above or around your tables. In this example, an ep.Text component is added before the
ep.Table. We set its width to match the number of columns in the table and apply a background color and centered
alignment to create a unified title bar.
num_cols = len(df.columns)
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[
ep.Sheet(
name="Sheet1",
components=[
ep.Text(
text="Sales by Product",
width=num_cols,
style=ep.Style(
bold=True,
background="#ecedef",
align="center",
valign="vcenter",
),
),
ep.Table(
data=df,
header_style={
col: ep.Style(
bold=True, align="center", valign="vcenter"
)
for col in df.columns
},
column_style={"Value": ep.Style(numeric_format=",.2f")},
),
],
)
],
)
)
The resulting Excel sheet features a stylized title spanning across the top of the table.
Category coloring
Styles can be applied dynamically based on the cell content. By passing a function to column_style, we can change the
background and font color of the "Store" column depending on its value, making different categories easy to distinguish.
def get_store_color(store: str) -> ep.Style:
return ep.Style(
background=store_colors[store],
font_color=choose_font_color(store_colors[store]),
bold=True,
)
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[
ep.Sheet(
name="Sheet1",
components=[
ep.Table(
data=df,
column_style={
"Value": ep.Style(numeric_format=",.2f"),
"Store": get_store_color,
},
),
],
)
],
)
)
Each store now has its own unique color coding in the "Store" column.
Merging columns
By giving multiple columns the same name and setting merge_equal_headers=True (which is the default), they will be
merged in the header. In this example, all columns are renamed to the same title, creating a single merged header over
the entire table. We also use idx_column_style to apply styles by column index instead of name.
unified = "Sales by Product by Store"
df = df.rename(columns={col: unified for col in df.columns})
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[
ep.Sheet(
name="Sheet1",
components=[
ep.Table(
data=df,
header_style={
col: ep.Style(
bold=True, align="center", valign="vcenter"
)
for col in df.columns
},
body_style=ep.Style(align="center", valign="vcenter"),
idx_column_style={
0: get_store_color,
2: ep.Style(numeric_format=",.2f"),
},
header_filters=False,
)
],
)
],
)
)
The header columns are merged into one, and the body cells are centered.
Conditional formatting
You can also apply row-wise conditional formatting. Using the @ep.row_wise decorator on a styling function allows you
to access the entire row's data. Here, we highlight "Value" in red if it falls below the average for that product. We
also hide grid_lines and add padding to the sheet for a cleaner look.
@ep.row_wise
def get_value_style(row) -> ep.Style:
store, product, value = row
prod_avg = avg_by_product[product]
if value < prod_avg:
return ep.Style(font_color="#ff0014", numeric_format=",.2f", bold=True)
return ep.Style(numeric_format=",.2f", bold=True)
ep.save(
excel=ep.Excel(
path="output.xlsx",
sheets=[
ep.Sheet(
name="Sheet1",
components=[
ep.Table(
data=df,
idx_column_style={
0: get_store_color,
2: get_value_style,
},
header_filters=False,
),
ep.Fill(width=num_cols),
ep.Text(
text="Products that sold below average are highlighted in red",
style=ep.Style(
bold=True,
valign="vcenter",
align="center",
border=3,
border_color="#ff0014",
),
width=num_cols,
height=3,
),
],
grid_lines=False,
style=ep.Style(padding=2),
)
],
)
)
The final output features conditional red text for below-average sales, a descriptive footer box, and no visible grid lines.
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 excelipy-1.1.0.tar.gz.
File metadata
- Download URL: excelipy-1.1.0.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1df6c670e37da33ab17411ed0af02272967f368b0003d2c1eee9cf0ce76e08d4
|
|
| MD5 |
16c45dab103dd6e07777fe4dd41dbd5f
|
|
| BLAKE2b-256 |
af89e57cd2dd9ea69419f82c83ae47562fc22637ddc44e0323cb5e68d99e1744
|
File details
Details for the file excelipy-1.1.0-py3-none-any.whl.
File metadata
- Download URL: excelipy-1.1.0-py3-none-any.whl
- Upload date:
- Size: 17.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a3d42aaa3deb6f482877b27a6ae21f913d1c4b9035b76869914db0346d04684
|
|
| MD5 |
ece6c1998f3dfbf9b8a32e6ae82b9004
|
|
| BLAKE2b-256 |
37d8d1a4621fa567a3585220955bb1c91a2e47df1af1ffe45a983e08ae163bfd
|