Fill Series by month used the previous cell's day as an overflowing DATE()
day, so Jan 31 + 1 month became Mar 3 and February was skipped. The same
overflow affected year steps from Feb 29 and the autofill month pattern.
Each item is now computed from the start date plus n months and the day is
clamped to the target month's length (Jan 31, Feb 28, Mar 31, Apr 30), so
the clamp does not compound. Leap years are handled.
Fixes#132
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Excel documents the first argument of MIN as optional and returns 0
when there are no numbers. MIN was registered with a minimum of one
argument, so =MIN() returned #VALUE!. The aggregate already returns 0
for an empty list, so only the registered arity needed to change.
Fixes#138
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Histogram, box & whisker, waterfall, funnel, treemap and sunburst charts
were written as clustered columns, and reading skipped such charts in
files made by Excel, which keeps them as cx:chartSpace (chartex) parts.
The writer now writes these kinds as chartEx parts, as Excel lays them
out: the data goes through hidden _xlchart.v1.N workbook names, each
part comes with chart style and colour parts, and the drawing frames it
in mc:AlternateContent with a text-box fallback. Fills are written out
(series in theme accents, waterfall decreases and treemap/sunburst boxes
in their own, a white chart area), so they don't depend on the style
part. The reader reads the parts back (resolving the _xlchart names,
which aren't kept as names) with data, title, axis titles, legend,
labels and colours, and follows mc:AlternateContent in drawings.
Excel doesn't support spilled arrays in tables: a formula such as
=SEQUENCE(2) entered in a table cell shows #SPILL! ("Spill range in
table"). GridCraft spilled it over the table's cells. An array whose
formula is in a table is now blocked, both when it is computed and when
it is written back.
Go To (and the Name Box) with a table's name selected the whole table,
header and totals rows included. In Excel a table's name stands for its
data rows, as in formulas (=SUM(Table1) adds only the data).
Editing a table's header cell changed only the cell: the column kept its
old name, so =SUM(Table1[a]) still worked after the header read "zz",
and saving wrote the old names back into the header row, undoing the
edit on reopening. As in Excel, the column now takes the new header;
an emptied header becomes ColumnN and a repeated one gets a number
("a2"), written back into the cell, and structured references follow
the new name.
A formula whose references are only known while evaluating isn't in the
dependency graph, so when it read a spill area before the array was laid
out in the same pass, nothing evaluated it again. With the full
recalculation now laying every spill out afresh, =INDIRECT("F7") over
a spill moved by an inserted row read 0 after Calculate Now. Such
formulas are evaluated once more when a pass computed any array.
A dynamic array that couldn't spill was only rejected when results were
written back, after formulas evaluated later in the same pass had read
the array as if it had spilled. With 1s in A1:C3 except B2 =
SEQUENCE(2,2,9) (blocked), =SUM(A1:C3) gave 47 after a full
recalculation (opening a file, Calculate Now) instead of #SPILL!; a
reader through OFFSET kept the wrong value even when entered one cell
at a time. The spill area is now checked as soon as the array is
computed, so the anchor is #SPILL! for everything after it.
When two dynamic arrays were recalculated in the same pass and the
first read the second's spill area before the second was evaluated, it
read the old values. Formulas reading a spill area that changed are
evaluated again, but dynamic arrays were left out of that second round
(only to keep an array from re-queuing itself), so with D11 =
SEQUENCE(1,3,A1) and G5 = UNIQUE(VSTACK(F9:F12,A1)), changing A1 from 1
to 10 left 3 in G6 instead of 12. Only the array itself is left out
now.
With =SEQUENCE(5) in F8 and =SEQUENCE(1,3) in E10 (blocked by F10),
typing 0 into F9 blocks F8's array, which frees F10, but E10 stayed
#SPILL! until a full recalculation. When a formula stops spilling over
an area, #SPILL! anchors above or to the left of it are evaluated again.
Clearing a cell re-evaluated #SPILL! anchors only within 64 rows and
columns above and to the left of it, so =SEQUENCE(100) in A1 stayed
#SPILL! after the blocker in A90 was cleared. Emptied cells now look
for blocked anchors any distance above or to the left, with one pass
over the formulas per sheet however many cells were cleared.
Fixes#139.
Inserting or deleting rows and columns moved formula cells but not the
values they had spilled, and the full recalculation that follows
reconciled spills only at the formulas' new positions. =SEQUENCE(3) in
A5 with row 1 deleted showed #SPILL! in A4 (blocked by its own old
values in A6:A7); deleting the anchor's row left 2 and 3 behind. A full
recalculation now drops all spills and lays them out again from the
formulas.
Fixes#133.
=SUM(C3:INDEX(B9:C11,2,2)) adds C3:C10, but only C3 and B9:C11 were
recorded as its precedents, so typing into C5 left the total unchanged
until a full recalculation. A range whose ends are function results now
depends on the box spanned by the references inside it, which contains
any cell those functions can return.
Typing a value over a dynamic array formula, or clearing it, left the
values it had spilled: with =SEQUENCE(3) in A1, typing 2 into A1 kept
2 and 3 in A2:A3, and =SUM(A1:A3) gave 7. Only formulas are evaluated
again, so the old spill of a cell that no longer holds a formula was
never written back. It is now removed when the formula goes, and the
formulas reading its area are recalculated.
Add, Subtract, Multiply and Divide replaced every cell that didn't hold
a plain number with the pasted value: multiplying a column by 1 turned
numbers stored as text, headers and #N/A all into 1, and a formula into
a constant. As in Excel, numbers stored as text now take part (the
usual way to turn them into numbers), other text and errors stay, and
a formula is kept and combined with the pasted number: =(B3*2)*1.
The target was capped at 5 million cells but the source wasn't: with the
whole sheet as source and A1 as target, AutoFill read all 17 billion
source cells one column at a time and never finished.
A formula's result that is a blank cell shows 0, but blanks inside an
array result spilled as blank cells: =A1:A3, or FILTER or SORT of a
range with blanks, left empty cells that ISBLANK saw as blank and
COUNT skipped. Excel shows 0 in each. GROUPBY and PIVOTBY keep the
blank cells of their own layout.