@cj-tech-master/excelts 9.2.1 → 9.3.0

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 (383) hide show
  1. package/README.md +25 -2
  2. package/README_zh.md +29 -6
  3. package/dist/browser/index.browser.d.ts +1 -1
  4. package/dist/browser/index.browser.js +4 -0
  5. package/dist/browser/index.d.ts +1 -1
  6. package/dist/browser/index.js +4 -0
  7. package/dist/browser/modules/excel/cell.d.ts +17 -3
  8. package/dist/browser/modules/excel/cell.js +170 -22
  9. package/dist/browser/modules/excel/defined-names.d.ts +96 -1
  10. package/dist/browser/modules/excel/defined-names.js +411 -21
  11. package/dist/browser/modules/excel/image.d.ts +11 -0
  12. package/dist/browser/modules/excel/image.js +24 -1
  13. package/dist/browser/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  14. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +14 -0
  15. package/dist/browser/modules/excel/stream/workbook-reader.d.ts +2 -1
  16. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  17. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +48 -1
  18. package/dist/browser/modules/excel/stream/workbook-writer.d.ts +3 -2
  19. package/dist/browser/modules/excel/stream/worksheet-reader.js +17 -1
  20. package/dist/browser/modules/excel/stream/worksheet-writer.d.ts +39 -6
  21. package/dist/browser/modules/excel/stream/worksheet-writer.js +45 -5
  22. package/dist/browser/modules/excel/table.js +15 -2
  23. package/dist/browser/modules/excel/types.d.ts +133 -2
  24. package/dist/browser/modules/excel/utils/col-cache.d.ts +1 -0
  25. package/dist/browser/modules/excel/utils/col-cache.js +15 -0
  26. package/dist/browser/modules/excel/utils/drawing-utils.d.ts +3 -3
  27. package/dist/browser/modules/excel/utils/drawing-utils.js +4 -0
  28. package/dist/browser/modules/excel/utils/external-link-formula.d.ts +76 -0
  29. package/dist/browser/modules/excel/utils/external-link-formula.js +208 -0
  30. package/dist/browser/modules/excel/utils/iterate-stream.d.ts +9 -3
  31. package/dist/browser/modules/excel/utils/iterate-stream.js +3 -1
  32. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +19 -0
  33. package/dist/browser/modules/excel/utils/ooxml-paths.js +37 -2
  34. package/dist/browser/modules/excel/utils/shared-strings.d.ts +8 -3
  35. package/dist/browser/modules/excel/utils/shared-strings.js +21 -2
  36. package/dist/browser/modules/excel/utils/workbook-protection.d.ts +30 -0
  37. package/dist/browser/modules/excel/utils/workbook-protection.js +30 -0
  38. package/dist/browser/modules/excel/workbook.browser.d.ts +257 -6
  39. package/dist/browser/modules/excel/workbook.browser.js +318 -34
  40. package/dist/browser/modules/excel/workbook.d.ts +1 -1
  41. package/dist/browser/modules/excel/worksheet.d.ts +3 -1
  42. package/dist/browser/modules/excel/worksheet.js +21 -2
  43. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +15 -0
  44. package/dist/browser/modules/excel/xlsx/rel-type.js +16 -1
  45. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  46. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  47. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  48. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  49. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  50. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  51. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  52. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  53. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  54. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  55. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  56. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  57. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  58. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  59. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  60. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  61. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  62. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  63. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  64. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  65. package/dist/browser/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  66. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  67. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  68. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  69. package/dist/browser/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  70. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  71. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +410 -20
  72. package/dist/browser/modules/excel/xlsx/xlsx.d.ts +7 -4
  73. package/dist/browser/modules/excel/xlsx/xlsx.js +4 -5
  74. package/dist/browser/modules/formula/compile/address-utils.d.ts +62 -0
  75. package/dist/browser/modules/formula/compile/address-utils.js +83 -0
  76. package/dist/browser/modules/formula/compile/binder.d.ts +42 -0
  77. package/dist/browser/modules/formula/compile/binder.js +487 -0
  78. package/dist/browser/modules/formula/compile/bound-ast.d.ts +230 -0
  79. package/dist/browser/modules/formula/compile/bound-ast.js +80 -0
  80. package/dist/browser/modules/formula/compile/compiled-formula.d.ts +137 -0
  81. package/dist/browser/modules/formula/compile/compiled-formula.js +383 -0
  82. package/dist/browser/modules/formula/compile/dependency-analysis.d.ts +93 -0
  83. package/dist/browser/modules/formula/compile/dependency-analysis.js +432 -0
  84. package/dist/browser/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  85. package/dist/browser/modules/formula/compile/structured-ref-utils.js +136 -0
  86. package/dist/browser/modules/formula/default-syntax-probe.d.ts +79 -0
  87. package/dist/browser/modules/formula/default-syntax-probe.js +83 -0
  88. package/dist/browser/modules/formula/functions/_date-context.d.ts +4 -0
  89. package/dist/browser/modules/formula/functions/_date-context.js +29 -0
  90. package/dist/browser/modules/formula/functions/_shared.d.ts +121 -0
  91. package/dist/browser/modules/formula/functions/_shared.js +381 -0
  92. package/dist/browser/modules/formula/functions/conditional.d.ts +27 -0
  93. package/dist/browser/modules/formula/functions/conditional.js +343 -0
  94. package/dist/browser/modules/formula/functions/database.d.ts +37 -0
  95. package/dist/browser/modules/formula/functions/database.js +274 -0
  96. package/dist/browser/modules/formula/functions/date.d.ts +61 -0
  97. package/dist/browser/modules/formula/functions/date.js +855 -0
  98. package/dist/browser/modules/formula/functions/dynamic-array.d.ts +23 -0
  99. package/dist/browser/modules/formula/functions/dynamic-array.js +860 -0
  100. package/dist/browser/modules/formula/functions/engineering.d.ts +57 -0
  101. package/dist/browser/modules/formula/functions/engineering.js +1128 -0
  102. package/dist/browser/modules/formula/functions/financial.d.ts +202 -0
  103. package/dist/browser/modules/formula/functions/financial.js +2296 -0
  104. package/dist/browser/modules/formula/functions/lookup.d.ts +18 -0
  105. package/dist/browser/modules/formula/functions/lookup.js +886 -0
  106. package/dist/browser/modules/formula/functions/math.d.ts +114 -0
  107. package/dist/browser/modules/formula/functions/math.js +1406 -0
  108. package/dist/browser/modules/formula/functions/statistical.d.ts +193 -0
  109. package/dist/browser/modules/formula/functions/statistical.js +3390 -0
  110. package/dist/browser/modules/formula/functions/text.d.ts +86 -0
  111. package/dist/browser/modules/formula/functions/text.js +1845 -0
  112. package/dist/browser/modules/formula/host-registry.d.ts +53 -0
  113. package/dist/browser/modules/formula/host-registry.js +69 -0
  114. package/dist/browser/modules/formula/index.d.ts +39 -0
  115. package/dist/browser/modules/formula/index.js +49 -0
  116. package/dist/browser/modules/formula/install.d.ts +62 -0
  117. package/dist/browser/modules/formula/install.js +88 -0
  118. package/dist/browser/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  119. package/dist/browser/modules/formula/integration/apply-writeback-plan.js +210 -0
  120. package/dist/browser/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  121. package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +616 -0
  122. package/dist/browser/modules/formula/integration/calculate-formulas.d.ts +67 -0
  123. package/dist/browser/modules/formula/integration/calculate-formulas.js +68 -0
  124. package/dist/browser/modules/formula/integration/formula-instance.d.ts +64 -0
  125. package/dist/browser/modules/formula/integration/formula-instance.js +79 -0
  126. package/dist/browser/modules/formula/integration/workbook-adapter.d.ts +26 -0
  127. package/dist/browser/modules/formula/integration/workbook-adapter.js +324 -0
  128. package/dist/browser/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  129. package/dist/browser/modules/formula/integration/workbook-snapshot.js +77 -0
  130. package/dist/browser/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  131. package/dist/browser/modules/formula/materialize/build-writeback-plan.js +473 -0
  132. package/dist/browser/modules/formula/materialize/spill-engine.d.ts +9 -0
  133. package/dist/browser/modules/formula/materialize/spill-engine.js +38 -0
  134. package/dist/browser/modules/formula/materialize/types.d.ts +179 -0
  135. package/dist/browser/modules/formula/materialize/types.js +29 -0
  136. package/dist/browser/modules/formula/materialize/writeback-plan.d.ts +167 -0
  137. package/dist/browser/modules/formula/materialize/writeback-plan.js +27 -0
  138. package/dist/browser/modules/formula/runtime/evaluator.d.ts +151 -0
  139. package/dist/browser/modules/formula/runtime/evaluator.js +2291 -0
  140. package/dist/browser/modules/formula/runtime/function-registry.d.ts +47 -0
  141. package/dist/browser/modules/formula/runtime/function-registry.js +840 -0
  142. package/dist/browser/modules/formula/runtime/values.d.ts +211 -0
  143. package/dist/browser/modules/formula/runtime/values.js +385 -0
  144. package/dist/browser/modules/formula/syntax/ast.d.ts +129 -0
  145. package/dist/browser/modules/formula/syntax/ast.js +28 -0
  146. package/dist/browser/modules/formula/syntax/parser.d.ts +18 -0
  147. package/dist/browser/modules/formula/syntax/parser.js +439 -0
  148. package/dist/browser/modules/formula/syntax/token-types.d.ts +153 -0
  149. package/dist/browser/modules/formula/syntax/token-types.js +59 -0
  150. package/dist/browser/modules/formula/syntax/tokenizer.d.ts +10 -0
  151. package/dist/browser/modules/formula/syntax/tokenizer.js +1074 -0
  152. package/dist/browser/modules/pdf/excel-bridge.js +9 -0
  153. package/dist/cjs/index.js +4 -0
  154. package/dist/cjs/modules/excel/cell.js +170 -22
  155. package/dist/cjs/modules/excel/defined-names.js +411 -21
  156. package/dist/cjs/modules/excel/image.js +24 -1
  157. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +14 -0
  158. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +48 -1
  159. package/dist/cjs/modules/excel/stream/worksheet-reader.js +17 -1
  160. package/dist/cjs/modules/excel/stream/worksheet-writer.js +45 -5
  161. package/dist/cjs/modules/excel/table.js +15 -2
  162. package/dist/cjs/modules/excel/utils/col-cache.js +15 -0
  163. package/dist/cjs/modules/excel/utils/drawing-utils.js +4 -0
  164. package/dist/cjs/modules/excel/utils/external-link-formula.js +212 -0
  165. package/dist/cjs/modules/excel/utils/iterate-stream.js +3 -1
  166. package/dist/cjs/modules/excel/utils/ooxml-paths.js +42 -2
  167. package/dist/cjs/modules/excel/utils/shared-strings.js +21 -2
  168. package/dist/cjs/modules/excel/utils/workbook-protection.js +33 -0
  169. package/dist/cjs/modules/excel/workbook.browser.js +318 -34
  170. package/dist/cjs/modules/excel/worksheet.js +20 -1
  171. package/dist/cjs/modules/excel/xlsx/rel-type.js +16 -1
  172. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  173. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +333 -0
  174. package/dist/cjs/modules/excel/xlsx/xform/book/external-reference-xform.js +27 -0
  175. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  176. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-protection-xform.js +69 -0
  177. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  178. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +18 -0
  179. package/dist/cjs/modules/excel/xlsx/xform/core/metadata-xform.js +161 -0
  180. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +108 -0
  181. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  182. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  183. package/dist/cjs/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  184. package/dist/cjs/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  185. package/dist/cjs/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +83 -0
  186. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  187. package/dist/cjs/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  188. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +408 -18
  189. package/dist/cjs/modules/excel/xlsx/xlsx.js +4 -5
  190. package/dist/cjs/modules/formula/compile/address-utils.js +89 -0
  191. package/dist/cjs/modules/formula/compile/binder.js +489 -0
  192. package/dist/cjs/modules/formula/compile/bound-ast.js +68 -0
  193. package/dist/cjs/modules/formula/compile/compiled-formula.js +387 -0
  194. package/dist/cjs/modules/formula/compile/dependency-analysis.js +437 -0
  195. package/dist/cjs/modules/formula/compile/structured-ref-utils.js +141 -0
  196. package/dist/cjs/modules/formula/default-syntax-probe.js +87 -0
  197. package/dist/cjs/modules/formula/functions/_date-context.js +33 -0
  198. package/dist/cjs/modules/formula/functions/_shared.js +396 -0
  199. package/dist/cjs/modules/formula/functions/conditional.js +354 -0
  200. package/dist/cjs/modules/formula/functions/database.js +288 -0
  201. package/dist/cjs/modules/formula/functions/date.js +883 -0
  202. package/dist/cjs/modules/formula/functions/dynamic-array.js +881 -0
  203. package/dist/cjs/modules/formula/functions/engineering.js +1183 -0
  204. package/dist/cjs/modules/formula/functions/financial.js +2348 -0
  205. package/dist/cjs/modules/formula/functions/lookup.js +902 -0
  206. package/dist/cjs/modules/formula/functions/math.js +1487 -0
  207. package/dist/cjs/modules/formula/functions/statistical.js +3488 -0
  208. package/dist/cjs/modules/formula/functions/text.js +1889 -0
  209. package/dist/cjs/modules/formula/host-registry.js +75 -0
  210. package/dist/cjs/modules/formula/index.js +58 -0
  211. package/dist/cjs/modules/formula/install.js +93 -0
  212. package/dist/cjs/modules/formula/integration/apply-writeback-plan.js +213 -0
  213. package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +619 -0
  214. package/dist/cjs/modules/formula/integration/calculate-formulas.js +71 -0
  215. package/dist/cjs/modules/formula/integration/formula-instance.js +82 -0
  216. package/dist/cjs/modules/formula/integration/workbook-adapter.js +327 -0
  217. package/dist/cjs/modules/formula/integration/workbook-snapshot.js +84 -0
  218. package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +475 -0
  219. package/dist/cjs/modules/formula/materialize/spill-engine.js +42 -0
  220. package/dist/cjs/modules/formula/materialize/types.js +32 -0
  221. package/dist/cjs/modules/formula/materialize/writeback-plan.js +28 -0
  222. package/dist/cjs/modules/formula/runtime/evaluator.js +2298 -0
  223. package/dist/cjs/modules/formula/runtime/function-registry.js +846 -0
  224. package/dist/cjs/modules/formula/runtime/values.js +385 -0
  225. package/dist/cjs/modules/formula/syntax/ast.js +8 -0
  226. package/dist/cjs/modules/formula/syntax/parser.js +440 -0
  227. package/dist/cjs/modules/formula/syntax/token-types.js +32 -0
  228. package/dist/cjs/modules/formula/syntax/tokenizer.js +1076 -0
  229. package/dist/cjs/modules/pdf/excel-bridge.js +9 -0
  230. package/dist/esm/index.browser.js +4 -0
  231. package/dist/esm/index.js +4 -0
  232. package/dist/esm/modules/excel/cell.js +170 -22
  233. package/dist/esm/modules/excel/defined-names.js +411 -21
  234. package/dist/esm/modules/excel/image.js +24 -1
  235. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +14 -0
  236. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +48 -1
  237. package/dist/esm/modules/excel/stream/worksheet-reader.js +17 -1
  238. package/dist/esm/modules/excel/stream/worksheet-writer.js +45 -5
  239. package/dist/esm/modules/excel/table.js +15 -2
  240. package/dist/esm/modules/excel/utils/col-cache.js +15 -0
  241. package/dist/esm/modules/excel/utils/drawing-utils.js +4 -0
  242. package/dist/esm/modules/excel/utils/external-link-formula.js +208 -0
  243. package/dist/esm/modules/excel/utils/iterate-stream.js +3 -1
  244. package/dist/esm/modules/excel/utils/ooxml-paths.js +37 -2
  245. package/dist/esm/modules/excel/utils/shared-strings.js +21 -2
  246. package/dist/esm/modules/excel/utils/workbook-protection.js +30 -0
  247. package/dist/esm/modules/excel/workbook.browser.js +318 -34
  248. package/dist/esm/modules/excel/worksheet.js +21 -2
  249. package/dist/esm/modules/excel/xlsx/rel-type.js +16 -1
  250. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  251. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  252. package/dist/esm/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  253. package/dist/esm/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  254. package/dist/esm/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  255. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  256. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  257. package/dist/esm/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  258. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  259. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  260. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  261. package/dist/esm/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  262. package/dist/esm/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  263. package/dist/esm/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  264. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  265. package/dist/esm/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  266. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +410 -20
  267. package/dist/esm/modules/excel/xlsx/xlsx.js +4 -5
  268. package/dist/esm/modules/formula/compile/address-utils.js +83 -0
  269. package/dist/esm/modules/formula/compile/binder.js +487 -0
  270. package/dist/esm/modules/formula/compile/bound-ast.js +80 -0
  271. package/dist/esm/modules/formula/compile/compiled-formula.js +383 -0
  272. package/dist/esm/modules/formula/compile/dependency-analysis.js +432 -0
  273. package/dist/esm/modules/formula/compile/structured-ref-utils.js +136 -0
  274. package/dist/esm/modules/formula/default-syntax-probe.js +83 -0
  275. package/dist/esm/modules/formula/functions/_date-context.js +29 -0
  276. package/dist/esm/modules/formula/functions/_shared.js +381 -0
  277. package/dist/esm/modules/formula/functions/conditional.js +343 -0
  278. package/dist/esm/modules/formula/functions/database.js +274 -0
  279. package/dist/esm/modules/formula/functions/date.js +855 -0
  280. package/dist/esm/modules/formula/functions/dynamic-array.js +860 -0
  281. package/dist/esm/modules/formula/functions/engineering.js +1128 -0
  282. package/dist/esm/modules/formula/functions/financial.js +2296 -0
  283. package/dist/esm/modules/formula/functions/lookup.js +886 -0
  284. package/dist/esm/modules/formula/functions/math.js +1406 -0
  285. package/dist/esm/modules/formula/functions/statistical.js +3390 -0
  286. package/dist/esm/modules/formula/functions/text.js +1845 -0
  287. package/dist/esm/modules/formula/host-registry.js +69 -0
  288. package/dist/esm/modules/formula/index.js +49 -0
  289. package/dist/esm/modules/formula/install.js +88 -0
  290. package/dist/esm/modules/formula/integration/apply-writeback-plan.js +210 -0
  291. package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +616 -0
  292. package/dist/esm/modules/formula/integration/calculate-formulas.js +68 -0
  293. package/dist/esm/modules/formula/integration/formula-instance.js +79 -0
  294. package/dist/esm/modules/formula/integration/workbook-adapter.js +324 -0
  295. package/dist/esm/modules/formula/integration/workbook-snapshot.js +77 -0
  296. package/dist/esm/modules/formula/materialize/build-writeback-plan.js +473 -0
  297. package/dist/esm/modules/formula/materialize/spill-engine.js +38 -0
  298. package/dist/esm/modules/formula/materialize/types.js +29 -0
  299. package/dist/esm/modules/formula/materialize/writeback-plan.js +27 -0
  300. package/dist/esm/modules/formula/runtime/evaluator.js +2291 -0
  301. package/dist/esm/modules/formula/runtime/function-registry.js +840 -0
  302. package/dist/esm/modules/formula/runtime/values.js +385 -0
  303. package/dist/esm/modules/formula/syntax/ast.js +28 -0
  304. package/dist/esm/modules/formula/syntax/parser.js +439 -0
  305. package/dist/esm/modules/formula/syntax/token-types.js +59 -0
  306. package/dist/esm/modules/formula/syntax/tokenizer.js +1074 -0
  307. package/dist/esm/modules/pdf/excel-bridge.js +9 -0
  308. package/dist/iife/excelts.iife.js +2302 -373
  309. package/dist/iife/excelts.iife.js.map +1 -1
  310. package/dist/iife/excelts.iife.min.js +34 -34
  311. package/dist/types/index.browser.d.ts +1 -1
  312. package/dist/types/index.d.ts +1 -1
  313. package/dist/types/modules/excel/cell.d.ts +17 -3
  314. package/dist/types/modules/excel/defined-names.d.ts +96 -1
  315. package/dist/types/modules/excel/image.d.ts +11 -0
  316. package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  317. package/dist/types/modules/excel/stream/workbook-reader.d.ts +2 -1
  318. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  319. package/dist/types/modules/excel/stream/workbook-writer.d.ts +3 -2
  320. package/dist/types/modules/excel/stream/worksheet-writer.d.ts +39 -6
  321. package/dist/types/modules/excel/types.d.ts +133 -2
  322. package/dist/types/modules/excel/utils/col-cache.d.ts +1 -0
  323. package/dist/types/modules/excel/utils/drawing-utils.d.ts +3 -3
  324. package/dist/types/modules/excel/utils/external-link-formula.d.ts +76 -0
  325. package/dist/types/modules/excel/utils/iterate-stream.d.ts +9 -3
  326. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +19 -0
  327. package/dist/types/modules/excel/utils/shared-strings.d.ts +8 -3
  328. package/dist/types/modules/excel/utils/workbook-protection.d.ts +30 -0
  329. package/dist/types/modules/excel/workbook.browser.d.ts +257 -6
  330. package/dist/types/modules/excel/workbook.d.ts +1 -1
  331. package/dist/types/modules/excel/worksheet.d.ts +3 -1
  332. package/dist/types/modules/excel/xlsx/rel-type.d.ts +15 -0
  333. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  334. package/dist/types/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  335. package/dist/types/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  336. package/dist/types/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  337. package/dist/types/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  338. package/dist/types/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  339. package/dist/types/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  340. package/dist/types/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  341. package/dist/types/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  342. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  343. package/dist/types/modules/excel/xlsx/xlsx.d.ts +7 -4
  344. package/dist/types/modules/formula/compile/address-utils.d.ts +62 -0
  345. package/dist/types/modules/formula/compile/binder.d.ts +42 -0
  346. package/dist/types/modules/formula/compile/bound-ast.d.ts +230 -0
  347. package/dist/types/modules/formula/compile/compiled-formula.d.ts +137 -0
  348. package/dist/types/modules/formula/compile/dependency-analysis.d.ts +93 -0
  349. package/dist/types/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  350. package/dist/types/modules/formula/default-syntax-probe.d.ts +79 -0
  351. package/dist/types/modules/formula/functions/_date-context.d.ts +4 -0
  352. package/dist/types/modules/formula/functions/_shared.d.ts +121 -0
  353. package/dist/types/modules/formula/functions/conditional.d.ts +27 -0
  354. package/dist/types/modules/formula/functions/database.d.ts +37 -0
  355. package/dist/types/modules/formula/functions/date.d.ts +61 -0
  356. package/dist/types/modules/formula/functions/dynamic-array.d.ts +23 -0
  357. package/dist/types/modules/formula/functions/engineering.d.ts +57 -0
  358. package/dist/types/modules/formula/functions/financial.d.ts +202 -0
  359. package/dist/types/modules/formula/functions/lookup.d.ts +18 -0
  360. package/dist/types/modules/formula/functions/math.d.ts +114 -0
  361. package/dist/types/modules/formula/functions/statistical.d.ts +193 -0
  362. package/dist/types/modules/formula/functions/text.d.ts +86 -0
  363. package/dist/types/modules/formula/host-registry.d.ts +53 -0
  364. package/dist/types/modules/formula/index.d.ts +39 -0
  365. package/dist/types/modules/formula/install.d.ts +62 -0
  366. package/dist/types/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  367. package/dist/types/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  368. package/dist/types/modules/formula/integration/calculate-formulas.d.ts +67 -0
  369. package/dist/types/modules/formula/integration/formula-instance.d.ts +64 -0
  370. package/dist/types/modules/formula/integration/workbook-adapter.d.ts +26 -0
  371. package/dist/types/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  372. package/dist/types/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  373. package/dist/types/modules/formula/materialize/spill-engine.d.ts +9 -0
  374. package/dist/types/modules/formula/materialize/types.d.ts +179 -0
  375. package/dist/types/modules/formula/materialize/writeback-plan.d.ts +167 -0
  376. package/dist/types/modules/formula/runtime/evaluator.d.ts +151 -0
  377. package/dist/types/modules/formula/runtime/function-registry.d.ts +47 -0
  378. package/dist/types/modules/formula/runtime/values.d.ts +211 -0
  379. package/dist/types/modules/formula/syntax/ast.d.ts +129 -0
  380. package/dist/types/modules/formula/syntax/parser.d.ts +18 -0
  381. package/dist/types/modules/formula/syntax/token-types.d.ts +153 -0
  382. package/dist/types/modules/formula/syntax/tokenizer.d.ts +10 -0
  383. package/package.json +28 -28
