Skip to main content

officework

xlsx and docx engines that do not destroy your forms, plus a bridge that drives a running office app from Python — the way xlwings drives Excel, but on your own machine and without Excel.

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

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

Install

$ pip install officework

Wheels are abi3 (CPython 3.10+), so one wheel per platform covers every version; Linux, macOS and Windows are published. From 0.4.0 the wheel also carries the apps themselves — see below. pandas is imported only if you ask for it (pip install officework[pandas]).

Three ways in

from officework import sheet             # the engine — no app needed
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
from officework import doc               # the engine — docx, no app needed
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
from officework import calc as xw        # the bridge — drives the running app
import pandas as pd

wb = xw.Book()                           # a blank workbook comes up
wb.sheets.active["A1"].value = df        # the DataFrame lands in the sheet
df2 = wb.sheets.active["A1"].options(pd.DataFrame, expand="table").value

The bridge talks over a unix socket on this machine only — no TCP is opened. It needs officework running.

Let an AI drive the app (MCP)

$ pip install "officework[mcp]"

That installs officework-mcp, an MCP server speaking over stdin/stdout. Register it with an MCP client (Claude Code, Claude Desktop, …) and the assistant can read and write the workbook you have open — the same bridge the Python API uses, so the same rules apply: your machine only, no TCP.

// claude_desktop_config.json
{ "mcpServers": { "officework": { "command": "officework-mcp" } } }

The tools it exposes are deliberately few: book_info, used_range, read_range, read_formulas, write_range, set_format, autofit, save. Reading a range gives values; read_formulas gives the formulas behind them.

The apps come with it too

$ officework-calc report.xlsx
$ officework-writer report.docx

Since 0.4.0 the wheel carries the two apps (around 36 MB on Linux and Windows; more for the universal macOS wheel, which holds both architectures), so pip install officework is all it takes to get a spreadsheet and a word processor with a window. They are the same binaries the installers ship.

This is the least troublesome way to get them: a file that pip put on your disk carries neither macOS's quarantine flag nor Windows' Mark of the Web, so Gatekeeper and SmartScreen never ask. Nor is a bundled Python needed — you already have one.

If you would rather point at a build of your own:

$ OFFICEWORK_CALC=/path/to/calc officework-calc report.xlsx

Your old vocabulary still works

Code written for openpyxl, xlwings 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 …
xw.Range("B2").offset(1, 2).address     # xlwings: '$D$3' — resize,
xw.Range("A1").current_region           #   last_cell, current_region …
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 three libraries, judged one by one — is in the repo: docs/pysheet-gokan.ja.md. 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.

Since 0.3.0 the wheel also typesets 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.

New in 0.4.0, the bridge reaches the rest of a cell's formatting — align, valign, indent, rotation, shrink, locked, underline, strike, superscript, subscript — plus page setup and the table-design commands, so a macro can finish a form rather than only fill it.

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.4.0

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

Built distributions (wheels)

Table of built distributions (wheels) for officework 0.4.0
File Interpreter ABI Platform
officework-0.4.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
officework-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
officework-0.4.0-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 11.0+ ARM64, macOS 10.12+ x86-64 Details

Total release size: 100.2 MB

Release files / officework-0.4.0-cp310-abi3-win_amd64.whl

Download URL officework-0.4.0-cp310-abi3-win_amd64.whl
Size 22.1 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
387d67b4aeb960cb186d8a7ee2852f871af7f51a71caea6ebd9cc77367b11bb1
BLAKE2b-256 checksum
How to use checksums
7fe706bc0a08c20de05c1437d1c4f9f73150a73cc499f3606ce34b73e9d5d3cd
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 17, 2026.

Transparency log

Release files / officework-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL officework-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 37.4 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
507126431b7a824d87e617bfe8b6a5586741ce0b9244febc66f8104df4f08c43
BLAKE2b-256 checksum
How to use checksums
a40255ad362d12f92e124bf586240bc28ccab4b8718e32d37cfd0f76b8c9d48d
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 17, 2026.

Transparency log

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

Download URL officework-0.4.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 40.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
35327de6cff47768518b2e481302e650530a1d38d0d1f06ce7f1d323357d7ac0
BLAKE2b-256 checksum
How to use checksums
87d8a30f9bb385a3e285e211045453343edb3ee2679edc426946219f80008146
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 17, 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