Commit Graph
1133 Commits
Author SHA1 Message Date
neilcawse e5b12dab06 Functions: COUNTIF family counts the 255 criterion limit in UTF-16 units, as in Excel 2026-10-12 16:09:52 -04:00
vangel76andClaude Sonnet 5.5 5f992be525 Numfmt: no panic on a fraction denominator with 65,536 zeros; format codes are capped at 255 characters (#807)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 22:09:29 +02:00
vangel76andClaude Sonnet 5.5 fd53de7c46 Numfmt: TEXT() and chart labels parse each format code once (#806)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 22:09:09 +02:00
vangel76andClaude Sonnet 5.5 2be04524b3 Calc: SUBTOTAL(10x) recalculates when Row Height, AutoFit Row Height or Ungroup reveal rows
home.rowHeight, home.autofitRowHeight and data.ungroup change row hidden
state without marking the edit structural, so SUBTOTAL(101-111) kept a stale
value. Found by the command-sequence fuzz (seed 3).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:09:27 +02:00
Marco Arnulfo a5f531838b Functions: note the dependency gap of computed criteria (part of #737) 2026-10-12 21:08:20 +02:00
neilcawseandClaude Opus 5.5 aa2a580626 PivotTables: values on rows review fixes (Total header, Σ Values last in Columns)
With values on rows and no column field, the header cell above the data
column reads "Total", as Excel saves it (tabular checked against a real
file).

Σ Values in Columns always comes after the last column field: the column
layout doesn't place it anywhere else, so `pivot.moveField` no longer
stores a position there, the reader ignores where `-2` sits in colFields
and the writer puts it last.

`pivot.changeSource` removes dropped row and column fields one by one so
Σ Values keeps its place ahead of the field it preceded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:05:59 -04:00
vangel76andClaude Sonnet 5.5 bd105a569b Page Layout view: vertical ruler on the right for RTL sheets, header/footer distance clamped to the margins (#792)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:03:37 +02:00
vangel76andClaude Sonnet 5.5 600c25098f Fix footer clamp expectation in the drag test (#792)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:01:22 +02:00
vangel76andClaude Sonnet 5.5 c4ad8e3a9b Page Layout view: header/footer margins on the ruler, live re-pagination, right-to-left rulers (#792)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:01:09 +02:00
vangel76andClaude Sonnet 5.5 339f8ed35b Page Layout view: drag the margins on the rulers (#792)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:57:02 +02:00
Michał Marcin BrzuchalskiandClaude Opus 5.5 26ed66cfe1 i18n: look up the Format Cells dialog labels in the catalog
The Format Cells dialog drew English literals in every language. Its
tabs, labels, options and protection note now go through Language::tr,
as do dialog titles and the shared OK/Cancel buttons. The Fill tab is
keyed Format Cells|Fill because the Alignment tab's Fill is a different
word in some languages. d.tab keeps the English name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:35:10 +02:00
neilcawse 4c2bcd637c Functions: *IFS with two or more criteria pairs match the first 255 characters of a longer criterion, as in Excel 2026-10-12 14:34:18 -04:00
vangel76andClaude Sonnet 5.5 47c0af3f1b Data: Forecast Sheet Forecast Start option (#785)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:34:07 +02:00
Marco Arnulfo 531dc5a5aa functions: MODE comments name Excel 365 as the reference, not POI's cached values (#736) 2026-10-12 20:21:19 +02:00
neilcawse caf3193261 Functions: *IFS with two or more criteria pairs accept criteria over 255 characters, as in Excel 2026-10-12 14:19:29 -04:00
neilcawseandClaude Opus 5.5 5524e2520a Functions: COUNTIF family returns #VALUE! for criteria over 255 characters
Excel rejects a text criterion longer than 255 characters in COUNTIF(S),
SUMIF(S), AVERAGEIF(S), MAXIFS and MINIFS with #VALUE!; GridCraft matched
it anyway. Found by the calc oracle on an Excel-saved report where a
268-character concatenated criterion caches #VALUE!.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:19:29 -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
Marco Arnulfo 1767a28371 Numfmt: scientific formats with a literal after E±, a % or a comma match Excel (fixes #768)
The exponent sign goes right before the exponent digits, after any literal that follows
the E; ? pads exponent digits with spaces; % and commas never scale a scientific section;
zero shows 0 in every integer placeholder. Checked against the 248 TEXT() rows of Apache
POI's NumberFormatApproxTests.xlsx, copied as data into a test.
2026-10-12 19:43:33 +02:00
vangel76andClaude Sonnet 5.5 76e7f1de07 Grid: the selection outline stays visible when extended to the last row (#687)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 19:25:51 +02:00
vangel76andClaude Sonnet 5.5 afce16c8d2 Grid: deleting several Ctrl-selected rows removes them all (#758)
home.deleteRows/deleteColumns used only the last selected area. They now
take every area (or a comma list like "3:3,7:8"), merge them and delete
from the last to the first inside one edit, so it is one undo step.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 19:24:36 +02:00
Marco Arnulfo 4d2e8e3455 Functions: database functions evaluate computed criteria (part of #737)
A formula under a criteria label that names no field is evaluated for each record: its relative references move from the first record to that record, and the database labels name the record's fields, as in Excel. The calc evaluator passes the criteria reference to the database functions through Ctx::computed_criterion.
2026-10-12 19:16:00 +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
Marco Arnulfo f63a437d5b Formulas: keep _xludf. so user-defined calls stay user-defined (fixes #726)
The parser stripped _xludf. like _xlfn., but the two mean opposite things:
_xludf. marks a name Excel must not treat as a built-in. Keeping it in the
call name makes the call an unknown function (#NAME?, as in Excel) and the
writer emits it unchanged, so _xludf.EOMONTH() no longer saves as an
EOMONTH() call Excel repairs away.
2026-10-12 19:07:32 +02:00
Marco Arnulfo f968bb3269 CELL("width") returns the Column Width dialog value, without the padding (#735) 2026-10-12 19:05:41 +02:00
Marco Arnulfo 0a27d4a5d4 Functions: MIRR, COUNTIF, INDIRECT and USDOLLAR match Excel 365 (fixes #738) 2026-10-12 19:04:17 +02:00
Marco Arnulfo eb534b5caf Functions: DGET skips empty result fields and "" criteria match any text (part of #737) 2026-10-12 18:58:34 +02:00
Marco Arnulfo 94014c5594 Tables: structured references keep the spaces at the edges of a column name (fixes #732) 2026-10-12 18:51:40 +02:00
Marco Arnulfo f3e05e0ad8 XLS import: read the calculation mode and precision as displayed (fixes #724)
CalcMode repeats in every worksheet substream like the iteration records and sets wb.calc.mode from the first worksheet; CalcPrecision sits in the globals and sets precision_as_displayed, matching calcMode and fullPrecision on the .xlsx side.
2026-10-12 18:47:53 +02:00
Marco Arnulfo a34f106e93 XLS: open compound files whose last sector isn't padded (fixes #730) 2026-10-12 18:44:23 +02:00
Marco Arnulfo dbfed89a36 XLS import: read the iterative calculation settings (part of #724)
CalcIter, CalcCount and CalcDelta repeat in every worksheet substream and were skipped, so a workbook saved with iterative calculation on opened with it off and its circular references showed #CIRC!. They now set wb.calc from the first worksheet, as <calcPr iterate iterateCount iterateDelta> does for .xlsx.
2026-10-12 18:43:28 +02:00
Marco Arnulfo 3d0ed97d71 XLS: a FORMAT record shorter than its character count keeps the characters it holds (fixes #731) 2026-10-12 18:41:45 +02:00
Marco Arnulfo 0dc76090d7 functions: MODE skips typed text and logical arguments (fixes #736) 2026-10-12 18:38:01 +02:00
Marco Arnulfo 9e28655a8a ROMAN: forms 2 and 3 subtract IC, XM and VM like Excel (fixes #733) 2026-10-12 18:37:51 +02:00
Marco Arnulfo e88d3d7583 EDATE and EOMONTH: serial 0 is day 0 and February 1900 has 28 days (fixes #734)
Excel's EDATE and EOMONTH read serial 0 as 0 January 1900 and end
February 1900 on the 28th (serial 59), although the sheet itself keeps
the Lotus 29 February 1900 (serial 60). GridCraft clamped day 0 up to
day 1 and used the sheet's 29-day February, so EDATE(0,0) was 1,
EDATE(0,1) 32, EDATE(31,1) and EOMONTH(59,0) 60.

EDATE now keeps day 0 and both functions take the real calendar's month
lengths. Serial 60 still reads as 29 February, so EDATE(60,1) stays
29 March. DATE, DAY and the parser keep the leap day.

Tests: the Excel 365 table from the issue; the #124 cases that expected
60 at the end of February 1900 now expect 59.
2026-10-12 18:36:51 +02:00
Marco Arnulfo 15b346e6ca macOS: register the Window menu as NSApp's windowsMenu, so the tiling shortcuts work (fixes #716) 2026-10-12 18:36:00 +02:00
Marco Arnulfo ea5db94fe3 Numfmt: a negative number that rounds to zero shows no minus sign (fixes #729) 2026-10-12 18:35:01 +02:00
dantebertuzziandClaude Opus 5.5 de04cbe917 i18n(pt-BR): translate 546 more labels, dialog strings and tooltips
Brazilian Portuguese had 377 catalog entries, so most dialogs, menus and
tooltips showed in English with the interface set to Português (Brasil).
This adds every key the other catalogs translate (counting the open
Spanish-dialog #669, Russian #676, Czech #652, Polish #650, Turkish #663
and Italian #713 PRs), bringing pt-BR to 923 entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 13:29:17 -03: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
neilcawseandClaude Opus 5.5 1f7fd07c0d PivotTables: values on rows (Σ Values in Rows, dataOnRows)
With two or more value fields the Σ Values pseudo-field can sit in Rows
as well as Columns, at any position among the row fields. The model
records it (`PivotTable.values_on_rows`, `values_position`) and the
engine lays it out like Excel in compact, outline and tabular form: one
row item per value field at the Σ Values level, per-value subtotals
("East Sum of Sales") and grand totals ("Total Sum of Sales").

XLSX reads `dataOnRows` and the `-2` field's place in rowFields or
colFields and writes them back; the "values on rows are shown on
columns" warning is gone. `pivot.moveField` moves "Σ Values" between
Rows and Columns or within one, axis field moves keep it in place, and
the PivotTable Fields pane lists it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:06:30 -04:00
Marco Arnulfo 1a49d18dd1 Comments pane: one Show Comments button, and the pane keeps its width (fixes #710) 2026-10-12 18:02:02 +02:00
jonathanwxh-cell d4874373a4 #551: preserve editable ink through XLSX round trips 2026-10-12 23:54:44 +08:00
Losminek c167d59c70 Merge remote-tracking branch 'upstream/main' into cs-tooltips 2026-10-12 17:53:24 +02:00
Brandon ThomasandClaude Opus 5.5 fc45b7f6d8 Release 0.6.1: rebuild with the fixed shared release workflow
The previous release build failed in craft-common-actions, not in this
repo: riscv64 packaging got --formats deb,rpm,tar (fixed in
craft-common-actions#3), Linux jobs lacked the ALSA headers
(craft-common-actions#5), and Windows signing needed the AZURE_* secrets
listed in the caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.6.1
2026-10-12 11:11:15 -04:00
Brandon ThomasandClaude Opus 5.5 9cb931bac9 Release workflow: pass the Azure signing secrets so Windows builds are signed (#440)
Since the release workflow moved to storytold/craft-common-actions, it has
passed only the Apple and WINDOWS_CERTIFICATE secrets. The signing job reads
values from the release environment, but only for names the caller lists, so
the AZURE_* names that Trusted Signing uses came through empty and Windows
builds would ship unsigned. Same fix as storytold/craft-launcher#174.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:08:25 -04:00
skylar taylor-barrick 85bfcdfcfd Merge pull request #459 from storytold/codex/craft-print-onboarding
Print: select printers and submit jobs through craft-print
2026-10-12 09:05:31 -06:00
Isaac Levine 746a1e0364 File: Export as PDF in the File menu, and the palette asks for a path (#407) 2026-10-12 11:03:13 -04:00
skylar taylor-barrick 9fc4108899 Printing: expose native commands through control discovery 2026-10-12 16:50:03 +02:00
Marco Arnulfo dfb780a544 UI: clicking a column or row header in point mode inserts N:N / n:n (#691) 2026-10-12 15:56:22 +02:00
RichardandClaude Opus 5.5 ae54c84bc9 Key the cached Top 10 cutoff by criterion, not column (#661)
Two Top 10 criteria on one column (possible in native JSON files) shared one
cache entry, so the last cutoff overwrote the first. Reported by @derechopiano.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ut3hr3a13szpQdQ7gbYbfc
2026-10-13 00:10:54 +11:00
Vedran DobosandClaude Opus 5.5 3830cee850 View: Ctrl+wheel zoom steps along a ladder that never skips 100% (#689)
Each frame multiplied the whole-number zoom by egui's eased wheel
factor and rounded, so a notch out never undid a notch in:
100 -> 122 -> 101 -> 123 -> 102.

A notch now moves to the next step on WHEEL_ZOOM_LADDER (10 ... 85, 100,
120 ... 400; four per doubling, about 20% apart). A step less than 5%
away is skipped, but 100% and the limits never are, so 121% out goes
to 100% and 99% in goes to 100%. The wheel's turning is counted in
notches: parts of a notch add up, and a notch steps once 60% of it has
turned. With animations on the zoom glides to the step, and a notch
turned during a glide steps on from where it's going.

The status bar's Zoom In / Zoom Out keep their 10% steps; that, and
whether the glide needs a setting of its own, is noted in
docs/decisions.md for the maintainers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:57:57 +02:00