@@ -0,0 +1,473 @@
1
+ /**
2
+ * Build Writeback Plan — Convert evaluation results into a WritebackPlan.
3
+ *
4
+ * This module takes the evaluation results from the evaluator and
5
+ * produces a declarative `WritebackPlan` that describes all cell mutations.
6
+ * The plan is then applied by `apply-writeback-plan.ts`.
7
+ *
8
+ * ## Responsibilities
9
+ *
10
+ * 1. Classify each formula's result as scalar, CSE, or dynamic-array.
11
+ * 2. Check spill availability and detect #SPILL! conflicts.
12
+ * 3. Generate cleanup operations for stale ghost cells.
13
+ * 4. Track spill regions and ghost snapshots for persistence.
14
+ *
15
+ * ## Key Principle
16
+ *
17
+ * This module does NOT touch any live workbook objects. It reads only
18
+ * from the `WorkbookSnapshot` and the evaluation results.
19
+ */
20
+ import { parseRefRange } from "../compile/address-utils.js";
21
+ import { snapshotCellKey, spillCellKeyFromId, formulaCellKey } from "../integration/workbook-snapshot.js";
22
+ import { RVKind } from "../runtime/values.js";
23
+ // ============================================================================
24
+ // Build Writeback Plan
25
+ // ============================================================================
26
+ /**
27
+ * Build a complete `WritebackPlan` from evaluation results.
28
+ *
29
+ * @param snapshot - The workbook snapshot
30
+ * @param compiled - All compiled formulas in evaluation order
31
+ * @param results - Raw evaluation results, keyed by formula cell key
32
+ * @param previousSpills - Persistent spill regions from previous calculation
33
+ * @param previousGhosts - Persistent ghost snapshots from previous calculation
34
+ */
35
+ export function buildWritebackPlan(snapshot, compiled, results, previousSpills, previousGhosts) {
36
+ const operations = [];
37
+ const spillRegions = new Map();
38
+ const ghostSnapshots = new Map();
39
+ const removedSpillKeys = [];
40
+ // Target cells already claimed by a spill produced EARLIER in this
41
+ // calc pass. Without this set, two dynamic-array formulas whose spill
42
+ // regions overlap would each pass the availability check against the
43
+ // immutable snapshot and then silently clobber each other during
44
+ // apply. See R5-P0-6.
45
+ const activeSpillTargets = new Set();
46
+ // Build a set of current formula cell keys (using worksheet-id-based keys)
47
+ const formulaKeys = new Set();
48
+ for (const cf of compiled) {
49
+ formulaKeys.add(spillCellKeyFromId(cf.instance.sheetId, cf.instance.row, cf.instance.col));
50
+ }
51
+ // Build ghost map from previous spills (validated against snapshot)
52
+ const ghostMap = new Map();
53
+ for (const [srcKey, region] of previousSpills) {
54
+ for (let r = 0; r < region.rows; r++) {
55
+ for (let c = 0; c < region.cols; c++) {
56
+ if (r === 0 && c === 0) {
57
+ continue;
58
+ }
59
+ const targetRow = region.sourceRow + r;
60
+ const targetCol = region.sourceCol + c;
61
+ const targetKey = spillCellKeyFromId(region.worksheetId, targetRow, targetCol);
62
+ // Validate ghost cell is still unmodified
63
+ const ws = snapshot.worksheetsById.get(region.worksheetId);
64
+ if (ws) {
65
+ const cell = ws.cells.get(snapshotCellKey(targetRow, targetCol));
66
+ if (isGhostUnmodified(cell, targetKey, previousGhosts)) {
67
+ ghostMap.set(targetKey, srcKey);
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ // Clean up stale spill regions (source formula no longer exists)
74
+ for (const [srcKey, region] of previousSpills) {
75
+ if (!formulaKeys.has(srcKey)) {
76
+ const ws = snapshot.worksheetsById.get(region.worksheetId);
77
+ if (ws) {
78
+ emitPreviousSpillCleanup(region, previousGhosts, snapshot, operations, ws.name, region.worksheetId);
79
+ }
80
+ removedSpillKeys.push(srcKey);
81
+ }
82
+ }
83
+ // Process each compiled formula's result
84
+ for (const cf of compiled) {
85
+ const inst = cf.instance;
86
+ const fKey = formulaCellKey(inst.sheetName, inst.row, inst.col);
87
+ const result = results.get(fKey);
88
+ if (result === undefined) {
89
+ continue;
90
+ }
91
+ const isCSE = inst.kind === "cse" && inst.targetRef;
92
+ const isDynamic = inst.isDynamicArray || cf.isDynamicArrayFunction;
93
+ if (isCSE) {
94
+ // CSE array formula
95
+ const op = buildCSEWrite(inst, result);
96
+ if (op) {
97
+ operations.push(op);
98
+ }
99
+ }
100
+ else if (isDynamic &&
101
+ result.kind === RVKind.Array &&
102
+ (result.height > 1 || result.width > 1)) {
103
+ // Dynamic array formula with array result
104
+ const srcKey = spillCellKeyFromId(inst.sheetId, inst.row, inst.col);
105
+ // Check spill availability
106
+ const spillResult = buildSpillWrite(inst, result, srcKey, ghostMap, previousSpills.get(srcKey), previousGhosts, snapshot, spillRegions, ghostSnapshots, operations, activeSpillTargets);
107
+ if (spillResult === "error") {
108
+ operations.push({
109
+ type: "spill-error",
110
+ sheetName: inst.sheetName,
111
+ sheetId: inst.sheetId,
112
+ row: inst.row,
113
+ col: inst.col
114
+ });
115
+ }
116
+ }
117
+ else {
118
+ // Scalar result (or 1x1 array)
119
+ const scalar = scalarFromResult(result);
120
+ // If this formula previously had a spill region, clean it up
121
+ const srcKey = spillCellKeyFromId(inst.sheetId, inst.row, inst.col);
122
+ const prevRegion = previousSpills.get(srcKey);
123
+ if (prevRegion) {
124
+ emitPreviousSpillCleanup(prevRegion, previousGhosts, snapshot, operations, inst.sheetName, inst.sheetId);
125
+ removedSpillKeys.push(srcKey);
126
+ }
127
+ if (shouldPreserve(scalar, inst, snapshot)) {
128
+ operations.push({
129
+ type: "preserve",
130
+ sheetName: inst.sheetName,
131
+ row: inst.row,
132
+ col: inst.col
133
+ });
134
+ }
135
+ else {
136
+ operations.push({
137
+ type: "scalar",
138
+ sheetName: inst.sheetName,
139
+ row: inst.row,
140
+ col: inst.col,
141
+ value: runtimeToSnapshotValue(scalar)
142
+ });
143
+ }
144
+ }
145
+ }
146
+ return {
147
+ operations,
148
+ spillState: {
149
+ spillRegions,
150
+ ghostSnapshots,
151
+ removedSpillKeys
152
+ }
153
+ };
154
+ }
155
+ // ============================================================================
156
+ // CSE Write
157
+ // ============================================================================
158
+ function buildCSEWrite(inst, result) {
159
+ const ref = inst.targetRef;
160
+ if (!ref) {
161
+ return null;
162
+ }
163
+ const range = parseRefRange(ref);
164
+ if (!range) {
165
+ return null;
166
+ }
167
+ if (result.kind === RVKind.Array) {
168
+ const results = [];
169
+ const numRows = range.bottom - range.top + 1;
170
+ const numCols = range.right - range.left + 1;
171
+ for (let r = 0; r < numRows; r++) {
172
+ const row = [];
173
+ for (let c = 0; c < numCols; c++) {
174
+ // When the array result is smaller than the CSE target range,
175
+ // positions outside the array get #N/A (Excel behaviour) — not
176
+ // BLANK, which is what the previous `?? { kind: Blank }` gave
177
+ // us. R6-P1-3.
178
+ const inBounds = r < result.height && c < result.width;
179
+ const val = inBounds
180
+ ? result.rows[r][c]
181
+ : { kind: RVKind.Error, code: "#N/A" };
182
+ row.push(runtimeToSnapshotValue(val));
183
+ }
184
+ results.push(row);
185
+ }
186
+ return {
187
+ type: "cse",
188
+ sheetName: inst.sheetName,
189
+ top: range.top,
190
+ left: range.left,
191
+ bottom: range.bottom,
192
+ right: range.right,
193
+ results
194
+ };
195
+ }
196
+ // Scalar fill
197
+ const scalarVal = runtimeToSnapshotValue(scalarFromResult(result));
198
+ return {
199
+ type: "cse",
200
+ sheetName: inst.sheetName,
201
+ top: range.top,
202
+ left: range.left,
203
+ bottom: range.bottom,
204
+ right: range.right,
205
+ results: [],
206
+ scalarFill: scalarVal
207
+ };
208
+ }
209
+ // ============================================================================
210
+ // Spill Write
211
+ // ============================================================================
212
+ function buildSpillWrite(inst, arr, srcKey, ghostMap, previousRegion, previousGhosts, snapshot, spillRegions, ghostSnapshotsOut, operations,
213
+ /**
214
+ * Target cell keys claimed by spill regions produced EARLIER in this
215
+ * same calc pass. The snapshot is immutable during a pass, so without
216
+ * an explicit set the availability check wouldn't see the A1→A1:A5
217
+ * spill that the previous iteration just committed, and a subsequent
218
+ * formula spilling over A3:A7 would silently overwrite half of it.
219
+ */
220
+ activeSpillTargets) {
221
+ const ws = snapshot.worksheetsByName.get(inst.sheetName.toLowerCase());
222
+ if (!ws) {
223
+ return "error";
224
+ }
225
+ // 1x1 result: just write scalar, no spilling
226
+ if (arr.height <= 1 && arr.width <= 1) {
227
+ const val = arr.height > 0 && arr.width > 0 ? arr.rows[0][0] : { kind: RVKind.Blank };
228
+ operations.push({
229
+ type: "scalar",
230
+ sheetName: inst.sheetName,
231
+ row: inst.row,
232
+ col: inst.col,
233
+ value: runtimeToSnapshotValue(val)
234
+ });
235
+ // Clean up previous spill if any
236
+ if (previousRegion) {
237
+ emitPreviousSpillCleanup(previousRegion, previousGhosts, snapshot, operations, inst.sheetName, inst.sheetId);
238
+ }
239
+ return "ok";
240
+ }
241
+ // Reject if the spill region would extend past the sheet's maximum
242
+ // dimensions (1048576 rows x 16384 columns) — Excel reports #SPILL! here.
243
+ if (inst.row + arr.height - 1 > 1048576 || inst.col + arr.width - 1 > 16384) {
244
+ return "error";
245
+ }
246
+ // Check spill availability: verify all target ghost cells are unoccupied
247
+ for (let r = 0; r < arr.height; r++) {
248
+ for (let c = 0; c < arr.width; c++) {
249
+ if (r === 0 && c === 0) {
250
+ continue; // Source cell is always available
251
+ }
252
+ const targetRow = inst.row + r;
253
+ const targetCol = inst.col + c;
254
+ const targetKey = spillCellKeyFromId(inst.sheetId, targetRow, targetCol);
255
+ // Another spill in this calc pass already claimed this cell —
256
+ // report #SPILL! rather than silently overwrite.
257
+ if (activeSpillTargets.has(targetKey)) {
258
+ return "error";
259
+ }
260
+ // Check if the cell is a ghost from ANY previous spill.
261
+ // If the user hasn't modified it, it's safe to overwrite — the
262
+ // originating formula will clean it up (or we'll overwrite it).
263
+ if (ghostMap.has(targetKey)) {
264
+ const cell = ws.cells.get(snapshotCellKey(targetRow, targetCol));
265
+ if (!isGhostUnmodified(cell, targetKey, previousGhosts)) {
266
+ return "error"; // User wrote into a ghost → #SPILL!
267
+ }
268
+ continue;
269
+ }
270
+ // Check if the cell is occupied by another formula or has a value
271
+ const cell = ws.cells.get(snapshotCellKey(targetRow, targetCol));
272
+ if (cell && cell.value !== null && cell.formulaKind === "none") {
273
+ // Non-empty, non-formula cell → blocked
274
+ return "error";
275
+ }
276
+ if (cell && cell.formulaKind !== "none") {
277
+ // Formula cell → blocked (not our ghost)
278
+ return "error";
279
+ }
280
+ }
281
+ }
282
+ // Now that availability is confirmed, claim the target cells so the
283
+ // next spill in this pass sees them as occupied.
284
+ for (let r = 0; r < arr.height; r++) {
285
+ for (let c = 0; c < arr.width; c++) {
286
+ if (r === 0 && c === 0) {
287
+ continue;
288
+ }
289
+ const targetRow = inst.row + r;
290
+ const targetCol = inst.col + c;
291
+ activeSpillTargets.add(spillCellKeyFromId(inst.sheetId, targetRow, targetCol));
292
+ }
293
+ }
294
+ // Clean up previous spill region if size changed
295
+ if (previousRegion) {
296
+ emitPreviousSpillCleanup(previousRegion, previousGhosts, snapshot, operations, inst.sheetName, inst.sheetId);
297
+ }
298
+ // Build spill write operation
299
+ const results = [];
300
+ for (let r = 0; r < arr.height; r++) {
301
+ const row = [];
302
+ for (let c = 0; c < arr.width; c++) {
303
+ const val = arr.rows[r]?.[c] ?? { kind: RVKind.Blank };
304
+ const sv = runtimeToSnapshotValue(val);
305
+ row.push(sv);
306
+ // Record ghost snapshot
307
+ if (r !== 0 || c !== 0) {
308
+ const targetKey = spillCellKeyFromId(inst.sheetId, inst.row + r, inst.col + c);
309
+ ghostSnapshotsOut.set(targetKey, sv);
310
+ }
311
+ }
312
+ results.push(row);
313
+ }
314
+ operations.push({
315
+ type: "spill",
316
+ sheetName: inst.sheetName,
317
+ sheetId: inst.sheetId,
318
+ row: inst.row,
319
+ col: inst.col,
320
+ results
321
+ });
322
+ // Record spill region
323
+ spillRegions.set(srcKey, {
324
+ worksheetId: inst.sheetId,
325
+ sourceRow: inst.row,
326
+ sourceCol: inst.col,
327
+ rows: arr.height,
328
+ cols: arr.width
329
+ });
330
+ return "ok";
331
+ }
332
+ // ============================================================================
333
+ // Helpers
334
+ // ============================================================================
335
+ function collectStaleGhosts(region, previousGhosts, snapshot) {
336
+ const cells = [];
337
+ const ws = snapshot.worksheetsById.get(region.worksheetId);
338
+ if (!ws) {
339
+ return cells;
340
+ }
341
+ for (let r = 0; r < region.rows; r++) {
342
+ for (let c = 0; c < region.cols; c++) {
343
+ if (r === 0 && c === 0) {
344
+ continue;
345
+ }
346
+ const targetRow = region.sourceRow + r;
347
+ const targetCol = region.sourceCol + c;
348
+ const targetKey = spillCellKeyFromId(region.worksheetId, targetRow, targetCol);
349
+ const cell = ws.cells.get(snapshotCellKey(targetRow, targetCol));
350
+ if (isGhostUnmodified(cell, targetKey, previousGhosts)) {
351
+ cells.push({ row: targetRow, col: targetCol });
352
+ }
353
+ }
354
+ }
355
+ return cells;
356
+ }
357
+ /**
358
+ * Emit a cleanup operation for a previous spill region whose ghosts are
359
+ * still unmodified.
360
+ *
361
+ * Collects the stale ghost cells and, if any remain, pushes a single
362
+ * `CleanupWrite` onto `operations`. The caller is responsible for
363
+ * updating `removedSpillKeys` / `spillRegions` as appropriate for its
364
+ * situation (this helper deliberately does not touch them since the
365
+ * three callsites have slightly different follow-up actions).
366
+ */
367
+ function emitPreviousSpillCleanup(previousRegion, previousGhosts, snapshot, operations, sheetName, sheetId) {
368
+ const cleanupCells = collectStaleGhosts(previousRegion, previousGhosts, snapshot);
369
+ if (cleanupCells.length === 0) {
370
+ return;
371
+ }
372
+ operations.push({
373
+ type: "cleanup",
374
+ sheetName,
375
+ sheetId,
376
+ cells: cleanupCells
377
+ });
378
+ }
379
+ function isGhostUnmodified(cell, ghostKey, previousGhosts) {
380
+ if (!cell) {
381
+ return true;
382
+ }
383
+ if (cell.value === null) {
384
+ return true;
385
+ }
386
+ if (cell.formulaKind !== "none") {
387
+ return false;
388
+ }
389
+ const snapshot = previousGhosts.get(ghostKey);
390
+ if (snapshot === undefined) {
391
+ return true; // No snapshot — assume unmodified (conservative)
392
+ }
393
+ return snapshotValuesEqual(cell.value, snapshot);
394
+ }
395
+ /**
396
+ * Structural comparison for snapshot values.
397
+ * Handles error objects (which are reference types and fail `===` comparison)
398
+ * as well as primitives.
399
+ */
400
+ function snapshotValuesEqual(a, b) {
401
+ if (a === b) {
402
+ return true;
403
+ }
404
+ // Both are error objects — compare by error code
405
+ if (a !== null &&
406
+ typeof a === "object" &&
407
+ "error" in a &&
408
+ b !== null &&
409
+ typeof b === "object" &&
410
+ "error" in b) {
411
+ return a.error === b.error;
412
+ }
413
+ return false;
414
+ }
415
+ function scalarFromResult(v) {
416
+ if (v.kind === RVKind.Array) {
417
+ if (v.height > 0 && v.width > 0) {
418
+ return v.rows[0][0];
419
+ }
420
+ return { kind: RVKind.Blank };
421
+ }
422
+ if (v.kind === RVKind.Blank ||
423
+ v.kind === RVKind.Number ||
424
+ v.kind === RVKind.String ||
425
+ v.kind === RVKind.Boolean ||
426
+ v.kind === RVKind.Error) {
427
+ return v;
428
+ }
429
+ return { kind: RVKind.Blank };
430
+ }
431
+ function runtimeToSnapshotValue(v) {
432
+ switch (v.kind) {
433
+ case RVKind.Blank:
434
+ return null;
435
+ case RVKind.Number:
436
+ // Boundary guard: never let NaN or ±Infinity leak into the
437
+ // persisted workbook. Either comes from arithmetic the per-
438
+ // function guards missed (for example extreme ROUND digit
439
+ // counts before the R6-P1-2 clamp). Convert to #NUM! here so
440
+ // downstream readers see a clean error instead of a stringified
441
+ // "NaN" / "Infinity" value. See R6 architectural note.
442
+ if (!Number.isFinite(v.value)) {
443
+ return { error: "#NUM!" };
444
+ }
445
+ return v.value;
446
+ case RVKind.String:
447
+ return v.value;
448
+ case RVKind.Boolean:
449
+ return v.value;
450
+ case RVKind.Error:
451
+ return { error: v.code };
452
+ case RVKind.Array:
453
+ // Take top-left
454
+ if (v.height > 0 && v.width > 0) {
455
+ return runtimeToSnapshotValue(v.rows[0][0]);
456
+ }
457
+ return null;
458
+ default:
459
+ return null;
460
+ }
461
+ }
462
+ function shouldPreserve(computed, inst, snapshot) {
463
+ if (computed.kind !== RVKind.Error || computed.code !== "#NAME?") {
464
+ return false;
465
+ }
466
+ // Check if cell has a cached result in the snapshot
467
+ const ws = snapshot.worksheetsByName.get(inst.sheetName.toLowerCase());
468
+ if (!ws) {
469
+ return false;
470
+ }
471
+ const cell = ws.cells.get(snapshotCellKey(inst.row, inst.col));
472
+ return cell?.cachedResult !== undefined && cell.cachedResult !== null;
473
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Spill Engine — Persistent state management for dynamic array formulas.
3
+ *
4
+ * Manages persistent spill metadata that survives across
5
+ * `calculateFormulas()` invocations.
6
+ */
7
+ import type { SpillRegion, WorkbookLike } from "./types.js";
8
+ export declare function getPersistentSpillMap(workbook: WorkbookLike): Map<string, SpillRegion>;
9
+ export declare function getGhostSnapshots(workbook: WorkbookLike): Map<string, unknown>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Spill Engine — Persistent state management for dynamic array formulas.
3
+ *
4
+ * Manages persistent spill metadata that survives across
5
+ * `calculateFormulas()` invocations.
6
+ */
7
+ // ============================================================================
8
+ // Persistent State (WeakMap keyed by workbook — survives across invocations)
9
+ // ============================================================================
10
+ /**
11
+ * Persistent spill metadata: survives across calculateFormulas invocations.
12
+ * Key: "ws:<id>!row:col" of the source cell → SpillRegion.
13
+ * Stored in a WeakMap keyed by the workbook object to allow GC.
14
+ */
15
+ const persistentSpillRegions = new WeakMap();
16
+ export function getPersistentSpillMap(workbook) {
17
+ let map = persistentSpillRegions.get(workbook);
18
+ if (!map) {
19
+ map = new Map();
20
+ persistentSpillRegions.set(workbook, map);
21
+ }
22
+ return map;
23
+ }
24
+ /**
25
+ * Persistent snapshot of values written to ghost (spill target) cells.
26
+ * Key: ghost cell key "ws:<id>!row:col" → raw value written by spill.
27
+ * Used to detect whether a ghost cell has been modified by the user since
28
+ * the last calculation.
29
+ */
30
+ const persistentGhostSnapshots = new WeakMap();
31
+ export function getGhostSnapshots(workbook) {
32
+ let map = persistentGhostSnapshots.get(workbook);
33
+ if (!map) {
34
+ map = new Map();
35
+ persistentGhostSnapshots.set(workbook, map);
36
+ }
37
+ return map;
38
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Structural interfaces the formula engine consumes.
3
+ *
4
+ * The engine talks to these interfaces only — never to the concrete
5
+ * `Workbook` / `Worksheet` / `Cell` classes from the `excel` module. Any
6
+ * host that wants to drive the engine (including the Node/browser
7
+ * Workbook in `@excel/*`) must implement these shapes.
8
+ *
9
+ * This is what keeps the Layer 3 ↔ Layer 4 dependency one-way: the
10
+ * `excel` module imports from `formula`, never the reverse.
11
+ */
12
+ /**
13
+ * Excel-style error value carried inside a cell.
14
+ *
15
+ * Mirrors `CellErrorValue` in `@excel/types` so hosts can pass their
16
+ * concrete error objects straight through.
17
+ */
18
+ export interface CellErrorValueLike {
19
+ error: string;
20
+ }
21
+ /**
22
+ * The value the engine writes back as `cell.result` for formula cells.
23
+ */
24
+ export type FormulaResultLike = number | string | boolean | Date | CellErrorValueLike | undefined;
25
+ /**
26
+ * Numeric cell-type tag exposed by host cells. The engine only compares
27
+ * against `Null` and `Formula`; any other value is treated as a scalar
28
+ * literal.
29
+ *
30
+ * Kept as inline numeric literals (not an enum) so this file stays free
31
+ * of runtime dependencies. The `const` object and `type` alias share a
32
+ * name via TypeScript's declaration merging — the value form
33
+ * (`CellValueTypeLike.Null`, `CellValueTypeLike.Formula`) is used at
34
+ * comparison sites, the type form annotates `CellLike.type`.
35
+ */
36
+ export declare const CellValueTypeLike: {
37
+ readonly Null: 0;
38
+ readonly Formula: 6;
39
+ };
40
+ export type CellValueTypeLike = number;
41
+ /**
42
+ * The portion of a cell's persisted `model` the engine inspects for
43
+ * classifying a formula (shared / CSE / dynamic array, etc.).
44
+ */
45
+ export interface CellModelLike {
46
+ readonly shareType?: string;
47
+ readonly ref?: string;
48
+ readonly formula?: string;
49
+ readonly sharedFormula?: string;
50
+ readonly isDynamicArray?: boolean;
51
+ }
52
+ /**
53
+ * Minimal cell surface consumed by the engine. A host cell must allow
54
+ * both reading (for snapshot) and mutation (for writeback).
55
+ */
56
+ export interface CellLike {
57
+ readonly row: number;
58
+ readonly col: number;
59
+ readonly type: CellValueTypeLike;
60
+ readonly formula?: string;
61
+ readonly model: CellModelLike;
62
+ /**
63
+ * Host cells can carry any representation (hyperlinks, rich text,
64
+ * checkboxes, dates, scalars, errors, …). The engine narrows to plain
65
+ * scalars internally during snapshot construction, so this is typed
66
+ * as `unknown` to stay structurally compatible with any host shape.
67
+ */
68
+ value: unknown;
69
+ result: FormulaResultLike;
70
+ }
71
+ export interface RowLike {
72
+ readonly hidden?: boolean;
73
+ /**
74
+ * Excel's `eachCell` accepts either a bare callback or options + callback.
75
+ */
76
+ eachCell(callback: (cell: CellLike, colNumber: number) => void): void;
77
+ eachCell(opts: {
78
+ includeEmpty?: boolean;
79
+ }, callback: (cell: CellLike, colNumber: number) => void): void;
80
+ }
81
+ export interface DimensionsLike {
82
+ readonly top: number;
83
+ readonly left: number;
84
+ readonly bottom: number;
85
+ readonly right: number;
86
+ }
87
+ export interface TableColumnLike {
88
+ readonly name: string;
89
+ }
90
+ export interface TableDefinitionLike {
91
+ readonly name?: string;
92
+ readonly displayName?: string;
93
+ readonly tl?: {
94
+ readonly row: number;
95
+ readonly col: number;
96
+ };
97
+ readonly columns?: readonly TableColumnLike[];
98
+ readonly rows?: readonly unknown[];
99
+ readonly headerRow?: boolean;
100
+ readonly totalsRow?: boolean;
101
+ }
102
+ export interface TableRefLike {
103
+ readonly table?: TableDefinitionLike;
104
+ }
105
+ export interface WorksheetLike {
106
+ readonly id: number;
107
+ readonly name: string;
108
+ readonly dimensions: DimensionsLike | null;
109
+ /**
110
+ * Excel's `eachRow` accepts either a bare callback or an options bag
111
+ * followed by a callback. Mirror both signatures so concrete
112
+ * `Worksheet` classes remain structurally assignable.
113
+ */
114
+ eachRow(callback: (row: RowLike, rowNumber: number) => void): void;
115
+ eachRow(opts: {
116
+ includeEmpty?: boolean;
117
+ }, callback: (row: RowLike, rowNumber: number) => void): void;
118
+ findCell(row: number, col: number): CellLike | undefined;
119
+ getCell(row: number, col: number): CellLike;
120
+ getTables?(): TableRefLike[];
121
+ }
122
+ /**
123
+ * A complete defined name entry with all details.
124
+ */
125
+ export interface DefinedNameEntry {
126
+ name: string;
127
+ ranges: string[];
128
+ localSheetId?: number;
129
+ formulaExpression?: string;
130
+ }
131
+ export interface DefinedNamesLike {
132
+ /**
133
+ * Return all defined name entries with full details.
134
+ * Each entry is self-contained — no second lookup needed.
135
+ * Same bare name may appear multiple times with different scopes.
136
+ */
137
+ getAllEntries(): DefinedNameEntry[];
138
+ /** Enumerate name+scope pairs (lightweight). */
139
+ getAllNames(): {
140
+ name: string;
141
+ localSheetId?: number;
142
+ }[];
143
+ }
144
+ export interface WorkbookLike {
145
+ worksheets: WorksheetLike[];
146
+ getWorksheet(id?: number | string): WorksheetLike | undefined;
147
+ definedNames?: DefinedNamesLike;
148
+ /** Calculation properties — used for iterative calculation settings. */
149
+ calcProperties?: {
150
+ fullCalcOnLoad?: boolean;
151
+ /** Enable iterative calculation for circular references. */
152
+ iterate?: boolean;
153
+ /** Maximum number of iterations (default 100). */
154
+ iterateCount?: number;
155
+ /** Maximum change threshold for convergence (default 0.001). */
156
+ iterateDelta?: number;
157
+ };
158
+ /** Workbook properties including date system. */
159
+ properties?: {
160
+ date1904?: boolean;
161
+ };
162
+ }
163
+ /**
164
+ * Tracks a spill region: the source formula cell and the range of cells it
165
+ * has spilled into. Used for cleanup when a formula is re-evaluated with
166
+ * different-sized results.
167
+ */
168
+ export interface SpillRegion {
169
+ /** The worksheet id — stable across renames */
170
+ readonly worksheetId: number;
171
+ /** The source formula cell's row */
172
+ readonly sourceRow: number;
173
+ /** The source formula cell's col */
174
+ readonly sourceCol: number;
175
+ /** Number of rows in the spill (including source) */
176
+ readonly rows: number;
177
+ /** Number of cols in the spill (including source) */
178
+ readonly cols: number;
179
+ }