Commit Graph
64 Commits
Author SHA1 Message Date
aiongg 675d96ef17 Merge PR #1373: Protection: Protect Sheet entries unprotect, selectLockedCells enforced (#1346) 2026-10-22 02:34:56 +00:00
aiongg 2c73c2b18f Merge PR #1214: Grid: an armed Format Painter pastes onto the next cells clicked or dragged 2026-10-22 02:34:39 +00:00
Brandon Thomas 937cfd1e91 Merge pull request #1903 from justinjohn0306:fix/1855-backspace-undo 2026-10-19 12:21:29 -04:00
Vedran DobosandClaude Opus 5.5 6ac8ad9216 fix(edit): Ctrl+Enter gives each cell the number format typing gives it
range.fill parsed the input once at the active cell, then put back the old
style of every target that already held a cell, so 5%, $5, 3/4/2026 or
=DATE(...) lost their automatic format there (0.05, 5, 46085), and empty
targets took the active cell's style. Each target now gets what
input_to_cell gives for it (parsed once per distinct style), as typing does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 12:18:34 +02:00
justinjohn0306andClaude Opus 5.5 dcd4d1d13f #1855: redo selects the redone cell
Undo stored the selection at the moment of undoing (wherever the user had
clicked) in the redo entry, so redo jumped back there instead of to the
cells it changed. The redo entry now keeps the undone step's selection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:16:13 +05:30
Harrison O'Connor-Hoover 79e85c1b80 fix(edit): recalculate every cell changed by large clears (#1032) (#1128) 2026-10-15 13:38:13 -06:00
Marco Arnulfo 7a352cee09 Grid: an armed Format Painter paints whole rows and columns from their headers (refs #1211) 2026-10-15 21:22:40 +02:00
vangel76andClaude Sonnet 5.5 0d18137114 Protection: enforce selectLockedCells/selectUnlockedCells and offer them in Protect Sheet (#1346)
selection.set refuses a cell the protection forbids selecting, selection.move steps on to the
next selectable cell, and review.protectSheet keeps the sheet's current selection rights unless
told otherwise. The dialog gains the two select options and insert/delete columns.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 23:00:50 +02:00
Brandon Thomas 2d0a3f8a47 Merge main into #780
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/insert.rs
#	crates/engine/src/tests.rs
2026-10-13 01:02:28 -04:00
Brandon Thomas d6bb4bdf7a Merge pull request #763 from msaulc:fix/ctrl-shift-arrow-scroll 2026-10-12 23:49:25 -04:00
Brandon Thomas a435ef6ada Merge pull request #720 from dantebertuzzi:fix/cell-set-numeric-input 2026-10-12 23:49:02 -04:00
vangel76andClaude Sonnet 5.5 2797d468c5 Security: cell hyperlinks open only http, https and mailto, after a confirmation (#777)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:17:30 +02:00
msaulcandClaude Opus 5.5 77a91a714a Grid: extending the selection from the keyboard scrolls its moving end into view
Ctrl+Shift+Arrow (and Shift+Arrow, Shift+PageUp/PageDown, Alt+Shift+PageUp/PageDown,
Ctrl+Shift+Home/End, Shift+Home) extend the selection by moving its far corner while the
active cell stays on the anchor. After the move the grid set `ensure_visible`, but the
scroll-into-view step in `grid::show` always targeted `selection.active`, which is the
anchor and is already on screen. So the view never followed the extension past the last
visible row or column.

The keyboard extension paths now also set `GridState::reveal_moving_end`, and the
ensure-visible step then scrolls to `Selection::moving_end()`, the corner opposite the
anchor. `selection.move` now uses that same helper (it had the logic inline) to find where
an extension starts. Other ensure-visible callers (Go To, Name Box, plain moves) still
reveal the active cell.

Regression test: crates/ui-egui/tests/selection_scroll.rs drives Ctrl+Shift+Up/Down/
Left/Right, Shift+Down/Right and Ctrl+Shift+Home/End through real egui key events and
checks that the moving end ends up on screen while the anchor and active cell stay put.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:07:43 -06:00
dantebertuzziandClaude Opus 5.5 857f538c08 cell.set / set_cell: accept a number for input (#697)
`input` is documented as "text, number or =formula", but only a string
was read; a JSON number was dropped and the command failed (or, on 0.5.0,
silently cleared the cell). The undocumented `value` alias already went
through `json_to_input`. Both keys now share that converter, so numbers
and booleans are entered as typed. The MCP `set_cell` schema types
`input` as string, number or boolean to match its description.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:15:06 -03:00
MarekSpodBiedry 125f460cef Paste Special: copy the validation rule with the Validation and All options (#562) 2026-10-12 08:36:13 +02:00
Brandon Thomas 0a54876e2c Merge pull request #425 from neilcawse/test/command-sequence-fuzz
Engine: command-sequence fuzz harness (undo/redo, XLSX round-trip, full-recalc invariants) and the bugs it found
2026-10-11 18:06:03 -04:00
Shirish Veerabattini 3936f3b79c engine: correct which functions the entry check skips
IF, IFERROR, CHOOSE, SWITCH and INDEX are in the registry and are checked; the comment listed IF as skipped.

Claude-Session: https://claude.ai/code/session_01BGBBGBC2gRpQ7GDuwQ6WPt
2026-10-11 16:10:04 -05:00
neilcawseandClaude Opus 5.5 828efab385 Engine: command-sequence fuzz harness (undo/redo, XLSX round-trip, full-recalc invariants) and the bugs it found
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:39:31 -04:00
Shirish Veerabattini 993c108660 functions: share the argument-count rule between call and entry
FnSpec::accepts holds the arity check (including Excel's 255-argument
limit) that functions::call and the entry check both use, so entry also
refuses 256 arguments to a variadic function. The evaluator's own check
in calc is unchanged.

Claude-Session: https://claude.ai/code/session_01BGBBGBC2gRpQ7GDuwQ6WPt
2026-10-11 15:37:09 -05:00
Shirish Veerabattini 9b59966cc9 Merge upstream main into fix/formula-arg-count-363
Claude-Session: https://claude.ai/code/session_01BGBBGBC2gRpQ7GDuwQ6WPt
2026-10-11 15:20:56 -05:00
Shirish Veerabattini 56f784473d engine: refuse formulas with the wrong argument count on entry
A formula calling a built-in function with too few or too many
arguments (=DATEDIF(a,b), =SUM(), =DATE(2024,1)) was stored and showed
#VALUE! with no hint about what was wrong. Entry now refuses it with
the function's signature, e.g. "DATEDIF has too few arguments. Use
DATEDIF(start_date, end_date, unit)", and leaves the cell unchanged.

Only registered functions are checked: special forms the evaluator
handles itself (IF, LET, LAMBDA...), LAMBDA names and unknown functions
are skipped. Paste and Find & Replace keep turning input that fails
entry into text. DATEDIF's description now lists its units.

Fixes #363

Claude-Session: https://claude.ai/code/session_01BGBBGBC2gRpQ7GDuwQ6WPt
2026-10-11 13:29:14 -05:00
Brandon Thomas 76f3a29c79 Merge branch 'land' into fix-206 2026-10-11 14:23:51 -04:00
Brandon Thomas 9cb6cb2384 Merge branch 'land' into fix-288
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/edit.rs
#	docs/target-app-parity.md
2026-10-11 13:01:23 -04:00
Brandon Thomas 9d3b3a6074 Merge pull request #207 from mikl0s/fix/cell-set-requires-input-v2
Cell: cell.set without an input is an error
2026-10-11 12:46:03 -04:00
Brandon Thomas 95660dc132 Merge pull request #319 from vangel76/fix/excel-shortcuts
Keyboard: Excel shortcut audit, add the missing ones (#110)

# Conflicts:
#	docs/ui-parity.md
2026-10-11 12:06:40 -04:00
Brandon Thomas 2af0984af0 Merge pull request #308 from vangel76/feat/review-allow-edit-ranges
Review: Allow Edit Ranges with Excel-compatible password hashes (#307)

# Conflicts:
#	ROADMAP.md
#	crates/xlsx/src/sheet_write.rs
#	crates/xlsx/src/tests/malformed.rs
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/target-app-parity.md
2026-10-11 12:05:30 -04:00
Brandon Thomas 4dce1181e1 Merge pull request #305 from vangel76/feat/cell-checkbox
Checkboxes: ribbon button, Excel's value and Delete rules, XLSX cell controls (#196)

# Conflicts:
#	ROADMAP.md
2026-10-11 12:05:28 -04:00
Brandon Thomas f8903c9e98 Merge pull request #353 from LloydNicholson/fix/copy-multiple-ranges
Issue #348: copying multiple selections works when the areas line up, and explains when it can't

# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/tests/clipboard.rs
2026-10-11 12:04:15 -04:00
Brandon Thomas 59deadc4c3 Merge pull request #285 from vangel76/fix/currency-paste
Clipboard: pasted currency cells keep the number from the clipboard HTML (#257)
2026-10-11 11:43:48 -04:00
Brandon Thomas 96703b79d4 Merge pull request #278 from vangel76/fix/fill-handle-ctrl-series
Fill handle: Ctrl+drag swaps copying and extending a series (#264)

# Conflicts:
#	ROADMAP.md
2026-10-11 11:43:47 -04:00
lloydandClaude Opus 5.5 d665499055 Clipboard: copy lined-up multiple selections; say why others can't be copied (#348)
Copying a multi-area selection always failed in the engine, and the UI
dropped the error, so Ctrl+C did nothing and Ctrl+V had nothing to
paste. Now, as in Excel:

- Areas that cover the same rows (or the same columns) and don't
  overlap are copied as one block, slid together left to right (top to
  bottom). The clipboard keeps a snapshot with the block packed at the
  first area's place; formulas travel as their values, and column
  widths or row heights, comments, pictures and merges come along.
- Other layouts, Cut of several areas and Paste Link of a multi-area
  copy are refused with "This action won't work on multiple
  selections."; Copy and Cut from the keyboard, ribbon and context menus
  now show that message instead of failing silently.
- The marching ants go around each copied area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:02:39 +02:00
vangel76andClaude Opus 5.5 76c620fc32 Keyboard: Excel shortcut audit, add the missing ones (#110)
Audited the grid, ribbon and editor key handling against Microsoft's
published Windows and Mac shortcut lists. New keymap.rs binds the ones
whose feature already exists: Ctrl+Shift+~!@#$%^&_ number formats and
borders, Ctrl+2-5, Ctrl+Shift+: time, Ctrl+' / Ctrl+Shift+" from the cell
above, Ctrl+L, Ctrl+Shift+L, Ctrl+P, Ctrl+Alt+V, Alt+=, Alt+Down,
Alt+Page Down/Up, Ctrl+Shift+Home/End, Shift+Home, the F-key family
(Shift+F2/F3/F9/F10/F11, F5, F7, F12, Ctrl+F1/F3/F4, Alt+F1, Ctrl+Alt+F9)
and the Excel for Mac variants (Cmd+L/E alignment, Control+E Flash Fill,
Cmd+Option borders, Cmd+Shift+K/J/H/R). Number-format keys match the
physical key; AltGr text never triggers a Ctrl+Alt shortcut. Fixes the
command catalog's wrong shortcut labels and documents the audit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:43:51 +02:00
vangel76andClaude Opus 5.5 3b918ada2c Review: Allow Edit Ranges with Excel-compatible password hashes (#307)
- 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>
2026-10-11 12:26:14 +02:00
vangel76andClaude Opus 5.5 ce411edc91 Checkboxes: ribbon button, Excel's value and Delete rules, XLSX cell controls (#196)
insert.checkbox existed but had no ribbon button, replaced existing values
with FALSE and was written to XLSX as an invalid number format. Now:
Insert > Checkbox (Cell Controls); empty cells start FALSE, other values
stay and display as General; toggling an emptied box checks it and only
checkbox cells toggle; Delete unchecks first, then removes the boxes; XLSX
reads and writes the checkbox as Excel's feature-property-bag cell control
([MS-XLSX] 2.1.22, 2.3.9, 2.4.99).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:24:25 +02:00
vangel76andClaude Opus 5.5 33afc7d3a5 Clipboard: Insert Copied Cells and Insert Cut Cells (#21)
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>
2026-10-11 12:04:52 +02:00
vangel76andClaude Opus 5.5 b6618aee8e Clipboard: pasted currency cells keep the number from the clipboard HTML (#257)
Spreadsheets put an HTML table next to the tab-separated text; Excel
(x:num) and LibreOffice Calc (sdval) record each cell's number there.
Paste now reads the HTML flavour (new paste_html host service, arboard on
desktop) and edit.paste takes an optional html param: a field that would
paste as text becomes the recorded number when the HTML cell shows the
same text, with an inferred format ("Rp"#,##0.00) that renders it back
identically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:03:46 +02:00
vangel76andClaude Opus 5.5 1b9751ed82 Fill handle: Ctrl+drag swaps copying and extending a series (#264)
A plain drag copies a lone number and extends every other series; Ctrl+drag
(Cmd on macOS) now does the opposite, as in Excel: a lone number counts up
by 1, and numbers, dates, lists and `Item 1`-style text are copied.
edit.autoFill gains mode "alternate" for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:55:45 +02:00
webdevtodayjason fae90c8e4a selection.move: clamp extreme dr/dc to the sheet edge instead of overflowing 2026-10-10 21:05:58 -05:00
Mikkel Georgsen c9525ab5fb Cell references: an invalid reference is an error instead of the active cell
cell_param returned None for any cell argument it could not parse, so every
command that falls back to the selection (cell.set, view.freezePanes,
formulas.trace*, insert.* and others) silently used the active cell instead:
set_cell with cell "ZZZZ0" wrote A1 and reported success. It also dropped a
sheet prefix, so "Other!B2" was applied to the active sheet.

cell_param now returns Result<Option<CellRef>>. An absent or null value is still
None, so the selection fallback is unchanged; an unparsable or non-string value
is an error; a sheet prefix naming a sheet other than the one the command works
on is an error.

cell_param_on is for the commands that resolve their own sheet (cell.get, links,
comments, notes, checkboxes, chart placement, paste): they accept a prefix naming
that sheet. cell.set resolves its own target sheet and still writes to another
existing sheet.
2026-10-10 22:41:40 +02:00
Mikkel Georgsen f69861f7e3 Cell: cell.set without an input is an error
cell.set treated a missing input as an empty string, so a call that forgot the
input (or sent it under the wrong key) cleared the cell and reported success.
It now returns an error when neither `input` nor `value` is given. An explicit
empty string still clears the cell.
2026-10-10 22:41:40 +02:00
Brandon Thomas f23281db8c Merge pull request #144 from harrisonoconnorhover/codex/cross-sheet-cut
Preserve formula references when cutting cells across sheets

# Conflicts:
#	ROADMAP.md
#	crates/formula/src/adjust.rs
#	crates/formula/src/tests.rs
2026-10-10 15:48:08 -04:00
Brandon Thomas 49fbae245a Merge pull request #156 from nihilist-narwhal/fix-legacy-array-formulas
Legacy array formulas: fill the range they were entered in

# Conflicts:
#	crates/engine/src/cmd/edit.rs
#	crates/ui-egui/src/formula_bar.rs
2026-10-10 15:47:56 -04:00
Brandon Thomas 5c456df4b7 Merge pull request #152 from nihilist-narwhal/fix-whole-sheet-selection
Whole-sheet selection: Fill and Remove Duplicates no longer run out of memory or time
2026-10-10 15:47:10 -04:00
Brandon Thomas 92fb7cd1b3 Merge pull request #149 from nihilist-narwhal/fix-table-header-edits
Tables: typing in the header row renames the column; Go To a table selects its data

# Conflicts:
#	crates/engine/src/tables.rs
2026-10-10 15:47:10 -04:00
Brandon Thomas 20aa531d8c Merge pull request #150 from nihilist-narwhal/fix-paste-special-operations
Paste Special operations: keep text, errors and formulas
2026-10-10 15:35:41 -04:00
Brandon ThomasandClaude Opus 5.5 f75ded37e7 Merge pull request #105 from harrisonoconnorhover/codex/cell-pictures
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>
2026-10-10 15:02:44 -04:00
Harrison O'Connor-Hoover 9dc3aaf9fa Support static pictures inside cells with XLSX roundtrip (#61) 2026-10-10 12:43:27 -04:00
Brandon ThomasandClaude Opus 5.5 d2cc499c1d Review fix-up: return copy/cut HTML only when requested
edit.copy and edit.cut build and return the HTML table only with
{"html": true}; the UI asks for it when the host can publish HTML, so
MCP and control-channel responses are not bloated by up to 4 MB. Tests
cover the default, html:false and html:true.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:37:06 -04:00
Brandon Thomas 7712eb1b0e Merge origin/main into fix/rich-table-clipboard 2026-10-10 12:09:28 -04:00
Brandon Thomas e165db1ffd Merge pull request #74 from DWAA1660/fix/70-inherit-cell-formatting
Preserve whole-sheet formatting when entering empty cells (#70)
2026-10-10 11:57:28 -04:00