Commit Graph
47 Commits
Author SHA1 Message Date
Brandon Thomas 19094e2d62 Merge pull request #36 from harrisonoconnorhover/fix/rich-table-clipboard
Fix copying selected cells as rich HTML tables
2026-10-10 12:58:38 -04:00
Brandon Thomas e20a7b41af Merge pull request #84 from harrisonoconnorhover/codex/text-box-editing
Allow editing and selecting text inside worksheet text boxes
2026-10-10 12:58:37 -04:00
Brandon ThomasandClaude Opus 5.5 7f2146476e Fix clippy on main: allow the clock read in native-only import tests
#101/#100 added tests that name temp dirs with SystemTime::now(); #125's
disallowed-methods lint (wasm has no clock) landed alongside them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:58:22 -04:00
Brandon Thomas b68ae0fe53 Merge pull request #100 from harrisonoconnorhover/codex/ods-import
Import worksheet data and cached values from ODS files
2026-10-10 12:52:43 -04:00
Brandon Thomas 09b1ac8d16 Merge pull request #101 from harrisonoconnorhover/codex/xlsb-import
Import worksheet data and cached results from XLSB workbooks
2026-10-10 12:52:42 -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 ThomasandClaude Opus 5.5 c67931cff6 Review fix-up: protect and cap text box edits
shape.setText refuses edits on a protected sheet (drawing objects are
locked; there is no edit-objects allowance yet) and text longer than
32,767 characters, like a cell. The editor doesn't open on a protected
sheet and its TextEdit carries the same character limit. Tests for both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:23:51 -04:00
Brandon ThomasandClaude Opus 5.5 20e39fa3cd Review fix-up: clip blank ODS repeats past the sheet edge, struct-update Cell literal
Blank cell and row repeats that run past 16384 columns / 1048576 rows
(padding from writers with larger sheets) are clipped instead of
rejecting the file; any data or merge past the edge is still an error.
convert() builds its Cell with ..Cell::value(value) so new Cell fields
take their defaults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:22:51 -04:00
Brandon ThomasandClaude Opus 5.5 26b3db78db Merge codex/xlsb-import (with origin/main) into codex/ods-import
Resolves the shared integration points for both formats: combined sniff,
file.open spec, file filters, MCP description, docs. open_bytes now lets
sniffed content (ODS or XLSB) win over the extension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:20:30 -04:00
Brandon Thomas 7712eb1b0e Merge origin/main into fix/rich-table-clipboard 2026-10-10 12:09:28 -04:00
Brandon Thomas c5a8cf28fe Merge origin/main into codex/text-box-editing
# Conflicts:
#	apps/gridcraft/src/native_menu.rs
#	crates/engine/src/tests.rs
2026-10-10 12:08:36 -04:00
Brandon Thomas ea9d4c6b32 Merge origin/main into codex/xlsb-import 2026-10-10 12:04:33 -04:00
Brandon Thomas 15e0f0b6be Merge remote-tracking branch 'origin/main' into pr125 2026-10-10 12:04:21 -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
Brandon Thomas 38369a7566 Merge pull request #106 from harrisonoconnorhover/codex/border-previews
Preview border presets and fix shared-edge removal
2026-10-10 11:57:27 -04:00
Brandon Thomas 7f6739e665 Merge pull request #119 from agammann/fix/text-to-columns-escaped-quotes
Preserve doubled text qualifiers in Text to Columns
2026-10-10 11:57:26 -04:00
Brandon Thomas f736286f24 Merge pull request #50 from LloydNicholson/rotated-wrap-text
Issue #48: rotated text with Wrap Text draws upright (grid and print)

