@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.
- package/README.md +25 -2
- package/README_zh.md +29 -6
- package/dist/browser/index.browser.d.ts +1 -1
- package/dist/browser/index.browser.js +4 -0
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +4 -0
- package/dist/browser/modules/excel/cell.d.ts +17 -3
- package/dist/browser/modules/excel/cell.js +170 -22
- package/dist/browser/modules/excel/defined-names.d.ts +96 -1
- package/dist/browser/modules/excel/defined-names.js +411 -21
- package/dist/browser/modules/excel/image.d.ts +11 -0
- package/dist/browser/modules/excel/image.js +24 -1
- package/dist/browser/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
- package/dist/browser/modules/excel/stream/workbook-reader.browser.js +14 -0
- package/dist/browser/modules/excel/stream/workbook-reader.d.ts +2 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
- package/dist/browser/modules/excel/stream/workbook-writer.browser.js +48 -1
- package/dist/browser/modules/excel/stream/workbook-writer.d.ts +3 -2
- package/dist/browser/modules/excel/stream/worksheet-reader.js +17 -1
- package/dist/browser/modules/excel/stream/worksheet-writer.d.ts +39 -6
- package/dist/browser/modules/excel/stream/worksheet-writer.js +45 -5
- package/dist/browser/modules/excel/table.js +15 -2
- package/dist/browser/modules/excel/types.d.ts +133 -2
- package/dist/browser/modules/excel/utils/col-cache.d.ts +1 -0
- package/dist/browser/modules/excel/utils/col-cache.js +15 -0
- package/dist/browser/modules/excel/utils/drawing-utils.d.ts +3 -3
- package/dist/browser/modules/excel/utils/drawing-utils.js +4 -0
- package/dist/browser/modules/excel/utils/external-link-formula.d.ts +76 -0
- package/dist/browser/modules/excel/utils/external-link-formula.js +208 -0
- package/dist/browser/modules/excel/utils/iterate-stream.d.ts +9 -3
- package/dist/browser/modules/excel/utils/iterate-stream.js +3 -1
- package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +19 -0
- package/dist/browser/modules/excel/utils/ooxml-paths.js +37 -2
- package/dist/browser/modules/excel/utils/shared-strings.d.ts +8 -3
- package/dist/browser/modules/excel/utils/shared-strings.js +21 -2
- package/dist/browser/modules/excel/utils/workbook-protection.d.ts +30 -0
- package/dist/browser/modules/excel/utils/workbook-protection.js +30 -0
- package/dist/browser/modules/excel/workbook.browser.d.ts +257 -6
- package/dist/browser/modules/excel/workbook.browser.js +318 -34
- package/dist/browser/modules/excel/workbook.d.ts +1 -1
- package/dist/browser/modules/excel/worksheet.d.ts +3 -1
- package/dist/browser/modules/excel/worksheet.js +21 -2
- package/dist/browser/modules/excel/xlsx/rel-type.d.ts +15 -0
- package/dist/browser/modules/excel/xlsx/rel-type.js +16 -1
- package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
- package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
- package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
- package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
- package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
- package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
- package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
- package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
- package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
- package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
- package/dist/browser/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
- package/dist/browser/modules/excel/xlsx/xform/style/border-xform.js +4 -1
- package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +410 -20
- package/dist/browser/modules/excel/xlsx/xlsx.d.ts +7 -4
- package/dist/browser/modules/excel/xlsx/xlsx.js +4 -5
- package/dist/browser/modules/formula/compile/address-utils.d.ts +62 -0
- package/dist/browser/modules/formula/compile/address-utils.js +83 -0
- package/dist/browser/modules/formula/compile/binder.d.ts +42 -0
- package/dist/browser/modules/formula/compile/binder.js +487 -0
- package/dist/browser/modules/formula/compile/bound-ast.d.ts +230 -0
- package/dist/browser/modules/formula/compile/bound-ast.js +80 -0
- package/dist/browser/modules/formula/compile/compiled-formula.d.ts +137 -0
- package/dist/browser/modules/formula/compile/compiled-formula.js +383 -0
- package/dist/browser/modules/formula/compile/dependency-analysis.d.ts +93 -0
- package/dist/browser/modules/formula/compile/dependency-analysis.js +432 -0
- package/dist/browser/modules/formula/compile/structured-ref-utils.d.ts +93 -0
- package/dist/browser/modules/formula/compile/structured-ref-utils.js +136 -0
- package/dist/browser/modules/formula/default-syntax-probe.d.ts +79 -0
- package/dist/browser/modules/formula/default-syntax-probe.js +83 -0
- package/dist/browser/modules/formula/functions/_date-context.d.ts +4 -0
- package/dist/browser/modules/formula/functions/_date-context.js +29 -0
- package/dist/browser/modules/formula/functions/_shared.d.ts +121 -0
- package/dist/browser/modules/formula/functions/_shared.js +381 -0
- package/dist/browser/modules/formula/functions/conditional.d.ts +27 -0
- package/dist/browser/modules/formula/functions/conditional.js +343 -0
- package/dist/browser/modules/formula/functions/database.d.ts +37 -0
- package/dist/browser/modules/formula/functions/database.js +274 -0
- package/dist/browser/modules/formula/functions/date.d.ts +61 -0
- package/dist/browser/modules/formula/functions/date.js +855 -0
- package/dist/browser/modules/formula/functions/dynamic-array.d.ts +23 -0
- package/dist/browser/modules/formula/functions/dynamic-array.js +860 -0
- package/dist/browser/modules/formula/functions/engineering.d.ts +57 -0
- package/dist/browser/modules/formula/functions/engineering.js +1128 -0
- package/dist/browser/modules/formula/functions/financial.d.ts +202 -0
- package/dist/browser/modules/formula/functions/financial.js +2296 -0
- package/dist/browser/modules/formula/functions/lookup.d.ts +18 -0
- package/dist/browser/modules/formula/functions/lookup.js +886 -0
- package/dist/browser/modules/formula/functions/math.d.ts +114 -0
- package/dist/browser/modules/formula/functions/math.js +1406 -0
- package/dist/browser/modules/formula/functions/statistical.d.ts +193 -0
- package/dist/browser/modules/formula/functions/statistical.js +3390 -0
- package/dist/browser/modules/formula/functions/text.d.ts +86 -0
- package/dist/browser/modules/formula/functions/text.js +1845 -0
- package/dist/browser/modules/formula/host-registry.d.ts +53 -0
- package/dist/browser/modules/formula/host-registry.js +69 -0
- package/dist/browser/modules/formula/index.d.ts +39 -0
- package/dist/browser/modules/formula/index.js +49 -0
- package/dist/browser/modules/formula/install.d.ts +62 -0
- package/dist/browser/modules/formula/install.js +88 -0
- package/dist/browser/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
- package/dist/browser/modules/formula/integration/apply-writeback-plan.js +210 -0
- package/dist/browser/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
- package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +616 -0
- package/dist/browser/modules/formula/integration/calculate-formulas.d.ts +67 -0
- package/dist/browser/modules/formula/integration/calculate-formulas.js +68 -0
- package/dist/browser/modules/formula/integration/formula-instance.d.ts +64 -0
- package/dist/browser/modules/formula/integration/formula-instance.js +79 -0
- package/dist/browser/modules/formula/integration/workbook-adapter.d.ts +26 -0
- package/dist/browser/modules/formula/integration/workbook-adapter.js +324 -0
- package/dist/browser/modules/formula/integration/workbook-snapshot.d.ts +267 -0
- package/dist/browser/modules/formula/integration/workbook-snapshot.js +77 -0
- package/dist/browser/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
- package/dist/browser/modules/formula/materialize/build-writeback-plan.js +473 -0
- package/dist/browser/modules/formula/materialize/spill-engine.d.ts +9 -0
- package/dist/browser/modules/formula/materialize/spill-engine.js +38 -0
- package/dist/browser/modules/formula/materialize/types.d.ts +179 -0
- package/dist/browser/modules/formula/materialize/types.js +29 -0
- package/dist/browser/modules/formula/materialize/writeback-plan.d.ts +167 -0
- package/dist/browser/modules/formula/materialize/writeback-plan.js +27 -0
- package/dist/browser/modules/formula/runtime/evaluator.d.ts +151 -0
- package/dist/browser/modules/formula/runtime/evaluator.js +2291 -0
- package/dist/browser/modules/formula/runtime/function-registry.d.ts +47 -0
- package/dist/browser/modules/formula/runtime/function-registry.js +840 -0
- package/dist/browser/modules/formula/runtime/values.d.ts +211 -0
- package/dist/browser/modules/formula/runtime/values.js +385 -0
- package/dist/browser/modules/formula/syntax/ast.d.ts +129 -0
- package/dist/browser/modules/formula/syntax/ast.js +28 -0
- package/dist/browser/modules/formula/syntax/parser.d.ts +18 -0
- package/dist/browser/modules/formula/syntax/parser.js +439 -0
- package/dist/browser/modules/formula/syntax/token-types.d.ts +153 -0
- package/dist/browser/modules/formula/syntax/token-types.js +59 -0
- package/dist/browser/modules/formula/syntax/tokenizer.d.ts +10 -0
- package/dist/browser/modules/formula/syntax/tokenizer.js +1074 -0
- package/dist/browser/modules/pdf/excel-bridge.js +9 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/modules/excel/cell.js +170 -22
- package/dist/cjs/modules/excel/defined-names.js +411 -21
- package/dist/cjs/modules/excel/image.js +24 -1
- package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +14 -0
- package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +48 -1
- package/dist/cjs/modules/excel/stream/worksheet-reader.js +17 -1
- package/dist/cjs/modules/excel/stream/worksheet-writer.js +45 -5
- package/dist/cjs/modules/excel/table.js +15 -2
- package/dist/cjs/modules/excel/utils/col-cache.js +15 -0
- package/dist/cjs/modules/excel/utils/drawing-utils.js +4 -0
- package/dist/cjs/modules/excel/utils/external-link-formula.js +212 -0
- package/dist/cjs/modules/excel/utils/iterate-stream.js +3 -1
- package/dist/cjs/modules/excel/utils/ooxml-paths.js +42 -2
- package/dist/cjs/modules/excel/utils/shared-strings.js +21 -2
- package/dist/cjs/modules/excel/utils/workbook-protection.js +33 -0
- package/dist/cjs/modules/excel/workbook.browser.js +318 -34
- package/dist/cjs/modules/excel/worksheet.js +20 -1
- package/dist/cjs/modules/excel/xlsx/rel-type.js +16 -1
- package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
- package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +333 -0
- package/dist/cjs/modules/excel/xlsx/xform/book/external-reference-xform.js +27 -0
- package/dist/cjs/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
- package/dist/cjs/modules/excel/xlsx/xform/book/workbook-protection-xform.js +69 -0
- package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
- package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +18 -0
- package/dist/cjs/modules/excel/xlsx/xform/core/metadata-xform.js +161 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +108 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
- package/dist/cjs/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
- package/dist/cjs/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
- package/dist/cjs/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +83 -0
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
- package/dist/cjs/modules/excel/xlsx/xform/style/border-xform.js +4 -1
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +408 -18
- package/dist/cjs/modules/excel/xlsx/xlsx.js +4 -5
- package/dist/cjs/modules/formula/compile/address-utils.js +89 -0
- package/dist/cjs/modules/formula/compile/binder.js +489 -0
- package/dist/cjs/modules/formula/compile/bound-ast.js +68 -0
- package/dist/cjs/modules/formula/compile/compiled-formula.js +387 -0
- package/dist/cjs/modules/formula/compile/dependency-analysis.js +437 -0
- package/dist/cjs/modules/formula/compile/structured-ref-utils.js +141 -0
- package/dist/cjs/modules/formula/default-syntax-probe.js +87 -0
- package/dist/cjs/modules/formula/functions/_date-context.js +33 -0
- package/dist/cjs/modules/formula/functions/_shared.js +396 -0
- package/dist/cjs/modules/formula/functions/conditional.js +354 -0
- package/dist/cjs/modules/formula/functions/database.js +288 -0
- package/dist/cjs/modules/formula/functions/date.js +883 -0
- package/dist/cjs/modules/formula/functions/dynamic-array.js +881 -0
- package/dist/cjs/modules/formula/functions/engineering.js +1183 -0
- package/dist/cjs/modules/formula/functions/financial.js +2348 -0
- package/dist/cjs/modules/formula/functions/lookup.js +902 -0
- package/dist/cjs/modules/formula/functions/math.js +1487 -0
- package/dist/cjs/modules/formula/functions/statistical.js +3488 -0
- package/dist/cjs/modules/formula/functions/text.js +1889 -0
- package/dist/cjs/modules/formula/host-registry.js +75 -0
- package/dist/cjs/modules/formula/index.js +58 -0
- package/dist/cjs/modules/formula/install.js +93 -0
- package/dist/cjs/modules/formula/integration/apply-writeback-plan.js +213 -0
- package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +619 -0
- package/dist/cjs/modules/formula/integration/calculate-formulas.js +71 -0
- package/dist/cjs/modules/formula/integration/formula-instance.js +82 -0
- package/dist/cjs/modules/formula/integration/workbook-adapter.js +327 -0
- package/dist/cjs/modules/formula/integration/workbook-snapshot.js +84 -0
- package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +475 -0
- package/dist/cjs/modules/formula/materialize/spill-engine.js +42 -0
- package/dist/cjs/modules/formula/materialize/types.js +32 -0
- package/dist/cjs/modules/formula/materialize/writeback-plan.js +28 -0
- package/dist/cjs/modules/formula/runtime/evaluator.js +2298 -0
- package/dist/cjs/modules/formula/runtime/function-registry.js +846 -0
- package/dist/cjs/modules/formula/runtime/values.js +385 -0
- package/dist/cjs/modules/formula/syntax/ast.js +8 -0
- package/dist/cjs/modules/formula/syntax/parser.js +440 -0
- package/dist/cjs/modules/formula/syntax/token-types.js +32 -0
- package/dist/cjs/modules/formula/syntax/tokenizer.js +1076 -0
- package/dist/cjs/modules/pdf/excel-bridge.js +9 -0
- package/dist/esm/index.browser.js +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/modules/excel/cell.js +170 -22
- package/dist/esm/modules/excel/defined-names.js +411 -21
- package/dist/esm/modules/excel/image.js +24 -1
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +14 -0
- package/dist/esm/modules/excel/stream/workbook-writer.browser.js +48 -1
- package/dist/esm/modules/excel/stream/worksheet-reader.js +17 -1
- package/dist/esm/modules/excel/stream/worksheet-writer.js +45 -5
- package/dist/esm/modules/excel/table.js +15 -2
- package/dist/esm/modules/excel/utils/col-cache.js +15 -0
- package/dist/esm/modules/excel/utils/drawing-utils.js +4 -0
- package/dist/esm/modules/excel/utils/external-link-formula.js +208 -0
- package/dist/esm/modules/excel/utils/iterate-stream.js +3 -1
- package/dist/esm/modules/excel/utils/ooxml-paths.js +37 -2
- package/dist/esm/modules/excel/utils/shared-strings.js +21 -2
- package/dist/esm/modules/excel/utils/workbook-protection.js +30 -0
- package/dist/esm/modules/excel/workbook.browser.js +318 -34
- package/dist/esm/modules/excel/worksheet.js +21 -2
- package/dist/esm/modules/excel/xlsx/rel-type.js +16 -1
- package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
- package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
- package/dist/esm/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
- package/dist/esm/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
- package/dist/esm/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
- package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
- package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
- package/dist/esm/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
- package/dist/esm/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
- package/dist/esm/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
- package/dist/esm/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
- package/dist/esm/modules/excel/xlsx/xform/style/border-xform.js +4 -1
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +410 -20
- package/dist/esm/modules/excel/xlsx/xlsx.js +4 -5
- package/dist/esm/modules/formula/compile/address-utils.js +83 -0
- package/dist/esm/modules/formula/compile/binder.js +487 -0
- package/dist/esm/modules/formula/compile/bound-ast.js +80 -0
- package/dist/esm/modules/formula/compile/compiled-formula.js +383 -0
- package/dist/esm/modules/formula/compile/dependency-analysis.js +432 -0
- package/dist/esm/modules/formula/compile/structured-ref-utils.js +136 -0
- package/dist/esm/modules/formula/default-syntax-probe.js +83 -0
- package/dist/esm/modules/formula/functions/_date-context.js +29 -0
- package/dist/esm/modules/formula/functions/_shared.js +381 -0
- package/dist/esm/modules/formula/functions/conditional.js +343 -0
- package/dist/esm/modules/formula/functions/database.js +274 -0
- package/dist/esm/modules/formula/functions/date.js +855 -0
- package/dist/esm/modules/formula/functions/dynamic-array.js +860 -0
- package/dist/esm/modules/formula/functions/engineering.js +1128 -0
- package/dist/esm/modules/formula/functions/financial.js +2296 -0
- package/dist/esm/modules/formula/functions/lookup.js +886 -0
- package/dist/esm/modules/formula/functions/math.js +1406 -0
- package/dist/esm/modules/formula/functions/statistical.js +3390 -0
- package/dist/esm/modules/formula/functions/text.js +1845 -0
- package/dist/esm/modules/formula/host-registry.js +69 -0
- package/dist/esm/modules/formula/index.js +49 -0
- package/dist/esm/modules/formula/install.js +88 -0
- package/dist/esm/modules/formula/integration/apply-writeback-plan.js +210 -0
- package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +616 -0
- package/dist/esm/modules/formula/integration/calculate-formulas.js +68 -0
- package/dist/esm/modules/formula/integration/formula-instance.js +79 -0
- package/dist/esm/modules/formula/integration/workbook-adapter.js +324 -0
- package/dist/esm/modules/formula/integration/workbook-snapshot.js +77 -0
- package/dist/esm/modules/formula/materialize/build-writeback-plan.js +473 -0
- package/dist/esm/modules/formula/materialize/spill-engine.js +38 -0
- package/dist/esm/modules/formula/materialize/types.js +29 -0
- package/dist/esm/modules/formula/materialize/writeback-plan.js +27 -0
- package/dist/esm/modules/formula/runtime/evaluator.js +2291 -0
- package/dist/esm/modules/formula/runtime/function-registry.js +840 -0
- package/dist/esm/modules/formula/runtime/values.js +385 -0
- package/dist/esm/modules/formula/syntax/ast.js +28 -0
- package/dist/esm/modules/formula/syntax/parser.js +439 -0
- package/dist/esm/modules/formula/syntax/token-types.js +59 -0
- package/dist/esm/modules/formula/syntax/tokenizer.js +1074 -0
- package/dist/esm/modules/pdf/excel-bridge.js +9 -0
- package/dist/iife/excelts.iife.js +2302 -373
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +34 -34
- package/dist/types/index.browser.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/modules/excel/cell.d.ts +17 -3
- package/dist/types/modules/excel/defined-names.d.ts +96 -1
- package/dist/types/modules/excel/image.d.ts +11 -0
- package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
- package/dist/types/modules/excel/stream/workbook-reader.d.ts +2 -1
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
- package/dist/types/modules/excel/stream/workbook-writer.d.ts +3 -2
- package/dist/types/modules/excel/stream/worksheet-writer.d.ts +39 -6
- package/dist/types/modules/excel/types.d.ts +133 -2
- package/dist/types/modules/excel/utils/col-cache.d.ts +1 -0
- package/dist/types/modules/excel/utils/drawing-utils.d.ts +3 -3
- package/dist/types/modules/excel/utils/external-link-formula.d.ts +76 -0
- package/dist/types/modules/excel/utils/iterate-stream.d.ts +9 -3
- package/dist/types/modules/excel/utils/ooxml-paths.d.ts +19 -0
- package/dist/types/modules/excel/utils/shared-strings.d.ts +8 -3
- package/dist/types/modules/excel/utils/workbook-protection.d.ts +30 -0
- package/dist/types/modules/excel/workbook.browser.d.ts +257 -6
- package/dist/types/modules/excel/workbook.d.ts +1 -1
- package/dist/types/modules/excel/worksheet.d.ts +3 -1
- package/dist/types/modules/excel/xlsx/rel-type.d.ts +15 -0
- package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
- package/dist/types/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
- package/dist/types/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
- package/dist/types/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
- package/dist/types/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
- package/dist/types/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
- package/dist/types/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
- package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
- package/dist/types/modules/excel/xlsx/xlsx.d.ts +7 -4
- package/dist/types/modules/formula/compile/address-utils.d.ts +62 -0
- package/dist/types/modules/formula/compile/binder.d.ts +42 -0
- package/dist/types/modules/formula/compile/bound-ast.d.ts +230 -0
- package/dist/types/modules/formula/compile/compiled-formula.d.ts +137 -0
- package/dist/types/modules/formula/compile/dependency-analysis.d.ts +93 -0
- package/dist/types/modules/formula/compile/structured-ref-utils.d.ts +93 -0
- package/dist/types/modules/formula/default-syntax-probe.d.ts +79 -0
- package/dist/types/modules/formula/functions/_date-context.d.ts +4 -0
- package/dist/types/modules/formula/functions/_shared.d.ts +121 -0
- package/dist/types/modules/formula/functions/conditional.d.ts +27 -0
- package/dist/types/modules/formula/functions/database.d.ts +37 -0
- package/dist/types/modules/formula/functions/date.d.ts +61 -0
- package/dist/types/modules/formula/functions/dynamic-array.d.ts +23 -0
- package/dist/types/modules/formula/functions/engineering.d.ts +57 -0
- package/dist/types/modules/formula/functions/financial.d.ts +202 -0
- package/dist/types/modules/formula/functions/lookup.d.ts +18 -0
- package/dist/types/modules/formula/functions/math.d.ts +114 -0
- package/dist/types/modules/formula/functions/statistical.d.ts +193 -0
- package/dist/types/modules/formula/functions/text.d.ts +86 -0
- package/dist/types/modules/formula/host-registry.d.ts +53 -0
- package/dist/types/modules/formula/index.d.ts +39 -0
- package/dist/types/modules/formula/install.d.ts +62 -0
- package/dist/types/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
- package/dist/types/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
- package/dist/types/modules/formula/integration/calculate-formulas.d.ts +67 -0
- package/dist/types/modules/formula/integration/formula-instance.d.ts +64 -0
- package/dist/types/modules/formula/integration/workbook-adapter.d.ts +26 -0
- package/dist/types/modules/formula/integration/workbook-snapshot.d.ts +267 -0
- package/dist/types/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
- package/dist/types/modules/formula/materialize/spill-engine.d.ts +9 -0
- package/dist/types/modules/formula/materialize/types.d.ts +179 -0
- package/dist/types/modules/formula/materialize/writeback-plan.d.ts +167 -0
- package/dist/types/modules/formula/runtime/evaluator.d.ts +151 -0
- package/dist/types/modules/formula/runtime/function-registry.d.ts +47 -0
- package/dist/types/modules/formula/runtime/values.d.ts +211 -0
- package/dist/types/modules/formula/syntax/ast.d.ts +129 -0
- package/dist/types/modules/formula/syntax/parser.d.ts +18 -0
- package/dist/types/modules/formula/syntax/token-types.d.ts +153 -0
- package/dist/types/modules/formula/syntax/tokenizer.d.ts +10 -0
- 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,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Functions — Native RuntimeValue Implementation
|
|
3
|
+
*/
|
|
4
|
+
import type { RuntimeValue } from "../runtime/values.js";
|
|
5
|
+
export declare function fnDSUM(args: RuntimeValue[]): RuntimeValue;
|
|
6
|
+
export declare function fnDAVERAGE(args: RuntimeValue[]): RuntimeValue;
|
|
7
|
+
export declare function fnDCOUNT(args: RuntimeValue[]): RuntimeValue;
|
|
8
|
+
export declare function fnDMAX(args: RuntimeValue[]): RuntimeValue;
|
|
9
|
+
export declare function fnDMIN(args: RuntimeValue[]): RuntimeValue;
|
|
10
|
+
export declare function fnDPRODUCT(args: RuntimeValue[]): RuntimeValue;
|
|
11
|
+
export declare function fnDGET(args: RuntimeValue[]): RuntimeValue;
|
|
12
|
+
/**
|
|
13
|
+
* DCOUNTA(database, field, criteria) — count non-empty cells that match
|
|
14
|
+
* the criteria, in the specified field. Unlike DCOUNT (numeric-only),
|
|
15
|
+
* DCOUNTA counts any non-blank cell including text and booleans.
|
|
16
|
+
*/
|
|
17
|
+
export declare function fnDCOUNTA(args: RuntimeValue[]): RuntimeValue;
|
|
18
|
+
/**
|
|
19
|
+
* DSTDEV(database, field, criteria) — sample standard deviation of
|
|
20
|
+
* numeric cells matching criteria in the specified field.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fnDSTDEV(args: RuntimeValue[]): RuntimeValue;
|
|
23
|
+
/**
|
|
24
|
+
* DSTDEVP(database, field, criteria) — population standard deviation
|
|
25
|
+
* of numeric cells matching criteria.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fnDSTDEVP(args: RuntimeValue[]): RuntimeValue;
|
|
28
|
+
/**
|
|
29
|
+
* DVAR(database, field, criteria) — sample variance of matching numeric
|
|
30
|
+
* cells.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fnDVAR(args: RuntimeValue[]): RuntimeValue;
|
|
33
|
+
/**
|
|
34
|
+
* DVARP(database, field, criteria) — population variance of matching
|
|
35
|
+
* numeric cells.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fnDVARP(args: RuntimeValue[]): RuntimeValue;
|
|
@@ -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
|
+
}
|