Skip to main content

openpyxl-toolkit

PyPI Python versions CI Licence

Chainable formatting helpers for openpyxl worksheets that merge styles into what a cell already carries, rather than replacing the whole thing.

openpyxl stores a cell's style as one immutable object. Setting a font means building a whole Font and assigning it, which silently drops the size, the colour and everything else that was there. This toolkit allows you to change attributes one by one without having to copy previously set attributes.

>>> from openpyxl import Workbook
>>> from openpyxl_toolkit import WorksheetToolkit

>>> workbook = Workbook()
>>> sheet = workbook.active
>>> sheet["A1"] = "Region"

>>> toolkit = WorksheetToolkit(sheet)
>>> toolkit.set_font(cells="A1", size=14, color="#1d3557")
<WorksheetToolkit 'Sheet'>
>>> toolkit.set_font(cells="A1", bold=True)
<WorksheetToolkit 'Sheet'>

>>> sheet["A1"].font.sz, sheet["A1"].font.bold
(14.0, True)

The second call keeps the size and the colour. Written against openpyxl directly, sheet["A1"].font = Font(bold=True) would have thrown both away.

Install

pip install openpyxl-toolkit

Python 3.10 or newer, and openpyxl 3.1 or newer.

Choosing cells

Three ways, on every method that formats cells.

>>> toolkit.set_fill(cells="A1:C3", fill_type="solid", start_color="#f4f6f8")
<WorksheetToolkit 'Sheet'>
>>> toolkit.set_fill(cells="A:C", fill_type="solid", start_color="#f4f6f8")
<WorksheetToolkit 'Sheet'>
>>> toolkit.set_fill(rows=[1, 2], columns=[1, 2], intersections_only=True,
...                  fill_type="solid", start_color="#ffff00")
<WorksheetToolkit 'Sheet'>

cells takes a block ("A1:C3"), whole columns ("B:D"), whole rows ("2:5") or one cell ("C3"). Case does not matter, a reversed range such as "C3:A1" is normalised, and an unbounded side is filled in from the used range, so "B:B" means column B as far as the sheet goes rather than all 1,048,576 rows.

rows and columns take lists, for a selection that is computed rather than written out. A list, not a number:

>>> toolkit.set_font(rows=3, bold=True)
Traceback (most recent call last):
    ...
TypeError: rows takes a list of numbers, not a single one. Write rows=[3] rather than rows=3.

Tuples, ranges, sets and generators all work.

Given both rows and columns, intersections_only decides what they mean:

Cells formatted
intersections_only=True (default) where the rows and the columns cross — a block
intersections_only=False every cell in those rows and every cell in those columns — a cross

Giving both cells and rows/columns raises rather than quietly picking one.

Methods

Each returns the toolkit, so calls chain.

Method What it sets
set_font name, size, bold, italic, underline, strike, color
set_fill fill_type, start_color, end_color
set_alignment horizontal, vertical, text_rotation, wrap_text, shrink_to_fit, indent, reading_order
set_number_format how a value is displayed: currency, percent, dates, decimal places
set_border style and color, on any of six sides
set_outside_border one border around the edge of a block, leaving the inside alone
set_column_width / set_row_height an explicit size; 0 hides the column or row
set_column_best_fit a width that fits the widest cell
merge_cells / unmerge_cells a merged range; unmerging one that is not merged does nothing
freeze_panes rows above and columns left of a cell stay visible
set_zoom_scale 10 to 400

Every parameter is keyword-only, apart from freeze_panes, which takes its cell either way. Anything not named is left as it was, and None is not the same as leaving it out: set_font(color=None) clears the colour, while omitting color keeps whatever was there.

Fitting columns

set_column_best_fit measures every character at its own width in the font being used, so a column of i's does not come out as wide as a column of W's. Excel's own formula turns the total into a width:

width = (pixels of text + 5 padding pixels) / max digit width
>>> toolkit.set_column_best_fit(ignore_rows=[1], padding=1.5, min_width=9)
<WorksheetToolkit 'Sheet'>

Built-in metrics cover Aptos, Calibri, Arial, Helvetica, Times New Roman, Courier New, Cambria, Verdana, Georgia, Tahoma and Futura. Any other face is measured with Calibri's character widths unless measure is given.

Three items to note:

  • Text is assumed to be on one line. Wrapped text is not accounted for.
  • Only dates and times are rendered as Excel displays them. Other number formats, including the ones set_number_format writes, are measured as the value is stored, so a currency column can come out narrower than it needs to be. min_width is the answer.
  • Formula cells are skipped by default, since the formula text is not what the reader sees. Set that column's width directly, or pass ignore_formulas=False.

A merged title in row 1 will size column A to the whole title, because a merged range stores its value in the top-left cell. ignore_rows is what to reach for.

Type hints

The package ships py.typed. Alignment names, border styles, fill patterns and underline styles are Literal types, so an editor completes them and a checker catches a typo before the code runs:

error: Argument "horizontal" to "set_alignment" has incompatible type "Literal['centre']"

openpyxl rejects the same typo, but only once the call runs; the Literal types move it into the editor. Elsewhere the annotations really are stricter than openpyxl is at runtime, which matters more than it sounds: openpyxl accepts bold="no" and stores True, and name=42 and stores "42".

Licence

MIT.

Release files for openpyxl-toolkit 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openpyxl-toolkit 0.1.0
File Size Uploaded
openpyxl_toolkit-0.1.0.tar.gz 52.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openpyxl-toolkit 0.1.0
File Interpreter ABI Platform
openpyxl_toolkit-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 83.3 kB

Release files / openpyxl_toolkit-0.1.0.tar.gz

Download URL openpyxl_toolkit-0.1.0.tar.gz
Size 52.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3fba2b90781fe71775959f9df1ccbc0f325c5dd437d2d52def1293316b8d99ca
BLAKE2b-256 checksum
How to use checksums
022d6ede4e2440fcd75fff80c1e6f38e15abb7777fcb6b1e39170f229b7623a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / openpyxl_toolkit-0.1.0-py3-none-any.whl

Download URL openpyxl_toolkit-0.1.0-py3-none-any.whl
Size 30.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
093adfa70ed175e03f7eee6d20ea378fa7a0ead594ae1d3c1080c8b6210e101d
BLAKE2b-256 checksum
How to use checksums
ee8302243866280b1206bfe3ea4e73d74eae01fa730f0c912573ffcca0a43362
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page