@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,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
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Formula-syntax probe slot.
3
+ *
4
+ * ## What this is
5
+ *
6
+ * `DefinedNames` (in the excel module) needs a way to tell whether a raw
7
+ * defined-name text like `OFFSET(Sheet1!$A$1,0,0,3,1)` is a parseable
8
+ * formula or opaque content to preserve verbatim. The only authoritative
9
+ * answer comes from the formula tokenizer + parser, which ship in the
10
+ * `@cj-tech-master/excelts/formula` subpath and are an opt-in
11
+ * dependency.
12
+ *
13
+ * This file is a tiny passive registration slot — a single `let` with
14
+ * a getter/setter pair — carrying **no** formula-engine code. Importing
15
+ * `DefinedNames` pulls in this slot (~0.5 KB minified) but never drags
16
+ * in the tokenizer, parser, or evaluator.
17
+ *
18
+ * ## Classification semantics
19
+ *
20
+ * - **No probe installed** (default): `DefinedNames` classifies any
21
+ * non-range, non-wrapper text as **opaque**. The `rawText` is
22
+ * preserved so XLSX round-trip bytes are stable; the entry simply
23
+ * cannot be evaluated — which is correct, because no formula engine
24
+ * is available anyway.
25
+ *
26
+ * - **Probe installed** (after `installFormulaEngine()`): `DefinedNames`
27
+ * classifies strictly. Parseable text becomes `formula`, unparseable
28
+ * text becomes `opaque`.
29
+ *
30
+ * ## Why the slot lives in the formula module
31
+ *
32
+ * Module dependency direction: `excel` may import from `formula`
33
+ * (layer 4 → layer 3), but `formula` must not import from `excel`. The
34
+ * probe slot is a *formula-module concept* (it wraps a formula
35
+ * tokenizer+parser) that excel consults; keeping it here preserves the
36
+ * one-way dependency.
37
+ *
38
+ * ## Construction-time injection is also supported
39
+ *
40
+ * `Workbook` and `DefinedNames` each accept an explicit
41
+ * `formulaSyntaxProbe` option. That is the preferred API for callers
42
+ * who want deterministic, per-instance behaviour (e.g. a test that
43
+ * needs a specific probe without touching process-global state). The
44
+ * default-probe slot here is the convenience layer for
45
+ * `installFormulaEngine()` — call it once at startup and every
46
+ * subsequent `new Workbook()` picks up strict classification
47
+ * automatically.
48
+ *
49
+ * ## Lookup timing
50
+ *
51
+ * `DefinedNames` reads the default probe lazily, at the moment `model`
52
+ * is assigned (i.e. during XLSX parsing). This means the common
53
+ * sequence
54
+ *
55
+ * ```ts
56
+ * const wb = new Workbook();
57
+ * installFormulaEngine(); // later
58
+ * await wb.xlsx.load(buffer); // sees the installed probe
59
+ * ```
60
+ *
61
+ * works correctly — the probe installed before `load()` is the one
62
+ * used, regardless of when `Workbook` itself was constructed.
63
+ */
64
+ let defaultProbe = null;
65
+ /**
66
+ * Install (or clear) the process-wide default syntax probe.
67
+ *
68
+ * Called from `installFormulaEngine()` in `./install`. Passing `null`
69
+ * uninstalls the probe — symmetric with the formula-engine registry and
70
+ * useful for tests that exercise the "no probe" classification path.
71
+ */
72
+ export function setDefaultSyntaxProbe(probe) {
73
+ defaultProbe = probe;
74
+ }
75
+ /**
76
+ * Retrieve the currently-installed default probe, or `null` if none is
77
+ * installed. Consumers (chiefly `DefinedNames`) should treat `null` as
78
+ * a signal to use conservative (opaque) classification rather than
79
+ * guessing.
80
+ */
81
+ export function getDefaultSyntaxProbe() {
82
+ return defaultProbe;
83
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Date context shared between formula functions and the evaluator.
3
+ *
4
+ * Native function signatures (`NativeFn = (args: RuntimeValue[]) => RuntimeValue`)
5
+ * have no access to the evaluation context, so date/time functions cannot
6
+ * receive the workbook's `date1904` flag through a parameter. Rather than
7
+ * plumb a new argument through 200+ function signatures, we store the flag
8
+ * in a module-local variable. The evaluator sets it before evaluating any
9
+ * formula in a calculation session.
10
+ *
11
+ * ## Thread safety
12
+ *
13
+ * JavaScript runtimes are single-threaded and a single calculation session
14
+ * operates on exactly one workbook at a time, so a module-level variable is
15
+ * safe in practice. If the engine is ever extended to support concurrent
16
+ * calculations across different workbooks (e.g. via worker threads), each
17
+ * worker will have its own module instance and remain correctly isolated.
18
+ * Nested synchronous calls within the same session all share the same
19
+ * workbook, so the flag remains correct throughout.
20
+ */
21
+ let currentDate1904 = false;
22
+ /** Set the workbook-wide `date1904` mode for the current calculation session. */
23
+ export function setDate1904(v) {
24
+ currentDate1904 = v;
25
+ }
26
+ /** Read the workbook-wide `date1904` mode. */
27
+ export function isDate1904() {
28
+ return currentDate1904;
29
+ }