@rowsncolumns/spreadsheet-state 28.0.74 → 28.0.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/cjs/api/anchored-objects.d.ts +66 -0
  2. package/dist/cjs/api/anchored-objects.d.ts.map +1 -0
  3. package/dist/cjs/api/anchored-objects.js +259 -0
  4. package/dist/cjs/api/datatype.d.ts.map +1 -1
  5. package/dist/cjs/api/datatype.js +8 -1
  6. package/dist/cjs/api/dependency.d.ts +13 -2
  7. package/dist/cjs/api/dependency.d.ts.map +1 -1
  8. package/dist/cjs/api/dependency.js +11 -5
  9. package/dist/cjs/api/fill-series-spec.d.ts +35 -0
  10. package/dist/cjs/api/fill-series-spec.d.ts.map +1 -0
  11. package/dist/cjs/api/fill-series-spec.js +164 -0
  12. package/dist/cjs/api/fill.d.ts +95 -3
  13. package/dist/cjs/api/fill.d.ts.map +1 -1
  14. package/dist/cjs/api/fill.js +1186 -418
  15. package/dist/cjs/api/formula.d.ts +61 -4
  16. package/dist/cjs/api/formula.d.ts.map +1 -1
  17. package/dist/cjs/api/formula.js +250 -61
  18. package/dist/cjs/api/immer-utils.d.ts.map +1 -1
  19. package/dist/cjs/api/immer-utils.js +20 -15
  20. package/dist/cjs/api/intl.d.ts.map +1 -1
  21. package/dist/cjs/api/merges.d.ts +8 -0
  22. package/dist/cjs/api/merges.d.ts.map +1 -1
  23. package/dist/cjs/api/merges.js +64 -1
  24. package/dist/cjs/api/named-range-structural.d.ts +62 -0
  25. package/dist/cjs/api/named-range-structural.d.ts.map +1 -0
  26. package/dist/cjs/api/named-range-structural.js +197 -0
  27. package/dist/cjs/api/paint-format.d.ts +15 -1
  28. package/dist/cjs/api/paint-format.d.ts.map +1 -1
  29. package/dist/cjs/api/paint-format.js +69 -10
  30. package/dist/cjs/api/range-rule-helpers.d.ts +45 -1
  31. package/dist/cjs/api/range-rule-helpers.d.ts.map +1 -1
  32. package/dist/cjs/api/range-rule-helpers.js +159 -6
  33. package/dist/cjs/api/structural-formula-update.d.ts.map +1 -1
  34. package/dist/cjs/api/structural-formula-update.js +24 -6
  35. package/dist/cjs/api/structural-guards.d.ts +78 -0
  36. package/dist/cjs/api/structural-guards.d.ts.map +1 -0
  37. package/dist/cjs/api/structural-guards.js +202 -0
  38. package/dist/cjs/api/structural-table-refs.d.ts +94 -0
  39. package/dist/cjs/api/structural-table-refs.d.ts.map +1 -0
  40. package/dist/cjs/api/structural-table-refs.js +313 -0
  41. package/dist/cjs/commands.d.ts +11 -1
  42. package/dist/cjs/commands.d.ts.map +1 -1
  43. package/dist/cjs/constants.d.ts +25 -0
  44. package/dist/cjs/constants.d.ts.map +1 -0
  45. package/dist/cjs/constants.js +26 -0
  46. package/dist/cjs/hooks/use-calculation-worker.d.ts.map +1 -1
  47. package/dist/cjs/hooks/use-calculation-worker.js +64 -6
  48. package/dist/cjs/hooks/use-calculation.d.ts +8 -1
  49. package/dist/cjs/hooks/use-calculation.d.ts.map +1 -1
  50. package/dist/cjs/hooks/use-calculation.js +15 -0
  51. package/dist/cjs/hooks/use-on-calculation-success.d.ts +7 -0
  52. package/dist/cjs/hooks/use-on-calculation-success.d.ts.map +1 -1
  53. package/dist/cjs/hooks/use-on-calculation-success.js +7 -1
  54. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts +13 -3
  55. package/dist/cjs/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  56. package/dist/cjs/hooks/use-on-delete-cells-shift-left.js +27 -2
  57. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts +13 -3
  58. package/dist/cjs/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  59. package/dist/cjs/hooks/use-on-delete-cells-shift-up.js +27 -2
  60. package/dist/cjs/hooks/use-on-delete-column.d.ts +13 -4
  61. package/dist/cjs/hooks/use-on-delete-column.d.ts.map +1 -1
  62. package/dist/cjs/hooks/use-on-delete-column.js +14 -2
  63. package/dist/cjs/hooks/use-on-delete-row.d.ts +13 -4
  64. package/dist/cjs/hooks/use-on-delete-row.d.ts.map +1 -1
  65. package/dist/cjs/hooks/use-on-delete-row.js +14 -2
  66. package/dist/cjs/hooks/use-on-fill.d.ts +13 -4
  67. package/dist/cjs/hooks/use-on-fill.d.ts.map +1 -1
  68. package/dist/cjs/hooks/use-on-fill.js +28 -7
  69. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts +13 -3
  70. package/dist/cjs/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  71. package/dist/cjs/hooks/use-on-insert-cells-shift-down.js +27 -2
  72. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts +13 -3
  73. package/dist/cjs/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  74. package/dist/cjs/hooks/use-on-insert-cells-shift-right.js +27 -2
  75. package/dist/cjs/hooks/use-on-insert-column.d.ts +10 -3
  76. package/dist/cjs/hooks/use-on-insert-column.d.ts.map +1 -1
  77. package/dist/cjs/hooks/use-on-insert-column.js +33 -7
  78. package/dist/cjs/hooks/use-on-insert-row.d.ts +10 -3
  79. package/dist/cjs/hooks/use-on-insert-row.d.ts.map +1 -1
  80. package/dist/cjs/hooks/use-on-insert-row.js +32 -7
  81. package/dist/cjs/hooks/use-paint-format.d.ts.map +1 -1
  82. package/dist/cjs/hooks/use-paint-format.js +10 -7
  83. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +3 -3
  84. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  85. package/dist/cjs/hooks/use-spreadsheet-state.js +73 -16
  86. package/dist/cjs/hooks/use-structured-reference.d.ts.map +1 -1
  87. package/dist/cjs/hooks/use-structured-reference.js +10 -6
  88. package/dist/cjs/index.d.ts +3 -0
  89. package/dist/cjs/index.d.ts.map +1 -1
  90. package/dist/cjs/index.js +3 -0
  91. package/dist/cjs/interface/apply-fill.d.ts +3 -3
  92. package/dist/cjs/interface/apply-fill.d.ts.map +1 -1
  93. package/dist/cjs/interface/apply-fill.js +100 -53
  94. package/dist/cjs/interface/calculation-interface.d.ts +9 -0
  95. package/dist/cjs/interface/calculation-interface.d.ts.map +1 -1
  96. package/dist/cjs/interface/calculation-interface.js +31 -2
  97. package/dist/cjs/interface/delete-cells-shift-left.d.ts +8 -1
  98. package/dist/cjs/interface/delete-cells-shift-left.d.ts.map +1 -1
  99. package/dist/cjs/interface/delete-cells-shift-left.js +158 -80
  100. package/dist/cjs/interface/delete-cells-shift-up.d.ts +9 -1
  101. package/dist/cjs/interface/delete-cells-shift-up.d.ts.map +1 -1
  102. package/dist/cjs/interface/delete-cells-shift-up.js +155 -73
  103. package/dist/cjs/interface/delete-column.d.ts +1 -1
  104. package/dist/cjs/interface/delete-column.d.ts.map +1 -1
  105. package/dist/cjs/interface/delete-column.js +90 -31
  106. package/dist/cjs/interface/delete-row.d.ts +1 -1
  107. package/dist/cjs/interface/delete-row.d.ts.map +1 -1
  108. package/dist/cjs/interface/delete-row.js +85 -26
  109. package/dist/cjs/interface/insert-cells-shift-down.d.ts +10 -1
  110. package/dist/cjs/interface/insert-cells-shift-down.d.ts.map +1 -1
  111. package/dist/cjs/interface/insert-cells-shift-down.js +147 -52
  112. package/dist/cjs/interface/insert-cells-shift-right.d.ts +10 -1
  113. package/dist/cjs/interface/insert-cells-shift-right.d.ts.map +1 -1
  114. package/dist/cjs/interface/insert-cells-shift-right.js +154 -58
  115. package/dist/cjs/interface/insert-column.d.ts +1 -1
  116. package/dist/cjs/interface/insert-column.d.ts.map +1 -1
  117. package/dist/cjs/interface/insert-column.js +46 -8
  118. package/dist/cjs/interface/insert-row.d.ts +1 -1
  119. package/dist/cjs/interface/insert-row.d.ts.map +1 -1
  120. package/dist/cjs/interface/insert-row.js +47 -10
  121. package/dist/cjs/interface/spreadsheet-interface.d.ts +1 -1
  122. package/dist/cjs/interface/spreadsheet-interface.d.ts.map +1 -1
  123. package/dist/cjs/interface/spreadsheet-interface.js +33 -0
  124. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  125. package/dist/cjs/sheet-cell.js +30 -6
  126. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  127. package/dist/esm/api/anchored-objects.d.ts +66 -0
  128. package/dist/esm/api/anchored-objects.d.ts.map +1 -0
  129. package/dist/esm/api/anchored-objects.js +212 -0
  130. package/dist/esm/api/datatype.d.ts.map +1 -1
  131. package/dist/esm/api/datatype.js +8 -1
  132. package/dist/esm/api/dependency.d.ts +13 -2
  133. package/dist/esm/api/dependency.d.ts.map +1 -1
  134. package/dist/esm/api/dependency.js +10 -4
  135. package/dist/esm/api/fill-series-spec.d.ts +35 -0
  136. package/dist/esm/api/fill-series-spec.d.ts.map +1 -0
  137. package/dist/esm/api/fill-series-spec.js +160 -0
  138. package/dist/esm/api/fill.d.ts +95 -3
  139. package/dist/esm/api/fill.d.ts.map +1 -1
  140. package/dist/esm/api/fill.js +1158 -418
  141. package/dist/esm/api/formula.d.ts +61 -4
  142. package/dist/esm/api/formula.d.ts.map +1 -1
  143. package/dist/esm/api/formula.js +238 -60
  144. package/dist/esm/api/immer-utils.d.ts.map +1 -1
  145. package/dist/esm/api/immer-utils.js +20 -15
  146. package/dist/esm/api/intl.d.ts.map +1 -1
  147. package/dist/esm/api/merges.d.ts +8 -0
  148. package/dist/esm/api/merges.d.ts.map +1 -1
  149. package/dist/esm/api/merges.js +51 -0
  150. package/dist/esm/api/named-range-structural.d.ts +62 -0
  151. package/dist/esm/api/named-range-structural.d.ts.map +1 -0
  152. package/dist/esm/api/named-range-structural.js +176 -0
  153. package/dist/esm/api/paint-format.d.ts +15 -1
  154. package/dist/esm/api/paint-format.d.ts.map +1 -1
  155. package/dist/esm/api/paint-format.js +46 -1
  156. package/dist/esm/api/range-rule-helpers.d.ts +45 -1
  157. package/dist/esm/api/range-rule-helpers.d.ts.map +1 -1
  158. package/dist/esm/api/range-rule-helpers.js +153 -1
  159. package/dist/esm/api/structural-formula-update.d.ts.map +1 -1
  160. package/dist/esm/api/structural-formula-update.js +24 -6
  161. package/dist/esm/api/structural-guards.d.ts +78 -0
  162. package/dist/esm/api/structural-guards.d.ts.map +1 -0
  163. package/dist/esm/api/structural-guards.js +186 -0
  164. package/dist/esm/api/structural-table-refs.d.ts +94 -0
  165. package/dist/esm/api/structural-table-refs.d.ts.map +1 -0
  166. package/dist/esm/api/structural-table-refs.js +219 -0
  167. package/dist/esm/commands.d.ts +11 -1
  168. package/dist/esm/commands.d.ts.map +1 -1
  169. package/dist/esm/constants.d.ts +25 -0
  170. package/dist/esm/constants.d.ts.map +1 -0
  171. package/dist/esm/constants.js +26 -0
  172. package/dist/esm/hooks/use-calculation-worker.d.ts.map +1 -1
  173. package/dist/esm/hooks/use-calculation-worker.js +45 -0
  174. package/dist/esm/hooks/use-calculation.d.ts +8 -1
  175. package/dist/esm/hooks/use-calculation.d.ts.map +1 -1
  176. package/dist/esm/hooks/use-calculation.js +15 -0
  177. package/dist/esm/hooks/use-on-calculation-success.d.ts +7 -0
  178. package/dist/esm/hooks/use-on-calculation-success.d.ts.map +1 -1
  179. package/dist/esm/hooks/use-on-calculation-success.js +7 -1
  180. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts +13 -3
  181. package/dist/esm/hooks/use-on-delete-cells-shift-left.d.ts.map +1 -1
  182. package/dist/esm/hooks/use-on-delete-cells-shift-left.js +26 -2
  183. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts +13 -3
  184. package/dist/esm/hooks/use-on-delete-cells-shift-up.d.ts.map +1 -1
  185. package/dist/esm/hooks/use-on-delete-cells-shift-up.js +26 -2
  186. package/dist/esm/hooks/use-on-delete-column.d.ts +13 -4
  187. package/dist/esm/hooks/use-on-delete-column.d.ts.map +1 -1
  188. package/dist/esm/hooks/use-on-delete-column.js +14 -2
  189. package/dist/esm/hooks/use-on-delete-row.d.ts +13 -4
  190. package/dist/esm/hooks/use-on-delete-row.d.ts.map +1 -1
  191. package/dist/esm/hooks/use-on-delete-row.js +14 -2
  192. package/dist/esm/hooks/use-on-fill.d.ts +13 -4
  193. package/dist/esm/hooks/use-on-fill.d.ts.map +1 -1
  194. package/dist/esm/hooks/use-on-fill.js +24 -4
  195. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts +13 -3
  196. package/dist/esm/hooks/use-on-insert-cells-shift-down.d.ts.map +1 -1
  197. package/dist/esm/hooks/use-on-insert-cells-shift-down.js +26 -2
  198. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts +13 -3
  199. package/dist/esm/hooks/use-on-insert-cells-shift-right.d.ts.map +1 -1
  200. package/dist/esm/hooks/use-on-insert-cells-shift-right.js +26 -2
  201. package/dist/esm/hooks/use-on-insert-column.d.ts +10 -3
  202. package/dist/esm/hooks/use-on-insert-column.d.ts.map +1 -1
  203. package/dist/esm/hooks/use-on-insert-column.js +33 -7
  204. package/dist/esm/hooks/use-on-insert-row.d.ts +10 -3
  205. package/dist/esm/hooks/use-on-insert-row.d.ts.map +1 -1
  206. package/dist/esm/hooks/use-on-insert-row.js +32 -7
  207. package/dist/esm/hooks/use-paint-format.d.ts.map +1 -1
  208. package/dist/esm/hooks/use-paint-format.js +10 -7
  209. package/dist/esm/hooks/use-spreadsheet-state.d.ts +3 -3
  210. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  211. package/dist/esm/hooks/use-spreadsheet-state.js +73 -16
  212. package/dist/esm/hooks/use-structured-reference.d.ts.map +1 -1
  213. package/dist/esm/hooks/use-structured-reference.js +10 -6
  214. package/dist/esm/index.d.ts +3 -0
  215. package/dist/esm/index.d.ts.map +1 -1
  216. package/dist/esm/index.js +3 -0
  217. package/dist/esm/interface/apply-fill.d.ts +3 -3
  218. package/dist/esm/interface/apply-fill.d.ts.map +1 -1
  219. package/dist/esm/interface/apply-fill.js +93 -48
  220. package/dist/esm/interface/calculation-interface.d.ts +9 -0
  221. package/dist/esm/interface/calculation-interface.d.ts.map +1 -1
  222. package/dist/esm/interface/calculation-interface.js +33 -2
  223. package/dist/esm/interface/delete-cells-shift-left.d.ts +8 -1
  224. package/dist/esm/interface/delete-cells-shift-left.d.ts.map +1 -1
  225. package/dist/esm/interface/delete-cells-shift-left.js +135 -59
  226. package/dist/esm/interface/delete-cells-shift-up.d.ts +9 -1
  227. package/dist/esm/interface/delete-cells-shift-up.d.ts.map +1 -1
  228. package/dist/esm/interface/delete-cells-shift-up.js +133 -53
  229. package/dist/esm/interface/delete-column.d.ts +1 -1
  230. package/dist/esm/interface/delete-column.d.ts.map +1 -1
  231. package/dist/esm/interface/delete-column.js +80 -11
  232. package/dist/esm/interface/delete-row.d.ts +1 -1
  233. package/dist/esm/interface/delete-row.d.ts.map +1 -1
  234. package/dist/esm/interface/delete-row.js +81 -11
  235. package/dist/esm/interface/insert-cells-shift-down.d.ts +10 -1
  236. package/dist/esm/interface/insert-cells-shift-down.d.ts.map +1 -1
  237. package/dist/esm/interface/insert-cells-shift-down.js +116 -47
  238. package/dist/esm/interface/insert-cells-shift-right.d.ts +10 -1
  239. package/dist/esm/interface/insert-cells-shift-right.d.ts.map +1 -1
  240. package/dist/esm/interface/insert-cells-shift-right.js +120 -51
  241. package/dist/esm/interface/insert-column.d.ts +1 -1
  242. package/dist/esm/interface/insert-column.d.ts.map +1 -1
  243. package/dist/esm/interface/insert-column.js +46 -8
  244. package/dist/esm/interface/insert-row.d.ts +1 -1
  245. package/dist/esm/interface/insert-row.d.ts.map +1 -1
  246. package/dist/esm/interface/insert-row.js +47 -10
  247. package/dist/esm/interface/spreadsheet-interface.d.ts +1 -1
  248. package/dist/esm/interface/spreadsheet-interface.d.ts.map +1 -1
  249. package/dist/esm/interface/spreadsheet-interface.js +29 -0
  250. package/dist/esm/sheet-cell.d.ts.map +1 -1
  251. package/dist/esm/sheet-cell.js +30 -6
  252. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  253. package/package.json +17 -17
