@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,62 @@
1
+ /**
2
+ * Formula Address Utilities — Shared helpers for address parsing and conversion.
3
+ *
4
+ * These pure functions are used across the compile, runtime, and materialize
5
+ * layers. Centralizing them here eliminates duplication and ensures consistent
6
+ * behavior.
7
+ *
8
+ * ## Design Constraint
9
+ *
10
+ * This module must NOT import from `@excel/utils/col-cache` or any live
11
+ * workbook type. All functions are self-contained.
12
+ */
13
+ /**
14
+ * Convert a column letter string (e.g. "A", "AA", "XFD") to a 1-based number.
15
+ *
16
+ * - `"A"` → 1
17
+ * - `"Z"` → 26
18
+ * - `"AA"` → 27
19
+ * - `"XFD"` → 16384
20
+ */
21
+ export declare function colLetterToNumber(col: string): number;
22
+ /**
23
+ * A parsed defined-name range reference.
24
+ */
25
+ export interface ParsedNameRange {
26
+ readonly sheet: string;
27
+ readonly startRow: number;
28
+ readonly startCol: number;
29
+ readonly endRow: number;
30
+ readonly endCol: number;
31
+ }
32
+ /**
33
+ * Parse a defined-name range string like `"Sheet1!$A$1:$B$2"` or `"'Sheet Name'!$C$3"`
34
+ * into a `ParsedNameRange`. Returns `null` if the format is unrecognized.
35
+ */
36
+ export declare function parseDefinedNameRange(rangeStr: string): ParsedNameRange | null;
37
+ /**
38
+ * A parsed simple cell address (no sheet name).
39
+ */
40
+ export interface ParsedAddress {
41
+ readonly row: number;
42
+ readonly col: number;
43
+ }
44
+ /**
45
+ * Parse a simple cell address like `"A1"`, `"$B$2"`, or `"AA100"`.
46
+ * Dollar signs are stripped. Returns `null` on parse failure.
47
+ */
48
+ export declare function parseSimpleAddress(addr: string): ParsedAddress | null;
49
+ /**
50
+ * A parsed rectangular range (no sheet name).
51
+ */
52
+ export interface ParsedRefRange {
53
+ readonly top: number;
54
+ readonly left: number;
55
+ readonly bottom: number;
56
+ readonly right: number;
57
+ }
58
+ /**
59
+ * Parse a cell range string like `"A1:B2"` into a `ParsedRefRange`.
60
+ * Returns `null` if the format is unrecognized.
61
+ */
62
+ export declare function parseRefRange(ref: string): ParsedRefRange | null;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Formula Address Utilities — Shared helpers for address parsing and conversion.
3
+ *
4
+ * These pure functions are used across the compile, runtime, and materialize
5
+ * layers. Centralizing them here eliminates duplication and ensures consistent
6
+ * behavior.
7
+ *
8
+ * ## Design Constraint
9
+ *
10
+ * This module must NOT import from `@excel/utils/col-cache` or any live
11
+ * workbook type. All functions are self-contained.
12
+ */
13
+ // ============================================================================
14
+ // Column Letter ↔ Number
15
+ // ============================================================================
16
+ /**
17
+ * Convert a column letter string (e.g. "A", "AA", "XFD") to a 1-based number.
18
+ *
19
+ * - `"A"` → 1
20
+ * - `"Z"` → 26
21
+ * - `"AA"` → 27
22
+ * - `"XFD"` → 16384
23
+ */
24
+ export function colLetterToNumber(col) {
25
+ let result = 0;
26
+ for (let i = 0; i < col.length; i++) {
27
+ result = result * 26 + (col.charCodeAt(i) - 64); // 'A' = 65
28
+ }
29
+ return result;
30
+ }
31
+ const DEFINED_NAME_RANGE_RE = /^(?:'([^']*(?:''[^']*)*)'|([^!]+))!\$([A-Z]+)\$(\d+)(?::\$([A-Z]+)\$(\d+))?$/;
32
+ /**
33
+ * Parse a defined-name range string like `"Sheet1!$A$1:$B$2"` or `"'Sheet Name'!$C$3"`
34
+ * into a `ParsedNameRange`. Returns `null` if the format is unrecognized.
35
+ */
36
+ export function parseDefinedNameRange(rangeStr) {
37
+ const m = DEFINED_NAME_RANGE_RE.exec(rangeStr);
38
+ if (!m) {
39
+ return null;
40
+ }
41
+ // Sheet name: quoted (group 1, with '' unescaping) or unquoted (group 2)
42
+ const sheet = m[1] !== undefined ? m[1].replace(/''/g, "'") : m[2];
43
+ const startCol = colLetterToNumber(m[3]);
44
+ const startRow = parseInt(m[4], 10);
45
+ const endCol = m[5] ? colLetterToNumber(m[5]) : startCol;
46
+ const endRow = m[6] ? parseInt(m[6], 10) : startRow;
47
+ return { sheet, startRow, startCol, endRow, endCol };
48
+ }
49
+ /**
50
+ * Parse a simple cell address like `"A1"`, `"$B$2"`, or `"AA100"`.
51
+ * Dollar signs are stripped. Returns `null` on parse failure.
52
+ */
53
+ export function parseSimpleAddress(addr) {
54
+ const m = /^([A-Z]+)(\d+)$/.exec(addr.replace(/\$/g, ""));
55
+ if (!m) {
56
+ return null;
57
+ }
58
+ return {
59
+ row: parseInt(m[2], 10),
60
+ col: colLetterToNumber(m[1])
61
+ };
62
+ }
63
+ /**
64
+ * Parse a cell range string like `"A1:B2"` into a `ParsedRefRange`.
65
+ * Returns `null` if the format is unrecognized.
66
+ */
67
+ export function parseRefRange(ref) {
68
+ const parts = ref.split(":");
69
+ if (parts.length !== 2) {
70
+ return null;
71
+ }
72
+ const tl = parseSimpleAddress(parts[0]);
73
+ const br = parseSimpleAddress(parts[1]);
74
+ if (!tl || !br) {
75
+ return null;
76
+ }
77
+ return {
78
+ top: Math.min(tl.row, br.row),
79
+ left: Math.min(tl.col, br.col),
80
+ bottom: Math.max(tl.row, br.row),
81
+ right: Math.max(tl.col, br.col)
82
+ };
83
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Binder — Transform raw AST into BoundExpr.
3
+ *
4
+ * The binder performs static symbol resolution:
5
+ * - Cell/range references → BoundCellRef / BoundAreaRef with resolved sheet
6
+ * - Defined names → BoundCellRef / BoundAreaRef (if resolvable) or BoundNameExpr
7
+ * - Structured references → BoundCellRef / BoundAreaRef
8
+ * - Function calls → BoundCall or BoundSpecialCall
9
+ * - 3D references → BoundRef3D
10
+ *
11
+ * The binder operates on snapshot data only — no live workbook objects.
12
+ */
13
+ import type { WorkbookSnapshot } from "../integration/workbook-snapshot.js";
14
+ import type { AstNode } from "../syntax/ast.js";
15
+ import type { BoundExpr } from "./bound-ast.js";
16
+ /**
17
+ * Static context for the binder. Contains all information needed to
18
+ * resolve symbols at compile time.
19
+ */
20
+ export interface BindingContext {
21
+ /** The workbook snapshot. */
22
+ readonly snapshot: WorkbookSnapshot;
23
+ /** The current sheet name (for relative references). */
24
+ readonly currentSheet: string;
25
+ /**
26
+ * Identifier names that are bound locally (uppercase). Populated by
27
+ * LAMBDA when descending into its body; prevents local parameter names
28
+ * from being shadowed by same-named workbook-level defined names at
29
+ * compile time. LET uses a different mechanism (it keeps the body
30
+ * bound as-is and resolves names at runtime via `localBindings`), but
31
+ * LAMBDA's body is pre-bound when the lambda is constructed so we have
32
+ * to inject scope info up front.
33
+ */
34
+ readonly localNames?: ReadonlySet<string>;
35
+ }
36
+ /**
37
+ * Bind a raw AST node to produce a BoundExpr.
38
+ *
39
+ * This is the main entry point for the compilation phase. It recursively
40
+ * walks the AST and resolves all symbols against the snapshot.
41
+ */
42
+ export declare function bind(node: AstNode, ctx: BindingContext): BoundExpr;
@@ -0,0 +1,487 @@
1
+ /**
2
+ * Binder — Transform raw AST into BoundExpr.
3
+ *
4
+ * The binder performs static symbol resolution:
5
+ * - Cell/range references → BoundCellRef / BoundAreaRef with resolved sheet
6
+ * - Defined names → BoundCellRef / BoundAreaRef (if resolvable) or BoundNameExpr
7
+ * - Structured references → BoundCellRef / BoundAreaRef
8
+ * - Function calls → BoundCall or BoundSpecialCall
9
+ * - 3D references → BoundRef3D
10
+ *
11
+ * The binder operates on snapshot data only — no live workbook objects.
12
+ */
13
+ import { resolveDefinedName as resolveDefinedNameFromSnapshot } from "../integration/workbook-snapshot.js";
14
+ import { NodeType } from "../syntax/ast.js";
15
+ import { stripFunctionPrefix } from "../syntax/token-types.js";
16
+ import { colLetterToNumber, parseDefinedNameRange } from "./address-utils.js";
17
+ import { BoundExprKind, boundAreaRef, boundCall, boundCellRef, boundErrorLiteral, boundLiteral, boundNameExpr, boundSpecialCall } from "./bound-ast.js";
18
+ import { resolveStructuredRefRows, buildTableGeometry, resolveStructuredRefColumns } from "./structured-ref-utils.js";
19
+ // ============================================================================
20
+ // Special Form Registry
21
+ // ============================================================================
22
+ const SPECIAL_FORMS = new Set([
23
+ "IF",
24
+ "IFERROR",
25
+ "IFNA",
26
+ "IFS",
27
+ "SWITCH",
28
+ "CHOOSE",
29
+ "LET",
30
+ "LAMBDA",
31
+ "INDIRECT",
32
+ "OFFSET",
33
+ "MAP",
34
+ "REDUCE",
35
+ "SCAN",
36
+ "MAKEARRAY",
37
+ "BYROW",
38
+ "BYCOL"
39
+ ]);
40
+ /**
41
+ * Map prefixed names to their canonical special form name.
42
+ */
43
+ function canonicalSpecialForm(name) {
44
+ const canonical = stripFunctionPrefix(name);
45
+ if (SPECIAL_FORMS.has(canonical)) {
46
+ return canonical;
47
+ }
48
+ return undefined;
49
+ }
50
+ // ============================================================================
51
+ // Main Bind Function
52
+ // ============================================================================
53
+ /**
54
+ * Bind a raw AST node to produce a BoundExpr.
55
+ *
56
+ * This is the main entry point for the compilation phase. It recursively
57
+ * walks the AST and resolves all symbols against the snapshot.
58
+ */
59
+ export function bind(node, ctx) {
60
+ switch (node.type) {
61
+ case NodeType.Number:
62
+ return boundLiteral(node.value);
63
+ case NodeType.String:
64
+ return boundLiteral(node.value);
65
+ case NodeType.Boolean:
66
+ return boundLiteral(node.value);
67
+ case NodeType.Error:
68
+ return boundErrorLiteral(node.value);
69
+ case NodeType.Missing:
70
+ return boundLiteral(null);
71
+ case NodeType.CellRef:
72
+ return bindCellRef(node, ctx);
73
+ case NodeType.RangeRef:
74
+ return bindRangeRef(node, ctx);
75
+ case NodeType.ColRangeRef:
76
+ return bindColRangeRef(node, ctx);
77
+ case NodeType.RowRangeRef:
78
+ return bindRowRangeRef(node, ctx);
79
+ case NodeType.BinaryOp:
80
+ return {
81
+ kind: BoundExprKind.BinaryOp,
82
+ op: node.op,
83
+ left: bind(node.left, ctx),
84
+ right: bind(node.right, ctx)
85
+ };
86
+ case NodeType.UnaryOp:
87
+ return {
88
+ kind: BoundExprKind.UnaryOp,
89
+ op: node.op,
90
+ operand: bind(node.operand, ctx)
91
+ };
92
+ case NodeType.Percent:
93
+ return {
94
+ kind: BoundExprKind.Percent,
95
+ operand: bind(node.operand, ctx)
96
+ };
97
+ case NodeType.FunctionCall:
98
+ return bindFunctionCall(node.name, node.args, ctx);
99
+ case NodeType.Array:
100
+ return {
101
+ kind: BoundExprKind.Array,
102
+ rows: node.rows.map(row => row.map(elem => bind(elem, ctx)))
103
+ };
104
+ case NodeType.Name:
105
+ return bindName(node.name, ctx);
106
+ case NodeType.StructuredRef:
107
+ return bindStructuredRef(node.tableName, node.columns, node.specials, ctx);
108
+ default:
109
+ return assertNever(node);
110
+ }
111
+ }
112
+ /**
113
+ * Exhaustiveness helper: triggers a compile-time error if `bind` misses a
114
+ * discriminated-union variant. At runtime, this path is unreachable.
115
+ */
116
+ function assertNever(x) {
117
+ throw new Error(`unexpected AST node: ${JSON.stringify(x)}`);
118
+ }
119
+ // ============================================================================
120
+ // Cell Reference Binding
121
+ // ============================================================================
122
+ function bindCellRef(node, ctx) {
123
+ const sheet = node.sheet ?? ctx.currentSheet;
124
+ const row = parseInt(node.row, 10);
125
+ const col = colLetterToNumber(node.col);
126
+ // Excel's cell coordinate range is 1..1048576 for rows, 1..16384 for
127
+ // columns. The tokenizer enforces these when recognising cell refs,
128
+ // but we re-check here because the same binder runs on defined-name
129
+ // range strings that bypass the tokenizer and could carry arbitrary
130
+ // large values.
131
+ if (row < 1 || row > 1048576 || col < 1 || col > 16384) {
132
+ return boundErrorLiteral("#REF!");
133
+ }
134
+ // 3D cell reference: Sheet1:Sheet3!A1
135
+ if (node.endSheet) {
136
+ const sheets = getSheetsInRange(ctx.snapshot, sheet, node.endSheet);
137
+ if (!sheets) {
138
+ return boundErrorLiteral("#REF!");
139
+ }
140
+ const inner = boundCellRef(sheets[0], row, col);
141
+ return {
142
+ kind: BoundExprKind.Ref3D,
143
+ sheets,
144
+ inner
145
+ };
146
+ }
147
+ // Validate sheet exists
148
+ if (!ctx.snapshot.worksheetsByName.has(sheet.toLowerCase())) {
149
+ return boundErrorLiteral("#REF!");
150
+ }
151
+ return boundCellRef(sheet, row, col);
152
+ }
153
+ function bindRangeRef(node, ctx) {
154
+ const sheet = node.sheet ?? ctx.currentSheet;
155
+ const startRow = parseInt(node.start.row, 10);
156
+ const startCol = colLetterToNumber(node.start.col);
157
+ const endRow = parseInt(node.end.row, 10);
158
+ const endCol = colLetterToNumber(node.end.col);
159
+ const top = Math.min(startRow, endRow);
160
+ const bottom = Math.max(startRow, endRow);
161
+ const left = Math.min(startCol, endCol);
162
+ const right = Math.max(startCol, endCol);
163
+ // 3D range reference: Sheet1:Sheet3!A1:B2
164
+ if (node.endSheet) {
165
+ const sheets = getSheetsInRange(ctx.snapshot, sheet, node.endSheet);
166
+ if (!sheets) {
167
+ return boundErrorLiteral("#REF!");
168
+ }
169
+ const inner = boundAreaRef(sheets[0], top, left, bottom, right);
170
+ return {
171
+ kind: BoundExprKind.Ref3D,
172
+ sheets,
173
+ inner
174
+ };
175
+ }
176
+ return boundAreaRef(sheet, top, left, bottom, right);
177
+ }
178
+ function bindColRangeRef(node, ctx) {
179
+ const sheet = node.sheet ?? ctx.currentSheet;
180
+ const startCol = colLetterToNumber(node.startCol);
181
+ const endCol = colLetterToNumber(node.endCol);
182
+ const leftCol = Math.min(startCol, endCol);
183
+ const rightCol = Math.max(startCol, endCol);
184
+ // Validate sheet exists
185
+ if (!ctx.snapshot.worksheetsByName.has(sheet.toLowerCase())) {
186
+ return boundErrorLiteral("#REF!");
187
+ }
188
+ // 3D col range: Sheet1:Sheet3!A:B
189
+ if (node.endSheet) {
190
+ const sheets = getSheetsInRange(ctx.snapshot, sheet, node.endSheet);
191
+ if (!sheets) {
192
+ return boundErrorLiteral("#REF!");
193
+ }
194
+ // Return Ref3D wrapping an area for the full column range
195
+ const inner = boundAreaRef(sheets[0], 1, leftCol, 1048576, rightCol);
196
+ return {
197
+ kind: BoundExprKind.Ref3D,
198
+ sheets,
199
+ inner
200
+ };
201
+ }
202
+ return {
203
+ kind: BoundExprKind.ColRangeRef,
204
+ sheet,
205
+ leftCol,
206
+ rightCol
207
+ };
208
+ }
209
+ function bindRowRangeRef(node, ctx) {
210
+ const sheet = node.sheet ?? ctx.currentSheet;
211
+ const topRow = Math.min(node.startRow, node.endRow);
212
+ const bottomRow = Math.max(node.startRow, node.endRow);
213
+ // Validate sheet exists
214
+ if (!ctx.snapshot.worksheetsByName.has(sheet.toLowerCase())) {
215
+ return boundErrorLiteral("#REF!");
216
+ }
217
+ // 3D row range: Sheet1:Sheet3!1:5
218
+ if (node.endSheet) {
219
+ const sheets = getSheetsInRange(ctx.snapshot, sheet, node.endSheet);
220
+ if (!sheets) {
221
+ return boundErrorLiteral("#REF!");
222
+ }
223
+ const inner = boundAreaRef(sheets[0], topRow, 1, bottomRow, 16384);
224
+ return {
225
+ kind: BoundExprKind.Ref3D,
226
+ sheets,
227
+ inner
228
+ };
229
+ }
230
+ return {
231
+ kind: BoundExprKind.RowRangeRef,
232
+ sheet,
233
+ topRow,
234
+ bottomRow
235
+ };
236
+ }
237
+ // ============================================================================
238
+ // Name Binding
239
+ // ============================================================================
240
+ function bindName(name, ctx) {
241
+ // A lambda parameter (or other compile-time local) shadows any
242
+ // workbook-level defined name. Without this short-circuit,
243
+ // `LAMBDA(x, x*2)(10)` would pick up a defined name called `x` that
244
+ // resolves to a cell reference, computing the cell's value × 2
245
+ // instead of the lambda argument × 2.
246
+ if (ctx.localNames && ctx.localNames.has(name.toUpperCase())) {
247
+ return boundNameExpr(name);
248
+ }
249
+ // Try to resolve as a defined name that maps to a cell/range.
250
+ // Respects scope precedence: sheet-local > workbook-global.
251
+ const dn = resolveDefinedNameFromSnapshot(ctx.snapshot.definedNames, name, ctx.currentSheet);
252
+ if (dn) {
253
+ return resolveDefinedName(dn, ctx);
254
+ }
255
+ // Unresolved — could be a LET-bound local variable, a formula-based name,
256
+ // or a truly unknown name. Return BoundNameExpr for runtime resolution.
257
+ return boundNameExpr(name);
258
+ }
259
+ function resolveDefinedName(dn, ctx) {
260
+ if (dn.ranges.length === 0) {
261
+ return boundErrorLiteral("#NAME?");
262
+ }
263
+ // Multi-area names are not supported
264
+ if (dn.ranges.length > 1) {
265
+ return boundErrorLiteral("#VALUE!");
266
+ }
267
+ const rangeStr = dn.ranges[0];
268
+ // Try to parse as a cell/range reference
269
+ const parsed = parseDefinedNameRange(rangeStr);
270
+ if (parsed) {
271
+ // Single cell
272
+ if (parsed.startRow === parsed.endRow && parsed.startCol === parsed.endCol) {
273
+ return boundCellRef(parsed.sheet, parsed.startRow, parsed.startCol);
274
+ }
275
+ // Range
276
+ return boundAreaRef(parsed.sheet, Math.min(parsed.startRow, parsed.endRow), Math.min(parsed.startCol, parsed.endCol), Math.max(parsed.startRow, parsed.endRow), Math.max(parsed.startCol, parsed.endCol));
277
+ }
278
+ // The range string is a formula expression (e.g. "LAMBDA(x,y,x+y)").
279
+ // This must be resolved at runtime since it may produce a lambda or
280
+ // depend on the evaluation context. Return a BoundNameExpr.
281
+ return boundNameExpr(dn.name);
282
+ }
283
+ // ============================================================================
284
+ // Structured Reference Binding
285
+ // ============================================================================
286
+ function bindStructuredRef(tableName, columns, specials, ctx) {
287
+ // If the table name is empty (implicit @) or specials include #This Row,
288
+ // we need runtime context (current cell position) to resolve.
289
+ // Defer to the evaluator.
290
+ const needsRuntime = tableName === "" || specials.includes("#This Row");
291
+ // Find the table in the snapshot
292
+ const table = findTable(ctx.snapshot, tableName);
293
+ if (!table) {
294
+ if (needsRuntime) {
295
+ // Defer to runtime — return BoundStructuredRef
296
+ return {
297
+ kind: BoundExprKind.StructuredRef,
298
+ tableName,
299
+ columns: [...columns],
300
+ specials: [...specials]
301
+ };
302
+ }
303
+ return boundErrorLiteral("#REF!");
304
+ }
305
+ // If #This Row is present, defer to runtime even if table is found
306
+ if (needsRuntime) {
307
+ return {
308
+ kind: BoundExprKind.StructuredRef,
309
+ tableName: table.table.name,
310
+ columns: [...columns],
311
+ specials: [...specials]
312
+ };
313
+ }
314
+ const resolved = resolveStructuredRefBounds(table, columns, specials);
315
+ if (!resolved) {
316
+ return boundErrorLiteral("#REF!");
317
+ }
318
+ if (resolved.top === resolved.bottom && resolved.left === resolved.right) {
319
+ return boundCellRef(resolved.sheet, resolved.top, resolved.left);
320
+ }
321
+ return boundAreaRef(resolved.sheet, resolved.top, resolved.left, resolved.bottom, resolved.right);
322
+ }
323
+ function findTable(snapshot, tableName) {
324
+ if (!tableName) {
325
+ return null;
326
+ }
327
+ // Use the pre-built tablesByName index for O(1) lookup
328
+ const resolved = snapshot.tablesByName.get(tableName.toLowerCase());
329
+ if (resolved) {
330
+ return { table: resolved.table, sheetName: resolved.sheetName };
331
+ }
332
+ return null;
333
+ }
334
+ function resolveStructuredRefBounds(tw, columns, specials) {
335
+ const t = tw.table;
336
+ const geo = buildTableGeometry(t);
337
+ const colRange = resolveStructuredRefColumns(columns, t, "strict");
338
+ if (colRange === "error") {
339
+ return null;
340
+ }
341
+ const rowRange = resolveStructuredRefRows(specials, geo);
342
+ let rowTop;
343
+ let rowBottom;
344
+ if (rowRange === "error") {
345
+ return null;
346
+ }
347
+ else if (rowRange === "thisRow") {
348
+ // #This Row requires runtime context — use data range as static fallback
349
+ rowTop = geo.dataRowStart;
350
+ rowBottom = geo.dataRowEnd;
351
+ }
352
+ else {
353
+ rowTop = rowRange.rowTop;
354
+ rowBottom = rowRange.rowBottom;
355
+ }
356
+ return {
357
+ sheet: tw.sheetName,
358
+ top: rowTop,
359
+ left: colRange.colLeft,
360
+ bottom: rowBottom,
361
+ right: colRange.colRight
362
+ };
363
+ }
364
+ // ============================================================================
365
+ // Function Call Binding
366
+ // ============================================================================
367
+ function bindFunctionCall(name, args, ctx) {
368
+ const upperName = name.toUpperCase();
369
+ // Check for special forms (lazy evaluation)
370
+ const specialName = canonicalSpecialForm(upperName);
371
+ if (specialName) {
372
+ // LAMBDA is special: bind it into a BoundLambda if possible
373
+ if (specialName === "LAMBDA" && args.length >= 1) {
374
+ return bindLambda(args, ctx);
375
+ }
376
+ // LET has the shape LET(name, value, name, value, …, body). The
377
+ // `name` slots must be treated as pure locals, not resolved against
378
+ // workbook defined names, or e.g. a defined-name `X` pointing at
379
+ // `$A$1` would hijack `LET(X, 5, X+1)` and route the final body to
380
+ // `A1+1` instead of `5+1`. We extend `localNames` to cover every
381
+ // name slot before recursively binding the rest.
382
+ if (specialName === "LET" && args.length >= 3) {
383
+ return bindLet(args, ctx);
384
+ }
385
+ // All other special forms: bind args recursively but wrap as BoundSpecialCall
386
+ const boundArgs = args.map(arg => bind(arg, ctx));
387
+ return boundSpecialCall(specialName, boundArgs);
388
+ }
389
+ // Reference functions that need AST-level access (ROW, COLUMN, ROWS, COLUMNS)
390
+ // are bound as regular calls — the evaluator handles the AST → BoundExpr
391
+ // mapping for these since they work the same way with BoundExpr.
392
+ // Standard eager function call
393
+ const boundArgs = args.map(arg => bind(arg, ctx));
394
+ return boundCall(upperName, boundArgs);
395
+ }
396
+ /**
397
+ * Bind `LET(name1, value1, …, nameN, valueN, body)` with lexical scoping.
398
+ *
399
+ * Even-indexed slots (0, 2, 4, …) are Name AST nodes that introduce new
400
+ * locals. We add each such name to `localNames` progressively — Excel
401
+ * allows later `value_i` expressions to reference earlier LET-bound
402
+ * variables, but NOT the variable being defined on the same slot. The
403
+ * `body` (last arg) sees every local.
404
+ */
405
+ function bindLet(args, ctx) {
406
+ // args = [name1, value1, name2, value2, …, body]; length must be odd.
407
+ if (args.length < 3 || args.length % 2 === 0) {
408
+ return boundErrorLiteral("#VALUE!");
409
+ }
410
+ const locals = ctx.localNames ? new Set(ctx.localNames) : new Set();
411
+ const boundArgs = [];
412
+ for (let i = 0; i + 1 < args.length; i += 2) {
413
+ const nameNode = args[i];
414
+ if (nameNode.type !== NodeType.Name) {
415
+ // Not a Name-shaped slot: preserve whatever the user wrote so the
416
+ // evaluator's own LET implementation can report the error with
417
+ // better context.
418
+ boundArgs.push(bind(nameNode, ctx));
419
+ }
420
+ else {
421
+ // Bind the name slot as a runtime-resolved NameExpr rather than
422
+ // letting `bindName` eagerly pick up a workbook-level defined name.
423
+ boundArgs.push(boundNameExpr(nameNode.name));
424
+ }
425
+ // Bind the value expression with locals-so-far in scope.
426
+ const valueCtx = { ...ctx, localNames: new Set(locals) };
427
+ boundArgs.push(bind(args[i + 1], valueCtx));
428
+ // The just-bound name is now available to subsequent value slots
429
+ // and to the body.
430
+ if (nameNode.type === NodeType.Name) {
431
+ locals.add(nameNode.name.toUpperCase());
432
+ }
433
+ }
434
+ const bodyCtx = { ...ctx, localNames: locals };
435
+ boundArgs.push(bind(args[args.length - 1], bodyCtx));
436
+ return boundSpecialCall("LET", boundArgs);
437
+ }
438
+ function bindLambda(args, ctx) {
439
+ if (args.length < 1) {
440
+ return boundErrorLiteral("#VALUE!");
441
+ }
442
+ const paramNodes = args.slice(0, -1);
443
+ const bodyNode = args[args.length - 1];
444
+ const params = [];
445
+ // Detect duplicate parameter names up front. Excel rejects
446
+ // `LAMBDA(x, x, x*2)` with #VALUE! rather than silently letting the
447
+ // second occurrence shadow the first.
448
+ const seen = new Set();
449
+ for (const pNode of paramNodes) {
450
+ if (pNode.type !== NodeType.Name) {
451
+ return boundErrorLiteral("#VALUE!");
452
+ }
453
+ const upper = pNode.name.toUpperCase();
454
+ if (seen.has(upper)) {
455
+ return boundErrorLiteral("#VALUE!");
456
+ }
457
+ seen.add(upper);
458
+ params.push(upper);
459
+ }
460
+ // Extend the local-name scope with the lambda's parameters so nested
461
+ // name lookups inside the body bind to runtime locals rather than
462
+ // same-named workbook defined names.
463
+ const mergedLocals = ctx.localNames ? new Set(ctx.localNames) : new Set();
464
+ for (const p of params) {
465
+ mergedLocals.add(p);
466
+ }
467
+ const bodyCtx = { ...ctx, localNames: mergedLocals };
468
+ return {
469
+ kind: BoundExprKind.Lambda,
470
+ params,
471
+ body: bind(bodyNode, bodyCtx)
472
+ };
473
+ }
474
+ // ============================================================================
475
+ // 3D Reference Helpers
476
+ // ============================================================================
477
+ function getSheetsInRange(snapshot, startSheet, endSheet) {
478
+ const allSheets = snapshot.worksheets;
479
+ const startIdx = allSheets.findIndex(s => s.name.toLowerCase() === startSheet.toLowerCase());
480
+ const endIdx = allSheets.findIndex(s => s.name.toLowerCase() === endSheet.toLowerCase());
481
+ if (startIdx === -1 || endIdx === -1) {
482
+ return null;
483
+ }
484
+ const lo = Math.min(startIdx, endIdx);
485
+ const hi = Math.max(startIdx, endIdx);
486
+ return allSheets.slice(lo, hi + 1).map(s => s.name);
487
+ }