chore: sync upstream (162 Commits) #16
No reviewers
Labels
No labels
herkunft/alpha-feedback
status
blockiert
status
zu-testen
typ
bug
typ
docs
typ
enhancement
typ
feature
typ
idea
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
iris/gridcraft!16
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "chore/sync-upstream-20261104"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Upstream-Sync von
upstream/main(162 Commits). Fast-Forward.632e4a1bformula, calc: LET/LAMBDA names looked up through a map; ragged array literals refused before reserving (#3312)e5f6fa81ui-egui: reference colours through a map; cap fill-character repeats per cell (#3311)f77ed98cchart: a series without values takes no category-span entries (#3300)22c5dfe0engine: protected sheets gate filter reapply, outline, line sizes and floating pictures; pivot destination resolved before the structure check; user-limited edit ranges stay locked (#3296)cdd3a59dTreemap rows keep running aggregates; General-fit width is clamped (#3290)bebe7de8engine: cap header and footer sections at 64 KiB when fields expand (#3284)4421bc67engine: weekday fill series moves by whole weeks (#3272)017c8057functions: match TEXTSPLIT/TEXTBEFORE/TEXTAFTER delimiters through an index, within a work limit (#3263)a31178f5functions: NUMBERVALUE strips trailing percent signs in one pass (#3262)184c0ec8ods: charge a cell's text when the cell is read, not when its row ends (#3257)065f05dbSecurity: MODE counts through an index, FREQUENCY bins by binary search (#3198)db05400ecalc: list each dependent once when a change spreads (#3190)c0ea2976calc: cap the text one & over arrays may build in all (#3189)74111e5acheck: charge relationship parts to the package's decompression budget (#3185)014f030aengine: PivotTable filters test each record against a set of selected labels (#3279)Cell gains `py: Option<Arc<PyCode>>`, read with a serde default and not written for ordinary cells, so older native files load and ordinary cells serialize as before. PyCode holds the code, the return type (an Excel value or a Python object), the last result (value, type name, preview, whether it converted to cells) and a stale flag for manual calculation. The cell's `value` stays the cached result, so formulas, display and saving read a Python cell like any other. is_blank, CellStore::has and input_text (which returns the code) take the code into account; Cell::has_content and clear_content cover value, formula and code together. The model reads and writes the PY function's syntax as Microsoft documents it, PY("chunk"&"chunk",0|1), with string literals of at most 255 characters and the return type 0 for an Excel value, 1 for a Python object. The reader takes the `_xlfn._xlws.` prefix (and `_xlfn.` or `_xlws.` alone, in any letter case); to_file_formula writes it. (An xlsx file keeps the code in its Python part instead; the xlsx commit adds it.) The size limit is Excel's 8,192 characters for that formula, not a count of code characters: doubled quotes and the "&" between literals count, so code with many quotes fits in fewer characters (8,079 characters of plain code fit exactly). The model also finds the xl("...") literals in code, skipping comments and other strings; a plain literal may escape a quote or a backslash. A rewritten reference that holds the literal's quote (a sheet name that needs quotes, 'Q4 2026'!B2) takes the other quote as the literal's delimiter, or an escaped quote when it holds both, so it never ends the string early. Edits: cell.set over a Python cell, Clear Contents, Clear All and the cells a merge empties remove the code; Clear Formats keeps it. Copy and paste (All, Formulas), Fill, sort, cut-move, sheet copy and undo carry it; a cut to another sheet first qualifies its xl() references with the source sheet, as a moved formula's references are, so they keep reading the same cells. Paste Values and Paste Link do not carry it, and paste operations do not combine numbers with a Python cell. Fill copies Python cells instead of extending them as a series. cell.set with =PY(...) is refused with a message that points to python.set, and Text to Columns keeps a piece that reads as =PY(...) as text instead of clearing it. Goal Seek refuses a Python cell as its changing cell, and Solver as a variable cell, as both refuse formulas: the number written there would replace the code. The sheet-protection check compares the code, so a locked Python cell cannot be changed. cell.get reports {python: code, output, typeName, preview, stale}. The xl() literals follow reference-moving edits: rewrite_all_formulas (row and column insert and delete, cell insert and delete, cut-move), sheet rename and sheet delete adjust each literal like a formula reference, and replace it only when it changed. Errors: CellError gains Python, Busy, Timeout and Blocked, and ALL has 14 entries, so the lexer reads them as literals. ERROR.TYPE gives 11 for #BLOCKED!, the number Excel returns. Microsoft documents no ERROR.TYPE number for #PYTHON!, #BUSY! or #TIMEOUT!; they take 19, 20 and 21, after the numbers Excel is known to use. The xlsx writer caches the four as #VALUE!, as it already does #SPILL! and #CALC!, because they are not error codes of the file format. Tests cover the =PY refusal, removal by entry and clearing, undo, copy, paste values, fill and sort, xl() rewrites through row insert, sheet rename (also to names that need quotes, with one quote and with both), cut-move (also to another sheet) and column delete, Goal Seek and Solver refusing Python cells, Text to Columns keeping a =PY piece, native JSON round trips, the new errors, the prefixes, escaped quotes in literals, and the encoded size limit at 8,192 characters exactly and with doubled quotes.doesn't run it python.set {cell?, code, output?: object|value} makes the cell (the active cell by default) a Python cell, keeping its style and taking a formula and its spill away. `output` is the return type Microsoft documents for PY(): an Excel value (the default) or a Python object; without it a Python cell keeps the one it had. The code must fit in Excel's 8,192-character formula once written as PY(...), quotes doubled and literals joined, so the command checks the encoded formula rather than a character count. A table's header row refuses Python (it holds the column's name, as Excel keeps formulas out of headers), and a locked cell on a protected sheet refuses it through the usual protection check. Nothing runs Python here. Unchanged code keeps its cached result and value; new or changed code shows #BLOCKED!. One undo step takes the cell back. Sheet::clear_spill removes the spilled values inside a range with work bounded by the values stored, not by the range's size. In the interface, F2, a double click or the formula bar on a Python cell edits its code, and a changed text is committed through python.set, which keeps the return type; through cell.set it would have replaced the Python cell with an ordinary cell holding the code as text. Typing over a Python cell replaces it, as typing over a formula does, and committing the code unchanged writes nothing. Deleting all the code clears the cell through cell.set, as an empty entry clears any other cell; code of spaces is still code. Tests: the code and return type in cell.get, #BLOCKED! for new code, cached results kept for unchanged code, the active-cell default, undo, refused params (missing or non-text code, a bad cell, a bad return type), the encoded limit at 8,079 and 8,080 characters and with doubled quotes, a table header, a protected sheet, and a formula's spill taken away. A UI test edits a Python cell's code with F2 and Enter, commits it unchanged, and types over it; another clears a Python cell by deleting all its code, keeps code of spaces, and undoes the clearing.A Python cell's return type had no command of its own: python.set takes it, but only together with the code. python.output {cell?, mode?} sets it on its own; its command entry lists Excel's shortcut, Ctrl+Alt+Shift+M. Without a mode it switches to the other one, so the shortcut needs no parameters; a cell that isn't a Python cell is an error. A cached result belongs to the return type it was made for, so a switch treats it as python.set treats a new return type: the result goes, the cell shows #BLOCKED! until it runs, and its old spill goes with what read it recalculated. Both commands write the cell through one path, so python.output refuses a table header and a locked cell on a protected sheet as python.set does. Each switch is one undo step, and setting the mode a cell already has adds none. python.set now refuses an output that isn't text instead of ignoring it. The command-sequence fuzzer runs python.output too. A macro recording keeps the return type a switch without a mode set, as its mode (as Bold records on), also for a switch inside a recorded script run, so playing it back sets that type rather than switching again. Tests: switching without a mode drops the cached result, its spill and the value its reader saw, the same as python.set with the other return type; switching back brings no result back; the code is kept; one undo step per switch, undo brings the result back, and none for the mode a cell already has; a cell without a result stays #BLOCKED!; the refusals (no Python cell, a bad or non-text mode, a bad cell, a table header, a locked cell, a non-text output for python.set), an unlocked Hidden cell on a protected sheet switches, and a recorded switch played back on a cell that already has the new type keeps it.25881a8e) into the Python cells branch b78afc9b3c57d7ea9b, main25881a8e) into the Python mode layer 9a094696feui.pythonMode {on: true} (or a switch with Python mode off) answered {"on": false} when Python mode could not start, so a control or MCP client saw success. It now returns an error naming why: a locked cell on a protected sheet, a cell or draft inside another cell's spill, or code hidden on a protected sheet. Test: a_refused_ui_python_mode_start_is_an_error_with_the_reason (fails without the fix); python_mode_starts_no_edit_on_hidden_code and python_mode_does_not_start_on_a_draft_typed_inside_a_spill now expect the error.9f4ca54e) into the Python mode layer f988c2843e3379f12a) into the Python cells branch 7c5f417a5d7c5f417a, main3379f12a) into the Python mode layer 5579ec9a656f52cc50) into the Python cells branch 7ddcb800ea7ddcb800, main6f52cc50) into the Python mode layer e9430daa9aDragging the selection's border onto cells that hold data replaced them without asking, so dragging column B onto column A silently destroyed A. Excel asks "There's already data here. Do you want to replace it?" first (its "Alert before overwriting cells" option, on by default). The drop now runs a new `range.move {range?, to, overwrite?}` command: a cut and paste that returns a confirm question when the destination holds data other than the moved cells; the grid shows it with OK and Cancel, and OK runs it again with `overwrite: true`. A refused move leaves the sheet and the clipboard as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>A workbook with an in-cell picture and a dynamic-array formula wrote the XLDAPR futureMetadata extension URI in upper case ({BDBB8CDC-…}), and Excel refuses such a workbook. The metadata part written for dynamic arrays alone, which Excel opens, spells the same URI in lower case; the rich-value writer now does too. Together with #1533 (content types and the XLRICHVALUE URI) this lets Excel open a workbook with an in-cell picture and a spilled formula. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>A workbook with checkboxes saved by GridCraft made Excel repair it ("Repaired records: Format from /xl/styles.xml (Styles)") and drop every checkbox. The feature property bag part GridCraft writes for checkboxes left out extRef="XFComplementsMapperExtRef" on the XFComplements bag, the bag the cell formats' xfComplement indexes into. With it, Excel opens the file without repairing and shows the checkboxes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>The bottom edge of the formula bar is a resize handle: dragging it sets the height in whole lines (up to half the window; one line collapses the bar). Expanding again (the chevron, Ctrl+Shift+U) returns to the dragged height instead of a fixed five lines. The drag previews live and commits once through view.expandFormulaBar {lines}, which is also scriptable; the height is kept with the UI preferences. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>!, sheet as is 2caf435a38