Commit Graph
1777 Commits
Author SHA1 Message Date
derechopiano be20ca163d UI: keep PivotTable field-list scrollbar at pane edge 2026-10-15 04:13:02 +01:00
David ArdilaandClaude Opus 5.5 cd94a6d7b4 Recalculation: a spill anchor given a formula that reads its old spill area sees it empty
When a dynamic array's anchor gets a new formula, the formula is evaluated
while the old array is still laid out, so it can read the old spilled
values. The anchor was then never evaluated again: it is left out of its
own spill area's dependents, so as not to read its own array.

- `A1` was `=SEQUENCE(3)` and becomes `=SUM(A2:A3)+1`: it showed 6 (2 + 3
  + 1) with A2:A3 empty; recalculating from scratch gives 1.
- `A1` was `=SEQUENCE(3)` and becomes `=SEQUENCE(1,A2+1)`: it read A2 as 2
  and spilled over A1:C1 instead of showing 1.

The anchor is now evaluated again when its old array is gone or partly
freed. It is still left out when its new array covers the old one, where
it would read its own array.

Regression test in calc
(`an_anchor_given_a_formula_that_reads_its_old_spill_area_sees_it_empty`:
the new formula stops spilling, spills elsewhere, or spills over part of
the old area); it fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:05:37 -05:00
David ArdilaandClaude Opus 5.5 ac7595975a Recalculation: formulas reading an array that loses a spill conflict see #SPILL!
When two dynamic arrays of one recalculation want the same empty cells,
both look free while the pass runs, so formulas evaluated in that pass
read both arrays. The one laid out second becomes #SPILL! at write-back,
but nothing evaluated its readers again, and they kept its values.

With B1 `=SEQUENCE(3)` and A2 `=SEQUENCE(1,3)` (both want B2), a full
recalculation (opening a file, Calculate Now) leaves A2 at #SPILL!, yet
`=A2*10` showed 10, `=SUM(A2#)` 6, and `=C2` and `=SUM(C2:C3)` 3, though C2
is empty. Entering the same formulas one at a time gave the right values.

An array blocked at write-back now sends the formulas that read its anchor
or the area it would have spilled into to the next round, where they read
#SPILL! and empty cells.

Regression test in calc
(`formulas_reading_an_array_that_loses_a_spill_conflict_read_spill_errors`);
it fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:05:35 -05:00
Mario 4bfd0bc5a1 Improve Command Palette keyboard navigation and layout 2026-10-15 03:23:16 +02:00
Harrison BoothandClaude Opus 5.5 01eb237209 Docs: corpus count for dropped dynamic-array metadata
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:29:44 -05:00
Harrison BoothandClaude Opus 5.5 7ee11fe137 XLSX: keep dynamic-array cell metadata (cm) on save
A formula read with `cm` (Excel's XLDAPR dynamic-array record in
xl/metadata.xml) now carries `Formula::dynamic`, and the writer keeps the
`cm` and the metadata part for it even when the formula returns one value
and the export shape analysis would not need array evaluation. Before, such
formulas were saved as legacy formulas, so Excel recalculated some of them
with implicit intersection (SUMPRODUCT(IFERROR(range/range,0)) changed
value), and workbooks whose every dynamic formula was scalar lost
xl/metadata.xml altogether.

