Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

officework

xlsx and docx engines that do not destroy your forms — and that print. Read a spreadsheet or a document, change it, write it back with its borders, merges and styles intact, and turn it into a PDF. No office suite, no headless browser, no print driver.

Written in Rust (15,000+ lines, 240+ tests), exposed to Python through PyO3.

日本語の説明は GitHub にあります (Japanese documentation on GitHub): Python の手引き

Install

$ pip install officework

0.5.0 is in beta. It is published as a pre-release, so the line above still gives you 0.4.0. To try the beta:

$ pip install --pre officework

Wheels are abi3 (CPython 3.10+), so one wheel per platform covers every version; Linux, macOS and Windows are published. The wheel is just the engines — a few MB, no GUI, nothing to install alongside. pandas is imported only if you ask for it (pip install officework[pandas]).

Spreadsheets

from officework import sheet
b = sheet.Book.open("form7.xlsx")
s = b["quote"]
s["A30"] = "Nihon Funen Co., Ltd."       # borders, merges, widths stay intact
s["C30"] = "=B30*100"                    # a formula; recalculated on the spot
s.insert_row(30)                         # remaining formulas follow the move
b.save("out.xlsx")                       # shapes and print setup carried over

Documents

from officework import doc
d = doc.Doc.open("report.docx")
print(d.unsupported)                     # anything it could not read, never dropped in silence
d.replace("Old Name Ltd.", "New Name Ltd.")   # per-run formatting is left alone
d[3].text = "replaced"                   # the paragraph stays a heading, stays aligned
print(d.tables[0][1][2].text)            # table, row, cell
d.save("out.docx")                       # styles, headers, shapes, tracked changes carried over

PDF — the part the others cannot do

save() looks at the extension. The same book or document you just edited becomes a PDF, laid out by the same typesetting engine that drives the desktop app, so the paper matches the screen:

b.save("quote.pdf")                      # the sheet, paginated, repeating header rows
d.save("report.pdf")                     # the document, typeset

This runs on a server with nothing else installed. There is no LibreOffice to launch, no Chromium to drive, no wkhtmltopdf, no temporary HTML. It is one library call, and it is fast enough to sit inside a request handler.

Fonts are subsetted, so only the glyphs you used are embedded. A Japanese page comes out under 30 KB — measured here at 8 KB for plain text and 25 KB for a page with a table, colour and shading — where embedding a whole CJK font costs 20 MB. Line breaking follows JIS X 4051, so Japanese text does not break before a closing bracket or after an opening one.

Neither openpyxl nor python-docx can produce a PDF at all. The commercial libraries that can are priced accordingly.

Charts

Charts are drawn by this library, as shapes, rather than written as an instruction for Excel to render later. So they appear in the PDF, not only after someone opens the file in Excel:

ws.add_chart("bar", data="B3:C8", categories="A4:A8", at="A10",
             title="Target and actual")

Bar, line, pie and doughnut are built in. For finer control there is a small chart layer whose shape is borrowed from d3 — build a scale, then place marks through it:

from officework import chart
c = chart.Chart(340, 180, title="Attainment")
x = c.band(branches)
y = c.linear([0, 150])
c.axis_left(y, fmt=lambda v: f"{int(v)}%")
c.bars(x, y, rates, color="70AD47", labels=True)
c.place(ws, "A20")

What you give up is a live Excel chart: ours is fixed at the data it was drawn from. Redraw it to update it.

Equations

officework.tex takes LaTeX and returns SVG or PNG. With TeX installed it typesets there (matrix columns align); without it, matplotlib's mathtext does the job; with neither, it refuses with the reason — never a silent empty picture.

Your old vocabulary still works

Code written for openpyxl or python-docx largely runs as-is:

ws = wb.active                          # openpyxl: cell(), append, iter_rows,
ws.cell(2, 3).value                     #   dimensions, create_sheet,
ws.append(["Aug", "pens", 5000])        #   copy_worksheet, freeze_panes …
d.tables[0].cell(0, 1).text             # python-docx: row_cells, columns,
d[3].runs[0].font.name                  #   runs, clear …

The inventory — all 324 core members of the reference libraries, judged one by one — is in the repo: docs/pysheet-gokan.ja.adoc. Interop is proven with the originals' own eyes: openpyxl reads what this engine writes, including the computed values it cannot produce itself. See the Python manual for the details and the deliberate differences.

Why the engines exist

openpyxl and python-docx rewrite the parts of the file they do not understand. For a document used as a printed form — the way most Japanese offices use one — that means the borders, merged cells, column widths, shapes, styles and headers you spent an afternoon on come back wrong.

These engines keep the original as the source of truth and write back only what changed. b.unsupported / d.unsupported list anything they could not read, so nothing is dropped in silence.

The docx side is checked against an independent reader (genoffice's TypeScript docx engine) over 51 real documents, 43 of which this project did not write: 46 survive an open-and-save untouched, and no document loses a single part of its zip. The rest — footnote marks, second and later section breaks, equations — are listed in d.unsupported rather than dropped quietly.

Measured on one machine, 1096 rows × 20 columns (21,920 cells):

DataFrame → sheet 44 ms
sheet → DataFrame 65 ms

License

AGPL-3.0-or-later.

Using it inside your company — building forms, running ledgers, writing scripts — carries no obligations at all. Obligations appear only if you ship something built on it to third parties, or offer a modified version as a network service.

Release files for officework 0.5.0b2

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

Source distribution (sdist)

Source distribution for officework 0.5.0b2
File Size Uploaded
officework-0.5.0b2.tar.gz 972.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for officework 0.5.0b2
File Interpreter ABI Platform
officework-0.5.0b2-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
officework-0.5.0b2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
officework-0.5.0b2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 Details

Total release size: 14.5 MB

Release files / officework-0.5.0b2.tar.gz

Download URL officework-0.5.0b2.tar.gz
Size 972.5 kB
Tags Source
SHA-256 checksum
How to use checksums
eaac6d19678e73db9e4881c849d0ffd048afeac94b3b92a6219c87dc35e9e9ec
BLAKE2b-256 checksum
How to use checksums
c1fd146821cfaff560bbdbe064eefa8898ebd0d8e5978ce090b1f59feeb1bfbe
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 28, 2026.

Transparency log

Release files / officework-0.5.0b2-cp310-abi3-win_amd64.whl

Download URL officework-0.5.0b2-cp310-abi3-win_amd64.whl
Size 3.2 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
662328e590b578f8984630327379bbd3e153331adebb825b6d8b9ff4fdaa75ba
BLAKE2b-256 checksum
How to use checksums
2651b0fc631d2204f4e818775317259151fa8a9cba545b83cab59d097c3f03de
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 28, 2026.

Transparency log

Release files / officework-0.5.0b2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL officework-0.5.0b2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.7 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
ed78be2bbb1d590a09e3c2da5e325bb0ca7dce432920737c2e7ebba98ba4ce44
BLAKE2b-256 checksum
How to use checksums
6a8ec8600f05a6780d7c17e5c437f91248891c392eca251acad2be18c817c0b4
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 28, 2026.

Transparency log

Release files / officework-0.5.0b2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL officework-0.5.0b2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 6.6 MB
Tags CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
de6b586eb26f607402b9b2000287be18e6f221e3db7260c961ae3b6532df5b94
BLAKE2b-256 checksum
How to use checksums
e3406ddb43a73de1c6b7c1cc5968db4585d49dd96306446242af4f3c9dc6986e
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 28, 2026.

Transparency log
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