Skip to main content

odsslicer

CI PyPI

Python reader and writer for .ods files (OpenDocument Spreadsheet — LibreOffice / OpenOffice Calc), with a numpy-inspired indexing API:

from odsslicer import ODSReader

table = ODSReader("workbook.ods")
sheet = table.sheet("Sheet1")

sheet["A1"].value          # typed value: str / float / bool / date / time / None
sheet["A1:B3"].to_numpy()  # any block as a numpy array
sheet[:, 0]                 # entire column A

sheet["C1"].formula = "SUM(A1:A10)"
sheet["C1"].style.bold = True
table.save("out.ods")                     # add recalculate=True to have LibreOffice compute formulas/pivots

odsslicer works directly on the ODF XML (via BeautifulSoup/lxml), so it preserves what other tools tend to drop — cell formats (currency, percentage, date, time), formulas, merged and repeated cells, styles, comments — and writes them back faithfully. It has no calculation engine of its own: like ODF itself, it describes what to compute — and can hand the file to a local LibreOffice (save(..., recalculate=True)) to compute formulas and pivot tables for you.

Full documentation with an example for every feature: DOCS.md.

Installation

pip install odsslicer

Requires Python ≥ 3.10. Dependencies (beautifulsoup4, lxml, numpy) are installed automatically. For local development:

git clone https://github.com/antnardo/odsslicer.git
cd odsslicer
pip install -e ".[test]"

What it does

Each line links to the detailed section (with examples) in DOCS.md.

Area Feature Example
Reading numpy-style indexing — addresses, slices, out-of-range returns empty cells sheet["A1"], sheet[0, 0], sheet["A1:B3"], sheet[:, 0]
Typed cells — value, displayed text, format, address cell.value, cell.text, cell.format
Arrays — to_list(), to_numpy(), numpy-like shapes sheet["A1:B3"].to_numpy()
Writing Values of every ODF type, then save() sheet["A1"].value = 42.5
Ranges at once — broadcast or element-wise sheet["A1:C1"].value = [1, 2, 3]
Auto-unrolling of repeated/merged cells on first write transparent
Auto-growth when writing past the sheet's extent sheet["Z100"].value = 1
Displayed text inferred from the document's own formats "50,00 %", "05/01/30"
Files & sheets New file from scratch ODSReader.new()
Add / rename / reorder / delete sheets — renaming fixes cross-sheet formulas table.rename_sheet("Sheet1", "Q4")
Structure Delete rows/columns — formula references follow, batchable sheet.delete_rows([3, 7, 20])
Copy cells/ranges — value + formula + style, overlap-safe sheet.copy("A1:B2", "D5")
Sort a range — stable, None last, formulas follow their row sheet.sort("A2:C10", by=1)
Merge / unmerge + read merge state sheet.merge("A1:C2"), cell.merge_range
Formulas Write in ordinary syntax, translated to ODF's cell.formula = "IF(A1>0,1,-1)"
Read back in ordinary syntax cell.formula_friendly
Fill across a range like a fill handle cell.fill_formula("B3:B10")
{r}/{c} templates for per-cell patterns sheet["A2:A10"].formula = "$A{r-1}+1"
Pivot tables — definition written, computed by the spreadsheet sheet.create_pivot_table(...)
Recalculate with LibreOffice — formulas + pivot refresh, headless, no UNO needed table.save("out.ods", recalculate=True)
Styles Read and write cell styles — font, colors, alignment, borders, rotation, wrap… cell.style.bold = True
Copy a style in one shot b.style = a.style
Number formats — read, assign, or create from scratch NumberFormat.create(table, "currency", ...)
Conditional formats (e.g. negatives in red) fmt.add_condition("value()<0", red)
Row / column / sheet styles — height, width, visibility, tab color sheet.column_style(0).width = "5cm"
Annotations Comments — text, author, date, visibility cell.comment = "Check this"
Hyperlinks cell.hyperlink = "https://…"
Document Properties — title, author, keywords, typed custom properties table.properties.title = "Q4"

