@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,432 @@
1
+ /**
2
+ * Dependency Graph for Formula Calculation
3
+ *
4
+ * Builds a dependency graph from compiled formulas' static dependencies,
5
+ * then produces a topological evaluation order with circular reference
6
+ * detection.
7
+ *
8
+ * Key exports:
9
+ * - `buildDependencyGraphFromDeps()` — build graph from CompiledFormula static deps
10
+ * - `topologicalSort()` — produce evaluation order, detecting circular refs
11
+ */
12
+ // ============================================================================
13
+ // Cell Key Helpers
14
+ // ============================================================================
15
+ function makeKey(sheet, row, col) {
16
+ return `${sheet}!${row}:${col}`;
17
+ }
18
+ // ============================================================================
19
+ // Dependency Reference → Cell Key Expansion
20
+ // ============================================================================
21
+ /**
22
+ * Type guard: is this a range reference (has `top` property)?
23
+ */
24
+ function isRange(ref) {
25
+ return "top" in ref;
26
+ }
27
+ /**
28
+ * Expand a set of DepRefs into concrete cell keys.
29
+ * For single-cell refs, the key is produced directly.
30
+ * For range refs, we check which formula cells fall within the range rather
31
+ * than enumerating every cell (which would be prohibitively expensive for
32
+ * whole-column ranges like A:A).
33
+ */
34
+ function expandRefsToKeys(refs, formulaKeySet, formulaCellCoordsBySheet) {
35
+ const keys = new Set();
36
+ for (const ref of refs) {
37
+ if (isRange(ref)) {
38
+ const rangeSize = (ref.bottom - ref.top + 1) * (ref.right - ref.left + 1);
39
+ if (rangeSize <= 10000) {
40
+ // Small-to-medium range: enumerate every cell
41
+ for (let r = ref.top; r <= ref.bottom; r++) {
42
+ for (let c = ref.left; c <= ref.right; c++) {
43
+ keys.add(makeKey(ref.sheet, r, c));
44
+ }
45
+ }
46
+ }
47
+ else {
48
+ // Large range (e.g. whole column A:A): scan formula cells in the
49
+ // referenced sheet only and check containment.
50
+ const sheetCoords = formulaCellCoordsBySheet.get(ref.sheet);
51
+ if (sheetCoords) {
52
+ for (const [fKey, coord] of sheetCoords) {
53
+ if (coord.row >= ref.top &&
54
+ coord.row <= ref.bottom &&
55
+ coord.col >= ref.left &&
56
+ coord.col <= ref.right) {
57
+ keys.add(fKey);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ else {
64
+ // Single cell — always add
65
+ keys.add(makeKey(ref.sheet, ref.row, ref.col));
66
+ }
67
+ }
68
+ return keys;
69
+ }
70
+ // ============================================================================
71
+ // Build Dependency Graph from CompiledFormula StaticDeps
72
+ // ============================================================================
73
+ /**
74
+ * Build a dependency graph from compiled formulas' static dependencies.
75
+ *
76
+ * Operates on the already-resolved `StaticDependencySet` from each compiled
77
+ * formula. Since names and structured references are already resolved by
78
+ * the binder, the dependency edges are complete.
79
+ *
80
+ * @param compiled - Map from formula cell key to compiled formula with static deps
81
+ * @param producerMap - Optional map from cell key → formula key that produces
82
+ * that cell's value (via CSE distribution or dynamic-array spill). Allows
83
+ * dependency edges to be added to the producer even when the target cell
84
+ * isn't itself a formula.
85
+ * @returns The complete dependency graph
86
+ */
87
+ export function buildDependencyGraphFromDeps(compiled, producerMap) {
88
+ // Build a lookup of all formula cell coordinates for range intersection.
89
+ // We group by sheet so that large-range containment scans only visit the
90
+ // relevant sheet's formula cells instead of the entire workbook.
91
+ const formulaKeySet = new Set();
92
+ const formulaCellCoordsBySheet = new Map();
93
+ const formulaKeys = [];
94
+ for (const [key, cf] of compiled) {
95
+ formulaKeySet.add(key);
96
+ // Use the instance's already-known coordinates instead of reverse-parsing
97
+ // the key string — saves two lastIndexOf calls and two parseInt calls
98
+ // per formula on cold-start.
99
+ const inst = cf.instance;
100
+ const coord = { sheet: inst.sheetName, row: inst.row, col: inst.col };
101
+ let list = formulaCellCoordsBySheet.get(inst.sheetName);
102
+ if (!list) {
103
+ list = [];
104
+ formulaCellCoordsBySheet.set(inst.sheetName, list);
105
+ }
106
+ list.push([key, coord]);
107
+ formulaKeys.push(key);
108
+ }
109
+ // Forward edges: formula key → set of keys it depends on
110
+ const dependsOn = new Map();
111
+ // Reverse edges: cell key → set of formula keys that depend on it
112
+ const dependedBy = new Map();
113
+ for (const [key, cf] of compiled) {
114
+ const deps = cf.staticDeps;
115
+ // Convert StaticDependencySet to DepRef[]
116
+ const refs = [];
117
+ // Direct cell deps always pass through verbatim.
118
+ for (const cell of deps.cells) {
119
+ refs.push({ sheet: cell.sheet, row: cell.row, col: cell.col });
120
+ }
121
+ // Area deps normally expand into every cell in the range. For areas
122
+ // that start at a dynamic-array master (e.g. the `A1:A5` in
123
+ // `SUM(A1:A5)` where A1 is a live `=SEQUENCE(5)`), we replace the
124
+ // expansion with a single dependency on the master. Evaluator-time
125
+ // `getCellValue` then reads the master's cached array result for
126
+ // the ghost positions, so downstream formulas see the full spill
127
+ // in the same calc pass. Without this, A2..A5 aren't yet in the
128
+ // snapshot on the first run and the SUM only picks up A1.
129
+ const dynMasterDeps = [];
130
+ for (const area of deps.areas) {
131
+ const topLeftKey = makeKey(area.sheet, area.top, area.left);
132
+ const masterCf = compiled.get(topLeftKey);
133
+ const isDynMaster = masterCf !== undefined &&
134
+ (masterCf.instance.isDynamicArray || masterCf.isDynamicArrayFunction);
135
+ if (isDynMaster) {
136
+ dynMasterDeps.push(topLeftKey);
137
+ continue;
138
+ }
139
+ refs.push({
140
+ sheet: area.sheet,
141
+ top: area.top,
142
+ left: area.left,
143
+ bottom: area.bottom,
144
+ right: area.right
145
+ });
146
+ }
147
+ // Expand to concrete cell keys
148
+ const depKeys = expandRefsToKeys(refs, formulaKeySet, formulaCellCoordsBySheet);
149
+ for (const mk of dynMasterDeps) {
150
+ depKeys.add(mk);
151
+ }
152
+ // Remap producer keys: if a dep points to a cell that's not a formula
153
+ // but IS produced by another formula (CSE target or spill target),
154
+ // depend on the producer instead.
155
+ if (producerMap && producerMap.size > 0) {
156
+ const remapped = new Set();
157
+ for (const depKey of depKeys) {
158
+ if (!formulaKeySet.has(depKey)) {
159
+ const producer = producerMap.get(depKey);
160
+ if (producer) {
161
+ remapped.add(producer);
162
+ continue;
163
+ }
164
+ }
165
+ remapped.add(depKey);
166
+ }
167
+ dependsOn.set(key, remapped);
168
+ for (const depKey of remapped) {
169
+ let set = dependedBy.get(depKey);
170
+ if (!set) {
171
+ set = new Set();
172
+ dependedBy.set(depKey, set);
173
+ }
174
+ set.add(key);
175
+ }
176
+ continue;
177
+ }
178
+ dependsOn.set(key, depKeys);
179
+ // Build reverse index
180
+ for (const depKey of depKeys) {
181
+ let set = dependedBy.get(depKey);
182
+ if (!set) {
183
+ set = new Set();
184
+ dependedBy.set(depKey, set);
185
+ }
186
+ set.add(key);
187
+ }
188
+ }
189
+ // Detect circular references
190
+ const { circularKeys } = detectCircularRefs(formulaKeys, dependsOn);
191
+ return {
192
+ dependsOn,
193
+ dependedBy,
194
+ formulaKeys,
195
+ circularKeys
196
+ };
197
+ }
198
+ // ============================================================================
199
+ // Merge Runtime Dynamic Dependencies
200
+ // ============================================================================
201
+ /**
202
+ * Merge runtime-discovered dynamic dependencies into a dependency graph.
203
+ *
204
+ * After evaluating formulas that contain INDIRECT/OFFSET, the runtime
205
+ * dependency recorder has collected the actual cell accesses. This function
206
+ * incorporates those dynamic edges into the graph and re-detects cycles.
207
+ *
208
+ * Returns a new graph if edges were added, or the original graph if no
209
+ * dynamic deps were recorded.
210
+ */
211
+ export function mergeDynamicDeps(graph, dynamicDeps) {
212
+ if (dynamicDeps.size === 0) {
213
+ return { graph, changed: false };
214
+ }
215
+ // First pass: detect whether any new edges would actually be added.
216
+ // Cloning the full dependsOn/dependedBy maps is expensive for large
217
+ // workbooks; skip it entirely when there's no real work to do.
218
+ let needsClone = false;
219
+ for (const [formulaKey, accessedKeys] of dynamicDeps) {
220
+ const existing = graph.dependsOn.get(formulaKey);
221
+ for (const k of accessedKeys) {
222
+ if (!existing || !existing.has(k)) {
223
+ needsClone = true;
224
+ break;
225
+ }
226
+ }
227
+ if (needsClone) {
228
+ break;
229
+ }
230
+ }
231
+ if (!needsClone) {
232
+ return { graph, changed: false };
233
+ }
234
+ // Clone forward and reverse edges
235
+ const newDependsOn = new Map();
236
+ for (const [k, v] of graph.dependsOn) {
237
+ newDependsOn.set(k, new Set(v));
238
+ }
239
+ const newDependedBy = new Map();
240
+ for (const [k, v] of graph.dependedBy) {
241
+ newDependedBy.set(k, new Set(v));
242
+ }
243
+ // Add dynamic edges
244
+ for (const [formulaKey, accessedKeys] of dynamicDeps) {
245
+ let deps = newDependsOn.get(formulaKey);
246
+ if (!deps) {
247
+ deps = new Set();
248
+ newDependsOn.set(formulaKey, deps);
249
+ }
250
+ for (const accessedKey of accessedKeys) {
251
+ if (!deps.has(accessedKey)) {
252
+ deps.add(accessedKey);
253
+ // Update reverse edge
254
+ let rev = newDependedBy.get(accessedKey);
255
+ if (!rev) {
256
+ rev = new Set();
257
+ newDependedBy.set(accessedKey, rev);
258
+ }
259
+ rev.add(formulaKey);
260
+ }
261
+ }
262
+ }
263
+ // Re-detect cycles with the augmented graph
264
+ const { circularKeys } = detectCircularRefs(graph.formulaKeys, newDependsOn);
265
+ return {
266
+ graph: {
267
+ dependsOn: newDependsOn,
268
+ dependedBy: newDependedBy,
269
+ formulaKeys: graph.formulaKeys,
270
+ circularKeys
271
+ },
272
+ changed: true
273
+ };
274
+ }
275
+ // ============================================================================
276
+ // Circular Reference Detection
277
+ // ============================================================================
278
+ /**
279
+ * Detect circular references using Tarjan's SCC algorithm.
280
+ *
281
+ * A formula is "circular" if it belongs to a strongly connected component
282
+ * of size > 1, or if it has a direct self-loop (A = f(A)).
283
+ *
284
+ * This correctly identifies ALL nodes in cycles, including nodes reachable
285
+ * only through cross-edges to already-visited SCC members — a case that
286
+ * a simple 3-color DFS misses (e.g. diamond cycles like A→B→C→A plus A→D→C).
287
+ */
288
+ function detectCircularRefs(formulaKeys, dependsOn) {
289
+ const circularKeys = new Set();
290
+ // Tarjan's iterative SCC
291
+ const index = new Map();
292
+ const lowlink = new Map();
293
+ const onStack = new Set();
294
+ const sccStack = [];
295
+ let nextIndex = 0;
296
+ for (const startKey of formulaKeys) {
297
+ if (index.has(startKey)) {
298
+ continue;
299
+ }
300
+ const dfsStack = [];
301
+ index.set(startKey, nextIndex);
302
+ lowlink.set(startKey, nextIndex);
303
+ nextIndex++;
304
+ sccStack.push(startKey);
305
+ onStack.add(startKey);
306
+ dfsStack.push({
307
+ key: startKey,
308
+ iter: (dependsOn.get(startKey) ?? new Set())[Symbol.iterator](),
309
+ pendingChild: null
310
+ });
311
+ while (dfsStack.length > 0) {
312
+ const frame = dfsStack[dfsStack.length - 1];
313
+ // If we just returned from a child, update our lowlink
314
+ if (frame.pendingChild !== null) {
315
+ const childLow = lowlink.get(frame.pendingChild);
316
+ lowlink.set(frame.key, Math.min(lowlink.get(frame.key), childLow));
317
+ frame.pendingChild = null;
318
+ }
319
+ const next = frame.iter.next();
320
+ if (next.done) {
321
+ // Finished processing all children — check if this is an SCC root
322
+ if (lowlink.get(frame.key) === index.get(frame.key)) {
323
+ const scc = [];
324
+ let node;
325
+ do {
326
+ node = sccStack.pop();
327
+ onStack.delete(node);
328
+ scc.push(node);
329
+ } while (node !== frame.key);
330
+ // Mark as circular if SCC has > 1 node, OR if it's a self-loop
331
+ const hasSelfLoop = scc.length === 1 && dependsOn.get(scc[0])?.has(scc[0]);
332
+ if (scc.length > 1 || hasSelfLoop) {
333
+ for (const k of scc) {
334
+ circularKeys.add(k);
335
+ }
336
+ }
337
+ }
338
+ dfsStack.pop();
339
+ // Record returning to parent so it can update its lowlink
340
+ if (dfsStack.length > 0) {
341
+ dfsStack[dfsStack.length - 1].pendingChild = frame.key;
342
+ }
343
+ continue;
344
+ }
345
+ const depKey = next.value;
346
+ if (!index.has(depKey)) {
347
+ // Unvisited — push new frame
348
+ index.set(depKey, nextIndex);
349
+ lowlink.set(depKey, nextIndex);
350
+ nextIndex++;
351
+ sccStack.push(depKey);
352
+ onStack.add(depKey);
353
+ dfsStack.push({
354
+ key: depKey,
355
+ iter: (dependsOn.get(depKey) ?? new Set())[Symbol.iterator](),
356
+ pendingChild: null
357
+ });
358
+ }
359
+ else if (onStack.has(depKey)) {
360
+ // Back edge — update lowlink with dep's index
361
+ lowlink.set(frame.key, Math.min(lowlink.get(frame.key), index.get(depKey)));
362
+ }
363
+ // Cross edge to fully-processed SCC: skip (correct Tarjan behavior)
364
+ }
365
+ }
366
+ return { circularKeys };
367
+ }
368
+ // ============================================================================
369
+ // Topological Sort (Kahn's Algorithm)
370
+ // ============================================================================
371
+ /**
372
+ * Produce a topological evaluation order for formula cells using Kahn's algorithm.
373
+ * Cells with no dependencies are evaluated first. Circular references are
374
+ * appended at the end in their original order.
375
+ */
376
+ export function topologicalSort(graph) {
377
+ const { formulaKeys, dependsOn, circularKeys } = graph;
378
+ const formulaKeySet = new Set(formulaKeys);
379
+ const inDegree = new Map();
380
+ for (const key of formulaKeys) {
381
+ if (circularKeys.has(key)) {
382
+ continue;
383
+ }
384
+ const deps = dependsOn.get(key);
385
+ if (!deps) {
386
+ inDegree.set(key, 0);
387
+ continue;
388
+ }
389
+ let count = 0;
390
+ for (const depKey of deps) {
391
+ if (formulaKeySet.has(depKey) && !circularKeys.has(depKey)) {
392
+ count++;
393
+ }
394
+ }
395
+ inDegree.set(key, count);
396
+ }
397
+ const queue = [];
398
+ for (const key of formulaKeys) {
399
+ if (circularKeys.has(key)) {
400
+ continue;
401
+ }
402
+ if ((inDegree.get(key) ?? 0) === 0) {
403
+ queue.push(key);
404
+ }
405
+ }
406
+ const sorted = [];
407
+ let head = 0;
408
+ while (head < queue.length) {
409
+ const key = queue[head++];
410
+ sorted.push(key);
411
+ const dependents = graph.dependedBy.get(key);
412
+ if (dependents) {
413
+ for (const depKey of dependents) {
414
+ if (circularKeys.has(depKey) || !formulaKeySet.has(depKey)) {
415
+ continue;
416
+ }
417
+ const deg = (inDegree.get(depKey) ?? 1) - 1;
418
+ inDegree.set(depKey, deg);
419
+ if (deg === 0) {
420
+ queue.push(depKey);
421
+ }
422
+ }
423
+ }
424
+ }
425
+ // Append circular reference cells at the end in original order
426
+ for (const key of formulaKeys) {
427
+ if (circularKeys.has(key)) {
428
+ sorted.push(key);
429
+ }
430
+ }
431
+ return sorted;
432
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Shared utilities for structured reference (table) row-range resolution.
3
+ *
4
+ * The row-range logic for structured references is needed in three places:
5
+ * - binder (compile-time range resolution)
6
+ * - compiled-formula (static dependency extraction)
7
+ * - evaluator (runtime evaluation)
8
+ *
9
+ * This module provides the canonical implementation to avoid triplication.
10
+ */
11
+ /**
12
+ * Minimum subset of table snapshot fields required to derive geometry
13
+ * and resolve structured-reference columns.
14
+ *
15
+ * Declared structurally (not as a nominal import of `TableSnapshot`) so
16
+ * this module stays dependency-free and can serve both compile- and
17
+ * runtime-side callers that carry their own table-shape types.
18
+ */
19
+ export interface TableLike {
20
+ readonly topLeft: {
21
+ readonly row: number;
22
+ readonly col: number;
23
+ };
24
+ readonly dataRowCount: number;
25
+ readonly hasHeaderRow: boolean;
26
+ readonly hasTotalsRow: boolean;
27
+ readonly columns: readonly {
28
+ readonly name: string;
29
+ }[];
30
+ }
31
+ /**
32
+ * Table geometry needed for structured ref resolution.
33
+ */
34
+ export interface TableGeometry {
35
+ /** Top-left row of the table (including header if present). */
36
+ readonly topLeftRow: number;
37
+ /** First row of the data body. */
38
+ readonly dataRowStart: number;
39
+ /** Last row of the data body. */
40
+ readonly dataRowEnd: number;
41
+ /** Whether the table has a header row. */
42
+ readonly hasHeaderRow: boolean;
43
+ /** Whether the table has a totals row. */
44
+ readonly hasTotalsRow: boolean;
45
+ }
46
+ /**
47
+ * Derive `TableGeometry` from a table's snapshot fields.
48
+ *
49
+ * The data row range excludes the header (if any) but also excludes the
50
+ * totals row — totals, when present, occupy `dataRowEnd + 1`.
51
+ */
52
+ export declare function buildTableGeometry(table: TableLike): TableGeometry;
53
+ /**
54
+ * Resolve a list of structured-reference column names to a contiguous
55
+ * column range `[colLeft, colRight]` in absolute sheet coordinates.
56
+ *
57
+ * @param columns - Requested column names (case-insensitive match).
58
+ * @param table - Table whose columns are searched.
59
+ * @param mode -
60
+ * - `"strict"` — return `"error"` if any name is missing (used by
61
+ * binder and evaluator — unknown columns are `#REF!` errors).
62
+ * - `"permissive"` — ignore missing names; if ALL names are missing,
63
+ * falls back to the full table width (used by static-deps extraction,
64
+ * where a conservative over-estimate is acceptable).
65
+ * @returns `{ colLeft, colRight }`, or `"error"` in strict mode when a
66
+ * column name is not found. If `columns` is empty, returns the full
67
+ * table width.
68
+ */
69
+ export declare function resolveStructuredRefColumns(columns: readonly string[], table: TableLike, mode: "strict" | "permissive"): {
70
+ colLeft: number;
71
+ colRight: number;
72
+ } | "error";
73
+ /**
74
+ * Result of resolving structured reference specials to a row range.
75
+ *
76
+ * - `{rowTop, rowBottom}` — resolved range
77
+ * - `"thisRow"` — the `#This Row` special was used; caller must resolve
78
+ * using the current cell address
79
+ * - `"error"` — invalid special combination (e.g., #Totals on a table
80
+ * without a totals row)
81
+ */
82
+ export type StructuredRefRowRange = {
83
+ rowTop: number;
84
+ rowBottom: number;
85
+ } | "thisRow" | "error";
86
+ /**
87
+ * Resolve structured reference specials to a row range.
88
+ *
89
+ * This is the single source of truth for the mapping from
90
+ * `#All`, `#Headers`, `#Data`, `#Totals`, `#This Row` (and their
91
+ * combinations) to concrete row numbers.
92
+ */
93
+ export declare function resolveStructuredRefRows(specials: readonly string[], geo: TableGeometry): StructuredRefRowRange;
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Shared utilities for structured reference (table) row-range resolution.
3
+ *
4
+ * The row-range logic for structured references is needed in three places:
5
+ * - binder (compile-time range resolution)
6
+ * - compiled-formula (static dependency extraction)
7
+ * - evaluator (runtime evaluation)
8
+ *
9
+ * This module provides the canonical implementation to avoid triplication.
10
+ */
11
+ /**
12
+ * Derive `TableGeometry` from a table's snapshot fields.
13
+ *
14
+ * The data row range excludes the header (if any) but also excludes the
15
+ * totals row — totals, when present, occupy `dataRowEnd + 1`.
16
+ */
17
+ export function buildTableGeometry(table) {
18
+ const topLeftRow = table.topLeft.row;
19
+ const dataRowStart = topLeftRow + (table.hasHeaderRow ? 1 : 0);
20
+ const dataRowEnd = dataRowStart + table.dataRowCount - 1;
21
+ return {
22
+ topLeftRow,
23
+ dataRowStart,
24
+ dataRowEnd,
25
+ hasHeaderRow: table.hasHeaderRow,
26
+ hasTotalsRow: table.hasTotalsRow
27
+ };
28
+ }
29
+ /**
30
+ * Resolve a list of structured-reference column names to a contiguous
31
+ * column range `[colLeft, colRight]` in absolute sheet coordinates.
32
+ *
33
+ * @param columns - Requested column names (case-insensitive match).
34
+ * @param table - Table whose columns are searched.
35
+ * @param mode -
36
+ * - `"strict"` — return `"error"` if any name is missing (used by
37
+ * binder and evaluator — unknown columns are `#REF!` errors).
38
+ * - `"permissive"` — ignore missing names; if ALL names are missing,
39
+ * falls back to the full table width (used by static-deps extraction,
40
+ * where a conservative over-estimate is acceptable).
41
+ * @returns `{ colLeft, colRight }`, or `"error"` in strict mode when a
42
+ * column name is not found. If `columns` is empty, returns the full
43
+ * table width.
44
+ */
45
+ export function resolveStructuredRefColumns(columns, table, mode) {
46
+ const tl = table.topLeft;
47
+ const width = table.columns.length;
48
+ if (columns.length === 0) {
49
+ return { colLeft: tl.col, colRight: tl.col + width - 1 };
50
+ }
51
+ const indices = [];
52
+ for (const colName of columns) {
53
+ const idx = table.columns.findIndex(c => c.name.toLowerCase() === colName.toLowerCase());
54
+ if (idx === -1) {
55
+ if (mode === "strict") {
56
+ return "error";
57
+ }
58
+ continue;
59
+ }
60
+ indices.push(idx);
61
+ }
62
+ if (indices.length === 0) {
63
+ // permissive + all names missing → conservative full-width fallback
64
+ return { colLeft: tl.col, colRight: tl.col + width - 1 };
65
+ }
66
+ return {
67
+ colLeft: tl.col + Math.min(...indices),
68
+ colRight: tl.col + Math.max(...indices)
69
+ };
70
+ }
71
+ /**
72
+ * Resolve structured reference specials to a row range.
73
+ *
74
+ * This is the single source of truth for the mapping from
75
+ * `#All`, `#Headers`, `#Data`, `#Totals`, `#This Row` (and their
76
+ * combinations) to concrete row numbers.
77
+ */
78
+ export function resolveStructuredRefRows(specials, geo) {
79
+ // Tokenizer stashes unknown `[#Something]` tokens with a sentinel
80
+ // prefix. Surface them as errors rather than let them alias to the
81
+ // default-data-range path below.
82
+ for (const s of specials) {
83
+ if (s.startsWith("#__INVALID__")) {
84
+ return "error";
85
+ }
86
+ }
87
+ const hasAll = specials.includes("#All");
88
+ const hasHeaders = specials.includes("#Headers");
89
+ const hasTotals = specials.includes("#Totals");
90
+ const hasData = specials.includes("#Data");
91
+ const hasThisRow = specials.includes("#This Row");
92
+ if (hasAll) {
93
+ return {
94
+ rowTop: geo.topLeftRow,
95
+ rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
96
+ };
97
+ }
98
+ if (hasThisRow) {
99
+ return "thisRow";
100
+ }
101
+ if (hasHeaders && hasTotals) {
102
+ return {
103
+ rowTop: geo.topLeftRow,
104
+ rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
105
+ };
106
+ }
107
+ if (hasHeaders && hasData) {
108
+ return {
109
+ rowTop: geo.hasHeaderRow ? geo.topLeftRow : geo.dataRowStart,
110
+ rowBottom: geo.dataRowEnd
111
+ };
112
+ }
113
+ if (hasData && hasTotals) {
114
+ return {
115
+ rowTop: geo.dataRowStart,
116
+ rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
117
+ };
118
+ }
119
+ if (hasHeaders) {
120
+ if (geo.hasHeaderRow) {
121
+ return { rowTop: geo.topLeftRow, rowBottom: geo.topLeftRow };
122
+ }
123
+ // Table without a header row: Excel reports #REF! rather than silently
124
+ // aliasing to the first data row. Returning the data row here would
125
+ // route `Table1[#Headers]` to real data values, masking user mistakes.
126
+ return "error";
127
+ }
128
+ if (hasTotals) {
129
+ if (geo.hasTotalsRow) {
130
+ return { rowTop: geo.dataRowEnd + 1, rowBottom: geo.dataRowEnd + 1 };
131
+ }
132
+ return "error";
133
+ }
134
+ // #Data or no specials → data range
135
+ return { rowTop: geo.dataRowStart, rowBottom: geo.dataRowEnd };
136
+ }