@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,886 @@
1
+ /**
2
+ * Lookup / Reference Functions — Native RuntimeValue Implementation
3
+ */
4
+ import { RVKind, ERRORS, BLANK, rvNumber, rvString, rvArray, toNumberRV, toBooleanRV, toStringRV, topLeft, scalarEquals, compareScalarsSameKind, isError, isArray } from "../runtime/values.js";
5
+ import { excelWildcardToRegex, getCell, hasUnescapedWildcard, unescapeExcelWildcard } from "./_shared.js";
6
+ // ============================================================================
7
+ // Helpers
8
+ // ============================================================================
9
+ /** Compare two scalar values for same-type ordering. */
10
+ function sameType(a, b) {
11
+ return a.kind === b.kind;
12
+ }
13
+ function scalarIsNumber(v) {
14
+ return v.kind === RVKind.Number;
15
+ }
16
+ function scalarIsString(v) {
17
+ return v.kind === RVKind.String;
18
+ }
19
+ function scalarStringEquals(a, b) {
20
+ return scalarIsString(a) && scalarIsString(b) && a.value.toLowerCase() === b.value.toLowerCase();
21
+ }
22
+ /**
23
+ * Ordered comparison of two scalars. Numbers compared by value; strings by
24
+ * case-insensitive lexical order. Returns NaN when the two operands have
25
+ * incompatible types (e.g. number vs string) so callers can skip them.
26
+ */
27
+ /**
28
+ * @deprecated Use `compareScalarsSameKind` from `runtime/values` directly —
29
+ * the two are identical. Retained only as a local alias to keep the diff
30
+ * small; callers inside this file are free to migrate.
31
+ */
32
+ const compareScalar = compareScalarsSameKind;
33
+ // ============================================================================
34
+ // Functions
35
+ // ============================================================================
36
+ export function fnROW(args) {
37
+ // The reference-aware path is handled in evaluator.ts via tryEvaluateRefFunction.
38
+ // This fallback is only reached when the argument is not a reference (e.g.
39
+ // ROW(INDIRECT("A5")) or ROW({1,2,3})), which Excel rejects as #VALUE!.
40
+ return ERRORS.VALUE;
41
+ }
42
+ export function fnCOLUMN(args) {
43
+ // See fnROW. Non-reference argument → #VALUE!.
44
+ return ERRORS.VALUE;
45
+ }
46
+ export function fnROWS(args) {
47
+ const a = args[0];
48
+ if (a.kind === RVKind.Array) {
49
+ return rvNumber(a.height);
50
+ }
51
+ return rvNumber(1);
52
+ }
53
+ export function fnCOLUMNS(args) {
54
+ const a = args[0];
55
+ if (a.kind === RVKind.Array) {
56
+ return rvNumber(a.width);
57
+ }
58
+ return rvNumber(1);
59
+ }
60
+ export function fnINDEX(args) {
61
+ if (!isArray(args[0])) {
62
+ return topLeft(args[0]);
63
+ }
64
+ const arr = args[0];
65
+ const rowNumV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
66
+ if (isError(rowNumV)) {
67
+ return rowNumV;
68
+ }
69
+ // Excel truncates fractional indices toward zero before bounds checks.
70
+ // Without this, `INDEX(a, 1.5, 1)` would index into `arr.rows[0.5]`, which
71
+ // in V8 silently returns `undefined` and corrupts downstream values.
72
+ const rowNum = Math.trunc(rowNumV.value);
73
+ const colNumV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(0);
74
+ if (isError(colNumV)) {
75
+ return colNumV;
76
+ }
77
+ const colNum = Math.trunc(colNumV.value);
78
+ if (rowNum < 0 || colNum < 0) {
79
+ return ERRORS.VALUE;
80
+ }
81
+ if (rowNum === 0 && colNum === 0) {
82
+ return arr;
83
+ }
84
+ // rowNum=0: return entire column as array
85
+ if (rowNum === 0) {
86
+ const c = colNum - 1;
87
+ if (c < 0 || c >= arr.width) {
88
+ return ERRORS.REF;
89
+ }
90
+ const rows = [];
91
+ for (let r = 0; r < arr.height; r++) {
92
+ rows.push([getCell(arr, r, c)]);
93
+ }
94
+ return rvArray(rows);
95
+ }
96
+ // colNum=0: return entire row as array
97
+ if (colNum === 0) {
98
+ const r = rowNum - 1;
99
+ if (r < 0 || r >= arr.height) {
100
+ return ERRORS.REF;
101
+ }
102
+ return rvArray([[...arr.rows[r]]]);
103
+ }
104
+ // Single cell
105
+ const r = rowNum - 1;
106
+ const c = colNum - 1;
107
+ if (r < 0 || r >= arr.height || c < 0 || c >= arr.width) {
108
+ return ERRORS.REF;
109
+ }
110
+ return arr.rows[r][c];
111
+ }
112
+ export function fnMATCH(args) {
113
+ const lookupValue = topLeft(args[0]);
114
+ if (lookupValue.kind === RVKind.Error) {
115
+ return lookupValue;
116
+ }
117
+ if (!isArray(args[1])) {
118
+ return ERRORS.NA;
119
+ }
120
+ const lookupArr = args[1];
121
+ const matchTypeV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(1);
122
+ if (isError(matchTypeV)) {
123
+ return matchTypeV;
124
+ }
125
+ const matchType = matchTypeV.value;
126
+ // Flatten to 1D
127
+ const flat = [];
128
+ for (let r = 0; r < lookupArr.height; r++) {
129
+ for (let c = 0; c < lookupArr.width; c++) {
130
+ flat.push(getCell(lookupArr, r, c));
131
+ }
132
+ }
133
+ if (matchType === 0) {
134
+ // Exact match (with wildcard support for string lookups). The shared
135
+ // `excelWildcardToRegex` converter applies the same `~*`, `~?`, `~~`
136
+ // escape rules used by SEARCH, XLOOKUP, and SUMIF so behaviour is
137
+ // consistent across the engine.
138
+ const lookupStr = scalarIsString(lookupValue) ? lookupValue.value : null;
139
+ const hasWildcard = lookupStr !== null && hasUnescapedWildcard(lookupStr);
140
+ let wildcardRe = null;
141
+ if (hasWildcard && lookupStr !== null) {
142
+ try {
143
+ wildcardRe = new RegExp("^" + excelWildcardToRegex(lookupStr) + "$", "i");
144
+ }
145
+ catch {
146
+ wildcardRe = null;
147
+ }
148
+ }
149
+ for (let i = 0; i < flat.length; i++) {
150
+ if (scalarEquals(flat[i], lookupValue)) {
151
+ return rvNumber(i + 1);
152
+ }
153
+ const fi = flat[i];
154
+ if (scalarIsString(fi) && scalarIsString(lookupValue)) {
155
+ if (wildcardRe) {
156
+ if (wildcardRe.test(fi.value)) {
157
+ return rvNumber(i + 1);
158
+ }
159
+ }
160
+ else {
161
+ // No unescaped wildcard — but the pattern may still contain
162
+ // `~*` / `~?` / `~~` escape sequences that should reduce to
163
+ // their literal character before comparison. Calling
164
+ // `unescapeExcelWildcard` here matches the treatment that
165
+ // SEARCH and the criteria predicate use; without it,
166
+ // `MATCH("a~*b", ...)` would literally look for `"a~*b"`
167
+ // instead of `"a*b"`.
168
+ const literal = unescapeExcelWildcard(lookupValue.value).toLowerCase();
169
+ if (fi.value.toLowerCase() === literal) {
170
+ return rvNumber(i + 1);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ return ERRORS.NA;
176
+ }
177
+ if (matchType === 1 || matchType > 0) {
178
+ // Sorted ascending. Find largest value <= lookupValue.
179
+ let bestIdx = -1;
180
+ for (let i = 0; i < flat.length; i++) {
181
+ const v = flat[i];
182
+ if (sameType(v, lookupValue)) {
183
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue)) {
184
+ if (v.value <= lookupValue.value) {
185
+ bestIdx = i;
186
+ }
187
+ else {
188
+ break;
189
+ }
190
+ }
191
+ else if (scalarIsString(v) && scalarIsString(lookupValue)) {
192
+ if (v.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
193
+ bestIdx = i;
194
+ }
195
+ else {
196
+ break;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ return bestIdx >= 0 ? rvNumber(bestIdx + 1) : ERRORS.NA;
202
+ }
203
+ // matchType === -1: Sorted descending. Find smallest value >= lookupValue.
204
+ let bestIdx = -1;
205
+ for (let i = 0; i < flat.length; i++) {
206
+ const v = flat[i];
207
+ if (sameType(v, lookupValue)) {
208
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue)) {
209
+ if (v.value >= lookupValue.value) {
210
+ bestIdx = i;
211
+ }
212
+ else {
213
+ break;
214
+ }
215
+ }
216
+ else if (scalarIsString(v) && scalarIsString(lookupValue)) {
217
+ if (v.value.toLowerCase() >= lookupValue.value.toLowerCase()) {
218
+ bestIdx = i;
219
+ }
220
+ else {
221
+ break;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ return bestIdx >= 0 ? rvNumber(bestIdx + 1) : ERRORS.NA;
227
+ }
228
+ export function fnVLOOKUP(args) {
229
+ const lookupValue = topLeft(args[0]);
230
+ if (lookupValue.kind === RVKind.Error) {
231
+ return lookupValue;
232
+ }
233
+ if (!isArray(args[1])) {
234
+ return ERRORS.NA;
235
+ }
236
+ const table = args[1];
237
+ const colIndexV = toNumberRV(args[2]);
238
+ if (isError(colIndexV)) {
239
+ return colIndexV;
240
+ }
241
+ // VLOOKUP truncates the column index toward zero before bounds checks.
242
+ const colIndex = Math.trunc(colIndexV.value);
243
+ const rangeLookupV = args.length > 3 ? toBooleanRV(args[3]) : { kind: RVKind.Boolean, value: true };
244
+ if (isError(rangeLookupV)) {
245
+ return rangeLookupV;
246
+ }
247
+ const rangeLookup = rangeLookupV.value;
248
+ if (colIndex < 1 || colIndex > table.width) {
249
+ return ERRORS.REF;
250
+ }
251
+ if (!rangeLookup) {
252
+ // Exact match
253
+ for (let r = 0; r < table.height; r++) {
254
+ const cell = getCell(table, r, 0);
255
+ if (scalarEquals(cell, lookupValue)) {
256
+ return getCell(table, r, colIndex - 1);
257
+ }
258
+ if (scalarStringEquals(cell, lookupValue)) {
259
+ return getCell(table, r, colIndex - 1);
260
+ }
261
+ }
262
+ return ERRORS.NA;
263
+ }
264
+ // Approximate match: sorted ascending by first column.
265
+ let bestRow = -1;
266
+ for (let r = 0; r < table.height; r++) {
267
+ const v = getCell(table, r, 0);
268
+ if (sameType(v, lookupValue)) {
269
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue)) {
270
+ if (v.value <= lookupValue.value) {
271
+ bestRow = r;
272
+ }
273
+ else {
274
+ break;
275
+ }
276
+ }
277
+ else if (scalarIsString(v) && scalarIsString(lookupValue)) {
278
+ if (v.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
279
+ bestRow = r;
280
+ }
281
+ else {
282
+ break;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ return bestRow >= 0 ? getCell(table, bestRow, colIndex - 1) : ERRORS.NA;
288
+ }
289
+ export function fnHLOOKUP(args) {
290
+ const lookupValue = topLeft(args[0]);
291
+ if (lookupValue.kind === RVKind.Error) {
292
+ return lookupValue;
293
+ }
294
+ if (!isArray(args[1])) {
295
+ return ERRORS.NA;
296
+ }
297
+ const table = args[1];
298
+ const rowIndexV = toNumberRV(args[2]);
299
+ if (isError(rowIndexV)) {
300
+ return rowIndexV;
301
+ }
302
+ // HLOOKUP truncates the row index toward zero before bounds checks.
303
+ const rowIndex = Math.trunc(rowIndexV.value);
304
+ const rangeLookupV = args.length > 3 ? toBooleanRV(args[3]) : { kind: RVKind.Boolean, value: true };
305
+ if (isError(rangeLookupV)) {
306
+ return rangeLookupV;
307
+ }
308
+ const rangeLookup = rangeLookupV.value;
309
+ if (rowIndex < 1 || rowIndex > table.height) {
310
+ return ERRORS.REF;
311
+ }
312
+ if (!rangeLookup) {
313
+ for (let c = 0; c < table.width; c++) {
314
+ if (scalarEquals(getCell(table, 0, c), lookupValue)) {
315
+ return getCell(table, rowIndex - 1, c);
316
+ }
317
+ }
318
+ return ERRORS.NA;
319
+ }
320
+ let bestCol = -1;
321
+ for (let c = 0; c < table.width; c++) {
322
+ const hv = getCell(table, 0, c);
323
+ if (sameType(hv, lookupValue)) {
324
+ // For approximate match, find largest <= lookupValue
325
+ if (scalarIsNumber(hv) && scalarIsNumber(lookupValue)) {
326
+ if (hv.value <= lookupValue.value) {
327
+ bestCol = c;
328
+ }
329
+ }
330
+ else if (scalarIsString(hv) && scalarIsString(lookupValue)) {
331
+ if (hv.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
332
+ bestCol = c;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ return bestCol >= 0 ? getCell(table, rowIndex - 1, bestCol) : ERRORS.NA;
338
+ }
339
+ export function fnXLOOKUP(args) {
340
+ const lookupValue = topLeft(args[0]);
341
+ if (lookupValue.kind === RVKind.Error) {
342
+ return lookupValue;
343
+ }
344
+ if (!isArray(args[1])) {
345
+ return ERRORS.VALUE;
346
+ }
347
+ const lookupArr = args[1];
348
+ if (!isArray(args[2])) {
349
+ return ERRORS.VALUE;
350
+ }
351
+ const returnArr = args[2];
352
+ const ifNotFound = args.length > 3 ? topLeft(args[3]) : null;
353
+ const matchModeV = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
354
+ if (isError(matchModeV)) {
355
+ return matchModeV;
356
+ }
357
+ const matchMode = matchModeV.value;
358
+ const searchModeV = args.length > 5 ? toNumberRV(args[5]) : rvNumber(1);
359
+ if (isError(searchModeV)) {
360
+ return searchModeV;
361
+ }
362
+ const searchMode = searchModeV.value;
363
+ // Flatten lookup array to 1D
364
+ const flat = [];
365
+ const isRow = lookupArr.height === 1;
366
+ if (isRow) {
367
+ for (let c = 0; c < lookupArr.width; c++) {
368
+ flat.push(getCell(lookupArr, 0, c));
369
+ }
370
+ }
371
+ else {
372
+ for (let r = 0; r < lookupArr.height; r++) {
373
+ flat.push(getCell(lookupArr, r, 0));
374
+ }
375
+ }
376
+ let foundIdx = -1;
377
+ const doCompare = (a, b) => {
378
+ // Use `compareScalarsSameKind` (shared with sorting / linear match)
379
+ // instead of `localeCompare`. `localeCompare` is locale-sensitive and
380
+ // can disagree with the `toLowerCase+===` equality check used on the
381
+ // linear-search path — binary search would then skip the exact cell
382
+ // that linear search would find (e.g. Turkish dotless I, ß→ss, etc.).
383
+ // See R6-P1-11.
384
+ const cmp = compareScalarsSameKind(a, b);
385
+ return Number.isFinite(cmp) ? cmp : 0;
386
+ };
387
+ // ── Binary search for sorted data (searchMode = ±2) ──
388
+ // Excel assumes the data is sorted ascending (2) or descending (-2). The
389
+ // array must contain values of a single type compatible with `lookupValue`;
390
+ // cells of an incompatible type make the sort invalid and binary search
391
+ // cannot produce a meaningful result, so we fall back to #N/A in that
392
+ // scenario (matching Excel's behaviour when the data is "not sorted").
393
+ //
394
+ // Supports matchMode 0 (exact), -1 (exact or next smaller), 1 (exact or
395
+ // next larger). Wildcard matchMode (2) is incompatible with binary search
396
+ // by definition — Excel silently downgrades to linear scan, which we do
397
+ // by leaving `searchMode` as 1 below.
398
+ const isBinary = (searchMode === 2 || searchMode === -2) && matchMode !== 2;
399
+ if (isBinary) {
400
+ const ascending = searchMode === 2;
401
+ let lo = 0;
402
+ let hi = flat.length - 1;
403
+ let exact = -1;
404
+ let nextSmaller = -1; // largest index with value < lookupValue (ascending)
405
+ let nextLarger = -1; // smallest index with value > lookupValue (ascending)
406
+ while (lo <= hi) {
407
+ const mid = (lo + hi) >>> 1;
408
+ const v = flat[mid];
409
+ if (!sameType(v, lookupValue)) {
410
+ // Heterogeneous array — binary search preconditions violated.
411
+ exact = -1;
412
+ nextSmaller = -1;
413
+ nextLarger = -1;
414
+ break;
415
+ }
416
+ const cmp = doCompare(v, lookupValue);
417
+ if (cmp === 0) {
418
+ exact = mid;
419
+ break;
420
+ }
421
+ // In descending order, the ordering is inverted: treat `cmp > 0` on
422
+ // the left half as "still greater than target" → search right.
423
+ const goLeft = ascending ? cmp > 0 : cmp < 0;
424
+ if (goLeft) {
425
+ // mid is larger (ascending) or smaller (descending) than target
426
+ if (ascending) {
427
+ nextLarger = nextLarger === -1 || mid < nextLarger ? mid : nextLarger;
428
+ }
429
+ else {
430
+ nextSmaller = nextSmaller === -1 || mid < nextSmaller ? mid : nextSmaller;
431
+ }
432
+ hi = mid - 1;
433
+ }
434
+ else {
435
+ if (ascending) {
436
+ nextSmaller = nextSmaller === -1 || mid > nextSmaller ? mid : nextSmaller;
437
+ }
438
+ else {
439
+ nextLarger = nextLarger === -1 || mid > nextLarger ? mid : nextLarger;
440
+ }
441
+ lo = mid + 1;
442
+ }
443
+ }
444
+ if (exact !== -1) {
445
+ foundIdx = exact;
446
+ }
447
+ else if (matchMode === -1) {
448
+ foundIdx = nextSmaller;
449
+ }
450
+ else if (matchMode === 1) {
451
+ foundIdx = nextLarger;
452
+ }
453
+ else {
454
+ foundIdx = -1;
455
+ }
456
+ }
457
+ else if (matchMode === 0) {
458
+ // Exact match
459
+ const start = searchMode === -1 ? flat.length - 1 : 0;
460
+ const end = searchMode === -1 ? -1 : flat.length;
461
+ const step = searchMode === -1 ? -1 : 1;
462
+ for (let i = start; i !== end; i += step) {
463
+ if (scalarEquals(flat[i], lookupValue)) {
464
+ foundIdx = i;
465
+ break;
466
+ }
467
+ if (scalarStringEquals(flat[i], lookupValue)) {
468
+ foundIdx = i;
469
+ break;
470
+ }
471
+ }
472
+ }
473
+ else if (matchMode === -1) {
474
+ // Exact match or next smaller
475
+ let best = -1;
476
+ for (let i = 0; i < flat.length; i++) {
477
+ if (sameType(flat[i], lookupValue)) {
478
+ const cmp = doCompare(flat[i], lookupValue);
479
+ if (cmp === 0) {
480
+ best = i;
481
+ break;
482
+ }
483
+ if (cmp < 0 && (best === -1 || doCompare(flat[i], flat[best]) > 0)) {
484
+ best = i;
485
+ }
486
+ }
487
+ }
488
+ foundIdx = best;
489
+ }
490
+ else if (matchMode === 1) {
491
+ // Exact match or next larger
492
+ let best = -1;
493
+ for (let i = 0; i < flat.length; i++) {
494
+ if (sameType(flat[i], lookupValue)) {
495
+ const cmp = doCompare(flat[i], lookupValue);
496
+ if (cmp === 0) {
497
+ best = i;
498
+ break;
499
+ }
500
+ if (cmp > 0 && (best === -1 || doCompare(flat[i], flat[best]) < 0)) {
501
+ best = i;
502
+ }
503
+ }
504
+ }
505
+ foundIdx = best;
506
+ }
507
+ else if (matchMode === 2) {
508
+ // Wildcard match — uses the shared Excel wildcard converter so SEARCH,
509
+ // MATCH, XLOOKUP, and SUMIF/COUNTIF agree on `~*`, `~?`, `~~` escaping.
510
+ const lookupStr = toStringRV(lookupValue);
511
+ const pattern = excelWildcardToRegex(lookupStr);
512
+ try {
513
+ const re = new RegExp("^" + pattern + "$", "i");
514
+ for (let i = 0; i < flat.length; i++) {
515
+ if (re.test(toStringRV(flat[i]))) {
516
+ foundIdx = i;
517
+ break;
518
+ }
519
+ }
520
+ }
521
+ catch {
522
+ for (let i = 0; i < flat.length; i++) {
523
+ if (toStringRV(flat[i]).toLowerCase() === lookupStr.toLowerCase()) {
524
+ foundIdx = i;
525
+ break;
526
+ }
527
+ }
528
+ }
529
+ }
530
+ if (foundIdx === -1) {
531
+ return ifNotFound !== null ? ifNotFound : ERRORS.NA;
532
+ }
533
+ // Return from return array
534
+ if (isRow) {
535
+ // Horizontal lookup: the lookup axis is the column axis of the return
536
+ // array, so `foundIdx` selects a column. A single-row return array
537
+ // yields a scalar; a multi-row return array yields a column vector.
538
+ if (foundIdx >= returnArr.width) {
539
+ return BLANK;
540
+ }
541
+ if (returnArr.height === 1) {
542
+ return getCell(returnArr, 0, foundIdx);
543
+ }
544
+ const col = [];
545
+ for (let r = 0; r < returnArr.height; r++) {
546
+ col.push([getCell(returnArr, r, foundIdx)]);
547
+ }
548
+ return rvArray(col);
549
+ }
550
+ // Vertical lookup: `foundIdx` selects a row; a single-column return
551
+ // array yields a scalar; a multi-column array yields a row vector.
552
+ if (foundIdx < returnArr.height) {
553
+ if (returnArr.width === 1) {
554
+ return getCell(returnArr, foundIdx, 0);
555
+ }
556
+ const row = [];
557
+ for (let c = 0; c < returnArr.width; c++) {
558
+ row.push(getCell(returnArr, foundIdx, c));
559
+ }
560
+ return rvArray([row]);
561
+ }
562
+ return BLANK;
563
+ }
564
+ export function fnXMATCH(args) {
565
+ const lookupValue = topLeft(args[0]);
566
+ if (lookupValue.kind === RVKind.Error) {
567
+ return lookupValue;
568
+ }
569
+ if (!isArray(args[1])) {
570
+ return ERRORS.VALUE;
571
+ }
572
+ const lookupArr = args[1];
573
+ const matchModeV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(0);
574
+ if (isError(matchModeV)) {
575
+ return matchModeV;
576
+ }
577
+ const matchMode = matchModeV.value;
578
+ const searchModeV = args.length > 3 ? toNumberRV(args[3]) : rvNumber(1);
579
+ if (isError(searchModeV)) {
580
+ return searchModeV;
581
+ }
582
+ const searchMode = searchModeV.value;
583
+ const flat = [];
584
+ if (lookupArr.height === 1) {
585
+ for (let c = 0; c < lookupArr.width; c++) {
586
+ flat.push(getCell(lookupArr, 0, c));
587
+ }
588
+ }
589
+ else {
590
+ for (let r = 0; r < lookupArr.height; r++) {
591
+ flat.push(getCell(lookupArr, r, 0));
592
+ }
593
+ }
594
+ if (matchMode === 0) {
595
+ const start = searchMode === -1 ? flat.length - 1 : 0;
596
+ const end = searchMode === -1 ? -1 : flat.length;
597
+ const step = searchMode === -1 ? -1 : 1;
598
+ for (let i = start; i !== end; i += step) {
599
+ if (scalarEquals(flat[i], lookupValue)) {
600
+ return rvNumber(i + 1);
601
+ }
602
+ if (scalarStringEquals(flat[i], lookupValue)) {
603
+ return rvNumber(i + 1);
604
+ }
605
+ }
606
+ return ERRORS.NA;
607
+ }
608
+ if (matchMode === 2) {
609
+ // Wildcard matching — `*` and `?` (with `~` escape). Only meaningful
610
+ // when the lookup value is a string; for non-string lookup values
611
+ // Excel falls back to plain comparison.
612
+ if (lookupValue.kind !== RVKind.String) {
613
+ // Fall through to exact-match semantics for non-string lookups.
614
+ const start = searchMode === -1 ? flat.length - 1 : 0;
615
+ const end = searchMode === -1 ? -1 : flat.length;
616
+ const step = searchMode === -1 ? -1 : 1;
617
+ for (let i = start; i !== end; i += step) {
618
+ if (scalarEquals(flat[i], lookupValue)) {
619
+ return rvNumber(i + 1);
620
+ }
621
+ }
622
+ return ERRORS.NA;
623
+ }
624
+ const pattern = lookupValue.value;
625
+ const matcher = hasUnescapedWildcard(pattern)
626
+ ? new RegExp(`^${excelWildcardToRegex(pattern)}$`, "iu")
627
+ : null;
628
+ const literal = matcher ? null : unescapeExcelWildcard(pattern).toLowerCase();
629
+ const start = searchMode === -1 ? flat.length - 1 : 0;
630
+ const end = searchMode === -1 ? -1 : flat.length;
631
+ const step = searchMode === -1 ? -1 : 1;
632
+ for (let i = start; i !== end; i += step) {
633
+ const cell = flat[i];
634
+ if (cell.kind !== RVKind.String) {
635
+ continue;
636
+ }
637
+ if (matcher) {
638
+ if (matcher.test(cell.value)) {
639
+ return rvNumber(i + 1);
640
+ }
641
+ }
642
+ else if (cell.value.toLowerCase() === literal) {
643
+ return rvNumber(i + 1);
644
+ }
645
+ }
646
+ return ERRORS.NA;
647
+ }
648
+ if (matchMode === -1) {
649
+ // Next-smaller-or-equal: largest item <= lookupValue.
650
+ let best = -1;
651
+ for (let i = 0; i < flat.length; i++) {
652
+ const cmp = compareScalar(flat[i], lookupValue);
653
+ if (Number.isNaN(cmp)) {
654
+ continue;
655
+ }
656
+ if (cmp <= 0 && (best === -1 || compareScalar(flat[i], flat[best]) > 0)) {
657
+ best = i;
658
+ }
659
+ }
660
+ return best >= 0 ? rvNumber(best + 1) : ERRORS.NA;
661
+ }
662
+ if (matchMode === 1) {
663
+ // Next-larger-or-equal: smallest item >= lookupValue.
664
+ let best = -1;
665
+ for (let i = 0; i < flat.length; i++) {
666
+ const cmp = compareScalar(flat[i], lookupValue);
667
+ if (Number.isNaN(cmp)) {
668
+ continue;
669
+ }
670
+ if (cmp >= 0 && (best === -1 || compareScalar(flat[i], flat[best]) < 0)) {
671
+ best = i;
672
+ }
673
+ }
674
+ return best >= 0 ? rvNumber(best + 1) : ERRORS.NA;
675
+ }
676
+ return ERRORS.NA;
677
+ }
678
+ export function fnADDRESS(args) {
679
+ const rowNumV = toNumberRV(args[0]);
680
+ if (isError(rowNumV)) {
681
+ return rowNumV;
682
+ }
683
+ const rowNum = Math.trunc(rowNumV.value);
684
+ const colNumV = toNumberRV(args[1]);
685
+ if (isError(colNumV)) {
686
+ return colNumV;
687
+ }
688
+ const colNum = Math.trunc(colNumV.value);
689
+ // ADDRESS rejects non-positive row/col with #VALUE!. Without this guard
690
+ // ADDRESS(0, 1) would silently return "$A$0" and ADDRESS(1, 0) would
691
+ // produce "$$1" (no column letter) — neither is a legal cell reference.
692
+ if (!Number.isFinite(rowNum) || !Number.isFinite(colNum) || rowNum < 1 || colNum < 1) {
693
+ return ERRORS.VALUE;
694
+ }
695
+ const absNumV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(1);
696
+ if (isError(absNumV)) {
697
+ return absNumV;
698
+ }
699
+ const absNum = Math.trunc(absNumV.value);
700
+ // Excel only accepts abs_num ∈ {1, 2, 3, 4}; anything else is #VALUE!.
701
+ if (absNum < 1 || absNum > 4) {
702
+ return ERRORS.VALUE;
703
+ }
704
+ // a1 style (true/default) vs r1c1 (false)
705
+ const a1Arg = args.length > 3 ? topLeft(args[3]) : { kind: RVKind.Boolean, value: true };
706
+ const a1 = a1Arg.kind === RVKind.Boolean ? a1Arg.value : true;
707
+ const sheetText = args.length > 4 ? toStringRV(args[4]) : "";
708
+ if (!a1) {
709
+ // R1C1 style
710
+ const rPart = absNum === 1 || absNum === 2 ? `R${rowNum}` : `R[${rowNum}]`;
711
+ const cPart = absNum === 1 || absNum === 3 ? `C${colNum}` : `C[${colNum}]`;
712
+ const prefix = sheetText ? `${renderSheetPrefix(sheetText)}!` : "";
713
+ return rvString(prefix + rPart + cPart);
714
+ }
715
+ // Convert column number to letters
716
+ let col = "";
717
+ let cv = colNum;
718
+ while (cv > 0) {
719
+ cv--;
720
+ col = String.fromCharCode(65 + (cv % 26)) + col;
721
+ cv = Math.floor(cv / 26);
722
+ }
723
+ let result;
724
+ switch (absNum) {
725
+ case 1:
726
+ result = "$" + col + "$" + rowNum;
727
+ break;
728
+ case 2:
729
+ result = col + "$" + rowNum;
730
+ break;
731
+ case 3:
732
+ result = "$" + col + rowNum;
733
+ break;
734
+ case 4:
735
+ result = col + rowNum;
736
+ break;
737
+ default:
738
+ // Unreachable — `absNum` is already validated to {1, 2, 3, 4} above.
739
+ result = "$" + col + "$" + rowNum;
740
+ }
741
+ if (sheetText) {
742
+ result = renderSheetPrefix(sheetText) + "!" + result;
743
+ }
744
+ return rvString(result);
745
+ }
746
+ /**
747
+ * Quote a sheet name for use in a reference prefix the way Excel does:
748
+ * - plain `Name` (letters, digits, underscore, leading non-digit) → as-is
749
+ * - anything else → wrapped in single quotes with embedded `'` doubled
750
+ */
751
+ function renderSheetPrefix(name) {
752
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
753
+ return name;
754
+ }
755
+ return `'${name.replace(/'/g, "''")}'`;
756
+ }
757
+ export function fnLOOKUP(args) {
758
+ const lookupValue = topLeft(args[0]);
759
+ if (lookupValue.kind === RVKind.Error) {
760
+ return lookupValue;
761
+ }
762
+ if (!isArray(args[1])) {
763
+ return ERRORS.NA;
764
+ }
765
+ const lookupArr = args[1];
766
+ if (args.length > 2 && isArray(args[2])) {
767
+ const resultArr = args[2];
768
+ const flat = [];
769
+ const isRow = lookupArr.height === 1;
770
+ if (isRow) {
771
+ for (let c = 0; c < lookupArr.width; c++) {
772
+ flat.push(getCell(lookupArr, 0, c));
773
+ }
774
+ }
775
+ else {
776
+ for (let r = 0; r < lookupArr.height; r++) {
777
+ flat.push(getCell(lookupArr, r, 0));
778
+ }
779
+ }
780
+ let bestIdx = -1;
781
+ for (let i = 0; i < flat.length; i++) {
782
+ const v = flat[i];
783
+ if (sameType(v, lookupValue)) {
784
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue) && v.value <= lookupValue.value) {
785
+ bestIdx = i;
786
+ }
787
+ else if (scalarIsString(v) &&
788
+ scalarIsString(lookupValue) &&
789
+ v.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
790
+ bestIdx = i;
791
+ }
792
+ }
793
+ }
794
+ if (bestIdx === -1) {
795
+ return ERRORS.NA;
796
+ }
797
+ if (isRow) {
798
+ return resultArr.height === 1
799
+ ? bestIdx < resultArr.width
800
+ ? getCell(resultArr, 0, bestIdx)
801
+ : BLANK
802
+ : bestIdx < resultArr.height
803
+ ? getCell(resultArr, bestIdx, 0)
804
+ : BLANK;
805
+ }
806
+ return bestIdx < resultArr.height ? getCell(resultArr, bestIdx, 0) : BLANK;
807
+ }
808
+ const rows = lookupArr.height;
809
+ const cols = lookupArr.width;
810
+ if (cols === 0) {
811
+ return ERRORS.NA;
812
+ }
813
+ if (cols >= rows) {
814
+ let bestIdx = -1;
815
+ for (let c = 0; c < cols; c++) {
816
+ const v = getCell(lookupArr, 0, c);
817
+ if (sameType(v, lookupValue)) {
818
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue) && v.value <= lookupValue.value) {
819
+ bestIdx = c;
820
+ }
821
+ else if (scalarIsString(v) &&
822
+ scalarIsString(lookupValue) &&
823
+ v.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
824
+ bestIdx = c;
825
+ }
826
+ }
827
+ }
828
+ return bestIdx >= 0 ? getCell(lookupArr, rows - 1, bestIdx) : ERRORS.NA;
829
+ }
830
+ let bestIdx = -1;
831
+ for (let r = 0; r < rows; r++) {
832
+ const v = getCell(lookupArr, r, 0);
833
+ if (sameType(v, lookupValue)) {
834
+ if (scalarIsNumber(v) && scalarIsNumber(lookupValue) && v.value <= lookupValue.value) {
835
+ bestIdx = r;
836
+ }
837
+ else if (scalarIsString(v) &&
838
+ scalarIsString(lookupValue) &&
839
+ v.value.toLowerCase() <= lookupValue.value.toLowerCase()) {
840
+ bestIdx = r;
841
+ }
842
+ }
843
+ }
844
+ return bestIdx >= 0 ? getCell(lookupArr, bestIdx, cols - 1) : ERRORS.NA;
845
+ }
846
+ export function fnTRANSPOSE(args) {
847
+ if (!isArray(args[0])) {
848
+ const sv = topLeft(args[0]);
849
+ // Excel propagates errors through TRANSPOSE rather than burying them
850
+ // inside a 1×1 array — callers that then aggregate the result (e.g.
851
+ // `SUM(TRANSPOSE(#N/A))`) expect the error to surface. R8-P1 fix.
852
+ if (sv.kind === RVKind.Error) {
853
+ return sv;
854
+ }
855
+ return rvArray([[sv]]);
856
+ }
857
+ const arr = args[0];
858
+ const rows = arr.height;
859
+ const cols = arr.width;
860
+ const result = [];
861
+ for (let c = 0; c < cols; c++) {
862
+ const row = [];
863
+ for (let r = 0; r < rows; r++) {
864
+ row.push(getCell(arr, r, c));
865
+ }
866
+ result.push(row);
867
+ }
868
+ return rvArray(result);
869
+ }
870
+ export function fnAREAS(args) {
871
+ if (args.length === 0) {
872
+ return ERRORS.VALUE;
873
+ }
874
+ // Error in the argument propagates (Excel parity). A reference value
875
+ // counts as one area; the engine does not yet build multi-area
876
+ // references via `(A1, B1)` union syntax — when that lands, the arity
877
+ // should be `v.areas.length`, not a hardcoded 1.
878
+ const a = args[0];
879
+ if (a.kind === RVKind.Error) {
880
+ return a;
881
+ }
882
+ if (a.kind === RVKind.Reference) {
883
+ return rvNumber(a.areas.length);
884
+ }
885
+ return rvNumber(1);
886
+ }