See Known limitations for what's deliberately out of scope (no calculation engine, no charts/images, no partial rich text…).

Are there already equivalent PyPI modules?

Package Read/Write Latest release Notes
odfpy Low-level R/W 1.4.1 — Jan 2020 Dormant, but still the brick pandas uses internally
odfdo Full R/W 3.24 — Aug 2026 Actively maintained modern fork of odfpy; generic DOM-like API for all ODF document types
pyexcel-ods3 R/W 0.6.1 — Jan 2022 Inactive; values only, no styles/formulas
ezodf R/W 0.3.2 — Dec 2015 Abandoned
pandas (engine="odf") Read (via odfpy) follows pandas Convenient for data frames; loses formulas and fine-grained formats
python-calamine Read-only (Rust), fast 0.8 — Jul 2026 The best option for fast pure reading
pandas-ods-reader Read-only → DataFrame 1.0.2 — May 2025 Maintained, limited scope

(Versions and dates as of August 2026.)

Where odsslicer sits: a spreadsheet-shaped API (sheet["A1:B3"], numpy arrays, fill handles, copy/sort/merge) rather than a generic ODF DOM, with read and write of the things data-oriented tools usually lose — formats, formulas (in ordinary syntax), styles, merged cells, comments, pivot definitions — and every write verified against a real LibreOffice. If you only need to read values fast, use python-calamine; if you need to manipulate arbitrary ODF documents (text, presentations) at the XML level, use odfdo.

Tests

pip install -e ".[test]"
pytest

The main suite (tests/test_odsslicer.py) covers every feature above plus regression tests for the bugs fixed along the way; it runs on every push/PR via GitHub Actions across Python 3.10 to 3.13.

tests/test_libreoffice_consistency.py is an opt-in suite that hands files odsslicer wrote to a real, local LibreOffice (soffice --headless --convert-to fods) and inspects what LibreOffice itself made of them — the strongest available signal that a write is genuinely valid ODF, not just something our own reader happens to parse back. It skips automatically if no soffice/libreoffice binary is on PATH.

Versions

Version numbers are derived automatically from git tags (via setuptools-scm) and follow Semantic Versioning — while the major version stays 0, the API can still change between minor versions. See CHANGELOG.md (and the Releases page) for what changed in each version.

License

MIT — reuse with essentially no restriction, just keep the copyright notice.

Project name

odsslicer, to reflect the module's real differentiator — numpy-style indexing/slicing by cell address — rather than a generic "ods reader".

Release files for odsslicer 0.10.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 odsslicer 0.10.0
File Size Uploaded
odsslicer-0.10.0.tar.gz 4.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for odsslicer 0.10.0
File Interpreter ABI Platform
odsslicer-0.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 4.4 MB

Release files / odsslicer-0.10.0.tar.gz

Download URL odsslicer-0.10.0.tar.gz
Size 4.4 MB
Tags Source
SHA-256 checksum
How to use checksums
2e2ba3f52e116ed70560d55276da24f447d35760a5879c913ee782d098d2d401
BLAKE2b-256 checksum
How to use checksums
e32ce470495fff93733a84d5dbb3c4a5653aaefedad14bcb3fb382f6d3df78c6
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 Aug 24, 2026.

Transparency log

Release files / odsslicer-0.10.0-py3-none-any.whl

Download URL odsslicer-0.10.0-py3-none-any.whl
Size 66.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d19f9260435e5589b203a39c4f4181de8b3f23f57a8e8ded64d8137b936dffbc
BLAKE2b-256 checksum
How to use checksums
11bcc9c64119f0b7fab85502a432b29320f350b40380fe44494214cdb6051f8d
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 Aug 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.13.2

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.3

2 release files

0.12.2

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.11.1

2 release files

0.11.0

2 release files

This release

0.10.0 This release

2 release files

0.9.1

2 release files

0.9.0

1 release file

0.1.0

1 release file

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