Commit Graph
534 Commits
Author SHA1 Message Date
prxnvt 66e69cb946 Engine: a linked paste carries the file's trust whatever it pastes
Paste Link writes a formula into every cell whatever `what` says, so a linked
paste of formats from a file now makes the destination FromFile as a paste of
formulas does. Column widths and notes write no cells, linked or not, and
still carry nothing. Regression test for the three kinds.
2026-10-23 20:01:21 -04:00
prxnvt 5ca886507c Engine: writing a stash item checks for a clashing visible name in one pass over the names
The check ran once per chunk, each a scan of every defined name: an item of many chunks in a workbook with thousands of names compared every pair. One pass now parses each visible workbook-scope name and refuses when it is a chunk of this key below the chunk count. The behaviour and its test are unchanged.
2026-10-23 16:21:48 -04:00
prxnvt 602d4450a2 Merge main into #462 2026-10-23 16:10:43 -04:00
Brandon ThomasandClaude Opus 5.5 7cf44d0fbb Integration and review fixes for #2367, #2369 and #2387
- #2369: its test joins the single ui-egui integration-test binary (tests/it), as main now builds them.
- #2367: a cell set to empty text is a blank entry and doesn't grow the AutoFilter (CodeRabbit).
- #2387: MOD's range check also covers the sign-corrected remainder (CodeRabbit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 16:05:43 -04:00
Brandon Thomas 68da23e2eb Merge PR #2386 2026-10-23 16:05:01 -04:00
Marco Arnulfo 43a5a3c435 PivotTables: Show Details checks the report is up to date before looking at the cell 2026-10-23 21:00:07 +02:00
Marco Arnulfo 7111812b87 PivotTables: Show Details refuses an out-of-date report, and reports its errors instead of editing the cell 2026-10-23 20:41:47 +02:00
Marco Arnulfo 0c14f59555 PivotTables: Show Details, double-click a value cell to list its source records on a new sheet (#2364) 2026-10-23 20:21:27 +02:00
MarekSpodBiedry 599762f534 AutoFilter: grow the range when a value is entered in the row below it (#2342) 2026-10-23 17:36:39 +02:00
Brandon ThomasandClaude Opus 5.5 f1e29fa828 Review fixes for #2267 and #2292
- range.setValues with parse: false still turns on Wrap Text for a line break (CodeRabbit).
- Japanese: the fill-handle hint says AutoFill (オートフィル), not paint (CodeRabbit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:15:31 -04:00
Brandon Thomas bcf55f0f00 Merge PR #2274
# Conflicts:
#	docs/ui-parity.md
2026-10-23 10:11:33 -04:00
Brandon Thomas e92d8b4e48 Merge PR #2295 2026-10-23 10:11:12 -04:00
Brandon Thomas 50e5a3e928 Merge PR #2267 2026-10-23 10:11:11 -04:00
D. Fender 09f78cb3a8 Tables: Format as Table inside a table restyles it
Home > Format as Table on a cell or range inside an existing table
failed with "A table can't overlap another table." Excel applies the
picked style to that table instead. The command now returns that table
and its range, as it does for a new table. A range crossing a table's
edge is still rejected.

Without a range, the active area of the selection decides, as it does
for Insert > Table. The native Format menu's Format as Table now runs
home.formatAsTable instead of insert.table.
2026-10-22 11:43:58 -07:00
Higgs32584andClaude Opus 5.5 b5b3969377 scripts: trust gate review fixes (#2178)
- automate.trustScripts: only a missing `trusted` defaults to true; a
  non-boolean value is an error and leaves the workbook untrusted.
- The refusal message points at Trust Scripts in View > Macros (Alt+F8)
  and at automate.trustScripts.
- Catalog row for automate.trustScripts; parity checklist regenerated.
- Script steps run inside an io::ScriptSandbox (thread-local) so
  read_file/write_file refuse whatever the parameter is called, and a
  step that raises OpenUrl is dropped and stops the script. The id/param
  deny list stays as the up-front refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 12:43:48 -04:00
Higgs32584 6dedb9310b Merge remote-tracking branch 'origin/main' into fix/2178-script-trust-gate 2026-10-22 12:32:28 -04:00
Dominik StrebelandClaude Opus 5.5 840ba5c3a5 view: Show Outline Symbols (Ctrl+8), read and written
A sheet can hide its outline's level buttons and brackets while keeping
the outline (Excel's Ctrl+8, saved as showOutlineSymbols="0"). It wasn't
modelled, so such sheets showed a wide outline band Excel doesn't.

- model: Sheet::show_outline_symbols (default on, also for older JSON).
- xlsx: read and written on the sheet view.
- engine: view.showOutlineSymbols {on?} (Ctrl+8), undoable.
- ui: no outline bands while it's off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:54:06 +02:00
Hamza 99f92f4a28 range.setValues: parse: false stores a string as the text it is (#2255)
Every string in `values` went through typed input, which reads it with en-US
rules, and nothing said so:

    "05.04.2026"  (dd.mm.yyyy)  → the date 4 May 2026
    "02/11/2026"  (dd/mm/yyyy)  → the date 11 February 2026
    "2.500"       (thousands)   → the number 2.5
    "4.25 %"      (text)        → 0.0425, formatted 0.00%

A workbook built from Turkish-format exports therefore held different values
than the script put in it, and the only way to notice was to read the saved
file back cell by cell.

`parse: false` stores every string as the text it is. A formula is still a
formula — `=` means a formula in a cell, and the ticket asks for that — and
numbers, booleans and null are unaffected either way. A leading apostrophe is
part of the text rather than the marker that makes it text, since nothing is
being marked.

The default is unchanged: `parse` is absent in every existing call, and those
calls behave exactly as before. A `parse` that is neither true nor false is a
usage error rather than a quiet default.

The test pins both sides — the swapped date, the decimal point and the
percentage under today's default; each of the six strings stored verbatim with
`parse: false`, with `=1+1` still calculating 2; numbers and booleans either
way; and the refused `parse` values. Without the change the first string comes
back as a date.
2026-10-22 18:05:53 +05:00
prxnvt 38ad2dba83 Merge main into #2144
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-22 02:37:04 -04:00
prxnvt 66f7993ba5 Merge main into #462
# Conflicts:
#	crates/engine/src/lib.rs
#	crates/engine/src/tests.rs
#	docs/architecture.md
2026-10-22 02:30:25 -04:00
prxnvt bf456c9ff8 Engine: a macro's footprint dry runs keep to the run's timeLimit
footprint always ran its dry run with the default 60 second limit, so
macro.run with timeLimit 5 could run for over two minutes (a dry run,
then another after a shift) and fail with "ran longer than 60 seconds".

footprint now takes the run's clock and limit. make_way starts the
run's clock before the dry runs, so the checks and the run share one
limit, and macro.check takes timeLimit too.
2026-10-22 02:26:32 -04:00
prxnvt 54c08645b9 Engine: macro.run and macro.check: input checks, footprint dry run, policy
macro.run runs a macro as one undo step ("Run Macro: <name>"); an error
at any step rolls everything back and names the step and its path (3,
2.1 inside a Repeat, 4.then.1 inside an If). It works in four parts:

- Policy (macro_policy). File, app, window, automate and macro commands
  and Undo and Redo never run in a macro. Reading or writing files
  (data.getData, data.fromTextCsv, insert.picture, Page Layout
  Background, or an export with a path) needs the command in the
  macro's permissions and the person's approval. A macro in a workbook
  opened from a file asks before it runs. Approval holds for the
  session until the macro's content changes; it is asked for with the
  new EngineError::Approve and given with approve: true. A step that
  would open a dialog or a web page fails instead.
- Inputs. Each declared input is bound (given, its default, or the
  selection for the first one), whole columns shrink to the used range,
  and the shape and column types are checked with messages that name
  the cells: "Input column 2 (Amount) must hold numbers; C4 holds text".
- Footprint. Unless the macro may overwrite, it first runs in dry-run
  mode on the real workbook inside an undo group that is rolled back,
  with the session's clipboard, journal, windows and the document's
  trust put back. CellStore::diff on every sheet, plus the cells
  commands wrote (DocState::touched), sheets and objects, gives what it
  would write outside its inputs; cells that only recalculated do not
  count. Writing over data, deleting a sheet or deleting an object is a
  conflict: ask (the new EngineError::Confirm, so programmatic runs fail
  unless they pass onConflict or overwrite), fail, overwrite, or shift
  the data down or right with Insert Cells and check again. A step that
  would fail, for example past the edge of the sheet, fails the run
  before anything changes. File steps and Solver stop the dry run early
  and are reported.
- Steps run on a machine with an explicit frame stack: Repeat over the
  rows or columns of a range with Row or Column bound, If on one cell
  with Excel's comparisons, and Stop, which keeps the changes or rolls
  them back. A run executes at most 100,000 steps within a time limit
  (60 s by default, timeLimit to change; the web build has no clock, so
  only the step limit applies there).

macro.check reports the bound inputs, the output anchor, the approval
needed, the footprint and the conflicts without changing anything;
nothing from an unapproved macro runs, not even as a dry run.
2026-10-22 02:26:32 -04:00
prxnvt 471114e296 Engine: a visible name of the item shape is not workbook data
The item store read, listed and removed every workbook-scope name of the `_gc_<key>_<n>` shape,
visible or not, so saving an item removed a person's own visible name that happened to look like
one. Items are the hidden names the store writes; a legacy `_sc_<key>` name still reads. A visible
`_gc_` name is left alone by every operation, and writing an item that would need that name is
refused before anything changes: a hidden name beside it with the same name is the one an xlsx
file drops, so the item would be lost on save.
2026-10-22 02:24:55 -04:00
aiongg d5cdd2ea2b Integration: track t15
# Conflicts:
#	contributors/people.toml
#	crates/engine/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
2026-10-22 03:05:39 +00:00
aiongg 561382cc6d Integration: track t14
# Conflicts:
#	ROADMAP.md
#	contributors/people.toml
#	crates/formula/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
#	docs/ui-parity.md
2026-10-22 03:05:30 +00:00
aiongg ca1cdd4229 Integration: track t13
# Conflicts:
#	ROADMAP.md
#	contributors/people.toml
#	crates/engine/src/cmd/data.rs
#	crates/xlsx/src/tests/mod.rs
#	docs/chart-parity.md
#	docs/file-format-parity.md
#	docs/function-parity.md
#	docs/gaps.md
#	docs/localization-parity.md
#	docs/target-app-parity.md
2026-10-22 03:05:18 +00:00
aiongg c7fd66d807 Integration: track t12
# Conflicts:
#	ROADMAP.md
#	crates/calc/src/tests.rs
#	crates/chart/src/tests.rs
#	crates/engine/src/tests.rs
#	crates/xlsx/src/tests/mod.rs
#	docs/chart-parity.md
2026-10-22 03:05:03 +00:00
aiongg 9350ab1def Integration: track t11
# Conflicts:
#	ROADMAP.md
#	apps/gridcraft-web/Cargo.toml
#	crates/ui-egui/src/i18n.rs
#	docs/control-protocol.md
#	docs/gaps.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-22 03:04:52 +00:00
aiongg 4c5c345c31 Integration: track t10
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/tests/sheet_tabs.rs
#	crates/xlsx/src/tests/roundtrip.rs
#	docs/gaps.md
#	docs/ui-parity.md
2026-10-22 03:04:30 +00:00
aiongg 6dda6be2c6 Integration: track t09
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/pt.rs
#	docs/file-format-parity.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-22 03:04:21 +00:00
aiongg d3201e7cea Integration: track t08
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
2026-10-22 03:03:55 +00:00
aiongg 4c81d658ec Integration: track t05
# Conflicts:
#	crates/ui-egui/tests/keyboard_shortcuts.rs
#	docs/ui-parity.md
2026-10-22 03:01:39 +00:00
aiongg 512b2aa9fd Integration: track t04
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/edit.rs
#	crates/engine/src/cmd/formulas.rs
#	crates/engine/src/tests.rs
#	crates/formula/src/lib.rs
#	crates/formula/src/parser.rs
#	crates/formula/src/tests.rs
#	crates/ui-egui/src/control.rs
#	crates/ui-egui/src/formula_bar.rs
#	crates/ui-egui/src/grid.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/ribbon.rs
#	crates/ui-egui/tests/selection.rs
#	docs/function-parity.md
#	docs/ui-parity.md
2026-10-22 03:01:31 +00:00
aiongg b0b6409112 Integration: track t03
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/tests/keyboard_shortcuts.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
#	docs/ui-parity.md
2026-10-22 03:00:13 +00:00
aiongg 54d0f7cfc0 Integration: track t02
# Conflicts:
#	ROADMAP.md
#	crates/core/src/lib.rs
#	crates/ui-egui/src/editor.rs
#	crates/ui-egui/src/grid.rs
#	crates/ui-egui/src/tabs.rs
#	docs/chart-parity.md
#	docs/localization-parity.md
#	docs/ui-parity.md
2026-10-22 02:59:55 +00:00
aiongg 1d9b29ff57 Integration: cargo fmt 2026-10-22 02:45:22 +00:00
aiongg 1316d39865 Merge PR #1151: Charts: a huge trendline forecast no longer collapses the chart (#1148)
ROADMAP.md: all rows kept.
crates/chart/src/tests.rs: both tests kept.
2026-10-22 02:37:37 +00:00
aiongg 169c78dda8 Merge PR #1111: Respect workbook structure protection in sheet rename, move, copy, hide and unhide (#1049) 2026-10-22 02:37:22 +00:00
aiongg 470a2ae2c1 Merge PR #1765: Sheet protection: obey the Sort and Use AutoFilter boxes
Conflicts:
- crates/engine/src/cmd/data.rs: do_sort keeps #1284's sheet parameter and checks Sorting on it; toggle_filter checks Filtering after #1285's data_target
- crates/engine/src/tests.rs: adjacent tests, both kept
2026-10-22 02:37:16 +00:00
aiongg 431aaaaf69 Merge PR #2022: Reject unparseable conditional-format formulas (#1999)
crates/engine/src/cmd/insert.rs: kept both sides: PR #884's is_string_literal and cf_style_json, and PR #2022's check_cf_* before edit(); 884's kept string literals parse
2026-10-22 02:36:33 +00:00
aiongg 8ec29a8b3b Merge PR #1652: Fill handle: right-drag opens the fill menu (Copy Cells, Fill Series, Fill Formatting Only, Fill Without Formatting, Series…)
crates/ui-egui/src/grid.rs: kept both GridState fields (context_menu_frame, fill_menu); previous_popups tuple has four elements inside the touch_pan branch; release match has Drag::Rows|Cols, then the two Drag::Fill arms
docs/ui-parity.md: kept HEAD header line, both change rows
2026-10-22 02:36:24 +00:00
aiongg d97f61748e Merge PR #1946: XLSX: keep cell fonts' charset (Arabic 178) and family on save
crates/xlsx/src/styles.rs: family/charset block ported into the dxf.is_none() branch of font_xml (PR #1225 made it take Option<&DxfStated>)
docs/file-format-parity.md: header Change line keeps both sides' clauses
2026-10-22 02:36:23 +00:00
aiongg 8e2974cc65 Merge PR #1629: Memory: undo steps share picture and macro bytes instead of copying them
Conflicts:
- ROADMAP.md: both progress-log and revision rows kept
- crates/xlsx/src/sheet_write.rs: keeps #995's image_part call; drops #1629's to_vec line (image_part copies from &[u8])
2026-10-22 02:36:22 +00:00
aiongg cba89cfda8 Merge PR #1066: Engine: formulas.evaluate refuses what cell entry refuses, saying why
ROADMAP.md: both progress-log rows kept.
2026-10-22 02:36:20 +00:00
aiongg ced3f7ce7a Merge PR #1912: Print CJK text with a CID font instead of question marks
crates/pdf/src/lib.rs: add_page keeps both fonts [bool; FONT_SLOTS] and links Vec
2026-10-22 02:36:20 +00:00
aiongg 7fd1553a8b Merge PR #1626: Keyboard: Ctrl+6 hides and shows objects, saved as workbookPr showObjects
Conflicts:
- docs/file-format-parity.md: header and the three .xlsx rows keep main's text plus the show-objects entry; both log rows kept
- docs/ui-parity.md: header keeps main's text plus Ctrl+6; both log rows kept
2026-10-22 02:36:15 +00:00
aiongg 8590dca0db Merge PR #2207: clipboard: bound HTML colspan/rowspan expansion (#2171) 2026-10-22 02:36:12 +00:00
aiongg d0394a0f34 Merge PR #2005: AutoFill refuses a target that doesn't hold the source in a corner (whole rows into whole columns aborted the app)
crates/engine/src/fill.rs: kept both tests (#1360 and #2005).
2026-10-22 02:36:12 +00:00
aiongg d67193f403 Merge PR #1685: #1447: a PivotChart's link names the workbook
docs/file-format-parity.md: header Change line names both pivot fixes; both change log rows kept
2026-10-22 02:36:11 +00:00
aiongg 635056bd23 Merge PR #2131: Print: JIS B4/B5 and Japanese paper sizes (はがき・封筒・B6)
ROADMAP.md: one status line naming both changes; both feature-table and progress-log rows, newest first.
2026-10-22 02:36:10 +00:00