@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
@@ -1,10 +1,226 @@
1
1
  import { Range } from "./range.js";
2
2
  import { CellMatrix } from "./utils/cell-matrix.js";
3
3
  import { colCache } from "./utils/col-cache.js";
4
+ import { getDefaultSyntaxProbe } from "../formula/default-syntax-probe.js";
4
5
  const rangeRegexp = /[$](\w+)[$](\d+)(:[$](\w+)[$](\d+))?/;
6
+ // ============================================================================
7
+ // Range validation helpers (moved from defined-name-xform.ts)
8
+ // ============================================================================
9
+ // Regex to validate cell range format:
10
+ // - Cell: $A$1 or A1
11
+ // - Range: $A$1:$B$10 or A1:B10
12
+ // - Row range: $1:$2 (for print titles)
13
+ // - Column range: $A:$B (for print titles)
14
+ const cellRangeRegexp = /^[$]?[A-Za-z]{1,3}[$]?\d+(:[$]?[A-Za-z]{1,3}[$]?\d+)?$/;
15
+ const rowRangeRegexp = /^[$]?\d+:[$]?\d+$/;
16
+ const colRangeRegexp = /^[$]?[A-Za-z]{1,3}:[$]?[A-Za-z]{1,3}$/;
17
+ function isValidRange(range) {
18
+ // Skip array constants wrapped in {} - these are not valid cell ranges
19
+ if (range.startsWith("{") || range.endsWith("}")) {
20
+ return false;
21
+ }
22
+ // Extract the cell reference part (after the sheet name if present)
23
+ const cellRef = range.split("!").pop() ?? "";
24
+ // Must match one of the valid patterns
25
+ if (!cellRangeRegexp.test(cellRef) &&
26
+ !rowRangeRegexp.test(cellRef) &&
27
+ !colRangeRegexp.test(cellRef)) {
28
+ return false;
29
+ }
30
+ try {
31
+ const decoded = colCache.decodeEx(range);
32
+ if (("row" in decoded && typeof decoded.row === "number") ||
33
+ ("top" in decoded && typeof decoded.top === "number") ||
34
+ ("left" in decoded && typeof decoded.left === "number")) {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ /**
44
+ * Extract valid cell/range references from a raw defined name text string.
45
+ * Handles comma-separated ranges and quoted sheet names that may contain commas.
46
+ */
47
+ function extractRanges(parsedText) {
48
+ const trimmed = parsedText.trim();
49
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
50
+ return [];
51
+ }
52
+ const ranges = [];
53
+ let quotesOpened = false;
54
+ let last = "";
55
+ parsedText.split(",").forEach(item => {
56
+ if (!item) {
57
+ return;
58
+ }
59
+ const quotes = (item.match(/'/g) ?? []).length;
60
+ if (!quotes) {
61
+ if (quotesOpened) {
62
+ last += `${item},`;
63
+ }
64
+ else if (isValidRange(item)) {
65
+ ranges.push(item);
66
+ }
67
+ return;
68
+ }
69
+ const quotesEven = quotes % 2 === 0;
70
+ if (!quotesOpened && quotesEven && isValidRange(item)) {
71
+ ranges.push(item);
72
+ }
73
+ else if (quotesOpened && !quotesEven) {
74
+ quotesOpened = false;
75
+ if (isValidRange(last + item)) {
76
+ ranges.push(last + item);
77
+ }
78
+ last = "";
79
+ }
80
+ else {
81
+ quotesOpened = true;
82
+ last += `${item},`;
83
+ }
84
+ });
85
+ return ranges;
86
+ }
87
+ // ============================================================================
88
+ // Classifier — Stage 2 of the two-phase defined name design
89
+ // ============================================================================
90
+ /**
91
+ * Check whether a string contains a '(' character outside of single-quoted
92
+ * sheet name segments. Sheet names in cell references use single quotes:
93
+ * e.g. `'Sheet (1)'!$A$1` — the '(' is inside quotes and does NOT indicate
94
+ * a function call. A genuine formula like `OFFSET(Sheet1!$A$1,0,0,3,1)`
95
+ * has '(' outside of any quotes.
96
+ */
97
+ function hasUnquotedParen(s) {
98
+ let inQuote = false;
99
+ for (let i = 0; i < s.length; i++) {
100
+ const ch = s[i];
101
+ if (ch === "'") {
102
+ inQuote = !inQuote;
103
+ }
104
+ else if (ch === "(" && !inQuote) {
105
+ return true;
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+ /**
111
+ * Classify a raw defined name text into one of three categories:
112
+ * 1. **reference** — pure cell/range union (goes into matrixMap)
113
+ * 2. **formula** — parseable expression (goes into formulaMap)
114
+ * 3. **opaque** — unrecognised content preserved for round-trip
115
+ *
116
+ * Classification order matters:
117
+ * - If the text contains an unquoted `(`, it is likely a formula — try the
118
+ * formula parser first (this prevents `extractRanges` from misinterpreting
119
+ * function arguments as partial range references).
120
+ * - Otherwise try to extract ranges (pure cell references).
121
+ * - If neither works, fall back to opaque.
122
+ *
123
+ * **Probe semantics:** `probe` is the formula tokenizer+parser oracle. It
124
+ * is the *only* authority for deciding whether a non-range, non-wrapper
125
+ * string is a formula. When `probe` is `null` (no formula engine
126
+ * installed and no probe injected), any such string is classified as
127
+ * **opaque** — we have no evidence it is a formula, and leaving it
128
+ * opaque preserves round-trip bytes via `rawText`.
129
+ *
130
+ * This function is pure: the classification of a given input depends
131
+ * entirely on (rawText, ranges, probe) and no global state. Two calls
132
+ * with the same arguments always produce the same result.
133
+ */
134
+ function classifyDefinedName(rawText, ranges, probe) {
135
+ // If rawText is missing, fall back to existing ranges (programmatic API path)
136
+ if (rawText === undefined) {
137
+ if (ranges.length > 0) {
138
+ return { kind: "reference", ranges };
139
+ }
140
+ return { kind: "opaque", ranges: [] };
141
+ }
142
+ const trimmed = rawText.trim();
143
+ if (trimmed.length === 0) {
144
+ return { kind: "opaque", ranges: [] };
145
+ }
146
+ // Opaque-looking wrappers — array constants, string literals, error
147
+ // values — are preserved verbatim and never routed through formula
148
+ // parsing. Detect them once, up front.
149
+ const isArrayConst = trimmed.startsWith("{") && trimmed.endsWith("}");
150
+ const isStringLit = trimmed.startsWith('"') && trimmed.endsWith('"');
151
+ const isErrorVal = trimmed.startsWith("#");
152
+ const isOpaqueWrapper = isArrayConst || isStringLit || isErrorVal;
153
+ const hasParen = hasUnquotedParen(trimmed);
154
+ // If the text contains an unquoted parenthesis (e.g. OFFSET(...),
155
+ // LAMBDA(...)), it is either a formula or a malformed expression —
156
+ // never a cell-range union. `extractRanges` is not safe to call on
157
+ // such text because it splits on commas and can mis-identify
158
+ // `OFFSET(Sheet1` as a partial range reference.
159
+ //
160
+ // With a probe: confirm the expression parses before classifying as
161
+ // formula; if the probe rejects it, fall through to opaque.
162
+ // Without a probe: we cannot confirm it parses, so preserve the text
163
+ // verbatim as opaque. This is deliberately strict — the alternative
164
+ // (silently promoting unverified text to `formula`) produced
165
+ // classification results that depended on global install state.
166
+ if (hasParen && !isOpaqueWrapper) {
167
+ if (probe && probe(trimmed)) {
168
+ return { kind: "formula", ranges: [trimmed], formulaExpression: trimmed };
169
+ }
170
+ return { kind: "opaque", ranges: [] };
171
+ }
172
+ // Try to extract cell/range references (handles comma-separated
173
+ // multi-area names). Safe to call only after the paren check above,
174
+ // because `extractRanges` splits on commas.
175
+ const extracted = extractRanges(rawText);
176
+ if (extracted.length > 0) {
177
+ return { kind: "reference", ranges: extracted };
178
+ }
179
+ // Opaque wrappers that didn't pass as a formula above classify
180
+ // straight to opaque — we preserve them verbatim without calculating.
181
+ if (isOpaqueWrapper) {
182
+ return { kind: "opaque", ranges: [] };
183
+ }
184
+ // No parens and not a range — could still be a parseable constant
185
+ // expression or a reference to another defined name. Only classify as
186
+ // formula if a probe can confirm it parses; otherwise stay opaque so
187
+ // round-trip text is preserved without silently promoting unparseable
188
+ // content to the formula bucket.
189
+ if (probe && probe(trimmed)) {
190
+ return { kind: "formula", ranges: [trimmed], formulaExpression: trimmed };
191
+ }
192
+ // Nothing worked — opaque
193
+ return { kind: "opaque", ranges: [] };
194
+ }
195
+ // ============================================================================
196
+ // Internal Key — disambiguates same-name entries with different scopes
197
+ // ============================================================================
198
+ /**
199
+ * Build the internal storage key for a defined name entry.
200
+ * Workbook-scoped: just the bare name.
201
+ * Sheet-scoped: `"name\0sheetId"` (null char separator avoids collisions).
202
+ */
203
+ function storageKey(name, localSheetId) {
204
+ return localSheetId !== undefined ? `${name}\0${localSheetId}` : name;
205
+ }
206
+ // ============================================================================
207
+ // DefinedNames class
208
+ // ============================================================================
5
209
  class DefinedNames {
6
- constructor() {
210
+ /**
211
+ * @param probe Optional formula-syntax probe used when classifying
212
+ * defined-name text. Injecting a probe here makes classification
213
+ * deterministic for this instance regardless of process-global
214
+ * `installFormulaEngine()` state. When omitted, the instance defers
215
+ * to the default probe at classification time (see `set model`).
216
+ */
217
+ constructor(probe) {
7
218
  this.matrixMap = {};
219
+ this.formulaMap = {};
220
+ this.localSheetIdMap = {};
221
+ this.opaqueMap = {};
222
+ this.nameForKey = {};
223
+ this._explicitProbe = probe ?? null;
8
224
  }
9
225
  getMatrix(name) {
10
226
  const matrix = this.matrixMap[name] || (this.matrixMap[name] = new CellMatrix());
@@ -16,6 +232,11 @@ class DefinedNames {
16
232
  if ("error" in location) {
17
233
  return; // Invalid reference, skip
18
234
  }
235
+ // A name is either cell-reference or formula — clear any formula/opaque binding
236
+ // (programmatic API always operates on workbook-scoped names)
237
+ delete this.formulaMap[name];
238
+ delete this.opaqueMap[name];
239
+ this.nameForKey[name] = name;
19
240
  this.addEx(location, name);
20
241
  }
21
242
  addEx(location, name) {
@@ -39,6 +260,24 @@ class DefinedNames {
39
260
  matrix.addCellEx(location);
40
261
  }
41
262
  }
263
+ /**
264
+ * Register a formula-based defined name.
265
+ *
266
+ * Unlike `add()` which binds a name to a cell/range reference, this binds
267
+ * a name to an arbitrary formula expression that will be evaluated at
268
+ * calculation time.
269
+ *
270
+ * @param name - The defined name (e.g. "MyArray")
271
+ * @param expression - The formula expression (e.g. "{1,2;3,4}", "LAMBDA(x,y,x+y)")
272
+ */
273
+ addFormula(name, expression) {
274
+ // A name is either formula or cell-reference — clear any cell-reference/opaque binding
275
+ // (programmatic API always operates on workbook-scoped names)
276
+ delete this.matrixMap[name];
277
+ delete this.opaqueMap[name];
278
+ this.nameForKey[name] = name;
279
+ this.formulaMap[name] = expression;
280
+ }
42
281
  remove(locStr, name) {
43
282
  const location = colCache.decodeEx(locStr);
44
283
  if ("error" in location) {
@@ -86,9 +325,10 @@ class DefinedNames {
86
325
  });
87
326
  }
88
327
  forEach(callback) {
89
- Object.entries(this.matrixMap).forEach(([name, matrix]) => {
328
+ Object.entries(this.matrixMap).forEach(([sKey, matrix]) => {
329
+ const bareName = this.nameForKey[sKey] ?? sKey;
90
330
  matrix.forEach((cell) => {
91
- callback(name, cell);
331
+ callback(bareName, cell);
92
332
  });
93
333
  });
94
334
  }
@@ -102,20 +342,73 @@ class DefinedNames {
102
342
  }
103
343
  getNamesEx(address) {
104
344
  return Object.entries(this.matrixMap)
105
- .map(([name, matrix]) => matrix.findCellEx(address, false) && name)
345
+ .map(([sKey, matrix]) => matrix.findCellEx(address, false) && (this.nameForKey[sKey] ?? sKey))
106
346
  .filter((name) => Boolean(name));
107
347
  }
348
+ /**
349
+ * Return all defined name entries in this collection, including scope info.
350
+ * Each entry has the bare name and optional localSheetId.
351
+ * Same bare name may appear multiple times with different scopes.
352
+ */
353
+ getAllNames() {
354
+ return this.getAllEntries().map(e => e.localSheetId !== undefined
355
+ ? { name: e.name, localSheetId: e.localSheetId }
356
+ : { name: e.name });
357
+ }
358
+ /**
359
+ * Return all defined name entries with full details (name, ranges, scope).
360
+ *
361
+ * This is the primary enumeration API. Each entry is self-contained —
362
+ * no second lookup is needed. Same bare name may appear multiple times
363
+ * with different scopes.
364
+ */
365
+ getAllEntries() {
366
+ const result = [];
367
+ const seen = new Set();
368
+ for (const sKey of Object.keys(this.matrixMap)) {
369
+ if (seen.has(sKey)) {
370
+ continue;
371
+ }
372
+ seen.add(sKey);
373
+ const model = this.getRanges(sKey);
374
+ const localSheetId = this.localSheetIdMap[sKey];
375
+ result.push(localSheetId !== undefined ? { ...model, localSheetId } : model);
376
+ }
377
+ for (const sKey of Object.keys(this.formulaMap)) {
378
+ if (seen.has(sKey)) {
379
+ continue;
380
+ }
381
+ seen.add(sKey);
382
+ const model = this.getRanges(sKey);
383
+ const localSheetId = this.localSheetIdMap[sKey];
384
+ result.push(localSheetId !== undefined ? { ...model, localSheetId } : model);
385
+ }
386
+ for (const sKey of Object.keys(this.opaqueMap)) {
387
+ if (seen.has(sKey)) {
388
+ continue;
389
+ }
390
+ seen.add(sKey);
391
+ const bareName = this.nameForKey[sKey] ?? sKey;
392
+ const entry = this.opaqueMap[sKey];
393
+ result.push({
394
+ name: bareName,
395
+ ranges: [],
396
+ rawText: entry.rawText,
397
+ localSheetId: entry.localSheetId,
398
+ kind: "opaque"
399
+ });
400
+ }
401
+ return result;
402
+ }
108
403
  _explore(matrix, cell) {
109
404
  cell.mark = false;
110
- const sheetName = cell.sheetName; // Always set for cells in defined names
405
+ const sheetName = cell.sheetName;
111
406
  const range = new Range(cell.row, cell.col, cell.row, cell.col, sheetName);
112
407
  let x;
113
408
  let y;
114
- // Helper to get cell with proper type
115
409
  const getCell = (row, col) => {
116
410
  return matrix.findCellAt(sheetName, row, col);
117
411
  };
118
- // grow vertical - only one col to worry about
119
412
  function vGrow(yy, edge) {
120
413
  const c = getCell(yy, cell.col);
121
414
  if (!c || !c.mark) {
@@ -131,7 +424,6 @@ class DefinedNames {
131
424
  for (y = cell.row + 1; vGrow(y, "bottom"); y++) {
132
425
  /* advance */
133
426
  }
134
- // grow horizontal - ensure all rows can grow
135
427
  function hGrow(xx, edge) {
136
428
  const cells = [];
137
429
  for (y = range.top; y <= range.bottom; y++) {
@@ -157,10 +449,28 @@ class DefinedNames {
157
449
  }
158
450
  return range;
159
451
  }
452
+ /**
453
+ * Get ranges for a specific scoped entry.
454
+ *
455
+ * Unlike `getRanges(name)` which uses the bare name (and may hit the
456
+ * wrong scope when the same name exists both globally and locally),
457
+ * this method uses the internal `storageKey` to look up the exact entry.
458
+ */
459
+ getRangesScoped(name, localSheetId) {
460
+ const sKey = storageKey(name, localSheetId);
461
+ return this.getRanges(sKey);
462
+ }
160
463
  getRanges(name, matrix) {
464
+ // `name` can be a bare name (backward compat) or a storageKey.
465
+ // Try storageKey first, then bare name (workbook-scoped).
466
+ const formula = this.formulaMap[name];
161
467
  matrix = matrix || this.matrixMap[name];
468
+ const bareName = this.nameForKey[name] ?? name;
162
469
  if (!matrix) {
163
- return { name, ranges: [] };
470
+ if (formula) {
471
+ return { name: bareName, ranges: [formula], formulaExpression: formula };
472
+ }
473
+ return { name: bareName, ranges: [] };
164
474
  }
165
475
  // mark and sweep!
166
476
  matrix.forEach((cell) => {
@@ -171,7 +481,7 @@ class DefinedNames {
171
481
  .filter((range) => Boolean(range))
172
482
  .map((range) => range.$shortRange);
173
483
  return {
174
- name,
484
+ name: bareName,
175
485
  ranges
176
486
  };
177
487
  }
@@ -201,22 +511,102 @@ class DefinedNames {
201
511
  });
202
512
  }
203
513
  get model() {
204
- // To get names per cell - just iterate over all names finding cells if they exist
205
- return Object.entries(this.matrixMap)
206
- .map(([name, matrix]) => this.getRanges(name, matrix))
514
+ // Cell-reference based names from matrixMap
515
+ const cellNames = Object.entries(this.matrixMap)
516
+ .map(([sKey, matrix]) => {
517
+ const result = this.getRanges(sKey, matrix);
518
+ const localSheetId = this.localSheetIdMap[sKey];
519
+ if (localSheetId !== undefined) {
520
+ return { ...result, localSheetId };
521
+ }
522
+ return result;
523
+ })
207
524
  .filter((definedName) => definedName.ranges.length);
525
+ // Formula-based names from formulaMap (only include names not already in matrixMap)
526
+ const formulaNames = Object.entries(this.formulaMap)
527
+ .filter(([sKey]) => !this.matrixMap[sKey])
528
+ .map(([sKey, expression]) => {
529
+ const bareName = this.nameForKey[sKey] ?? sKey;
530
+ const result = {
531
+ name: bareName,
532
+ ranges: [expression],
533
+ formulaExpression: expression
534
+ };
535
+ const localSheetId = this.localSheetIdMap[sKey];
536
+ if (localSheetId !== undefined) {
537
+ return { ...result, localSheetId };
538
+ }
539
+ return result;
540
+ });
541
+ // Opaque names — rawText preserved for round-trip
542
+ const opaqueNames = Object.entries(this.opaqueMap).map(([sKey, entry]) => {
543
+ const bareName = this.nameForKey[sKey] ?? sKey;
544
+ return {
545
+ name: bareName,
546
+ ranges: [],
547
+ rawText: entry.rawText,
548
+ localSheetId: entry.localSheetId,
549
+ kind: "opaque"
550
+ };
551
+ });
552
+ return [...cellNames, ...formulaNames, ...opaqueNames];
208
553
  }
554
+ /**
555
+ * Deserialise an array of `DefinedNameModel` entries (typically from XLSX parsing).
556
+ *
557
+ * Stage 2 of the two-phase design: each entry's `rawText` is classified
558
+ * into reference / formula / opaque by `classifyDefinedName()`. Entries
559
+ * that arrive without `rawText` (programmatic API) fall back to inspecting
560
+ * the existing `ranges` and `formulaExpression` fields for compatibility.
561
+ */
209
562
  set model(value) {
210
- // value is [ { name, ranges }, ... ]
211
563
  const matrixMap = (this.matrixMap = {});
212
- value.forEach(definedName => {
213
- const matrix = (matrixMap[definedName.name] = new CellMatrix());
214
- definedName.ranges.forEach(rangeStr => {
215
- if (rangeRegexp.test(rangeStr.split("!").pop() ?? "")) {
216
- matrix.addCell(rangeStr);
564
+ const formulaMap = (this.formulaMap = {});
565
+ const localSheetIdMap = (this.localSheetIdMap = {});
566
+ const opaqueMap = (this.opaqueMap = {});
567
+ const nameForKeyMap = (this.nameForKey = {});
568
+ // Resolve probe lazily: a caller may have constructed the Workbook
569
+ // before `installFormulaEngine()` but load XLSX data afterwards. We
570
+ // want whichever probe is registered at *load* time, not construct
571
+ // time. An explicit per-instance probe always wins when provided.
572
+ const probe = this._explicitProbe ?? getDefaultSyntaxProbe();
573
+ for (const definedName of value) {
574
+ const sKey = storageKey(definedName.name, definedName.localSheetId);
575
+ nameForKeyMap[sKey] = definedName.name;
576
+ // Track localSheetId for all name kinds
577
+ if (definedName.localSheetId !== undefined) {
578
+ localSheetIdMap[sKey] = definedName.localSheetId;
579
+ }
580
+ // Programmatic API path: formulaExpression already set and no rawText
581
+ if (definedName.formulaExpression && definedName.rawText === undefined) {
582
+ formulaMap[sKey] = definedName.formulaExpression;
583
+ continue;
584
+ }
585
+ // XLSX parse path (rawText present) or programmatic path with ranges only
586
+ const classified = classifyDefinedName(definedName.rawText, definedName.ranges, probe);
587
+ switch (classified.kind) {
588
+ case "reference": {
589
+ const matrix = (matrixMap[sKey] = new CellMatrix());
590
+ for (const rangeStr of classified.ranges) {
591
+ if (rangeRegexp.test(rangeStr.split("!").pop() ?? "")) {
592
+ matrix.addCell(rangeStr);
593
+ }
594
+ }
595
+ break;
217
596
  }
218
- });
219
- });
597
+ case "formula":
598
+ formulaMap[sKey] = classified.formulaExpression;
599
+ break;
600
+ case "opaque":
601
+ if (definedName.rawText) {
602
+ opaqueMap[sKey] = {
603
+ rawText: definedName.rawText,
604
+ localSheetId: definedName.localSheetId
605
+ };
606
+ }
607
+ break;
608
+ }
609
+ }
220
610
  }
221
611
  }
222
612
  export { DefinedNames };
@@ -34,6 +34,19 @@ class Image {
34
34
  if (!range) {
35
35
  throw new ImageError("Image has no range");
36
36
  }
37
+ // Absolute positioning — no cell anchors
38
+ if (range.pos) {
39
+ return {
40
+ type: this.type,
41
+ imageId: this.imageId ?? "",
42
+ hyperlinks: range.hyperlinks,
43
+ range: {
44
+ tl: { nativeCol: 0, nativeColOff: 0, nativeRow: 0, nativeRowOff: 0 },
45
+ ext: range.ext,
46
+ pos: range.pos
47
+ }
48
+ };
49
+ }
37
50
  return {
38
51
  type: this.type,
39
52
  imageId: this.imageId ?? "",
@@ -69,6 +82,15 @@ class Image {
69
82
  };
70
83
  }
71
84
  }
85
+ else if (range && "pos" in range && range.pos) {
86
+ // Absolute positioning — preserve pos/ext, use dummy tl anchor
87
+ this.range = {
88
+ tl: new Anchor(this.worksheet, null, 0),
89
+ ext: range.ext,
90
+ hyperlinks: hyperlinks || ("hyperlinks" in range ? range.hyperlinks : undefined),
91
+ pos: range.pos
92
+ };
93
+ }
72
94
  else if (range) {
73
95
  this.range = {
74
96
  tl: new Anchor(this.worksheet, range.tl, 0),
@@ -95,7 +117,8 @@ class Image {
95
117
  br: this.range.br ? this.range.br.clone(target) : undefined,
96
118
  ext: this.range.ext ? { ...this.range.ext } : undefined,
97
119
  editAs: this.range.editAs,
98
- hyperlinks: this.range.hyperlinks ? { ...this.range.hyperlinks } : undefined
120
+ hyperlinks: this.range.hyperlinks ? { ...this.range.hyperlinks } : undefined,
121
+ pos: this.range.pos ? { ...this.range.pos } : undefined
99
122
  };
100
123
  }
101
124
  return cloned;
@@ -15,6 +15,7 @@ import { WorksheetReader } from "./worksheet-reader.js";
15
15
  import { iterateStream } from "../utils/iterate-stream.js";
16
16
  import { getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, normalizeZipPath, OOXML_PATHS, worksheetRelTarget } from "../utils/ooxml-paths.js";
17
17
  import { WorkbookXform } from "../xlsx/xform/book/workbook-xform.js";
18
+ import { MetadataXform } from "../xlsx/xform/core/metadata-xform.js";
18
19
  import { RelationshipsXform } from "../xlsx/xform/core/relationships-xform.js";
19
20
  import { StylesXform } from "../xlsx/xform/style/styles-xform.js";
20
21
  import { Readable } from "../../stream/index.js";
@@ -36,6 +37,8 @@ export class WorkbookReaderBase extends EventEmitter {
36
37
  }
37
38
  constructor(input, options, WorksheetReaderClass, HyperlinkReaderClass) {
38
39
  super();
40
+ /** Whether xl/metadata.xml contains XLDAPR dynamic array metadata */
41
+ this.hasDynamicArrayMetadata = false;
39
42
  /** Running total of bytes buffered for waiting worksheets. */
40
43
  this._totalBufferedBytes = 0;
41
44
  this.input = input;
@@ -443,6 +446,14 @@ export class WorkbookReaderBase extends EventEmitter {
443
446
  await this.styles.parseStream(iterateStream(entry));
444
447
  }
445
448
  }
449
+ async _parseMetadata(entry) {
450
+ const xform = new MetadataXform();
451
+ const result = await xform.parseStream(iterateStream(entry));
452
+ if (result) {
453
+ this.hasDynamicArrayMetadata = !!result.hasDynamicArrays;
454
+ this.dynamicArrayCmIndices = result.dynamicArrayCmIndices;
455
+ }
456
+ }
446
457
  *_parseWorksheet(iterator, sheetNo) {
447
458
  this._emitEntry({ type: "worksheet", id: sheetNo });
448
459
  const sheetNoNumber = parseInt(sheetNo, 10);
@@ -511,6 +522,9 @@ export class WorkbookReaderBase extends EventEmitter {
511
522
  case OOXML_PATHS.xlStyles:
512
523
  await this._parseStyles(entry);
513
524
  break;
525
+ case OOXML_PATHS.xlMetadata:
526
+ await this._parseMetadata(entry);
527
+ break;
514
528
  default:
515
529
  sheetNo = getWorksheetNoFromWorksheetPath(normalizedPath)?.toString();
516
530
  if (sheetNo) {