OK on the untouched field says the password is incorrect instead of
asking again; the Backstage closes once the workbook opens; app.open on
the control channel takes a password and never opens the dialog. Control
protocol docs cover file.open {password}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ribbon button toggled structure protection silently. It now opens a
Protect Structure and Windows dialog with an optional password; when a
password was set, unprotecting asks for it and really verifies it
(SHA-512, spin count 100000, salted). The password hash is read from and
written to XLSX workbookProtection (workbookAlgorithmName/HashValue/
SaltValue/SpinCount or the legacy workbookPassword); an unreadable one
stays locked. File › Info uses the same flow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Data: Analysis ToolPak with 13 tools and the Data Analysis dialog (#312)
# Conflicts:
# crates/ui-egui/src/dialogs.rs
# docs/gaps.md
# docs/parity-checklist.md
The password fields in Protect Sheet and Unprotect Sheet were plain
text fields, so the password was readable on screen and in the
accessibility tree. A new Password form field masks it as typed and adds
a "Show password" check box that reveals it on purpose (off each time
the dialog opens).
These are the only password fields in the UI: Protect Workbook runs
without a dialog and encrypted files are refused on open.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
data.solver maximises, minimises or targets a value in an objective cell by
changing variable cells under <=, >=, =, int and bin constraints. Simplex LP
linearises the model through recalculation, checks linearity and solves it
with a two-phase simplex; integers use branch and bound. The GRG Nonlinear
choice runs an augmented-Lagrangian projected-gradient method. The model is
saved as hidden solver_* names; Solver Parameters and Solver Results dialogs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New sheet before the active one with the sorted history, a FORECAST.ETS
forecast column, FORECAST.ETS.CONFINT lower/upper bounds, an optional
FORECAST.ETS.STAT table, an Excel table over the data and a line or column
chart. Parameters: timeline/values (default: the selection's first two
columns), end or periods, confidence interval, seasonality, missing-point
fill, duplicate aggregation, statistics, chart kind. Data ribbon button
opens a form dialog; programmatic calls never do. gridcraft-functions
exports Timeline to continue a timeline (numeric step or calendar months).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
data.analysisToolPak runs Descriptive Statistics, Histogram, Correlation,
Covariance, Regression, Moving Average, Exponential Smoothing, Rank and
Percentile, the three t-Tests, F-Test and Anova: Single Factor, writing a
static report to an output range or a new sheet. Non-empty output cells are
refused unless overwrite is set; the dialog asks instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Model: Sheet.edit_ranges (title, ranges, optional password hash,
security descriptor) and gridcraft_model::password: the ECMA-376 legacy
16-bit hash and the salted, iterated SHA-2 hash (SHA-512/384/256; other
algorithms, damaged hashes and spin counts over 10,000,000 are refused).
New passwords use SHA-512, spin count 100000. Adds the sha2 crate.
- XLSX: <protectedRanges> read and written; an unreadable password keeps
the range locked.
- review.allowEditRanges {action: list|add|modify|delete|unlock, ...}: empty
params list; ranges can't change while the sheet is protected; unlock
verifies the password for the session. Not journaled (passwords).
- Locked-cell checks (commit guard, cell.set, picture in cell) let edits
through in open or unlocked ranges; ranges move with structural edits.
- Ribbon button and a form dialog (menu invocation only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A value field can be a calculated field whose formula is evaluated on
the sums of the fields it names for each report cell (Excel's documented
semantics). Command to add/change/delete, dialog from the field pane,
XLSX cacheField formula round trip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A line chart from numeric X values (years) plotted them as a series and
there was no way to set the axis labels. Now:
- a blank top-left cell over a header row makes the first column the
category labels even when it holds numbers (the usual convention);
- chart.selectData takes categories (Horizontal (Category) Axis Labels,
"" clears) and removeSeries, and range is optional;
- Chart Design gets a Select Data button opening a Select Data Source
dialog: chart data range, legend entries with Remove, axis labels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ribbon button inserted a column chart straight away. It now opens an
Insert Chart dialog: a Recommended tab (insert.chartRecommendations, a
heuristic over the data's shape: series, points, labels, negatives) and an
All Charts tab, each with a live preview of the chart for the selection.
OK inserts the chosen type and selects the chart.
insert.recommendedCharts stays dialog-free for programmatic calls: without
a type it inserts the first recommendation; type/subtype pick one.
insert_chart is split into build_chart (also used for previews).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dialogs::show put the Name Manager back into app.dialog after its body
had opened the New Name dialog, so New… did nothing. A dialog opened from
another one now takes over and the opener waits behind it (back), coming
back when the child closes; Go To still hands over to Go To Special.
The Name Manager gets Excel's New…/Edit…/Delete buttons over a selectable
list. formulas.defineName takes oldName/oldScope to edit a name in place;
a renamed name is renamed in cell formulas and other names' definitions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New command home.insertCopiedCells: makes room at the active cell and
pastes the clipboard there, as one undo step. Whole copied rows or columns
insert whole rows or columns; a copied block shifts the cells down or right
(Insert Paste dialog from the menu). A cut of whole rows or columns moves
them and closes the gap (Insert Cut Cells). The cell and header context
menus show the entry while the clipboard holds a copy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- review.previousComment / review.nextComment select the previous/next
threaded comment in reading order (row by row), across visible sheets in
tab order, wrapping around; disabled when the workbook has no comments.
- review.showComments {on?} toggles the Comments pane as session state, so
the CLI, MCP and control channel can drive it; the UI pane follows it.
- review.showAllNotes {on?} displays every note (session display setting,
not saved in the file).
- review.convertToComments turns every note in the workbook into a threaded
comment with the same author and text, as one undoable edit.
- Ribbon: Previous/Next and a Show Comments toggle in the Comments group;
Show All Notes and Convert to Comments in the Notes menu. Strings in all
catalogs. Parity checklist regenerated (263 / 290).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clicking the Save icon in the toolbar, or the Save button in the "save
changes?" dialog, called file.save directly without first committing a
cell edit still in progress (e.g. double-click a cell, type a new value,
then click Save with the mouse instead of pressing Enter). The pending
text in EditState was never flushed into the document, so the saved
file still held the pre-edit value, silently.
The File > Save menu item already guards against this
(app.commit_edit(...) before running the command); this applies the
same guard to the toolbar icon and the saveChanges dialog's Save button.
Add static pictures inside cells with XLSX roundtrip
Rebased onto main (conflicts with #83/#98 and main resolved by maintainer); the contributor's branch does not allow maintainer edits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moving a sheet left its sheet-level names on whatever sheet took its
index, and copying it shifted nothing and copied no names. Moving now
re-indexes name scopes, and a copy gets copies of the sheet's names,
referring to the copy, as in Excel.
Deleting a sheet left names that referred to it pointing at nothing;
they now become #REF!. formulas.deleteName honours scope, and the Name
Manager's Delete passes it.
The engine now preserves a workbook's VBA project, but the UI had no surface
for it and silently dropped every open-time warning. Give preserved macros an
honest, Excel-shaped home without a false "Enable Content":
- Info bar under the ribbon (Excel's message-bar slot) showing the warning a
`file.open` result carries. A VBA project gets an amber bar reading "This
workbook contains VBA macros. GridCraft keeps them intact when you save, but
does not run them." with a "What this means" button; anything else becomes a
blue informational bar. Dismissable; a clean open clears a stale notice.
- Macros dialog (Automate ▸ Macros, Alt+F8): lists GridCraft's own scripts and
the preserved VBA project (presence + size, not module names — the blob is
opaque). Mirrors Excel's Developer ▸ Macros without claiming to run VBA.
- Status-bar badge "Macros preserved (not executed)" whenever the workbook
carries a VBA project.
New panel `notice_bar` reuses theme tokens (notice_warn_*/notice_info_*), so it
follows light/dark. Two new UI commands, `ui.notice` and `ui.notice.dismiss`,
reach it from the control channel.
Tests: info bar appears for a macro workbook and clears on dismiss; a non-VBA
warning becomes an info bar; clean open clears the notice; the macros dialog
lists the VBA entry; status bar renders with a VBA project; Alt+F8 opens the
dialog. Snapshot-verified in light and dark.
The font dropdown showed a hardcoded 17-name list and cells always
rendered in the built-in Calibri/role font, so a font installed on the
machine could not be listed or chosen. Both trace to one constraint:
egui panics when asked for a FontFamily::Name that was never bound to
font data, so only the 8 built-in roles were ever bound.
Scan the platform font folders for installed families (a bounded read of
each file's name table via skrifa, already compiled transitively through
epaint), bind the faces a workbook actually uses into egui as
fnt:{family}:{b|n}{i|n} roles chained to the defaults, and offer the
installed families in the font combos after the standard set. cell_family
returns the installed role when it is bound, else the previous bucketing,
so it never names an unbound family. The scan runs in the background and
the first frame that rebinds skips painting, like the existing startup
gate. Native only; wasm keeps the standard list.
Incidental: newer local clippy flagged pre-existing lints in untouched
crates (no toolchain is pinned); fixed behavior-preservingly so the gate
passes.
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)
Adds an About GridCraft dialog (tabs About · Contributors · Models) following the craftrules
standard (standards/contributors.md): contributors/contributors.json is generated by
craftrules/scripts/contributors.py and baked into the binary by crates/ui-egui/build.rs as
static tables. Each contributor line: @username, opt-in display/real name, PRs, commits,
lines +/−/Δ, binary assets +/−, first/last commit. Sortable by every column; alphabetical
ignores case and the leading @.
Reachable from the macOS app menu (About GridCraft, previously a web link), Help ▸
Contributors…, and Automate ▸ About GridCraft in the ribbon (all platforms and the web).
Dialog hyperlinks open through the host's open_url service. The snapshot example gains
--dialog 'name={json}' for offscreen renders of dialogs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section
build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Contributors: regenerate (verified people.toml entries)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- 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>