Read, edit and write OpenDocument (.ods), Office Open XML (.xlsx),
Gnumeric and delimited text from Jennifer, over
one Workbook model of typed cells. It translates formulas between the ODS and
XLSX dialects, evaluates about 110 spreadsheet functions, applies number
formats and styles, streams sheets too large to hold in memory, and exports to
HTML, JSON and PDF.
jvc add @deckyard/sheetsjvc vendors the deck's src/ into vendor/deckyard/sheets/. Without jvc,
unpack src/ from a release archive (deckyard-sheets-<version>.tar.gz) into
that directory.
Requires Jennifer 0.25.0 or newer. No capabilities: no network, subprocesses
or database. open and save use fs; every codec also has a bytes entry
point.
import "@deckyard/sheets/" as sheet;
def wb as sheet.Workbook init sheet.open("sales.xlsx");
def s as sheet.Sheet init sheet.sheetByName($wb, "Q3");
for (def line in sheet.rows($s)) {
io.printf("%s: %f\n", sheet.asString($line[0]), sheet.asNumber($line[1]));
}
$s = sheet.addRow($s, [sheet.text("East"), sheet.number(1510.25)]);
$wb = sheet.putSheet($wb, $s);
sheet.save($wb, "sales.ods"); # the extension picks the format
tools/check-all.sh # the whole gate, as CI runs it
jennifer test src/sheets_test.j # the test suite
tools/check-extra.sh # LibreOffice / Gnumeric validation and oracles
tools/pack.sh dist # the release archiveCI also opens every written file in LibreOffice and compares the values back
(.github/workflows/validate.yml): the only check that catches a file this
deck reads but a real application rejects.
LGPL-3.0-only, see LICENSE. Copyright (C) 2026 mplx <mplx@jennifer-lang.dev>.