Automation API¶
abax.api is a small, documented Python surface for driving abax headlessly —
open or create a workbook, read and write cells, let formulas recompute, and save
back out, all from an ordinary Python program. It is a thin convenience wrapper
over the engine (Document / Workbook / Sheet) and adds no
evaluation logic of its own, so anything you can do here you can also do against
the engine directly — this just makes the common case pleasant.
It needs only the standard library and the always-present engine; nothing on this
page requires an optional extra (opening a foreign format like .xlsx still uses
that format's adapter, exactly as the GUI does).
See also: index · macros & scripting · architecture · file formats · worked examples: first workbook, headless CLI.
A first script¶
import abax
book = abax.new() # a fresh workbook (one blank "Sheet1")
sheet = book.active # the active sheet
sheet["A1"] = 10 # write cells by A1 reference
sheet["A2"] = 20
sheet["A3"] = "=SUM(A1:A2)"
print(sheet["A3"]) # -> 30 (computed on read)
book.save("totals.abax") # native JSON format, chosen from the extension
abax.new() and abax.open(path) are the two entry points; both return a
Book.
Reading and writing cells¶
A Sheet is addressed two ways — pick whichever reads better at the call site.
By A1 string (subscript).
sheet["B2"] = "=A1*2" # write one cell
value = sheet["B2"] # read one computed value -> a number/str/bool/None
block = sheet["A1:B3"] # read a range -> a 2-D list: rows of columns
raw = sheet.formula("B2") # the raw source text -> "=A1*2"
sheet["A1:B3"] returns a list of rows, each a list of column values:
sheet["A1"] = 1; sheet["B1"] = 2
sheet["A2"] = "=A1+10"; sheet["B2"] = "=B1+10"
sheet["A1:B2"] # -> [[1, 2], [11, 12]]
Assigning to a range key is rejected (raise cell-by-cell, or use set in a
loop) — a subscript write always targets a single cell.
By zero-based coordinates — convenient inside loops:
for r in range(10):
sheet.set(r, 0, r) # A1..A10 = 0..9 (row, col are 0-based)
sheet.set(r, 1, f"=A{r+1}*A{r+1}")
total = sum(sheet.value(r, 0) for r in range(10))
Values you write are coerced the way typing into a cell would be: strings pass
through verbatim (so "=SUM(...)" stays a formula), numbers and booleans
round-trip through the engine's literal parsing, and None clears the cell.
Reads return computed values. A blank cell reads as None; a formula that
errors reads as a CellError value (its str() is the Excel code):
from abax.core.errors import CellError
sheet["A1"] = "=1/0"
v = sheet["A1"]
isinstance(v, CellError) # True
str(v) # "#DIV/0!"
Use sheet.formula(ref) when you want the source text instead of the value.
Recalculation¶
The API uses the engine's default automatic calculation. Every edit invalidates the cached values of the cells that depend on it, so the next read recomputes them lazily and on demand — reads always reflect the current formulas, with no explicit step to remember:
sheet["A1"] = 10
sheet["B1"] = "=A1*2"
sheet["B1"] # -> 20
sheet["A1"] = 100 # a dependency changes...
sheet["B1"] # -> 200 (refreshed on read, automatically)
book.recalc() forces a full recompute of every cell (the equivalent of the
GUI's F9). You rarely need it — reach for it after a bulk edit, to refresh a
volatile function, or if you have switched the underlying workbook to manual
calculation.
Multiple sheets¶
book = abax.new()
data = book.add_sheet("Data") # add and return the new sheet
data["A1"] = 5
book["Sheet1"]["A1"] = "=Data!A1*2" # cross-sheet reference
book["Sheet1"]["A1"] # -> 10
book.sheets # -> ["Sheet1", "Data"] (names, in order)
"Data" in book # -> True
[s.name for s in book] # iterate sheets as Sheet wrappers
book["Missing"] # -> KeyError (message lists the sheets that exist)
add_sheet with no name lets the engine pick the next "SheetN"; a duplicate
name raises ValueError.
Opening, saving, round-tripping¶
abax.open(path) reads any format the engine recognizes from its extension —
.abax / .json (native), .csv / .tsv, .xlsx, .parquet, .ods, and
more. book.save(path) writes, choosing the format from the
extension; book.save() with no argument re-saves to the path the book was opened
from (and raises ValueError if there is none).
book = abax.open("input.csv")
book.active["D1"] = "=SUM(A1:C1)"
book.save("output.abax") # convert CSV -> native, formulas and all
again = abax.open("output.abax")
again.active["D1"] # the formula survived and recomputes
Context manager¶
A Book is a context manager, which is handy for scoping a short automation:
The with block does not auto-save on exit — persistence is always an
explicit book.save(...), so a read-only or aborted block leaves the file
untouched.
Reference¶
| Call | Result |
|---|---|
abax.open(path) |
open a file → Book |
abax.new() |
fresh empty workbook → Book |
book[name] |
the named Sheet (KeyError if missing) |
book.active |
the active Sheet |
book.sheets |
list of sheet names, in order |
book.add_sheet(name=None) |
add and return a Sheet (ValueError on duplicate) |
book.recalc() |
force a full recompute (F9) |
book.save(path=None) |
write to path, or the opened-from path |
sheet[ref] |
computed value (scalar) or 2-D list (range) |
sheet[ref] = value |
set one cell (value coerced; None clears) |
sheet.value(row, col) |
computed value at zero-based (row, col) |
sheet.set(row, col, text) |
set the cell at zero-based (row, col) |
sheet.formula(ref) |
raw source text of a cell |
sheet.name |
the sheet's name |
For anything beyond this surface — styling, insert/delete rows, conditional
formats, the science/RF toolkit — reach through book.workbook (the core
Workbook) or sheet.core (the core Sheet); see
macros & scripting and
architecture.
```