skills/productivity/xlsx/references/restructuring.md
scripts/xlsx_restructure.py performs one row/column insert or delete
and rewrites everything that references the moved cells. This document
gives the exact rewrite rules and honest limits.
| Artifact | Scope | Behavior |
|---|---|---|
| Formula references | ALL sheets | A1 refs into the edited sheet are shifted; refs into a fully deleted region become #REF! |
| Merged-cell ranges | edited sheet | shifted; expanded when they span the insertion point; dropped (reported to: null) when fully deleted |
| Autofilter ref | edited sheet | shifted/expanded like a range |
| Freeze panes | edited sheet | anchor cell shifted (never below row/col of the pane's own minimum) |
| Data validations | edited sheet | each range in the sqref shifted; deleted ranges removed |
| Conditional formats | edited sheet | applied range (sqref) shifted |
| Native tables | edited sheet | table ref shifted/expanded |
| Defined names | workbook scope | attr_text refs into the edited sheet rewritten |
| Row heights / column widths | edited sheet | dimension keys re-indexed |
B2, $B2, B$2,
$B$2 — the $ flags are preserved through the shift.B2:D9, including partial-absolute endpoints.Data!B2, 'My Sheet'!$A$1:$C$9 (quoted names may
contain doubled quotes ''). Only refs whose sheet qualifier matches
the edited sheet are touched; unqualified refs are interpreted
relative to the formula's own sheet."See B2") are never rewritten.LOG10(...)) are not touched
(a reference is never followed by ().B:B, 2:2) pass through unchanged — Excel
semantics keep them valid across inserts within the span.Insert of N at index i: every coordinate >= i moves +N; range endpoints move independently, so a range spanning i grows by N.
Delete of N at index i: coordinates before i are unchanged; coordinates
past the deleted block move -N; a single cell inside the block becomes
#REF!; a RANGE partially covering the block is clamped (Excel does the
same); a range entirely inside the block becomes #REF! (formulas) or
is removed (merges/validations).
cell_is/expression rules (e.g.
$B1>100) are left as-is. Review them if they reference moved cells.Table1[Sales]) don't
need shifting (they follow the table), and are left alone.Every run prints a JSON report listing exactly which formulas, merges,
tables, names, and ranges were changed, plus a fixed not_shifted list
of the above limits — inspect it after any structural edit.
The CLI takes exactly one of --insert-rows/--delete-rows/ --insert-cols/--delete-cols (as IDX[:N]; columns accept letters).
For multiple operations run it repeatedly — ordering compound shifts in
one pass is where spreadsheet tools historically corrupt references.