@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,343 @@
1
+ /**
2
+ * Conditional Aggregate Functions — Native RuntimeValue Implementation
3
+ */
4
+ import { RVKind, ERRORS, rvNumber, toStringRV, topLeft, isArray, isError } from "../runtime/values.js";
5
+ import { asArray, excelWildcardToRegex, getCell, hasUnescapedWildcard, unescapeExcelWildcard } from "./_shared.js";
6
+ // ============================================================================
7
+ // Criteria Predicate Builder (RuntimeValue version)
8
+ // ============================================================================
9
+ /**
10
+ * Build a criteria predicate from a ScalarValue.
11
+ * Matches Excel SUMIF/COUNTIF criteria semantics:
12
+ * - number → exact numeric match
13
+ * - boolean → exact boolean match
14
+ * - string with operator prefix (">5", "<=10", "<>abc") → comparison
15
+ * - string with wildcards (* ?) → pattern match
16
+ * - plain string → case-insensitive exact match (or numeric if parseable)
17
+ */
18
+ export function buildCriteriaPredicateRV(criteria) {
19
+ if (criteria.kind === RVKind.Number) {
20
+ const n = criteria.value;
21
+ return v => v.kind === RVKind.Number && v.value === n;
22
+ }
23
+ if (criteria.kind === RVKind.Boolean) {
24
+ const b = criteria.value;
25
+ return v => v.kind === RVKind.Boolean && v.value === b;
26
+ }
27
+ if (criteria.kind === RVKind.Error) {
28
+ return () => false;
29
+ }
30
+ // Blank criteria: match blank/empty-string
31
+ if (criteria.kind === RVKind.Blank) {
32
+ return v => v.kind === RVKind.Blank || (v.kind === RVKind.String && v.value === "");
33
+ }
34
+ // String criteria
35
+ const s = criteria.kind === RVKind.String ? criteria.value : "";
36
+ // Operator-prefixed criteria. Order the regex alternatives longest-first
37
+ // so that `<>abc` matches the `<>` branch (not `<` with `>abc` as the
38
+ // value). Without the explicit ordering, `/^[<>]=?/` would greedily
39
+ // consume just `<` and silently mis-route every not-equal criterion to
40
+ // the `<` branch.
41
+ const opMatch = /^(<>|<=|>=|<|>|=)(.*)$/.exec(s);
42
+ if (opMatch) {
43
+ const [, op, valStr] = opMatch;
44
+ const numVal = Number(valStr);
45
+ const isNum = !isNaN(numVal) && valStr.trim() !== "";
46
+ // For numeric comparisons Excel coerces booleans (TRUE→1, FALSE→0) and
47
+ // blank (→0); numeric strings are NOT coerced (COUNTIF stays textual
48
+ // for those). Only real Number / Boolean / Blank cells participate in
49
+ // numeric comparisons; everything else falls back to string compare.
50
+ const numericOf = (v) => {
51
+ if (v.kind === RVKind.Number) {
52
+ return v.value;
53
+ }
54
+ if (v.kind === RVKind.Boolean) {
55
+ return v.value ? 1 : 0;
56
+ }
57
+ if (v.kind === RVKind.Blank) {
58
+ return 0;
59
+ }
60
+ return Number.NaN;
61
+ };
62
+ return (v) => {
63
+ const vn = numericOf(v);
64
+ const vs = toStringRV(v).toLowerCase();
65
+ const cs = valStr.toLowerCase();
66
+ switch (op) {
67
+ case "=":
68
+ return isNum ? vn === numVal : vs === cs;
69
+ case "<>":
70
+ return isNum ? vn !== numVal : vs !== cs;
71
+ case ">":
72
+ return isNum ? vn > numVal : vs > cs;
73
+ case "<":
74
+ return isNum ? vn < numVal : vs < cs;
75
+ case ">=":
76
+ return isNum ? vn >= numVal : vs >= cs;
77
+ case "<=":
78
+ return isNum ? vn <= numVal : vs <= cs;
79
+ default:
80
+ return false;
81
+ }
82
+ };
83
+ }
84
+ // Wildcard match (case-insensitive). Excel treats `~*`, `~?`, `~~` as
85
+ // literal `*`, `?`, `~` and everything else as a regex special character
86
+ // that must be escaped. Only an unescaped `*` or `?` triggers the wildcard
87
+ // path; a pattern like `~*` matches a literal asterisk.
88
+ if (hasUnescapedWildcard(s)) {
89
+ try {
90
+ const re = new RegExp("^" + excelWildcardToRegex(s) + "$", "i");
91
+ return v => re.test(toStringRV(v));
92
+ }
93
+ catch {
94
+ const literal = unescapeExcelWildcard(s).toLowerCase();
95
+ return v => toStringRV(v).toLowerCase() === literal;
96
+ }
97
+ }
98
+ // No wildcards: strip any `~` escapes and do a literal case-insensitive compare.
99
+ const literal = unescapeExcelWildcard(s);
100
+ // Exact match (case-insensitive for strings, numeric for numbers)
101
+ const numCriteria = Number(literal);
102
+ if (!isNaN(numCriteria) && literal.trim() !== "") {
103
+ return v => v.kind === RVKind.Number && v.value === numCriteria;
104
+ }
105
+ const literalLc = literal.toLowerCase();
106
+ return v => toStringRV(v).toLowerCase() === literalLc;
107
+ }
108
+ /**
109
+ * Scan a criteria string for an unescaped `*` or `?`. A backslash-style
110
+ * escape in Excel is `~`; so `~*` and `~?` are literals, while `*` and `?`
111
+ * on their own or at a position not preceded by `~` count as wildcards.
112
+ */
113
+ // ── Wildcard helpers live in `_shared.ts` and are re-used by SEARCH / MATCH /
114
+ // XLOOKUP / SUMIF / COUNTIF so every function agrees on the same escape
115
+ // semantics (`~*`, `~?`, `~~`). See `excelWildcardToRegex`,
116
+ // `hasUnescapedWildcard`, and `unescapeExcelWildcard`.
117
+ // ============================================================================
118
+ // Functions
119
+ // ============================================================================
120
+ export function fnSUMIF(args) {
121
+ const rangeArr = asArray(args[0]);
122
+ if (!rangeArr) {
123
+ return ERRORS.VALUE;
124
+ }
125
+ const criteriaScalar = topLeft(args[1]);
126
+ if (isError(criteriaScalar)) {
127
+ return criteriaScalar;
128
+ }
129
+ const pred = buildCriteriaPredicateRV(criteriaScalar);
130
+ const sumArr = args.length > 2 ? (asArray(args[2]) ?? rangeArr) : rangeArr;
131
+ let sum = 0;
132
+ for (let r = 0; r < rangeArr.height; r++) {
133
+ for (let c = 0; c < rangeArr.width; c++) {
134
+ if (pred(getCell(rangeArr, r, c))) {
135
+ const sv = getCell(sumArr, r, c);
136
+ if (sv.kind === RVKind.Number) {
137
+ sum += sv.value;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ return rvNumber(sum);
143
+ }
144
+ /**
145
+ * Scan successive `(range, criteria)` argument pairs starting at
146
+ * `startIdx`. Returns a list of `{ arr, pred }` ready for iteration, or
147
+ * an `{ error }` sentinel when a range argument is missing, a criteria
148
+ * value is itself an error, or a criteria range's shape does not match
149
+ * `target`'s shape (Excel's SUMIFS/COUNTIFS require identical shapes —
150
+ * silently zero-extending with `BLANK` produced wrong counts).
151
+ *
152
+ * Used by SUMIFS/COUNTIFS/AVERAGEIFS/MAXIFS/MINIFS which share the
153
+ * "target array + N criteria pairs" shape.
154
+ */
155
+ function collectCriteriaPairs(args, startIdx, target) {
156
+ const pairs = [];
157
+ for (let i = startIdx; i < args.length - 1; i += 2) {
158
+ const critRange = asArray(args[i]);
159
+ if (!critRange) {
160
+ return { error: ERRORS.VALUE };
161
+ }
162
+ if (critRange.height !== target.height || critRange.width !== target.width) {
163
+ return { error: ERRORS.VALUE };
164
+ }
165
+ const cs = topLeft(args[i + 1]);
166
+ if (isError(cs)) {
167
+ return { error: cs };
168
+ }
169
+ pairs.push({ arr: critRange, pred: buildCriteriaPredicateRV(cs) });
170
+ }
171
+ return { pairs };
172
+ }
173
+ /**
174
+ * Walk every (row, col) position in `target` and invoke `onMatch(r, c)`
175
+ * whenever all criteria predicates evaluate true at that position. The
176
+ * criteria arrays are expected to share `target`'s shape — Excel returns
177
+ * `#VALUE!` at the call site if they don't, which callers can detect by
178
+ * checking `target.height` / `target.width` before invoking this helper.
179
+ */
180
+ function iterateMultiCriteria(target, pairs, onMatch) {
181
+ const rows = target.height;
182
+ const cols = target.width;
183
+ for (let r = 0; r < rows; r++) {
184
+ for (let c = 0; c < cols; c++) {
185
+ let allMatch = true;
186
+ for (const p of pairs) {
187
+ if (!p.pred(getCell(p.arr, r, c))) {
188
+ allMatch = false;
189
+ break;
190
+ }
191
+ }
192
+ if (allMatch) {
193
+ onMatch(r, c);
194
+ }
195
+ }
196
+ }
197
+ }
198
+ export function fnSUMIFS(args) {
199
+ const sumArr = asArray(args[0]);
200
+ if (!sumArr || args.length < 3) {
201
+ return ERRORS.VALUE;
202
+ }
203
+ const pairs = collectCriteriaPairs(args, 1, sumArr);
204
+ if ("error" in pairs) {
205
+ return pairs.error;
206
+ }
207
+ let sum = 0;
208
+ iterateMultiCriteria(sumArr, pairs.pairs, (r, c) => {
209
+ const sv = getCell(sumArr, r, c);
210
+ if (sv.kind === RVKind.Number) {
211
+ sum += sv.value;
212
+ }
213
+ });
214
+ return rvNumber(sum);
215
+ }
216
+ export function fnCOUNTIF(args) {
217
+ const rangeArr = asArray(args[0]);
218
+ if (!rangeArr) {
219
+ return ERRORS.VALUE;
220
+ }
221
+ const cs = topLeft(args[1]);
222
+ if (isError(cs)) {
223
+ return cs;
224
+ }
225
+ const pred = buildCriteriaPredicateRV(cs);
226
+ let count = 0;
227
+ for (let r = 0; r < rangeArr.height; r++) {
228
+ for (let c = 0; c < rangeArr.width; c++) {
229
+ if (pred(getCell(rangeArr, r, c))) {
230
+ count++;
231
+ }
232
+ }
233
+ }
234
+ return rvNumber(count);
235
+ }
236
+ export function fnCOUNTIFS(args) {
237
+ if (args.length < 2 || !isArray(args[0])) {
238
+ return ERRORS.VALUE;
239
+ }
240
+ // The first range defines the target shape; every subsequent criteria
241
+ // range must match. `collectCriteriaPairs` also validates args[0]
242
+ // against itself (trivially passes) as a nice-to-have for consistency.
243
+ const target = args[0];
244
+ const pairs = collectCriteriaPairs(args, 0, target);
245
+ if ("error" in pairs) {
246
+ return pairs.error;
247
+ }
248
+ let count = 0;
249
+ iterateMultiCriteria(target, pairs.pairs, () => {
250
+ count++;
251
+ });
252
+ return rvNumber(count);
253
+ }
254
+ export function fnAVERAGEIF(args) {
255
+ const rangeArr = asArray(args[0]);
256
+ if (!rangeArr) {
257
+ return ERRORS.VALUE;
258
+ }
259
+ const cs = topLeft(args[1]);
260
+ if (isError(cs)) {
261
+ return cs;
262
+ }
263
+ const pred = buildCriteriaPredicateRV(cs);
264
+ const avgArr = args.length > 2 ? (asArray(args[2]) ?? rangeArr) : rangeArr;
265
+ let sum = 0;
266
+ let count = 0;
267
+ for (let r = 0; r < rangeArr.height; r++) {
268
+ for (let c = 0; c < rangeArr.width; c++) {
269
+ if (pred(getCell(rangeArr, r, c))) {
270
+ const sv = getCell(avgArr, r, c);
271
+ if (sv.kind === RVKind.Number) {
272
+ sum += sv.value;
273
+ count++;
274
+ }
275
+ }
276
+ }
277
+ }
278
+ return count === 0 ? ERRORS.DIV0 : rvNumber(sum / count);
279
+ }
280
+ export function fnAVERAGEIFS(args) {
281
+ const avgArr = asArray(args[0]);
282
+ if (!avgArr || args.length < 3) {
283
+ return ERRORS.VALUE;
284
+ }
285
+ const pairs = collectCriteriaPairs(args, 1, avgArr);
286
+ if ("error" in pairs) {
287
+ return pairs.error;
288
+ }
289
+ let sum = 0;
290
+ let count = 0;
291
+ iterateMultiCriteria(avgArr, pairs.pairs, (r, c) => {
292
+ const sv = getCell(avgArr, r, c);
293
+ if (sv.kind === RVKind.Number) {
294
+ sum += sv.value;
295
+ count++;
296
+ }
297
+ });
298
+ return count === 0 ? ERRORS.DIV0 : rvNumber(sum / count);
299
+ }
300
+ export function fnMAXIFS(args) {
301
+ const maxArr = asArray(args[0]);
302
+ if (!maxArr || args.length < 3) {
303
+ return ERRORS.VALUE;
304
+ }
305
+ const pairs = collectCriteriaPairs(args, 1, maxArr);
306
+ if ("error" in pairs) {
307
+ return pairs.error;
308
+ }
309
+ let result = -Infinity;
310
+ let found = false;
311
+ iterateMultiCriteria(maxArr, pairs.pairs, (r, c) => {
312
+ const sv = getCell(maxArr, r, c);
313
+ if (sv.kind === RVKind.Number) {
314
+ if (sv.value > result) {
315
+ result = sv.value;
316
+ }
317
+ found = true;
318
+ }
319
+ });
320
+ return rvNumber(found ? result : 0);
321
+ }
322
+ export function fnMINIFS(args) {
323
+ const minArr = asArray(args[0]);
324
+ if (!minArr || args.length < 3) {
325
+ return ERRORS.VALUE;
326
+ }
327
+ const pairs = collectCriteriaPairs(args, 1, minArr);
328
+ if ("error" in pairs) {
329
+ return pairs.error;
330
+ }
331
+ let result = Infinity;
332
+ let found = false;
333
+ iterateMultiCriteria(minArr, pairs.pairs, (r, c) => {
334
+ const sv = getCell(minArr, r, c);
335
+ if (sv.kind === RVKind.Number) {
336
+ if (sv.value < result) {
337
+ result = sv.value;
338
+ }
339
+ found = true;
340
+ }
341
+ });
342
+ return rvNumber(found ? result : 0);
343
+ }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Database Functions — Native RuntimeValue Implementation
3
+ */
4
+ import { RVKind, ERRORS, rvNumber, toStringRV, topLeft } from "../runtime/values.js";
5
+ import { asArray, getCell } from "./_shared.js";
6
+ import { buildCriteriaPredicateRV } from "./conditional.js";
7
+ /**
8
+ * Collect the field-column values from every database row that satisfies the
9
+ * criteria range. The returned list preserves each matching cell's original
10
+ * `ScalarValue` (numbers, strings, booleans, blanks, errors) so that callers
11
+ * can decide how to aggregate — numeric aggregators filter to numbers while
12
+ * DGET inspects the raw value.
13
+ *
14
+ * Returns an error RuntimeValue when the inputs are malformed (invalid array
15
+ * shapes, unknown field name, etc.). On success, returns `ScalarValue[]`.
16
+ */
17
+ function collectDatabaseMatches(args) {
18
+ const dbArr = asArray(args[0]);
19
+ const critArr = asArray(args[2]);
20
+ if (!dbArr || !critArr) {
21
+ return ERRORS.VALUE;
22
+ }
23
+ const fieldArg = topLeft(args[1]);
24
+ if (dbArr.height < 2 || critArr.height < 2) {
25
+ return ERRORS.VALUE;
26
+ }
27
+ // Determine field column index.
28
+ //
29
+ // Excel accepts the field argument as:
30
+ // - a 1-based integer column index (or TRUE/FALSE coerced to 1/0)
31
+ // - a string that matches one of the header cells (case-insensitive,
32
+ // and trimmed so imported data with stray whitespace still matches)
33
+ let fieldIdx = -1;
34
+ if (fieldArg.kind === RVKind.Number) {
35
+ fieldIdx = Math.trunc(fieldArg.value) - 1;
36
+ }
37
+ else if (fieldArg.kind === RVKind.Boolean) {
38
+ // TRUE → 1-based column 1 (index 0); FALSE → 0 → invalid (Excel
39
+ // rejects FALSE with #VALUE!). Match that routing explicitly.
40
+ fieldIdx = fieldArg.value ? 0 : -1;
41
+ }
42
+ else if (fieldArg.kind === RVKind.String) {
43
+ const want = fieldArg.value.trim().toLowerCase();
44
+ for (let c = 0; c < dbArr.width; c++) {
45
+ if (toStringRV(getCell(dbArr, 0, c))
46
+ .trim()
47
+ .toLowerCase() === want) {
48
+ fieldIdx = c;
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ if (fieldIdx < 0 || fieldIdx >= dbArr.width) {
54
+ return ERRORS.VALUE;
55
+ }
56
+ // Parse criteria: columns map to database header columns (trimmed,
57
+ // case-insensitive, same as the field-name path above).
58
+ const critColIndices = [];
59
+ for (let cc = 0; cc < critArr.width; cc++) {
60
+ const name = toStringRV(getCell(critArr, 0, cc))
61
+ .trim()
62
+ .toLowerCase();
63
+ let idx = -1;
64
+ for (let hc = 0; hc < dbArr.width; hc++) {
65
+ if (toStringRV(getCell(dbArr, 0, hc))
66
+ .trim()
67
+ .toLowerCase() === name) {
68
+ idx = hc;
69
+ break;
70
+ }
71
+ }
72
+ critColIndices.push(idx);
73
+ }
74
+ // Collect matching rows' field values
75
+ const matches = [];
76
+ for (let r = 1; r < dbArr.height; r++) {
77
+ let matchesAnyCritRow = false;
78
+ for (let cr = 1; cr < critArr.height; cr++) {
79
+ let allMatch = true;
80
+ for (let cc = 0; cc < critArr.width; cc++) {
81
+ const critVal = getCell(critArr, cr, cc);
82
+ if (critVal.kind === RVKind.Blank ||
83
+ (critVal.kind === RVKind.String && critVal.value === "")) {
84
+ continue;
85
+ }
86
+ const dbCol = critColIndices[cc];
87
+ if (dbCol < 0) {
88
+ allMatch = false;
89
+ break;
90
+ }
91
+ const pred = buildCriteriaPredicateRV(critVal);
92
+ if (!pred(getCell(dbArr, r, dbCol))) {
93
+ allMatch = false;
94
+ break;
95
+ }
96
+ }
97
+ if (allMatch) {
98
+ matchesAnyCritRow = true;
99
+ break;
100
+ }
101
+ }
102
+ if (matchesAnyCritRow) {
103
+ matches.push(getCell(dbArr, r, fieldIdx));
104
+ }
105
+ }
106
+ return matches;
107
+ }
108
+ /**
109
+ * Shared wrapper for numeric aggregators (DSUM, DAVERAGE, DCOUNT, DMAX, DMIN,
110
+ * DPRODUCT). Collects matches, filters to numeric values, and delegates to the
111
+ * caller-supplied reducer.
112
+ */
113
+ function databaseNumericAggregate(args, aggregator) {
114
+ const matches = collectDatabaseMatches(args);
115
+ if (!Array.isArray(matches)) {
116
+ return matches;
117
+ }
118
+ const values = [];
119
+ for (const v of matches) {
120
+ if (v.kind === RVKind.Number) {
121
+ values.push(v.value);
122
+ }
123
+ }
124
+ return aggregator(values);
125
+ }
126
+ export function fnDSUM(args) {
127
+ return databaseNumericAggregate(args, vals => rvNumber(vals.reduce((a, b) => a + b, 0)));
128
+ }
129
+ export function fnDAVERAGE(args) {
130
+ return databaseNumericAggregate(args, vals => vals.length === 0 ? ERRORS.DIV0 : rvNumber(vals.reduce((a, b) => a + b, 0) / vals.length));
131
+ }
132
+ export function fnDCOUNT(args) {
133
+ return databaseNumericAggregate(args, vals => rvNumber(vals.length));
134
+ }
135
+ export function fnDMAX(args) {
136
+ return databaseNumericAggregate(args, vals => {
137
+ if (vals.length === 0) {
138
+ return rvNumber(0);
139
+ }
140
+ // Avoid `Math.max(...vals)` — spreading a large numeric array onto the
141
+ // call stack throws `RangeError: Maximum call stack size exceeded` on
142
+ // databases with more than ~65k matching rows.
143
+ let m = vals[0];
144
+ for (let i = 1; i < vals.length; i++) {
145
+ if (vals[i] > m) {
146
+ m = vals[i];
147
+ }
148
+ }
149
+ return rvNumber(m);
150
+ });
151
+ }
152
+ export function fnDMIN(args) {
153
+ return databaseNumericAggregate(args, vals => {
154
+ if (vals.length === 0) {
155
+ return rvNumber(0);
156
+ }
157
+ let m = vals[0];
158
+ for (let i = 1; i < vals.length; i++) {
159
+ if (vals[i] < m) {
160
+ m = vals[i];
161
+ }
162
+ }
163
+ return rvNumber(m);
164
+ });
165
+ }
166
+ export function fnDPRODUCT(args) {
167
+ return databaseNumericAggregate(args, vals => rvNumber(vals.length === 0 ? 0 : vals.reduce((a, b) => a * b, 1)));
168
+ }
169
+ export function fnDGET(args) {
170
+ const matches = collectDatabaseMatches(args);
171
+ if (!Array.isArray(matches)) {
172
+ return matches;
173
+ }
174
+ // DGET aggregator semantics: 0 matches → #VALUE!, exactly 1 → the value,
175
+ // >1 → #NUM!.
176
+ if (matches.length === 0) {
177
+ return ERRORS.VALUE;
178
+ }
179
+ if (matches.length > 1) {
180
+ return ERRORS.NUM;
181
+ }
182
+ return matches[0];
183
+ }
184
+ /**
185
+ * DCOUNTA(database, field, criteria) — count non-empty cells that match
186
+ * the criteria, in the specified field. Unlike DCOUNT (numeric-only),
187
+ * DCOUNTA counts any non-blank cell including text and booleans.
188
+ */
189
+ export function fnDCOUNTA(args) {
190
+ const matches = collectDatabaseMatches(args);
191
+ if (!Array.isArray(matches)) {
192
+ return matches;
193
+ }
194
+ let count = 0;
195
+ for (const v of matches) {
196
+ // Count anything that is not Blank and not an empty string.
197
+ if (v.kind === RVKind.Blank) {
198
+ continue;
199
+ }
200
+ if (v.kind === RVKind.String && v.value === "") {
201
+ continue;
202
+ }
203
+ count++;
204
+ }
205
+ return rvNumber(count);
206
+ }
207
+ /**
208
+ * DSTDEV(database, field, criteria) — sample standard deviation of
209
+ * numeric cells matching criteria in the specified field.
210
+ */
211
+ export function fnDSTDEV(args) {
212
+ return databaseNumericAggregate(args, vals => {
213
+ if (vals.length < 2) {
214
+ return ERRORS.DIV0;
215
+ }
216
+ const mean = vals.reduce((a, b) => a + b, 0) / vals.length;
217
+ let ss = 0;
218
+ for (const v of vals) {
219
+ ss += (v - mean) * (v - mean);
220
+ }
221
+ return rvNumber(Math.sqrt(ss / (vals.length - 1)));
222
+ });
223
+ }
224
+ /**
225
+ * DSTDEVP(database, field, criteria) — population standard deviation
226
+ * of numeric cells matching criteria.
227
+ */
228
+ export function fnDSTDEVP(args) {
229
+ return databaseNumericAggregate(args, vals => {
230
+ if (vals.length === 0) {
231
+ return ERRORS.DIV0;
232
+ }
233
+ const mean = vals.reduce((a, b) => a + b, 0) / vals.length;
234
+ let ss = 0;
235
+ for (const v of vals) {
236
+ ss += (v - mean) * (v - mean);
237
+ }
238
+ return rvNumber(Math.sqrt(ss / vals.length));
239
+ });
240
+ }
241
+ /**
242
+ * DVAR(database, field, criteria) — sample variance of matching numeric
243
+ * cells.
244
+ */
245
+ export function fnDVAR(args) {
246
+ return databaseNumericAggregate(args, vals => {
247
+ if (vals.length < 2) {
248
+ return ERRORS.DIV0;
249
+ }
250
+ const mean = vals.reduce((a, b) => a + b, 0) / vals.length;
251
+ let ss = 0;
252
+ for (const v of vals) {
253
+ ss += (v - mean) * (v - mean);
254
+ }
255
+ return rvNumber(ss / (vals.length - 1));
256
+ });
257
+ }
258
+ /**
259
+ * DVARP(database, field, criteria) — population variance of matching
260
+ * numeric cells.
261
+ */
262
+ export function fnDVARP(args) {
263
+ return databaseNumericAggregate(args, vals => {
264
+ if (vals.length === 0) {
265
+ return ERRORS.DIV0;
266
+ }
267
+ const mean = vals.reduce((a, b) => a + b, 0) / vals.length;
268
+ let ss = 0;
269
+ for (const v of vals) {
270
+ ss += (v - mean) * (v - mean);
271
+ }
272
+ return rvNumber(ss / vals.length);
273
+ });
274
+ }