The parser upper-cases function names, so =Double(4) showed as
=DOUBLE(4). Calls of LAMBDA names are now spelled like the name when
a formula is entered and when a file is read.
They are not error codes of the file format, and Excel refuses to open a
file whose cached values contain them ("Parameter error"). Any workbook
with a blocked spill could not be opened in Excel. Excel caches these
errors as #VALUE! itself.
Add support for Excel's "smoothed line" chart style. The smooth flag flows
model -> resolve -> chart render, persists through XLSX (<c:smooth val="1"/>),
and is toggled via the chart.addElement "smooth" element.
Rendering interpolates each gap-free run with a uniform Catmull-Rom spline
(0.5 tangent scale, 100 sub-segments per data segment), so the curve passes
through every data point and rounds the vertices — matching Excel's observed
behaviour. Long runs are still decimated before smoothing.
- model: Series.smooth (#[serde(default)], so old workbooks load unchanged)
- chart: SeriesData.smooth; smooth_run + catmull in render; wired through
resolve and the sanitize() copy; draw_runs takes the flag (line + scatter)
- engine: chart.addElement element="smooth"
- xlsx: read/write <c:smooth val> instead of hard-coding val="0"
- tests: smooth_line_adds_interpolated_points_and_keeps_endpoints,
smooth_line_splits_at_gaps, smooth_line_setting_round_trips
- examples/smooth_demo.rs: generates a straight+smooth side-by-side workbook
cargo xtask ci: all 7 steps pass.
Opening an .xlsm and saving it silently stripped xl/vbaProject.bin, turning a
macro-enabled workbook into a macro-free one — data loss for anyone whose work
depends on macros. GridCraft still does not run VBA, but it now carries the
project through unchanged.
- model: `Workbook.vba_project: Option<Vec<u8>>` (base64 in JSON via a new
`b64::opt` helper). `None` = no macros.
- xlsx read: capture the `vbaProject` relationship's bytes instead of warning
and dropping them; warn that macros are kept but not executed.
- xlsx write: when present, emit `xl/vbaProject.bin` byte-identical, add the
`.../relationships/vbaProject` relationship, switch the main part to the
macro-enabled content type (`...sheet.macroEnabled.main+xml`) and add the
`application/vnd.ms-office.vbaProject` override.
- engine: `view.macros` lists the preserved project alongside GridCraft's own
scripts (`{"kind":"vba","executed":false}`), so callers can see it is there.
- ROADMAP: scope now "preserve, don't execute" (was "out of scope").
Tests: round-trip byte-identical blob + correct content types/relationship;
capture from a foreign-produced .xlsm; a macro-free workbook stays clean.
Excel-encrypted workbooks are CFB/OLE2 compound files (magic D0CF11E0),
not zip packages. sniff() now returns Format::Encrypted for them, and
open_bytes reports a clear password-protected message instead of the
cryptic 'not a valid zip package' error.
Excel anchors a floating object to the grid in one of three ways, stored in the
file as the drawing anchor's `editAs`: "move and size with cells" (twoCellAnchor,
the default), "move but don't size with cells" (oneCellAnchor / editAs="oneCell")
and "don't move or size with cells" (editAs="absolute"). GridCraft had no such
concept: xlsx import dropped `editAs`, export always wrote a plain twoCellAnchor,
and sorting/filtering never moved an object — so pictures stayed put when their
rows were reordered.
Model: add `AnchorMode` on `Anchor` (serde default = MoveAndSize, so existing
documents round-trip unchanged).
xlsx: read the anchor kind and `editAs` into the mode; write it back out
(editAs="oneCell"/"absolute" as Excel does).
Engine: sorting now moves objects anchored inside the sorted body with their
lines, re-fitting "move and size" objects, keeping "move but don't size"
objects' size, and leaving absolute ones pinned. Structural insert/delete
honours the same rule (previously it moved every object's cell unconditionally
and ignored shapes). New `object.setAnchorMode` command sets an object's mode;
`arrange.selectionPane` reports it.
Tests: sort moves images with their rows; absolute objects stay put across a
sort and a row delete; move-only keeps its size; the mode survives an xlsx
round-trip; the drawing fixture parses all three anchor kinds.
- ui-egui: title bar with QAT, full ribbon (Home/Insert/Draw/Page Layout/Formulas/Data/
Review/View/Automate + Table/Chart Design), formula bar with Name Box, virtualised grid
(frozen panes, overflow, borders, CF data bars/scales/icons, tables, sparklines, filter
buttons, charts/pictures/shapes), in-cell editor with point mode, reference colouring,
autocomplete and argument hints, sheet tabs, status bar, dialogs, control channel
- apps/sheetcraft: desktop app (control server, file dialogs, prefs, drag & drop)
- chart: toolkit-free chart layout/rendering for 25 chart kinds + sparklines + rasteriser
- mcp + sheetcraft-cli: MCP server (headless or bridged) and CLI (info/convert/eval/cat/run/mcp)
- xtask (ci/layers/assets/wasm/version/parity), release workflows, packaging, placeholder icon
- automatic row heights
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>