sheetpeek
sheetpeek shows an Excel workbook the way Excel shows it: as HTML, Markdown, terminal output or plain text. It is pure Python, needs no office suite, and gives programs access to the rendered cells. Number formats are applied by xlformat, whose output is tested against text captured from Excel 16 for Mac.
Documentation: https://sheetpeek.readthedocs.io.
Reading a sheet
read returns a Sheet: the cached values, number formats, styles, column widths, row
heights and merged ranges of one worksheet. Dates stay the serial numbers Excel stores.
>>> import tempfile, pathlib, openpyxl, sheetpeek
>>> path = pathlib.Path(tempfile.mkdtemp()) / "example.xlsx"
>>> wb = openpyxl.Workbook()
>>> wb.active["A1"] = 1234.5
>>> wb.active["A1"].number_format = "#,##0.00"
>>> wb.active.merge_cells("B1:C1")
>>> wb.save(path)
>>> sheet = sheetpeek.read(path)
>>> cell = sheet.cell(1, 1)
>>> cell.value, cell.kind, cell.number_format
(1234.5, 'number', '#,##0.00')
>>> [str(m) for m in sheet.merges]
['B1:C1']
Showing a sheet
sheetpeek.render draws a sheet with a backend. Each shows what Excel shows, as far as its
format can: number formats, # for a number too wide for its column, text spilling into empty
neighbors.
>>> path = pathlib.Path(tempfile.mkdtemp()) / "sales.xlsx"
>>> wb = openpyxl.Workbook()
>>> ws = wb.active
>>> ws.append(["Region", "Sales", "Change"])
>>> ws.append(["North", 1234.5, 0.125])
>>> ws.append(["South", -98765.4, -0.0425])
>>> ws.append(["A note long enough to spill"])
>>> for row in (2, 3):
... ws.cell(row, 2).number_format = "#,##0.00;[Red]-#,##0.00"
... ws.cell(row, 3).number_format = "0.0%"
>>> wb.save(path)
>>> sales = sheetpeek.read(path)
>>> print(sheetpeek.render(sales, "text"), end="")
Region Sales Change
North 1,234.50 12.5%
South ######## -4.3%
A note long enough to spill
>>> print(sheetpeek.render(sales, "markdown"), end="")
| Region | Sales | Change |
| --- | ---: | ---: |
| North | 1,234.50 | 12.5% |
| South | -98,765.40 | -4.3% |
| A note long enough to spill | | |
>>> print(sheetpeek.render(sales, "csv"), end="")
Region,Sales,Change
North,"1,234.50",12.5%
South,"-98,765.40",-4.3%
A note long enough to spill,,
>>> page = sheetpeek.render(sales, "html") # a static page in Excel's own geometry
>>> page.startswith("<!doctype html>")
True
Fixed-width text gives every column its width in characters; Markdown and CSV have no widths,
so they show every value in full. HTML is drawn in points from Excel's layout: column widths,
row heights, each text's position and clip window, the # runs in the section's color (the
negative is red), and fills. sheetpeek.render(sales, "rich"), or rich.print(sales), draws
the fixed-width layout in a terminal with fonts, colors and fills (the optional rich extra).
From the command line:
sheetpeek view sales.xlsx # rich on a terminal, plain text when piped
sheetpeek view sales.xlsx -t html > sales.html
sheetpeek serve reports/ # every workbook under reports/ as HTML pages
Sheet.layout gives the layout itself, the data every backend draws from: in excel mode each
column's position and width and each text's position in points, in characters mode the
characters each column draws. The documentation's usage page has examples.
Cells are read with openpyxl's read-only mode, so memory does not grow with the file while it is
read. The parts read-only mode leaves out, such as merges, widths and the used range, come from a
separate scan of the sheet's XML. ref="A1:H40" reads part of a sheet, and sheetpeek.open
reads several sheets with one load.
A file from someone you do not trust is checked before anything parses it, and limits= sets what
a read may cost; the documentation's usage page has the details. sheetpeek serve has no
authentication: with --host, anyone who can reach the address can read the folder. It is not for
production: it is built on Python's http.server, which Python's documentation does not recommend
for production. For a production service, call the Python API from a web framework and pass
limits=, since the library's defaults are not memory-safe for untrusted files.
Installation
pip install sheetpeek
pip install "sheetpeek[rich]" # with styled terminal output
Python 3.11 or later. Depends on openpyxl and xlformat.
Related packages
sheetpeek is part of the sheetmill project, with xlformat, which applies Excel number formats, and xlrecalc, a formula engine.
Development
uv sync --group docs then uv run pytest; CONTRIBUTING.md has the pip route, the full set of
checks and the commit conventions. ARCHITECTURE.md describes the design and the measurements
behind it.
Most of the code is written with Claude Code, reviewed before each commit and tested against
output captured from Excel; see CONTRIBUTING.md.
License
MIT.
Metadata
Release files for sheetpeek 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sheetpeek-0.2.0.tar.gz | 193.4 kB | With provenance | Details for sheetpeek-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sheetpeek-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for sheetpeek-0.2.0-py3-none-any.whl |
Total release size: 260.6 kB
Release files / sheetpeek-0.2.0.tar.gz
| Download URL | sheetpeek-0.2.0.tar.gz |
|---|---|
| Size | 193.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a34d62dbe2c9ef432bcceb63def6edab0119c317f059af97411e92e4b26bb0a
|
|
BLAKE2b-256 checksum How to use checksums |
6a25db11aaa33129a618609d21b2690e3261e8c27fe70c22df8119fec5be1e69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 5, 2026.
Transparency logRelease files / sheetpeek-0.2.0-py3-none-any.whl
| Download URL | sheetpeek-0.2.0-py3-none-any.whl |
|---|---|
| Size | 67.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2570622ffa1fc546987c66bdc9ddd3865a55685dc8f372b112a83fc8f6d84829
|
|
BLAKE2b-256 checksum How to use checksums |
b2076ba3ff569bc8e34e9df760d544a5503c6f2c1d4bf602c246bbe7812f214b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 5, 2026.
Transparency logSecurity for sheetpeek 0.2.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for sheetpeek-0.2.0.tar.gz
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 Nov 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.