@@ -22,6 +22,23 @@ export declare const updateNamedRangeName: (formulaValue: string, newName: strin
22
22
  * @param newName
23
23
  */
24
24
  export declare const updateColumnName: (formulaValue: string, newName: string, oldName: string) => string;
25
+ /** The column specifier Excel writes for a deleted table column (`Table1[@#REF!]`). */
26
+ export declare const REF_ERROR_COLUMN = "#REF!";
27
+ /**
28
+ * Rewrite every structured reference into `tableName` to the `#REF!` token —
29
+ * Excel's text for a formula whose table was deleted (`=SUM(Table1[Price])`
30
+ * → `=SUM(#REF!)`), so the cell evaluates to `#REF!` rather than `#NAME?`.
31
+ * Returns the input unchanged when the formula never names the table.
32
+ */
33
+ export declare const breakTableReferencesInFormula: (formulaValue: string, tableName: string) => string;
34
+ /**
35
+ * Rewrite the column specifiers of `columnNames` inside structured references
36
+ * to `tableName` (or, when `tableName` is undefined, the bare this-row form
37
+ * `[@Col]` whose table is implied by the formula's own cell) to `#REF!` —
38
+ * Excel's text for a deleted table column (`=Table1[@Qty]*2` →
39
+ * `=Table1[@#REF!]*2`). Keeps every other character of the reference as typed.
40
+ */
41
+ export declare const breakTableColumnsInFormula: (formulaValue: string, tableName: string | undefined, columnNames: string[]) => string;
25
42
  /**
26
43
  * Converts tokens to string
27
44
  * @param tokens
@@ -46,24 +63,64 @@ export declare const isAbsoluteColumnReference: (formula: string | undefined) =>
46
63
  * @param formula
47
64
  */
48
65
  export declare const isAbsoluteRowReference: (formula: string | undefined) => boolean;
66
+ export type StructuralRangeRewriteOptions = {
67
+ /**
68
+ * Whether references WITHOUT a sheet qualifier resolve to the edited sheet.
69
+ * True for a formula that lives on the edited sheet; false for a formula on
70
+ * another sheet, whose bare `A1:A3` is its own sheet's range and must not
71
+ * move when the edited sheet changes shape.
72
+ */
73
+ includeUnqualifiedReferences?: boolean;
74
+ /**
75
+ * Restrict the rewrite to ranges whose PERPENDICULAR span lies inside this
76
+ * band — an insert/delete-cells shift of columns `B:C` only touches ranges
77
+ * that live entirely inside columns B..C (SHF-08); a wider range keeps its
78
+ * address (SHF-07). Whole-column and whole-row references span the entire
79
+ * sheet, so they never fall inside a band.
80
+ */
81
+ bandSpan?: RangeBandSpan;
82
+ };
83
+ /** Alias kept for callers that import the scope options under this name. */
84
+ export type StructuralFormulaScopeOptions = StructuralRangeRewriteOptions;
85
+ /**
86
+ * Restricts `expandRangesInFormula` / `contractRangesInFormula` to ranges whose PERPENDICULAR span
87
+ * lies within a band — an insert/delete-cells shift of columns `B:C` only expands ranges that live
88
+ * entirely inside columns B..C (SHF-08); a wider range keeps its address (SHF-07). Whole-column and
89
+ * whole-row references span the entire sheet, so they never fall inside a band.
90
+ */
91
+ export type RangeBandSpan = {
92
+ startIndex: number;
93
+ endIndex: number;
94
+ };
49
95
  /**
50
96
  * Expands ranges in a formula when rows or columns are inserted within the range
51
97
  * @param formula The formula to process
52
98
  * @param insertionIndex The row or column index where insertion happens
53
99
  * @param count Number of rows or columns being inserted
54
100
  * @param dimension Whether inserting 'row' or 'column'
55
- * @param activeSheetName Active sheet name to scope range updates
101
+ * @param activeSheetName Name of the EDITED sheet: only references that resolve
102
+ * to it are touched
103
+ * @param options `includeUnqualifiedReferences` — whether references without a
104
+ * sheet qualifier resolve to the edited sheet (true when the formula lives on
105
+ * it; false for a formula on another sheet, whose bare `A1:A3` is its own)
56
106
  * @returns The formula with expanded ranges, or undefined if no changes
57
107
  */
58
- export declare const expandRangesInFormula: (formula: string | undefined, insertionIndex: number, count: number, dimension: "row" | "column", activeSheetName: string) => string | undefined;
108
+ export declare const expandRangesInFormula: (formula: string | undefined, insertionIndex: number, count: number, dimension: "row" | "column", activeSheetName: string, options?: StructuralRangeRewriteOptions) => string | undefined;
59
109
  /**
60
110
  * Contracts ranges in a formula when rows or columns are deleted within the range
61
111
  * @param formula The formula to process
62
112
  * @param deletionIndex The row or column index where deletion starts
63
113
  * @param count Number of rows or columns being deleted
64
114
  * @param dimension Whether deleting 'row' or 'column'
65
- * @param activeSheetName Active sheet name to scope range updates
115
+ * @param activeSheetName Name of the EDITED sheet: only references that resolve
116
+ * to it are touched
117
+ * @param options `includeUnqualifiedReferences` — see `expandRangesInFormula`
66
118
  * @returns The formula with contracted ranges, or undefined if no changes
119
+ *
120
+ * Excel semantics for the deleted band: a range whose rows/columns are ALL
121
+ * deleted becomes the `#REF!` token (`=SUM(A2:A3)` → `=SUM(#REF!)`); a single
122
+ * cell reference into the band becomes `#REF!` (`=A3+1` → `=#REF!+1`, a spill
123
+ * reference `=C1#` → `=#REF!#`); a partially covered range shrinks.
67
124
  */
68
- export declare const contractRangesInFormula: (formula: string | undefined, deletionIndex: number, count: number, dimension: "row" | "column", activeSheetName: string) => string | undefined;
125
+ export declare const contractRangesInFormula: (formula: string | undefined, deletionIndex: number, count: number, dimension: "row" | "column", activeSheetName: string, options?: StructuralRangeRewriteOptions) => string | undefined;
69
126
  //# sourceMappingURL=formula.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"formula.d.ts","sourceRoot":"","sources":["../../../api/formula.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,2BAA2B,CAAC;AAUpE,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WA4BhB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WAehB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WAYhB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,WAU/C,CAAC;AAiBF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACpC,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,aAAa,MAAM,WAGpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,MAAM,GAAG,SAAS,YAGpE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,GAAG,SAAS,YAGjE,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,MAAM,GAAG,SAAS,EAC3B,gBAAgB,MAAM,EACtB,OAAO,MAAM,EACb,WAAW,KAAK,GAAG,QAAQ,EAC3B,iBAAiB,MAAM,KACtB,MAAM,GAAG,SAmKX,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,GAAG,SAAS,EAC3B,eAAe,MAAM,EACrB,OAAO,MAAM,EACb,WAAW,KAAK,GAAG,QAAQ,EAC3B,iBAAiB,MAAM,KACtB,MAAM,GAAG,SA6NX,CAAC"}
1
+ {"version":3,"file":"formula.d.ts","sourceRoot":"","sources":["../../../api/formula.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,2BAA2B,CAAC;AAUpE,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WA4BhB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WAehB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,SAAS,MAAM,WAYhB,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAgDxC;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GACxC,cAAc,MAAM,EACpB,WAAW,MAAM,KAChB,MA4BF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GACrC,cAAc,MAAM,EACpB,WAAW,MAAM,GAAG,SAAS,EAC7B,aAAa,MAAM,EAAE,KACpB,MA+BF,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,WAU/C,CAAC;AAiBF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,GACpC,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,aAAa,MAAM,WAGpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,MAAM,GAAG,SAAS,YAGpE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,GAAG,SAAS,YAGjE,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,6BAA6B,GAAG,6BAA6B,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBrE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,MAAM,GAAG,SAAS,EAC3B,gBAAgB,MAAM,EACtB,OAAO,MAAM,EACb,WAAW,KAAK,GAAG,QAAQ,EAC3B,iBAAiB,MAAM,EACvB,UAAS,6BAAkC,KAC1C,MAAM,GAAG,SAyKX,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,GAAG,SAAS,EAC3B,eAAe,MAAM,EACrB,OAAO,MAAM,EACb,WAAW,KAAK,GAAG,QAAQ,EAC3B,iBAAiB,MAAM,EACvB,UAAS,6BAAkC,KAC1C,MAAM,GAAG,SAkPX,CAAC"}
@@ -1,5 +1,5 @@
1
- import { __assign, __values } from "tslib";
2
- import { isRangeToken, lexify, stripPropertyFromCellRef, tokenVocabulary, } from "@rowsncolumns/calculator";
1
+ import { __assign, __read, __values } from "tslib";
2
+ import { cleanupColumnName, cleanupTableName, isRangeToken, lexify, stripPropertyFromCellRef, tokenVocabulary, } from "@rowsncolumns/calculator";
3
3
  import { addressToCell, alpha2number, cellToAddress, desanitizeSheetName, number2Alpha, sanitizeSheetName, } from "@rowsncolumns/utils";
4
4
  export { ERROR_CIRCULAR_DEPENDENCY, ERROR_REFERENCE, formulaToRelativeReference, } from "@rowsncolumns/calculator";
5
5
  /**
@@ -99,6 +99,145 @@ export var updateColumnName = function (formulaValue, newName, oldName) {
99
99
  }
100
100
  return detokenize(newTokens);
101
101
  };
102
+ /** The column specifier Excel writes for a deleted table column (`Table1[@#REF!]`). */
103
+ export var REF_ERROR_COLUMN = "#REF!";
104
+ var REF_ERROR_TOKEN = "#REF!";
105
+ /**
106
+ * One `#REF!` token standing in for the run `start … end` (a range's start,
107
+ * colon and end): it keeps `start`'s position and stretches to `end` so
108
+ * `detokenize` (which re-inserts a space wherever adjacent tokens' offsets
109
+ * disagree) prints `SUM(#REF!)`, not `SUM(#REF! )`.
110
+ */
111
+ var collapseToRefError = function (start, end) {
112
+ var _a, _b;
113
+ return (__assign(__assign({}, start), { image: REF_ERROR_TOKEN, tokenType: tokenVocabulary.RefError, endOffset: (_a = end === null || end === void 0 ? void 0 : end.endOffset) !== null && _a !== void 0 ? _a : start.endOffset, endColumn: (_b = end === null || end === void 0 ? void 0 : end.endColumn) !== null && _b !== void 0 ? _b : start.endColumn }));
114
+ };
115
+ var isTableNameToken = function (token) {
116
+ return (token === null || token === void 0 ? void 0 : token.tokenType.name) === tokenVocabulary.TableName.name;
117
+ };
118
+ var isTableColumnToken = function (token) {
119
+ return (token === null || token === void 0 ? void 0 : token.tokenType.name) === tokenVocabulary.TableColumnName.name;
120
+ };
121
+ /** Bracket depth change contributed by one token's image (`Table1[` opens, `Qty]` closes). */
122
+ var bracketDelta = function (image) {
123
+ var e_4, _a;
124
+ var depth = 0;
125
+ try {
126
+ for (var image_1 = __values(image), image_1_1 = image_1.next(); !image_1_1.done; image_1_1 = image_1.next()) {
127
+ var ch = image_1_1.value;
128
+ if (ch === "[")
129
+ depth++;
130
+ else if (ch === "]")
131
+ depth--;
132
+ }
133
+ }
134
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
135
+ finally {
136
+ try {
137
+ if (image_1_1 && !image_1_1.done && (_a = image_1.return)) _a.call(image_1);
138
+ }
139
+ finally { if (e_4) throw e_4.error; }
140
+ }
141
+ return depth;
142
+ };
143
+ /**
144
+ * Index just past the last token of the structured reference that starts at
145
+ * `start` (a TableName token): consume tokens until the bracket the table name
146
+ * opened is closed again.
147
+ */
148
+ var structuredReferenceEnd = function (tokens, start) {
149
+ var depth = 0;
150
+ var i = start;
151
+ while (i < tokens.length) {
152
+ depth += bracketDelta(tokens[i].image);
153
+ i++;
154
+ if (depth <= 0)
155
+ break;
156
+ }
157
+ return i;
158
+ };
159
+ /**
160
+ * Rewrite every structured reference into `tableName` to the `#REF!` token —
161
+ * Excel's text for a formula whose table was deleted (`=SUM(Table1[Price])`
162
+ * → `=SUM(#REF!)`), so the cell evaluates to `#REF!` rather than `#NAME?`.
163
+ * Returns the input unchanged when the formula never names the table.
164
+ */
165
+ export var breakTableReferencesInFormula = function (formulaValue, tableName) {
166
+ var _a;
167
+ if (!formulaValue.includes("["))
168
+ return formulaValue;
169
+ var tokens = cloneTokens(lexify(formulaValue).tokens);
170
+ var newTokens = [];
171
+ var target = tableName.toLowerCase();
172
+ var hasChanges = false;
173
+ for (var i = 0; i < tokens.length; i++) {
174
+ var token = tokens[i];
175
+ if (isTableNameToken(token) &&
176
+ cleanupTableName(token.image).trim().toLowerCase() === target) {
177
+ var end = structuredReferenceEnd(tokens, i);
178
+ var last = (_a = tokens[end - 1]) !== null && _a !== void 0 ? _a : token;
179
+ newTokens.push(__assign(__assign({}, token), { image: REF_ERROR_TOKEN, endOffset: last.endOffset, endColumn: last.endColumn, tokenType: tokenVocabulary.RefError }));
180
+ i = end - 1;
181
+ hasChanges = true;
182
+ continue;
183
+ }
184
+ newTokens.push(token);
185
+ }
186
+ return hasChanges ? detokenize(newTokens) : formulaValue;
187
+ };
188
+ /**
189
+ * Rewrite the column specifiers of `columnNames` inside structured references
190
+ * to `tableName` (or, when `tableName` is undefined, the bare this-row form
191
+ * `[@Col]` whose table is implied by the formula's own cell) to `#REF!` —
192
+ * Excel's text for a deleted table column (`=Table1[@Qty]*2` →
193
+ * `=Table1[@#REF!]*2`). Keeps every other character of the reference as typed.
194
+ */
195
+ export var breakTableColumnsInFormula = function (formulaValue, tableName, columnNames) {
196
+ if (!formulaValue.includes("[") || columnNames.length === 0) {
197
+ return formulaValue;
198
+ }
199
+ var targets = new Set(columnNames.map(function (name) { return name.toLowerCase(); }));
200
+ var target = tableName === null || tableName === void 0 ? void 0 : tableName.toLowerCase();
201
+ var tokens = cloneTokens(lexify(formulaValue).tokens);
202
+ var hasChanges = false;
203
+ var i = 0;
204
+ while (i < tokens.length) {
205
+ var token = tokens[i];
206
+ if (isTableNameToken(token)) {
207
+ var end = structuredReferenceEnd(tokens, i);
208
+ var matches = target !== undefined &&
209
+ cleanupTableName(token.image).trim().toLowerCase() === target;
210
+ if (matches) {
211
+ for (var j = i + 1; j < end; j++) {
212
+ if (breakColumnToken(tokens[j], targets))
213
+ hasChanges = true;
214
+ }
215
+ }
216
+ i = end;
217
+ continue;
218
+ }
219
+ // A bare `[@Col]` / `[Col]` names the table the formula cell sits in.
220
+ if (target === undefined && isTableColumnToken(token)) {
221
+ if (breakColumnToken(token, targets))
222
+ hasChanges = true;
223
+ }
224
+ i++;
225
+ }
226
+ return hasChanges ? detokenize(tokens) : formulaValue;
227
+ };
228
+ var breakColumnToken = function (token, targets) {
229
+ if (!token || !isTableColumnToken(token))
230
+ return false;
231
+ var name = cleanupColumnName(token.image);
232
+ if (!name || !targets.has(name.toLowerCase()))
233
+ return false;
234
+ var at = token.image.indexOf(name);
235
+ if (at === -1)
236
+ return false;
237
+ token.image =
238
+ token.image.slice(0, at) + REF_ERROR_COLUMN + token.image.slice(at + name.length);
239
+ return true;
240
+ };
102
241
  /**
103
242
  * Converts tokens to string
104
243
  * @param tokens
@@ -158,19 +297,34 @@ export var isAbsoluteRowReference = function (formula) {
158
297
  return false;
159
298
  return /\$\d+/gi.test(formula);
160
299
  };
300
+ var isRangeWithinBandSpan = function (startCell, endCell, dimension, bandSpan) {
301
+ if (!bandSpan)
302
+ return true;
303
+ var _a = __read(dimension === "row"
304
+ ? [startCell.columnIndex, endCell.columnIndex]
305
+ : [startCell.rowIndex, endCell.rowIndex], 2), start = _a[0], end = _a[1];
306
+ return (Math.min(start, end) >= bandSpan.startIndex &&
307
+ Math.max(start, end) <= bandSpan.endIndex);
308
+ };
161
309
  /**
162
310
  * Expands ranges in a formula when rows or columns are inserted within the range
163
311
  * @param formula The formula to process
164
312
  * @param insertionIndex The row or column index where insertion happens
165
313
  * @param count Number of rows or columns being inserted
166
314
  * @param dimension Whether inserting 'row' or 'column'
167
- * @param activeSheetName Active sheet name to scope range updates
315
+ * @param activeSheetName Name of the EDITED sheet: only references that resolve
316
+ * to it are touched
317
+ * @param options `includeUnqualifiedReferences` — whether references without a
318
+ * sheet qualifier resolve to the edited sheet (true when the formula lives on
319
+ * it; false for a formula on another sheet, whose bare `A1:A3` is its own)
168
320
  * @returns The formula with expanded ranges, or undefined if no changes
169
321
  */
170
- export var expandRangesInFormula = function (formula, insertionIndex, count, dimension, activeSheetName) {
322
+ export var expandRangesInFormula = function (formula, insertionIndex, count, dimension, activeSheetName, options) {
323
+ if (options === void 0) { options = {}; }
171
324
  if (!formula || count <= 0) {
172
325
  return formula;
173
326
  }
327
+ var _a = options.includeUnqualifiedReferences, includeUnqualifiedReferences = _a === void 0 ? true : _a, bandSpan = options.bandSpan;
174
328
  var normalizedActiveSheetName = activeSheetName.toLowerCase();
175
329
  var tokens = cloneTokens(lexify(formula).tokens);
176
330
  var newTokens = [];
@@ -178,7 +332,9 @@ export var expandRangesInFormula = function (formula, insertionIndex, count, dim
178
332
  for (var i = 0; i < tokens.length; i++) {
179
333
  var token = tokens[i];
180
334
  var sheetName = getSheetNameFromToken(tokens[i - 1]);
181
- var skipSheet = sheetName && sheetName.toLowerCase() !== normalizedActiveSheetName;
335
+ var skipSheet = sheetName
336
+ ? sheetName.toLowerCase() !== normalizedActiveSheetName
337
+ : !includeUnqualifiedReferences;
182
338
  // Handle cell ranges (e.g., A1:A10)
183
339
  if (token.tokenType.name === tokenVocabulary.Cell.name) {
184
340
  var isRange = isRangeToken(tokens[i + 1]);
@@ -193,7 +349,9 @@ export var expandRangesInFormula = function (formula, insertionIndex, count, dim
193
349
  if (isRange && tokens[i + 2]) {
194
350
  var startCell = addressToCell(stripPropertyFromCellRef(token.image));
195
351
  var endCell = addressToCell(stripPropertyFromCellRef(tokens[i + 2].image));
196
- if (startCell && endCell) {
352
+ if (startCell &&
353
+ endCell &&
354
+ isRangeWithinBandSpan(startCell, endCell, dimension, bandSpan)) {
197
355
  var isAbsoluteEndRow = isAbsoluteRowReference(tokens[i + 2].image);
198
356
  var isAbsoluteEndCol = isAbsoluteColumnReference(tokens[i + 2].image);
199
357
  if (dimension === "row") {
@@ -233,7 +391,7 @@ export var expandRangesInFormula = function (formula, insertionIndex, count, dim
233
391
  if (dimension === "column" &&
234
392
  token.tokenType.name === tokenVocabulary.Column.name) {
235
393
  var isRange = isRangeToken(tokens[i + 1]);
236
- if (skipSheet) {
394
+ if (skipSheet || bandSpan) {
237
395
  if (isRange) {
238
396
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
239
397
  i += 2;
@@ -260,7 +418,7 @@ export var expandRangesInFormula = function (formula, insertionIndex, count, dim
260
418
  if (dimension === "row" &&
261
419
  token.tokenType.name === tokenVocabulary.Number.name) {
262
420
  var isRange = isRangeToken(tokens[i + 1]);
263
- if (skipSheet) {
421
+ if (skipSheet || bandSpan) {
264
422
  if (isRange) {
265
423
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
266
424
  i += 2;
@@ -293,22 +451,48 @@ export var expandRangesInFormula = function (formula, insertionIndex, count, dim
293
451
  * @param deletionIndex The row or column index where deletion starts
294
452
  * @param count Number of rows or columns being deleted
295
453
  * @param dimension Whether deleting 'row' or 'column'
296
- * @param activeSheetName Active sheet name to scope range updates
454
+ * @param activeSheetName Name of the EDITED sheet: only references that resolve
455
+ * to it are touched
456
+ * @param options `includeUnqualifiedReferences` — see `expandRangesInFormula`
297
457
  * @returns The formula with contracted ranges, or undefined if no changes
458
+ *
459
+ * Excel semantics for the deleted band: a range whose rows/columns are ALL
460
+ * deleted becomes the `#REF!` token (`=SUM(A2:A3)` → `=SUM(#REF!)`); a single
461
+ * cell reference into the band becomes `#REF!` (`=A3+1` → `=#REF!+1`, a spill
462
+ * reference `=C1#` → `=#REF!#`); a partially covered range shrinks.
298
463
  */
299
- export var contractRangesInFormula = function (formula, deletionIndex, count, dimension, activeSheetName) {
464
+ export var contractRangesInFormula = function (formula, deletionIndex, count, dimension, activeSheetName, options) {
465
+ if (options === void 0) { options = {}; }
300
466
  if (!formula || count <= 0) {
301
467
  return formula;
302
468
  }
469
+ var _a = options.includeUnqualifiedReferences, includeUnqualifiedReferences = _a === void 0 ? true : _a, bandSpan = options.bandSpan;
303
470
  var normalizedActiveSheetName = activeSheetName.toLowerCase();
304
471
  var tokens = cloneTokens(lexify(formula).tokens);
305
472
  var newTokens = [];
306
473
  var hasChanges = false;
307
474
  var deletionEnd = deletionIndex + count - 1;
475
+ var inDeletedBand = function (cell) {
476
+ var index = dimension === "row" ? cell.rowIndex : cell.columnIndex;
477
+ return index >= deletionIndex && index <= deletionEnd;
478
+ };
479
+ var overlapsBand = function (start, end) {
480
+ return deletionIndex <= end && deletionEnd >= start;
481
+ };
482
+ // The survivors of a span that overlaps (but is not swallowed by) the band:
483
+ // whatever lay before the band keeps its start, whatever lay inside starts at
484
+ // the deletion point; an end past the band moves up by the full count, an
485
+ // end inside the band stops just before it.
486
+ var contractSpan = function (start, end) { return ({
487
+ start: Math.min(start, deletionIndex),
488
+ end: end > deletionEnd ? end - count : deletionIndex - 1,
489
+ }); };
308
490
  for (var i = 0; i < tokens.length; i++) {
309
491
  var token = tokens[i];
310
492
  var sheetName = getSheetNameFromToken(tokens[i - 1]);
311
- var skipSheet = sheetName && sheetName.toLowerCase() !== normalizedActiveSheetName;
493
+ var skipSheet = sheetName
494
+ ? sheetName.toLowerCase() !== normalizedActiveSheetName
495
+ : !includeUnqualifiedReferences;
312
496
  // Handle cell ranges (e.g., A1:A10)
313
497
  if (token.tokenType.name === tokenVocabulary.Cell.name) {
314
498
  var isRange = isRangeToken(tokens[i + 1]);
@@ -320,10 +504,33 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
320
504
  }
321
505
  continue;
322
506
  }
507
+ if (!isRange) {
508
+ // Single cell: broken when it sits in the deleted band. The trailing
509
+ // spilled-range operator (`C1#`) stays on the token (`#REF!#`).
510
+ var spill = token.image.endsWith("#") ? "#" : "";
511
+ var cell = addressToCell(stripPropertyFromCellRef(spill ? token.image.slice(0, -1) : token.image));
512
+ if (cell &&
513
+ inDeletedBand(cell) &&
514
+ isRangeWithinBandSpan(cell, cell, dimension, bandSpan)) {
515
+ token.image = "".concat(REF_ERROR_TOKEN).concat(spill);
516
+ hasChanges = true;
517
+ }
518
+ newTokens.push(token);
519
+ continue;
520
+ }
323
521
  if (isRange && tokens[i + 2]) {
324
522
  var startCell = addressToCell(stripPropertyFromCellRef(token.image));
325
523
  var endCell = addressToCell(stripPropertyFromCellRef(tokens[i + 2].image));
326
- if (startCell && endCell) {
524
+ if (startCell &&
525
+ endCell &&
526
+ isRangeWithinBandSpan(startCell, endCell, dimension, bandSpan)) {
527
+ // Every row/column of the range deleted → the whole range is #REF!.
528
+ if (inDeletedBand(startCell) && inDeletedBand(endCell)) {
529
+ newTokens.push(collapseToRefError(token, tokens[i + 2]));
530
+ i += 2;
531
+ hasChanges = true;
532
+ continue;
533
+ }
327
534
  var isAbsoluteStartRow = isAbsoluteRowReference(token.image);
328
535
  var isAbsoluteEndRow = isAbsoluteRowReference(tokens[i + 2].image);
329
536
  var isAbsoluteStartCol = isAbsoluteColumnReference(token.image);
@@ -331,18 +538,10 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
331
538
  if (dimension === "row") {
332
539
  var rangeStart = startCell.rowIndex;
333
540
  var rangeEnd = endCell.rowIndex;
334
- // Check if deletion overlaps with range
335
- if (deletionIndex <= rangeEnd && deletionEnd >= rangeStart) {
336
- // Calculate how many deleted rows are within the range
337
- var overlapStart = Math.max(deletionIndex, rangeStart);
338
- var overlapEnd = Math.min(deletionEnd, rangeEnd);
339
- var rowsDeletedInRange = overlapEnd - overlapStart + 1;
340
- // Contract the end of the range
341
- endCell.rowIndex -= rowsDeletedInRange;
342
- // If entire range is deleted, result in #REF! (but we'll just contract to minimum)
343
- if (endCell.rowIndex < startCell.rowIndex) {
344
- endCell.rowIndex = startCell.rowIndex;
345
- }
541
+ if (overlapsBand(rangeStart, rangeEnd)) {
542
+ var survivors = contractSpan(rangeStart, rangeEnd);
543
+ startCell.rowIndex = survivors.start;
544
+ endCell.rowIndex = survivors.end;
346
545
  var newStartAddress = cellToAddress(startCell, isAbsoluteStartCol, isAbsoluteStartRow);
347
546
  var newEndAddress = cellToAddress(endCell, isAbsoluteEndCol, isAbsoluteEndRow);
348
547
  if (newStartAddress && newEndAddress) {
@@ -356,18 +555,10 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
356
555
  // dimension === 'column'
357
556
  var rangeStart = startCell.columnIndex;
358
557
  var rangeEnd = endCell.columnIndex;
359
- // Check if deletion overlaps with range
360
- if (deletionIndex <= rangeEnd && deletionEnd >= rangeStart) {
361
- // Calculate how many deleted columns are within the range
362
- var overlapStart = Math.max(deletionIndex, rangeStart);
363
- var overlapEnd = Math.min(deletionEnd, rangeEnd);
364
- var colsDeletedInRange = overlapEnd - overlapStart + 1;
365
- // Contract the end of the range
366
- endCell.columnIndex -= colsDeletedInRange;
367
- // If entire range is deleted, result in #REF! (but we'll just contract to minimum)
368
- if (endCell.columnIndex < startCell.columnIndex) {
369
- endCell.columnIndex = startCell.columnIndex;
370
- }
558
+ if (overlapsBand(rangeStart, rangeEnd)) {
559
+ var survivors = contractSpan(rangeStart, rangeEnd);
560
+ startCell.columnIndex = survivors.start;
561
+ endCell.columnIndex = survivors.end;
371
562
  var newStartAddress = cellToAddress(startCell, isAbsoluteStartCol, isAbsoluteStartRow);
372
563
  var newEndAddress = cellToAddress(endCell, isAbsoluteEndCol, isAbsoluteEndRow);
373
564
  if (newStartAddress && newEndAddress) {
@@ -387,7 +578,7 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
387
578
  if (dimension === "column" &&
388
579
  token.tokenType.name === tokenVocabulary.Column.name) {
389
580
  var isRange = isRangeToken(tokens[i + 1]);
390
- if (skipSheet) {
581
+ if (skipSheet || bandSpan) {
391
582
  if (isRange) {
392
583
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
393
584
  i += 2;
@@ -397,20 +588,19 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
397
588
  if (isRange && tokens[i + 2]) {
398
589
  var startColumnIndex = alpha2number(token.image);
399
590
  var endColumnIndex = alpha2number(tokens[i + 2].image);
400
- // Check if deletion overlaps with range
401
- if (deletionIndex <= endColumnIndex &&
402
- deletionEnd >= startColumnIndex) {
403
- // Calculate how many deleted columns are within the range
404
- var overlapStart = Math.max(deletionIndex, startColumnIndex);
405
- var overlapEnd = Math.min(deletionEnd, endColumnIndex);
406
- var colsDeletedInRange = overlapEnd - overlapStart + 1;
407
- // Contract the end column
408
- var newEndColumnIndex = endColumnIndex - colsDeletedInRange;
409
- // If entire range is deleted, keep at minimum
410
- if (newEndColumnIndex >= startColumnIndex) {
411
- tokens[i + 2].image = number2Alpha(newEndColumnIndex - 1);
591
+ if (overlapsBand(startColumnIndex, endColumnIndex)) {
592
+ // Every column deleted → #REF!; otherwise the survivors close up.
593
+ if (startColumnIndex >= deletionIndex &&
594
+ endColumnIndex <= deletionEnd) {
595
+ newTokens.push(collapseToRefError(token, tokens[i + 2]));
596
+ i += 2;
412
597
  hasChanges = true;
598
+ continue;
413
599
  }
600
+ var survivors = contractSpan(startColumnIndex, endColumnIndex);
601
+ token.image = number2Alpha(survivors.start - 1);
602
+ tokens[i + 2].image = number2Alpha(survivors.end - 1);
603
+ hasChanges = true;
414
604
  }
415
605
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
416
606
  i += 2;
@@ -421,7 +611,7 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
421
611
  if (dimension === "row" &&
422
612
  token.tokenType.name === tokenVocabulary.Number.name) {
423
613
  var isRange = isRangeToken(tokens[i + 1]);
424
- if (skipSheet) {
614
+ if (skipSheet || bandSpan) {
425
615
  if (isRange) {
426
616
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
427
617
  i += 2;
@@ -433,19 +623,18 @@ export var contractRangesInFormula = function (formula, deletionIndex, count, di
433
623
  tokens[i + 2].tokenType.name === tokenVocabulary.Number.name) {
434
624
  var startRowIndex = Number(token.image);
435
625
  var endRowIndex = Number(tokens[i + 2].image);
436
- // Check if deletion overlaps with range
437
- if (deletionIndex <= endRowIndex && deletionEnd >= startRowIndex) {
438
- // Calculate how many deleted rows are within the range
439
- var overlapStart = Math.max(deletionIndex, startRowIndex);
440
- var overlapEnd = Math.min(deletionEnd, endRowIndex);
441
- var rowsDeletedInRange = overlapEnd - overlapStart + 1;
442
- // Contract the end row
443
- var newEndRowIndex = endRowIndex - rowsDeletedInRange;
444
- // If entire range is deleted, keep at minimum
445
- if (newEndRowIndex >= startRowIndex) {
446
- tokens[i + 2].image = String(newEndRowIndex);
626
+ if (overlapsBand(startRowIndex, endRowIndex)) {
627
+ // Every row deleted → #REF!; otherwise the survivors close up.
628
+ if (startRowIndex >= deletionIndex && endRowIndex <= deletionEnd) {
629
+ newTokens.push(collapseToRefError(token, tokens[i + 2]));
630
+ i += 2;
447
631
  hasChanges = true;
632
+ continue;
448
633
  }
634
+ var survivors = contractSpan(startRowIndex, endRowIndex);
635
+ token.image = String(survivors.start);
636
+ tokens[i + 2].image = String(survivors.end);
637
+ hasChanges = true;
449
638
  }
450
639
  newTokens.push(token, tokens[i + 1], tokens[i + 2]);
451
640
  i += 2;
@@ -1 +1 @@
1
- {"version":3,"file":"immer-utils.d.ts","sourceRoot":"","sources":["../../../api/immer-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"immer-utils.d.ts","sourceRoot":"","sources":["../../../api/immer-utils.ts"],"names":[],"mappings":"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"}
@@ -50,8 +50,7 @@ var isGenericNumberFormatType = function (type) { return !type || type === "NUMB
50
50
  * Date-family types — when the derived (resolved) type is one of these
51
51
  * and the precedent's type is also in this set, we preserve the
52
52
  * precedent's exact custom pattern instead of synthesizing a locale
53
- * default. Mirrors Excel's behaviour for date-arithmetic functions
54
- * (EDATE, EOMONTH, …) where `=EDATE(A1, 1)` keeps A1's custom pattern.
53
+ * default (`=DATE(YEAR(A1), MONTH(A1), 1)` keeps A1's custom pattern).
55
54
  */
56
55
  var isDateFamilyType = function (type) { return type === "DATE" || type === "TIME" || type === "DATE_TIME"; };
57
56
  var customNumberFormatMap = {
@@ -164,18 +163,21 @@ var functionReturnTypes = {
164
163
  NETWORKDAYS: "NUMBER",
165
164
  "NETWORKDAYS.INTL": "NUMBER",
166
165
  DAYS360: "NUMBER",
166
+ // The date-arithmetic functions return date serials, but Excel does
167
+ // NOT auto-format them: `=EDATE(DATE(2026,1,31),1)` shows 46081 in a
168
+ // General cell until the user formats it (rowsncolumns/spreadsheet#642
169
+ // B-09). NUMBER — like DATEVALUE — rather than absent, so a nested
170
+ // DATE()/TODAY() argument cannot promote the result to a date (the
171
+ // outermost function decides, as in `=YEAR(TODAY())`).
172
+ EDATE: "NUMBER",
173
+ EOMONTH: "NUMBER",
174
+ WORKDAY: "NUMBER",
175
+ "WORKDAY.INTL": "NUMBER",
167
176
  // ─── Date/time — date producers (must render as DATE/TIME/DATE_TIME) ─
168
177
  NOW: "DATE_TIME",
169
178
  TODAY: "DATE",
170
179
  DATE: "DATE",
171
180
  TIME: "TIME",
172
- EDATE: "DATE",
173
- EOMONTH: "DATE",
174
- // WORKDAY returns a date serial number — must render as DATE, not
175
- // raw NUMBER (was a bug: cells showed e.g. "45292" instead of the
176
- // calendar date).
177
- WORKDAY: "DATE",
178
- "WORKDAY.INTL": "DATE",
179
181
  // ─── Aggregation / rounding (return NUMBER; CURRENCY precedent
180
182
  // preserved via the "expectedOutputType === NUMBER + numFormat
181
183
  // CURRENCY → keep numFormat" branch) ──────────────────────────
@@ -322,7 +324,10 @@ var currencyDecimalAdjustmentFunctions = new Set([
322
324
  "QUOTIENT",
323
325
  ]);
324
326
  // Get all function names from formula
325
- var functionRegex = /([A-Za-z0-9_]+)\s*\(/g;
327
+ // Function names may be dotted (`WORKDAY.INTL`, `PERCENTILE.INC`, `FORECAST.ETS`); without the
328
+ // `.` the match stopped at the suffix (`INTL(`) and the dotted keys of `functionReturnTypes` /
329
+ // `formatDerivationRules` never applied.
330
+ var functionRegex = /([A-Za-z0-9_.]+)\s*\(/g;
326
331
  export var getFunctionNamesFromFormula = function (formula) {
327
332
  var match;
328
333
  var matches = [];
@@ -522,7 +527,7 @@ resolvePrecedentNumberFormat) {
522
527
  effectivePrecedents = filterPrecedentsByBounds(effectivePrecedents, directBounds);
523
528
  var upperFormula = formula === null || formula === void 0 ? void 0 : formula.trim().toUpperCase();
524
529
  if (upperFormula) {
525
- var functionNameMatch = upperFormula.match(/^=([A-Z0-9_]+)\(/);
530
+ var functionNameMatch = upperFormula.match(/^=([A-Z0-9_.]+)\(/);
526
531
  topLevelFunctionName = functionNameMatch ? functionNameMatch[1] : undefined;
527
532
  var rule = topLevelFunctionName
528
533
  ? formatDerivationRules[topLevelFunctionName]
@@ -701,10 +706,10 @@ resolvePrecedentNumberFormat) {
701
706
  // Date/time types need a concrete pattern — without one the renderer
702
707
  // falls back to "General" and shows the serial number (the
703
708
  // =TODAY() bug). When the precedent itself is a date-family format
704
- // with a pattern, inherit that pattern (e.g. `=EDATE(A1, 1)` keeps
705
- // A1's custom `yyyy-mm-dd` instead of falling back to the locale
706
- // default). Otherwise mirror the format toolbar's default for the
707
- // type.
709
+ // with a pattern, inherit that pattern (e.g. `=DATE(YEAR(A1),
710
+ // MONTH(A1), 1)` keeps A1's custom `yyyy-mm-dd` instead of falling
711
+ // back to the locale default). Otherwise mirror the format toolbar's
712
+ // default for the type.
708
713
  if (isDateFamilyType(resolvedNumberFormat.type) &&
709
714
  isDateFamilyType(numFormat === null || numFormat === void 0 ? void 0 : numFormat.type) &&
710
715
  (numFormat === null || numFormat === void 0 ? void 0 : numFormat.pattern)) {
@@ -1 +1 @@
1
- {"version":3,"file":"intl.d.ts","sourceRoot":"","sources":["../../../api/intl.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,EAAE,gBAAc,WAK5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM;;;;;CA2ClD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM;eA1E5B,MAAM;YAAU,OAAO;YAAU,OAAO;iBAAe,OAAO;CAqH5E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM;UAtHxC,MAAM;YAAU,OAAO;YAAU,OAAO;CAkJjD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM;aA/JlC,MAAM;eAAa,MAAM;WAAS,MAAM;aAgMpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,wBAkBhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,YAuBnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,gBA0BtD,CAAC"}
1
+ {"version":3,"file":"intl.d.ts","sourceRoot":"","sources":["../../../api/intl.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,EAAE,gBAAc,WAK5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM;WAlCxC,MAAM;aAAW,MAAM;eAAa,MAAM;iBAAe,MAAM;CA6EzE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM;eA1E5B,MAAM;YAAU,OAAO;YAAU,OAAO;iBAAe,OAAO;CAqH5E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM;UAtHxC,MAAM;YAAU,OAAO;YAAU,OAAO;CAkJjD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM;aA/JlC,MAAM;eAAa,MAAM;WAAS,MAAM;aAgMpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,wBAkBhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,YAuBnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,gBA0BtD,CAAC"}