# Conflicts:
#	crates/ui-egui/tests/interaction.rs
2026-10-10 11:57:25 -04:00
Brandon Thomas 54df7e1fc5 Merge pull request #115 from nihilist-narwhal/feat-spill-range-operator
Formulas: the spill range operator (A1#)
2026-10-10 11:57:11 -04:00
Brandon Thomas c30a720998 Merge pull request #114 from nihilist-narwhal/fix-defined-name-entry
Names: R1C1-style names, Create from Selection bottom/right, LAMBDA name case
2026-10-10 11:57:10 -04:00
Brandon Thomas 986b6c6ea6 Merge pull request #113 from nihilist-narwhal/fix-defined-name-scopes
Names: keep sheet-level names with their sheet on move, copy and delete
2026-10-10 11:57:09 -04:00
Brandon Thomas 1cdee3ee02 Merge pull request #111 from nihilist-narwhal/fix-protection-commands
Protection: enforce locked cells for every command, keep hidden formulas hidden
2026-10-10 11:57:08 -04:00
Brandon Thomas a678c5d25f Merge pull request #34 from MarekSpodBiedry/issue-21
Fix: inserting or deleting rows, columns or cells cancels copy/cut mode (#21)
2026-10-10 11:57:08 -04:00
lloydandClaude Opus 5.5 e893621d76 Web app: committing a cell no longer traps on the clock
Every edit goes through cmd::commit, which read std::time::Instant::now()
up front for GRIDCRAFT_PROFILE timing, whether profiling was on or not.
wasm32-unknown-unknown has no clock: Instant::now panics there, and with
panic=abort the browser reports `RuntimeError: unreachable`. So in the
web app, typing 1 into A1 and pressing Enter trapped (#118). The native
apps and the CLI have a clock and were unaffected.

commit now reads the clock only when GRIDCRAFT_PROFILE is set, and
never on wasm. The other clock reads (NOW(), the current year for typed
dates, the UI's frame timer) already skip wasm.

Native tests can't see this trap, so clippy.toml now disallows
Instant::now and SystemTime::now. A clock read has to be gated off wasm
and allowed at the call, and `cargo clippy -D warnings` fails on the old
commit code. The existing, already-gated reads and the native-only perf
example allow it.

Checked by building the engine for wasm32-unknown-unknown into a small
cdylib that runs cell.set A1=1 on a new workbook, and running it in
Node: before the fix it traps with `RuntimeError: unreachable`, after
it returns normally.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:03:33 +02:00
agammann 06cb377c54 Fix escaped quotes in Text to Columns 2026-10-09 22:47:38 -07:00
nihilist-narwhal 9c29ef3fff Formulas: the spill range operator A1#
formula::parse("Sheet1!$D$1#") failed with "unknown error literal".
A # right after a cell reference is now the spill range operator: it
evaluates to the anchor's current spill range, or #REF! when the cell
doesn't spill (or its spill is blocked). Its users depend on the
anchor, so they recalculate when the spill grows or shrinks. Names can
use it.

Files have no # operator: like Excel, the writer stores A1# as
_xlfn.ANCHORARRAY(A1), and the parser reads that back as A1#.
2026-10-09 23:29:35 -05:00
nihilist-narwhal d4d38fd224 Names: calls of LAMBDA names keep the name's case
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.
2026-10-09 23:27:39 -05:00
nihilist-narwhal b28b4b729f Names: Create from Selection uses bottom and right, keeps existing names
formulas.createFromSelection ignored bottom and right, and replaced any
workbook name with the same label without asking. Bottom-row and
right-column labels now name the cells above and to their left. An
existing name is kept and listed in the result's skipped, unless
replace is set (Excel asks; a command doesn't open dialogs).
2026-10-09 23:27:38 -05:00
nihilist-narwhal 8029433b1c Names: refuse R1C1-style names
valid_name refused R and C but took R1C1, R2, C3 and RC, which Excel
refuses because they read as R1C1 references.
2026-10-09 23:27:38 -05:00
nihilist-narwhal 68fac6d861 Insert/Delete Cells: adjust references like Excel
Delete Cells built the references' edit and then discarded it, so
references into the deleted cells didn't become #REF!, and Insert Cells
treated the shift as a move of everything below, so =SUM(A1:A5) didn't
grow to A1:A6 when A3 was inserted.

Two new structural edits, InsertCells and DeleteCells, adjust a
reference like inserting/deleting rows (columns) when it lies within the
shifted columns (rows), and leave it as it is otherwise, as Excel does.
Formulas, defined names, chart series, conditional-format, validation,
table and print-area ranges, notes, links and sparklines follow.
2026-10-09 23:27:21 -05:00
nihilist-narwhal e294345599 Protection: keep hidden formulas hidden
On a protected sheet a formula formatted Hidden still showed with Show
Formulas on, matched Find in formulas, and showed in the formula bar
when a cell of its spill range was selected.
2026-10-09 23:25:58 -05:00
nihilist-narwhal 2a3d1ffd7f Protection: refuse every edit of a locked cell on a protected sheet
Only cell.set checked protection. The check now runs where every edit
is committed: an edit that changes the value or formula of a locked
cell on a protected sheet is refused with Excel's message, whichever
command made it (clear, paste, fills, setValues, replace, goal seek,
sort, insert/delete cells...).

Inserting and deleting rows and columns follow the protection's
options, and deleted lines must not hold locked cells.
2026-10-09 23:25:58 -05:00
nihilist-narwhal b53a190ea1 Names: keep sheet-level names with their sheet
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.
2026-10-09 22:52:49 -05:00
Harrison O'Connor-Hoover b2386e1c23 Issue 30: preview border presets and clear shared edges 2026-10-09 22:45:41 -04:00
harrisonoconnorhover c51e51fe7b #92: import XLSB worksheet data and saved formula results 2026-10-09 22:19:36 -04:00
harrisonoconnorhover da0bf32d8a #16: import ODS worksheet data without overwriting source files 2026-10-09 22:09:09 -04:00
harrisonoconnorhover 628732ef58 Enable inline editing of worksheet text boxes (#56) 2026-10-09 17:47:58 -04:00
DWAA1660andCodex d7174f8297 M2: preserve inherited formatting when entering empty cells (#70)
Resolve input styles from the destination cell, row or column before
parsing. Preserve inherited alignment, borders and number formats for
single-cell and bulk entry, including text paste and array formulas.

Co-authored-by: Codex <noreply@openai.com>
2026-10-09 14:33:43 -06:00
lloydandClaude Opus 5.5 ad6e77f6ef Issue #48: rotated text with Wrap Text draws upright (grid and print)
Narrow columns with tall, upright headers (mark sheets) set both a text
rotation and Wrap Text. The wrap path drew the text flat and returned before
the rotation was applied, so headers came out as 3-4 character fragments.

- Rotated text no longer takes the flat wrap path. Upright (+/-90 deg) text
  wraps to the row height, its lines stacking across the column; other
  angles keep one line, as before.
- Downward text was anchored at the bottom-left and ran out of the cell
  (over the row headers); it now starts at the top, one block-height in.
- Upright text no longer overflows into empty neighbours: its width is its
  line height, and the overflow repainted their gridlines.
- Print/PDF gets the same three fixes.

Tests: ui-egui interaction test (shapes drawn at +/-90 deg, inside a
one-column clip) and a print test (every text block on the page rotated,
a few long lines each). Each failed before the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:13:40 +02:00
harrisonoconnorhover 51f3279135 Fix #23: copy selected cells as HTML tables 2026-10-09 05:56:08 -04:00
MarekSpodBiedry 4dd49f7b95 Fix: inserting or deleting rows, columns or cells cancels copy/cut mode (#21) 2026-10-09 10:45:50 +02:00
Brandon ThomasandClaude Opus 5.5 488e12de31 Rename SheetCraft to GridCraft everywhere (crates, apps, bundle ids, packaging, docs)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:39:08 -04:00
Brandon ThomasandClaude Opus 5.5 2618a233bf Perf: prefix-sum LineIndex for grid geometry (O(log n) with many custom row heights)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:36:28 -04:00
Brandon ThomasandClaude Opus 5.5 db4b00064c M7/M8: task panes — Format Chart, Comments (threaded replies, resolve), Watch Window, Selection
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:27:47 -04:00
Brandon ThomasandClaude Opus 5.5 f76a0beca3 M8: Draw tab — pen, highlighter, eraser, ink strokes and Ink to Shape
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:20:40 -04:00
Brandon ThomasandClaude Opus 5.5 168b8ec8b7 M4–M10: PivotTables, PDF export & printing, what-if analysis, spelling, more commands
- PivotTables: engine (grouping, date groups, multiple values, show-as, filters, layouts,
  refresh, recommended pivots) + PivotTable Fields task pane
- sheetcraft-pdf (dependency-free PDF writer, core-14 fonts) + file.exportPdf/print/
  printPreview/pageLayout.pageSetup with pagination, headers/footers, charts, images
- What-if: Goal Seek, Scenario Manager, data tables, advanced filter, consolidate
- Page Break Preview rendering; view mode buttons
- Spelling (system dictionary), icons library, cell checkboxes, recorded scripts,
  chart design/format commands, arrange, custom views, watch window, Get Data from CSV/JSON
- Native macOS menu bar
- UI interaction tests (kittest): fixed arrow keys losing grid focus and Escape not cancelling
- Perf: FxHash in calc, sparse range reads, Arc'd formula ASTs, fast auto row heights
- Parity 254/290 (87.6%)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:04:46 -04:00
Brandon ThomasandClaude Opus 5.5 beb353943e M1: Excel-style egui UI, desktop app, chart renderer, MCP server, CLI, release packaging
- 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>
2026-10-06 00:00:15 -04:00
Brandon ThomasandClaude Opus 5.5 1ba9daa263 M0: foundation — core, numfmt, formula, functions (478), model, calc, xlsx/csv, engine
Clean-room spreadsheet engine: addresses/values/dates, Excel number formats,
formula parser/printer/reference adjustment, worksheet function library,
copy-on-write workbook model, dependency-driven recalculation with dynamic
arrays, XLSX/CSV I/O, and a command engine (cell entry, clipboard, fill,
formatting, sheets, sort/filter, tables, charts, CF, names, view, file).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:18:10 -04:00