The mark survives moves, row and column insertion or deletion, sheet and
name renames and LAMBDA call-case fixes; retyping a formula drops it and
the writer decides from the formula's shape, as before. It is serialized
only when set, so saved documents without it are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:05:03 -05:00
Mario f9802ecc9d Improved font dropdown row sizing and scroll alignment 2026-10-15 01:15:15 +02:00
Harrison BoothandClaude Opus 5.5 ced7243234 calc: bounded references up to 1,048,576 cells keep their full shape (#1010)
A reference over 16,384 cells was cut to the sheet's used range when it was
read into an array. Next to a full-size operand the two no longer lined up:
SUMPRODUCT(D3:AZ400*B3:B400,(A3:A400=1)*(D1:AZ1=2)) gave #VALUE!,
D3:AZ400*B3:B400 filled with #N/A, and ROWS, COUNTBLANK and --(r="") lost
the blanks past the data. Excel keeps the reference's size.

Bounded references now keep their full shape up to one column's worth of
cells (1,048,576). References that run to the edge of the sheet (A:A,
A2:A1048576, several whole rows) and larger blocks still stop at the used
range, so whole-column formulas stay fast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:36:36 -05:00
midasmatterhorn 34a4ed3ead engine: rebuild cell-store bands and counts when importing a JSON workbook 2026-10-15 00:09:25 +03: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
midasmatterhorn d66ed11253 xlsx: keep every property of the default cell format when importing a file 2026-10-14 23:58:57 +03:00
vangel76andClaude Sonnet 5.5 33abe3a9f7 UI: Protect Sheet entries become Unprotect Sheet on a protected sheet (#1346)
Home > Format, HOP and RPS always opened the Protect Sheet dialog, which re-protected
the sheet. open_dialog now turns protectSheet into unprotectSheet for a protected sheet,
and unprotects at once when there is no password.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 22:57:29 +02:00
vangel76andClaude Sonnet 5.5 833fe0da1f Edit: text that would parse as a number or formula keeps its quote prefix in the editor (#1362)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 22:56:36 +02:00
NetterSilverandClaude Haiku 5.5 ac8f6f6ce4 Keep Middle/Bottom vertical alignment for wrapped text taller than its row
Fixes #1347

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 22:56:35 +02:00
midasmatterhorn 2c23b61908 engine: subtotal honours header:false instead of dropping the first data row 2026-10-14 23:51:59 +03:00
DCM4711andClaude Opus 5.5 7b10212b5a Header menus: Format Cells… for the selected rows or columns
As in Excel, right-clicking a row or column heading offers Format
Cells…, between Clear Contents and Row Height… / Column Width….

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:43:51 +02:00
midasmatterhorn 686c13c8b7 engine: keep case-insensitive replace from dropping text when folding shifts byte boundaries 2026-10-14 23:22:05 +03:00
Mario 50f8c0d42b Fix font dropdown resizing and keyboard navigation 2026-10-14 22:16:10 +02:00
midasmatterhorn 938762d796 engine: keep AutoFill text series from panicking or wrapping on i64 overflow 2026-10-14 22:56:07 +03:00
DCM4711andClaude Opus 5.5 d48bcaf043 Context menu: the right-click that opens it doesn't close it
A quick right-click delivers press and release in one frame. The menu
opens at the pointer, and its corner snaps to the nearest physical pixel
(252.46 -> 252.5 on a Retina display), which can leave the pointer just
outside it. The close check then saw that frame's press as a click
outside the menu and closed it right away, so the menu often flashed and
vanished on macOS.

The menu remembers the frame it opened in, and that frame's press no
longer counts as a click elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:55:20 +02:00
DCM4711andClaude Opus 5.5 a0ec1fb785 Selection: whole columns and rows don't widen to merged cells
Clicking column B's header on a sheet with A2:C2 merged selected A:C,
because selection.set grows every area until merged cells are whole.
Excel leaves header selections alone: column B stays B:B and row 3 stays
3:3. Cell ranges still take merged cells whole (B1:B3 -> A1:C3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:24:56 +02:00
Harrison BoothandClaude Opus 5.5 1241fbf260 calc: calculate long dependency chains with bounded stack
A formula that reads one later in row-major order (further down, or on a
later sheet) is calculated on demand, inside the formula that reads it.
Each level costs stack, so real models with chains of about 1,000 such
formulas overflowed the 1 MB main-thread stack on Windows and crashed on
open. Past 2,000 levels the chain gave #CIRC! instead.

On-demand evaluation now goes at most 64 formulas deep. A formula needed
deeper suspends the evaluations in progress: it is calculated from the
top, then the suspended ones again, reading the results kept so far.
Chains of any length calculate, with the same results. A suspended
formula read again is a circular reference, as a formula in progress is,
so loops are found at the same cell as before.

Regression tests build the chains in code: 20,000 formulas each reading
the row below, the same hopping between two sheets, a 5,000-formula loop,
and a loop closing into the middle of a deep chain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:08:42 -05:00
Marco Arnulfo 62729e3a99 Keyboard: Alt+= no longer starts an edit with the = it types (fixes #1327) 2026-10-14 19:52:36 +02:00
MarekSpodBiedry ef894c20e5 Reject a list data validation that has no formula1 (#1303) 2026-10-14 19:31:01 +02:00
Marco Arnulfo f36bc100d4 AutoFit measures each distinct text once, and quickly on large columns (#1316) 2026-10-14 18:14:09 +02:00
Marco Arnulfo f92b4d30cb AutoFit Column Width measures text in the font the grid draws it with (fixes #1316) 2026-10-14 18:01:11 +02:00
midasmatterhorn 450ef1aea0 engine: refuse removeDuplicates with no valid column instead of deleting all rows 2026-10-14 18:01:42 +03:00
dev-exeandClaude Opus 5.5 2cae3a22b1 Slicers: a table named in table is found on any sheet
insert.slicer and table.insertSlicer looked for the table named by `table` only on the active
sheet. With another sheet active, the call failed with "Select a cell inside a table first, or
pass `table`" although `table` was passed. Other table commands find a table by name in the
whole workbook (Workbook::table).

The named table is now found on any sheet, and the slicer goes on that table's sheet. `at` is
read on that sheet, so "Sheet1!G2" names the table's own sheet. A name that matches no table
gives "no table named `X`".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:30:46 +05:30
Pranav Chandra 3177fbe03f ui: show spill-cell formula as greyed out 2026-10-14 20:23:44 +05:30
MarekSpodBiedry 139098e174 Filter: count empty text and ="" results as (Blanks) (#1294) 2026-10-14 15:44:31 +02:00
Brandon ThomasandClaude Opus 5.5 d9d09f0baa Release 0.7.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.7.0
2026-10-14 09:33:30 -04:00
Harrison BoothandClaude Opus 5.5 efd081acc0 UI parity: form dialogs open ready to type
Column Width, Row Height and the other form dialogs now open with the cursor
in their first field and its value selected, as in Excel: Alt+H, O, W, then
12 and Enter sets the width without clicking into the field first.

- The first text or number field takes focus once it can (a new window's
  first frame is a sizing pass that ignores focus requests), and its value
  is selected so typing replaces it.
- Number fields commit while typing, so Enter or OK in the same frame no
  longer confirms the old value.

Tests: tests/dialog_focus.rs (Column Width and Row Height: type, Enter,
value applied).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:07:59 -05:00
derechopiano 78ffd3b4c3 fix(pdf): preserve exported links and allow CLI PDF conversion (#954) 2026-10-14 13:40:16 +01:00
Marco Arnulfo 39602e6ce1 Filter and Subtotal: a Sheet! prefix on the range works on that sheet, not the active one (refs #1283) 2026-10-14 13:00:17 +02:00
Marco Arnulfo 13691e95e5 Remove Duplicates: a Sheet! prefix on the range works on that sheet, not the active one (refs #1283) 2026-10-14 12:51:05 +02:00
Marco Arnulfo be1af2d6ac Sort: a Sheet! prefix on the range sorts that sheet, not the active one (fixes #1283) 2026-10-14 12:08:41 +02:00
Marco Arnulfo 531d292930 N() converts a computed array element by element, so it works inside SUMPRODUCT (fixes #1279) 2026-10-14 11:46:48 +02:00
RichardandClaude Fable 5.1 34aa98870d Zoom dialog: Excel's layout, current zoom pre-selected, Fit selection (#930)
View > Zoom is now one Magnification column as in Excel: 200%, 100%, 75%,
50%, 25%, Fit selection and Custom with its percentage box. The current zoom
is pre-selected (Custom when it matches no preset), the box shows whole
percentages clamped to 10..400 and typing in it selects Custom. Fit
selection runs view.zoomToSelection with the grid's size, the same answer
as the ribbon's Zoom to Selection. The window is 220 px wide instead of
380; its height is left to the shared dialog sizing work (#978).

Magnification and Fit selection are translated in every catalog.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2bJ3LxrZ6YnmppgrfwHwr
2026-10-14 20:22:00 +11:00
derechopiano 72db972de3 fix(engine): bound Undo history by retained cell storage (#1227) 2026-10-14 08:23:57 +01:00
Marco Arnulfo 89439636d8 Dialogs move by their title bar instead of staying pinned to the centre (fixes #1250) 2026-10-14 08:08:41 +02:00
RichardandClaude Opus 5.5 07f6fe0b0b Headers: mark hidden columns and rows, split cursor and double-click to unhide (#1247)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2bJ3LxrZ6YnmppgrfwHwr
2026-10-14 16:52:24 +11:00
Marco Arnulfo 736cc89b2b Opening an XLSX with a part over 512 MB says how to get the data in (fixes #1242) 2026-10-14 07:44:41 +02:00
Marco Arnulfo d1075c067b BAHTTEXT: a final one after the millions reads เอ็ด (fixes #1234) 2026-10-14 05:46:44 +02:00
allenyllee 938097f5b6 I1231: load Flatpak host fonts for native CJK fallback 2026-10-14 11:44:01 +08:00
Marco Arnulfo 9f11e26e78 Journal: cap by serialized size and keep a recording's start through trims (part of #1228) 2026-10-14 05:10:19 +02:00
Marco Arnulfo f519fd67f6 XLSX: keep a dxf's protection, font size and face, and the font parts it turns off (part of #1209) 2026-10-14 04:49:33 +02:00
RichardandClaude Opus 5.5 b5aacceb11 Sheet tabs: right-clicking a tab activates its sheet
As in Excel, a right-click on an inactive tab now activates that sheet, so
the tab menu's Protect/Unprotect Sheet and Select All Sheets act on the
sheet that was clicked rather than the one that was active.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2bJ3LxrZ6YnmppgrfwHwr
2026-10-14 13:36:51 +11:00
Marco Arnulfo 3f520a3420 File: Save a Copy asks where to save a bare name instead of writing it to the working directory (fixes #1212) 2026-10-14 03:03:33 +02:00
Marco Arnulfo 5e5e131be7 Grid: an armed Format Painter pastes onto the next cells clicked or dragged (fixes #1211) 2026-10-14 03:03:28 +02:00
RichardandClaude Opus 5.5 d95908f4ba Ribbon tooltips show each platform's shortcuts (#1191)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:26:06 +11:00