@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,860 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Array Functions — Native RuntimeValue Implementation
|
|
3
|
+
*/
|
|
4
|
+
import { RVKind, ERRORS, compareScalarsSameKind, rvNumber, rvArray, toNumberRV, toBooleanRV, topLeft, isError, isArray } from "../runtime/values.js";
|
|
5
|
+
import { asArray, getCell, stripErrorCells, stripHiddenRowCells, stripSubtotalMaskedCells } from "./_shared.js";
|
|
6
|
+
import { fnSUM, fnAVERAGE, fnMIN, fnMAX, fnCOUNT, fnCOUNTA, fnPRODUCT } from "./math.js";
|
|
7
|
+
import { fnSTDEV, fnSTDEVP, fnVAR, fnVARP, fnMEDIAN, fnLARGE, fnSMALL, fnMODE, fnPERCENTILE, fnPERCENTILEEXC, fnQUARTILE, fnQUARTILEEXC } from "./statistical.js";
|
|
8
|
+
function isScalarError(v) {
|
|
9
|
+
return v.kind === RVKind.Error;
|
|
10
|
+
}
|
|
11
|
+
function isScalarBlankOrEmpty(v) {
|
|
12
|
+
return v.kind === RVKind.Blank || (v.kind === RVKind.String && v.value === "");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Kind-priority ordering for cross-type sorting.
|
|
16
|
+
*
|
|
17
|
+
* `compareScalarsSameKind` returns `NaN` when the two operands have
|
|
18
|
+
* different kinds, so SORT/SORTBY need a deterministic tiebreak. Excel's
|
|
19
|
+
* workbook-grade sort groups values by kind — Numbers before Strings,
|
|
20
|
+
* Strings before Booleans, Booleans before Blanks/Errors — which is the
|
|
21
|
+
* priority we encode here.
|
|
22
|
+
*/
|
|
23
|
+
function kindPriority(k) {
|
|
24
|
+
switch (k) {
|
|
25
|
+
case RVKind.Number:
|
|
26
|
+
return 0;
|
|
27
|
+
case RVKind.String:
|
|
28
|
+
return 1;
|
|
29
|
+
case RVKind.Boolean:
|
|
30
|
+
return 2;
|
|
31
|
+
case RVKind.Blank:
|
|
32
|
+
return 3;
|
|
33
|
+
case RVKind.Error:
|
|
34
|
+
return 4;
|
|
35
|
+
default:
|
|
36
|
+
return 5;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Locale-independent comparator for SORT / SORTBY.
|
|
41
|
+
*
|
|
42
|
+
* Uses `compareScalarsSameKind` for same-kind ordering (strings compared
|
|
43
|
+
* case-insensitively, not via `localeCompare`, so results are stable
|
|
44
|
+
* across machines) and falls back to `kindPriority` when the operands
|
|
45
|
+
* differ in kind.
|
|
46
|
+
*/
|
|
47
|
+
function compareForSort(a, b) {
|
|
48
|
+
if (a.kind !== b.kind) {
|
|
49
|
+
return kindPriority(a.kind) - kindPriority(b.kind);
|
|
50
|
+
}
|
|
51
|
+
const cmp = compareScalarsSameKind(a, b);
|
|
52
|
+
return Number.isNaN(cmp) ? 0 : cmp;
|
|
53
|
+
}
|
|
54
|
+
export function fnFILTER(args) {
|
|
55
|
+
const dataArr = asArray(args[0]);
|
|
56
|
+
const includeArr = asArray(args[1]);
|
|
57
|
+
if (!dataArr || !includeArr) {
|
|
58
|
+
return ERRORS.VALUE;
|
|
59
|
+
}
|
|
60
|
+
// Excel requires `include` to be a 1-column vector matching data's
|
|
61
|
+
// height (the common row-filter shape). A mismatched shape previously
|
|
62
|
+
// let rows slip through silently because `getCell` out-of-bounds
|
|
63
|
+
// returns BLANK, which reads as FALSE.
|
|
64
|
+
if (includeArr.width !== 1 || includeArr.height !== dataArr.height) {
|
|
65
|
+
return ERRORS.VALUE;
|
|
66
|
+
}
|
|
67
|
+
const ifEmpty = args.length > 2 ? topLeft(args[2]) : null;
|
|
68
|
+
const resultRows = [];
|
|
69
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
70
|
+
const inc = getCell(includeArr, r, 0);
|
|
71
|
+
if (inc.kind === RVKind.Error) {
|
|
72
|
+
return inc;
|
|
73
|
+
}
|
|
74
|
+
if ((inc.kind === RVKind.Boolean && inc.value) ||
|
|
75
|
+
(inc.kind === RVKind.Number && inc.value !== 0)) {
|
|
76
|
+
const row = [];
|
|
77
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
78
|
+
row.push(getCell(dataArr, r, c));
|
|
79
|
+
}
|
|
80
|
+
resultRows.push(row);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (resultRows.length === 0) {
|
|
84
|
+
return ifEmpty !== null ? rvArray([[ifEmpty]]) : ERRORS.CALC;
|
|
85
|
+
}
|
|
86
|
+
return rvArray(resultRows);
|
|
87
|
+
}
|
|
88
|
+
export function fnSORT(args) {
|
|
89
|
+
const dataArr = asArray(args[0]);
|
|
90
|
+
if (!dataArr) {
|
|
91
|
+
return ERRORS.VALUE;
|
|
92
|
+
}
|
|
93
|
+
const rows = [];
|
|
94
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
95
|
+
const row = [];
|
|
96
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
97
|
+
row.push(getCell(dataArr, r, c));
|
|
98
|
+
}
|
|
99
|
+
rows.push(row);
|
|
100
|
+
}
|
|
101
|
+
const sortIndexV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(1);
|
|
102
|
+
if (isError(sortIndexV)) {
|
|
103
|
+
return sortIndexV;
|
|
104
|
+
}
|
|
105
|
+
const sortOrderV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(1);
|
|
106
|
+
if (isError(sortOrderV)) {
|
|
107
|
+
return sortOrderV;
|
|
108
|
+
}
|
|
109
|
+
const byColV = args.length > 3 ? toBooleanRV(args[3]) : { kind: RVKind.Boolean, value: false };
|
|
110
|
+
if (isError(byColV)) {
|
|
111
|
+
return byColV;
|
|
112
|
+
}
|
|
113
|
+
// Truncate the index so fractional inputs don't silently become NaN
|
|
114
|
+
// when used as array subscripts. Then bounds-check against the axis
|
|
115
|
+
// SORT will actually walk — this turns `SORT(arr, 0)` / out-of-range
|
|
116
|
+
// values into the documented #VALUE! instead of a soft-fail.
|
|
117
|
+
const sortIndex = Math.trunc(sortIndexV.value);
|
|
118
|
+
if (byColV.value) {
|
|
119
|
+
if (sortIndex < 1 || sortIndex > dataArr.height) {
|
|
120
|
+
return ERRORS.VALUE;
|
|
121
|
+
}
|
|
122
|
+
const colIndices = Array.from({ length: dataArr.width }, (_, i) => i);
|
|
123
|
+
const rowIdx = sortIndex - 1;
|
|
124
|
+
colIndices.sort((a, b) => {
|
|
125
|
+
const va = getCell(dataArr, rowIdx, a);
|
|
126
|
+
const vb = getCell(dataArr, rowIdx, b);
|
|
127
|
+
return compareForSort(va, vb) * sortOrderV.value;
|
|
128
|
+
});
|
|
129
|
+
return rvArray(rows.map(row => colIndices.map(c => row[c])));
|
|
130
|
+
}
|
|
131
|
+
if (sortIndex < 1 || sortIndex > dataArr.width) {
|
|
132
|
+
return ERRORS.VALUE;
|
|
133
|
+
}
|
|
134
|
+
const col = sortIndex - 1;
|
|
135
|
+
rows.sort((a, b) => compareForSort(a[col], b[col]) * sortOrderV.value);
|
|
136
|
+
return rvArray(rows);
|
|
137
|
+
}
|
|
138
|
+
export function fnUNIQUE(args) {
|
|
139
|
+
const dataArr = asArray(args[0]);
|
|
140
|
+
if (!dataArr) {
|
|
141
|
+
return ERRORS.VALUE;
|
|
142
|
+
}
|
|
143
|
+
const byColV = args.length > 1 ? toBooleanRV(args[1]) : { kind: RVKind.Boolean, value: false };
|
|
144
|
+
if (isError(byColV)) {
|
|
145
|
+
return byColV;
|
|
146
|
+
}
|
|
147
|
+
const exactlyOnceV = args.length > 2 ? toBooleanRV(args[2]) : { kind: RVKind.Boolean, value: false };
|
|
148
|
+
if (isError(exactlyOnceV)) {
|
|
149
|
+
return exactlyOnceV;
|
|
150
|
+
}
|
|
151
|
+
if (byColV.value) {
|
|
152
|
+
const transposed = [];
|
|
153
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
154
|
+
const col = [];
|
|
155
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
156
|
+
col.push(getCell(dataArr, r, c));
|
|
157
|
+
}
|
|
158
|
+
transposed.push(col);
|
|
159
|
+
}
|
|
160
|
+
const unique = applyUnique(transposed, exactlyOnceV.value);
|
|
161
|
+
if (unique.length === 0) {
|
|
162
|
+
return ERRORS.VALUE;
|
|
163
|
+
}
|
|
164
|
+
const numRows = unique[0].length;
|
|
165
|
+
const result = [];
|
|
166
|
+
for (let r = 0; r < numRows; r++) {
|
|
167
|
+
result.push(unique.map(ci => ci[r]));
|
|
168
|
+
}
|
|
169
|
+
return rvArray(result);
|
|
170
|
+
}
|
|
171
|
+
const dataRows = [];
|
|
172
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
173
|
+
const row = [];
|
|
174
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
175
|
+
row.push(getCell(dataArr, r, c));
|
|
176
|
+
}
|
|
177
|
+
dataRows.push(row);
|
|
178
|
+
}
|
|
179
|
+
const result = applyUnique(dataRows, exactlyOnceV.value);
|
|
180
|
+
return result.length > 0 ? rvArray(result) : ERRORS.VALUE;
|
|
181
|
+
}
|
|
182
|
+
function applyUnique(rows, exactlyOnce) {
|
|
183
|
+
const keyCount = new Map();
|
|
184
|
+
const keyToRows = new Map();
|
|
185
|
+
const order = [];
|
|
186
|
+
for (const row of rows) {
|
|
187
|
+
// Key the row by (kind, textual form) per cell so that UNIQUE preserves
|
|
188
|
+
// Excel's type-aware equality: the number `1` and the string `"1"` are
|
|
189
|
+
// distinct entries. Without the kind prefix they would collide because
|
|
190
|
+
// `toStringRV` renders both as `"1"`.
|
|
191
|
+
const key = row.map(c => `${c.kind}\u0001${scalarUniqueKey(c)}`).join("\u0002");
|
|
192
|
+
if (!keyCount.has(key)) {
|
|
193
|
+
order.push(key);
|
|
194
|
+
keyToRows.set(key, row);
|
|
195
|
+
}
|
|
196
|
+
keyCount.set(key, (keyCount.get(key) ?? 0) + 1);
|
|
197
|
+
}
|
|
198
|
+
const result = [];
|
|
199
|
+
for (const key of order) {
|
|
200
|
+
if (exactlyOnce && (keyCount.get(key) ?? 0) > 1) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
result.push(keyToRows.get(key));
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Produce a string that fully identifies a scalar for equality purposes,
|
|
209
|
+
* distinguishing kinds that stringify identically but must not merge.
|
|
210
|
+
*/
|
|
211
|
+
function scalarUniqueKey(v) {
|
|
212
|
+
if (v.kind === RVKind.Number) {
|
|
213
|
+
// Using `toString` instead of localised formatting keeps NaN/Infinity
|
|
214
|
+
// / -0 distinguishable from `0`, which matters for exact duplication
|
|
215
|
+
// detection.
|
|
216
|
+
return Object.is(v.value, -0) ? "-0" : String(v.value);
|
|
217
|
+
}
|
|
218
|
+
if (v.kind === RVKind.Boolean) {
|
|
219
|
+
return v.value ? "1" : "0";
|
|
220
|
+
}
|
|
221
|
+
if (v.kind === RVKind.Error) {
|
|
222
|
+
return v.code;
|
|
223
|
+
}
|
|
224
|
+
if (v.kind === RVKind.Blank) {
|
|
225
|
+
return "";
|
|
226
|
+
}
|
|
227
|
+
return v.value.toLowerCase();
|
|
228
|
+
}
|
|
229
|
+
export function fnSORTBY(args) {
|
|
230
|
+
const dataArr = asArray(args[0]);
|
|
231
|
+
if (!dataArr || args.length < 2) {
|
|
232
|
+
return ERRORS.VALUE;
|
|
233
|
+
}
|
|
234
|
+
const data = [];
|
|
235
|
+
for (let r = 0; r < dataArr.height; r++) {
|
|
236
|
+
const row = [];
|
|
237
|
+
for (let c = 0; c < dataArr.width; c++) {
|
|
238
|
+
row.push(getCell(dataArr, r, c));
|
|
239
|
+
}
|
|
240
|
+
data.push({ row, idx: r });
|
|
241
|
+
}
|
|
242
|
+
const sortKeys = [];
|
|
243
|
+
for (let i = 1; i < args.length; i += 2) {
|
|
244
|
+
const keyArr = asArray(args[i]);
|
|
245
|
+
if (!keyArr) {
|
|
246
|
+
return ERRORS.VALUE;
|
|
247
|
+
}
|
|
248
|
+
const orderV = i + 1 < args.length ? toNumberRV(args[i + 1]) : rvNumber(1);
|
|
249
|
+
if (isError(orderV)) {
|
|
250
|
+
return orderV;
|
|
251
|
+
}
|
|
252
|
+
sortKeys.push({ arr: keyArr, order: orderV.value });
|
|
253
|
+
}
|
|
254
|
+
data.sort((a, b) => {
|
|
255
|
+
for (const sk of sortKeys) {
|
|
256
|
+
const va = getCell(sk.arr, a.idx, 0);
|
|
257
|
+
const vb = getCell(sk.arr, b.idx, 0);
|
|
258
|
+
const cmp = compareForSort(va, vb);
|
|
259
|
+
if (cmp !== 0) {
|
|
260
|
+
return cmp * sk.order;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return 0;
|
|
264
|
+
});
|
|
265
|
+
return rvArray(data.map(d => d.row));
|
|
266
|
+
}
|
|
267
|
+
export function fnSUBTOTAL(args) {
|
|
268
|
+
const funcNumV = toNumberRV(args[0]);
|
|
269
|
+
if (isError(funcNumV)) {
|
|
270
|
+
return funcNumV;
|
|
271
|
+
}
|
|
272
|
+
// Excel skips cells whose own formula is SUBTOTAL/AGGREGATE to avoid
|
|
273
|
+
// double-counting when an outer aggregate spans a totals row or another
|
|
274
|
+
// subtotal cell. `buildRangeArray` marks those cells via
|
|
275
|
+
// `subtotalMask`; we strip them here before handing off to the
|
|
276
|
+
// underlying aggregator.
|
|
277
|
+
let dataArgs = stripSubtotalMaskedCells(args.slice(1));
|
|
278
|
+
// Truncate toward zero: Excel rejects non-integer function codes, so
|
|
279
|
+
// `SUBTOTAL(9.5, …)` should behave as `SUBTOTAL(9, …)` rather than
|
|
280
|
+
// slipping through the switch and returning #VALUE!. (R6-P1-9)
|
|
281
|
+
const rawFn = Math.trunc(funcNumV.value);
|
|
282
|
+
const fn = rawFn > 100 ? rawFn - 100 : rawFn;
|
|
283
|
+
// The 1xx variants (101-111) additionally skip hidden rows. Excel's
|
|
284
|
+
// plain 1-11 codes only skip filter-hidden rows — but our worksheet
|
|
285
|
+
// model carries a single `row.hidden` boolean that conflates the two
|
|
286
|
+
// states, so we apply hidden-row stripping only to the 1xx variants
|
|
287
|
+
// (matching manual-hide semantics; filter-hide remains a limitation
|
|
288
|
+
// at the adapter layer, not here).
|
|
289
|
+
if (rawFn > 100) {
|
|
290
|
+
dataArgs = stripHiddenRowCells(dataArgs);
|
|
291
|
+
}
|
|
292
|
+
switch (fn) {
|
|
293
|
+
case 1:
|
|
294
|
+
return fnAVERAGE(dataArgs);
|
|
295
|
+
case 2:
|
|
296
|
+
return fnCOUNT(dataArgs);
|
|
297
|
+
case 3:
|
|
298
|
+
return fnCOUNTA(dataArgs);
|
|
299
|
+
case 4:
|
|
300
|
+
return fnMAX(dataArgs);
|
|
301
|
+
case 5:
|
|
302
|
+
return fnMIN(dataArgs);
|
|
303
|
+
case 6:
|
|
304
|
+
return fnPRODUCT(dataArgs);
|
|
305
|
+
case 7:
|
|
306
|
+
return fnSTDEV(dataArgs);
|
|
307
|
+
case 8:
|
|
308
|
+
return fnSTDEVP(dataArgs);
|
|
309
|
+
case 9:
|
|
310
|
+
return fnSUM(dataArgs);
|
|
311
|
+
case 10:
|
|
312
|
+
return fnVAR(dataArgs);
|
|
313
|
+
case 11:
|
|
314
|
+
return fnVARP(dataArgs);
|
|
315
|
+
default:
|
|
316
|
+
return ERRORS.VALUE;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
export function fnAGGREGATE(args) {
|
|
320
|
+
const funcNumV = toNumberRV(args[0]);
|
|
321
|
+
if (isError(funcNumV)) {
|
|
322
|
+
return funcNumV;
|
|
323
|
+
}
|
|
324
|
+
// Resolve the "options" parameter (arg[1]). Excel's option codes
|
|
325
|
+
// (0–7) control which cells to skip:
|
|
326
|
+
// 0 or omitted → ignore nested SUBTOTAL/AGGREGATE
|
|
327
|
+
// 1 → ignore hidden rows + nested
|
|
328
|
+
// 2 → ignore errors + nested
|
|
329
|
+
// 3 → ignore hidden rows + errors + nested
|
|
330
|
+
// 4 → ignore nothing
|
|
331
|
+
// 5 → ignore hidden rows (keep nested)
|
|
332
|
+
// 6 → ignore errors (keep nested)
|
|
333
|
+
// 7 → ignore hidden rows + errors (keep nested)
|
|
334
|
+
const optV = args[1] !== undefined ? toNumberRV(args[1]) : undefined;
|
|
335
|
+
if (optV && isError(optV)) {
|
|
336
|
+
return optV;
|
|
337
|
+
}
|
|
338
|
+
const option = optV ? Math.trunc(optV.value) : 0;
|
|
339
|
+
const skipNested = option <= 3; // 0,1,2,3 skip nested SUBTOTAL/AGGREGATE
|
|
340
|
+
const skipHidden = option === 1 || option === 3 || option === 5 || option === 7;
|
|
341
|
+
const skipErrors = option === 2 || option === 3 || option === 6 || option === 7;
|
|
342
|
+
let dataArgs = args.slice(2);
|
|
343
|
+
if (skipNested) {
|
|
344
|
+
dataArgs = stripSubtotalMaskedCells(dataArgs);
|
|
345
|
+
}
|
|
346
|
+
if (skipHidden) {
|
|
347
|
+
dataArgs = stripHiddenRowCells(dataArgs);
|
|
348
|
+
}
|
|
349
|
+
if (skipErrors) {
|
|
350
|
+
dataArgs = stripErrorCells(dataArgs);
|
|
351
|
+
}
|
|
352
|
+
// Excel rejects non-integer function codes; truncate toward zero
|
|
353
|
+
// so AGGREGATE(9.5, …) behaves as AGGREGATE(9, …), matching SUBTOTAL.
|
|
354
|
+
const fnCode = Math.trunc(funcNumV.value);
|
|
355
|
+
switch (fnCode) {
|
|
356
|
+
case 1:
|
|
357
|
+
return fnAVERAGE(dataArgs);
|
|
358
|
+
case 2:
|
|
359
|
+
return fnCOUNT(dataArgs);
|
|
360
|
+
case 3:
|
|
361
|
+
return fnCOUNTA(dataArgs);
|
|
362
|
+
case 4:
|
|
363
|
+
return fnMAX(dataArgs);
|
|
364
|
+
case 5:
|
|
365
|
+
return fnMIN(dataArgs);
|
|
366
|
+
case 6:
|
|
367
|
+
return fnPRODUCT(dataArgs);
|
|
368
|
+
case 7:
|
|
369
|
+
return fnSTDEV(dataArgs);
|
|
370
|
+
case 8:
|
|
371
|
+
return fnSTDEVP(dataArgs);
|
|
372
|
+
case 9:
|
|
373
|
+
return fnSUM(dataArgs);
|
|
374
|
+
case 10:
|
|
375
|
+
return fnVAR(dataArgs);
|
|
376
|
+
case 11:
|
|
377
|
+
return fnVARP(dataArgs);
|
|
378
|
+
case 12:
|
|
379
|
+
return fnMEDIAN(dataArgs);
|
|
380
|
+
case 13:
|
|
381
|
+
return fnMODE(dataArgs);
|
|
382
|
+
case 14:
|
|
383
|
+
return fnLARGE(dataArgs);
|
|
384
|
+
case 15:
|
|
385
|
+
return fnSMALL(dataArgs);
|
|
386
|
+
case 16:
|
|
387
|
+
return fnPERCENTILE(dataArgs);
|
|
388
|
+
case 17:
|
|
389
|
+
return fnQUARTILE(dataArgs);
|
|
390
|
+
case 18:
|
|
391
|
+
return fnPERCENTILEEXC(dataArgs);
|
|
392
|
+
case 19:
|
|
393
|
+
return fnQUARTILEEXC(dataArgs);
|
|
394
|
+
default:
|
|
395
|
+
return ERRORS.VALUE;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
export function fnSEQUENCE(args) {
|
|
399
|
+
const rowsV = toNumberRV(args[0]);
|
|
400
|
+
if (isError(rowsV)) {
|
|
401
|
+
return rowsV;
|
|
402
|
+
}
|
|
403
|
+
const colsV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(1);
|
|
404
|
+
if (isError(colsV)) {
|
|
405
|
+
return colsV;
|
|
406
|
+
}
|
|
407
|
+
const startV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(1);
|
|
408
|
+
if (isError(startV)) {
|
|
409
|
+
return startV;
|
|
410
|
+
}
|
|
411
|
+
const stepV = args.length > 3 ? toNumberRV(args[3]) : rvNumber(1);
|
|
412
|
+
if (isError(stepV)) {
|
|
413
|
+
return stepV;
|
|
414
|
+
}
|
|
415
|
+
// Excel truncates row/col counts toward zero and rejects anything
|
|
416
|
+
// below 1. Without this guard `SEQUENCE(-3)` would produce an empty
|
|
417
|
+
// ArrayValue which breaks downstream rectangularisation, and
|
|
418
|
+
// `SEQUENCE(2.5, 2)` would generate 3 rows instead of Excel's 2.
|
|
419
|
+
const rowCount = Math.trunc(rowsV.value);
|
|
420
|
+
const colCount = Math.trunc(colsV.value);
|
|
421
|
+
if (!Number.isFinite(rowCount) || !Number.isFinite(colCount) || rowCount < 1 || colCount < 1) {
|
|
422
|
+
return ERRORS.NUM;
|
|
423
|
+
}
|
|
424
|
+
// Bound the output to the same 10M-cell budget the rest of the array
|
|
425
|
+
// pipeline uses. SEQUENCE(1e9, 1e9) would otherwise try to allocate
|
|
426
|
+
// 1e18 scalars before OOM-ing (R6-P1-4).
|
|
427
|
+
if (rowCount * colCount > 10000000) {
|
|
428
|
+
return ERRORS.NUM;
|
|
429
|
+
}
|
|
430
|
+
const result = [];
|
|
431
|
+
let val = startV.value;
|
|
432
|
+
for (let r = 0; r < rowCount; r++) {
|
|
433
|
+
const row = [];
|
|
434
|
+
for (let c = 0; c < colCount; c++) {
|
|
435
|
+
row.push(rvNumber(val));
|
|
436
|
+
val += stepV.value;
|
|
437
|
+
}
|
|
438
|
+
result.push(row);
|
|
439
|
+
}
|
|
440
|
+
return rvArray(result);
|
|
441
|
+
}
|
|
442
|
+
export function fnRANDARRAY(args) {
|
|
443
|
+
const rowsV = args.length > 0 ? toNumberRV(args[0]) : rvNumber(1);
|
|
444
|
+
if (isError(rowsV)) {
|
|
445
|
+
return rowsV;
|
|
446
|
+
}
|
|
447
|
+
const colsV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(1);
|
|
448
|
+
if (isError(colsV)) {
|
|
449
|
+
return colsV;
|
|
450
|
+
}
|
|
451
|
+
const minV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(0);
|
|
452
|
+
if (isError(minV)) {
|
|
453
|
+
return minV;
|
|
454
|
+
}
|
|
455
|
+
const maxV = args.length > 3 ? toNumberRV(args[3]) : rvNumber(1);
|
|
456
|
+
if (isError(maxV)) {
|
|
457
|
+
return maxV;
|
|
458
|
+
}
|
|
459
|
+
const wholeV = args.length > 4 ? toBooleanRV(args[4]) : { kind: RVKind.Boolean, value: false };
|
|
460
|
+
if (isError(wholeV)) {
|
|
461
|
+
return wholeV;
|
|
462
|
+
}
|
|
463
|
+
const rowCount = Math.trunc(rowsV.value);
|
|
464
|
+
const colCount = Math.trunc(colsV.value);
|
|
465
|
+
// Excel rejects rows/cols < 1 and min > max with #VALUE!, and when the
|
|
466
|
+
// `whole` flag is TRUE it additionally requires integer min/max.
|
|
467
|
+
if (!Number.isFinite(rowCount) ||
|
|
468
|
+
!Number.isFinite(colCount) ||
|
|
469
|
+
rowCount < 1 ||
|
|
470
|
+
colCount < 1 ||
|
|
471
|
+
minV.value > maxV.value) {
|
|
472
|
+
return ERRORS.VALUE;
|
|
473
|
+
}
|
|
474
|
+
if (wholeV.value && (!Number.isInteger(minV.value) || !Number.isInteger(maxV.value))) {
|
|
475
|
+
return ERRORS.VALUE;
|
|
476
|
+
}
|
|
477
|
+
// Same 10M-cell budget as SEQUENCE / MAKEARRAY / broadcastBinaryOp —
|
|
478
|
+
// otherwise `RANDARRAY(1e6, 1e6)` OOMs the host. (R6-P1-4)
|
|
479
|
+
if (rowCount * colCount > 10000000) {
|
|
480
|
+
return ERRORS.NUM;
|
|
481
|
+
}
|
|
482
|
+
const result = [];
|
|
483
|
+
for (let r = 0; r < rowCount; r++) {
|
|
484
|
+
const row = [];
|
|
485
|
+
for (let c = 0; c < colCount; c++) {
|
|
486
|
+
if (wholeV.value) {
|
|
487
|
+
// Draw a uniform integer in [min, max] inclusive. The old code
|
|
488
|
+
// did `Math.floor(min + random() * (max - min))` which excluded
|
|
489
|
+
// `max` almost always.
|
|
490
|
+
const span = maxV.value - minV.value + 1;
|
|
491
|
+
row.push(rvNumber(minV.value + Math.floor(Math.random() * span)));
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
row.push(rvNumber(minV.value + Math.random() * (maxV.value - minV.value)));
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
result.push(row);
|
|
498
|
+
}
|
|
499
|
+
return rvArray(result);
|
|
500
|
+
}
|
|
501
|
+
export function fnTOCOL(args) {
|
|
502
|
+
if (!isArray(args[0])) {
|
|
503
|
+
return rvArray([[topLeft(args[0])]]);
|
|
504
|
+
}
|
|
505
|
+
const arr = args[0];
|
|
506
|
+
const ignoreV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
|
|
507
|
+
if (isError(ignoreV)) {
|
|
508
|
+
return ignoreV;
|
|
509
|
+
}
|
|
510
|
+
const scanV = args.length > 2 ? toBooleanRV(args[2]) : { kind: RVKind.Boolean, value: false };
|
|
511
|
+
if (isError(scanV)) {
|
|
512
|
+
return scanV;
|
|
513
|
+
}
|
|
514
|
+
const result = [];
|
|
515
|
+
const addCell = (v) => {
|
|
516
|
+
if (ignoreV.value === 1 && isScalarBlankOrEmpty(v)) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (ignoreV.value === 2 && isScalarError(v)) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (ignoreV.value === 3 && (isScalarBlankOrEmpty(v) || isScalarError(v))) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
result.push([v]);
|
|
526
|
+
};
|
|
527
|
+
if (scanV.value) {
|
|
528
|
+
for (let c = 0; c < arr.width; c++) {
|
|
529
|
+
for (let r = 0; r < arr.height; r++) {
|
|
530
|
+
addCell(getCell(arr, r, c));
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
for (let r = 0; r < arr.height; r++) {
|
|
536
|
+
for (let c = 0; c < arr.width; c++) {
|
|
537
|
+
addCell(getCell(arr, r, c));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return result.length > 0 ? rvArray(result) : ERRORS.CALC;
|
|
542
|
+
}
|
|
543
|
+
export function fnTOROW(args) {
|
|
544
|
+
if (!isArray(args[0])) {
|
|
545
|
+
return rvArray([[topLeft(args[0])]]);
|
|
546
|
+
}
|
|
547
|
+
const arr = args[0];
|
|
548
|
+
const ignoreV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
|
|
549
|
+
if (isError(ignoreV)) {
|
|
550
|
+
return ignoreV;
|
|
551
|
+
}
|
|
552
|
+
const scanV = args.length > 2 ? toBooleanRV(args[2]) : { kind: RVKind.Boolean, value: false };
|
|
553
|
+
if (isError(scanV)) {
|
|
554
|
+
return scanV;
|
|
555
|
+
}
|
|
556
|
+
const result = [];
|
|
557
|
+
const addCell = (v) => {
|
|
558
|
+
if (ignoreV.value === 1 && isScalarBlankOrEmpty(v)) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
if (ignoreV.value === 2 && isScalarError(v)) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (ignoreV.value === 3 && (isScalarBlankOrEmpty(v) || isScalarError(v))) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
result.push(v);
|
|
568
|
+
};
|
|
569
|
+
if (scanV.value) {
|
|
570
|
+
for (let c = 0; c < arr.width; c++) {
|
|
571
|
+
for (let r = 0; r < arr.height; r++) {
|
|
572
|
+
addCell(getCell(arr, r, c));
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
for (let r = 0; r < arr.height; r++) {
|
|
578
|
+
for (let c = 0; c < arr.width; c++) {
|
|
579
|
+
addCell(getCell(arr, r, c));
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return result.length > 0 ? rvArray([result]) : ERRORS.CALC;
|
|
584
|
+
}
|
|
585
|
+
export function fnCHOOSEROWS(args) {
|
|
586
|
+
const d = asArray(args[0]);
|
|
587
|
+
if (!d) {
|
|
588
|
+
return ERRORS.VALUE;
|
|
589
|
+
}
|
|
590
|
+
const result = [];
|
|
591
|
+
for (let i = 1; i < args.length; i++) {
|
|
592
|
+
const nV = toNumberRV(args[i]);
|
|
593
|
+
if (isError(nV)) {
|
|
594
|
+
return nV;
|
|
595
|
+
}
|
|
596
|
+
const idx = nV.value > 0 ? nV.value - 1 : d.height + nV.value;
|
|
597
|
+
if (idx < 0 || idx >= d.height) {
|
|
598
|
+
return ERRORS.VALUE;
|
|
599
|
+
}
|
|
600
|
+
const row = [];
|
|
601
|
+
for (let c = 0; c < d.width; c++) {
|
|
602
|
+
row.push(getCell(d, idx, c));
|
|
603
|
+
}
|
|
604
|
+
result.push(row);
|
|
605
|
+
}
|
|
606
|
+
return rvArray(result);
|
|
607
|
+
}
|
|
608
|
+
export function fnCHOOSECOLS(args) {
|
|
609
|
+
const d = asArray(args[0]);
|
|
610
|
+
if (!d) {
|
|
611
|
+
return ERRORS.VALUE;
|
|
612
|
+
}
|
|
613
|
+
const ci = [];
|
|
614
|
+
for (let i = 1; i < args.length; i++) {
|
|
615
|
+
const nV = toNumberRV(args[i]);
|
|
616
|
+
if (isError(nV)) {
|
|
617
|
+
return nV;
|
|
618
|
+
}
|
|
619
|
+
const idx = nV.value > 0 ? nV.value - 1 : d.width + nV.value;
|
|
620
|
+
if (idx < 0 || idx >= d.width) {
|
|
621
|
+
return ERRORS.VALUE;
|
|
622
|
+
}
|
|
623
|
+
ci.push(idx);
|
|
624
|
+
}
|
|
625
|
+
const result = [];
|
|
626
|
+
for (let r = 0; r < d.height; r++) {
|
|
627
|
+
result.push(ci.map(c => getCell(d, r, c)));
|
|
628
|
+
}
|
|
629
|
+
return rvArray(result);
|
|
630
|
+
}
|
|
631
|
+
export function fnVSTACK(args) {
|
|
632
|
+
const rows = [];
|
|
633
|
+
let maxWidth = 0;
|
|
634
|
+
for (const a of args) {
|
|
635
|
+
if (a.kind === RVKind.Array) {
|
|
636
|
+
for (let r = 0; r < a.height; r++) {
|
|
637
|
+
const row = [];
|
|
638
|
+
for (let c = 0; c < a.width; c++) {
|
|
639
|
+
row.push(a.rows[r][c]);
|
|
640
|
+
}
|
|
641
|
+
rows.push(row);
|
|
642
|
+
if (a.width > maxWidth) {
|
|
643
|
+
maxWidth = a.width;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
rows.push([topLeft(a)]);
|
|
649
|
+
if (maxWidth < 1) {
|
|
650
|
+
maxWidth = 1;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (rows.length === 0) {
|
|
655
|
+
return ERRORS.VALUE;
|
|
656
|
+
}
|
|
657
|
+
// Pad with #N/A (not BLANK) to match Excel, and to stay symmetric with
|
|
658
|
+
// HSTACK's existing behaviour. The previous code left short rows to be
|
|
659
|
+
// rectangularised by `rvArray`, which used BLANK — visually wrong and
|
|
660
|
+
// inconsistent with how HSTACK reports "missing" cells.
|
|
661
|
+
for (const row of rows) {
|
|
662
|
+
while (row.length < maxWidth) {
|
|
663
|
+
row.push(ERRORS.NA);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return rvArray(rows);
|
|
667
|
+
}
|
|
668
|
+
export function fnHSTACK(args) {
|
|
669
|
+
let maxRows = 0;
|
|
670
|
+
const arrays = [];
|
|
671
|
+
for (const a of args) {
|
|
672
|
+
if (a.kind === RVKind.Array) {
|
|
673
|
+
arrays.push(a);
|
|
674
|
+
if (a.height > maxRows) {
|
|
675
|
+
maxRows = a.height;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
arrays.push(rvArray([[topLeft(a)]]));
|
|
680
|
+
if (maxRows < 1) {
|
|
681
|
+
maxRows = 1;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const result = [];
|
|
686
|
+
for (let r = 0; r < maxRows; r++) {
|
|
687
|
+
const row = [];
|
|
688
|
+
for (const arr of arrays) {
|
|
689
|
+
if (r < arr.height) {
|
|
690
|
+
for (let c = 0; c < arr.width; c++) {
|
|
691
|
+
row.push(arr.rows[r][c]);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
for (let c = 0; c < arr.width; c++) {
|
|
696
|
+
row.push(ERRORS.NA);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
result.push(row);
|
|
701
|
+
}
|
|
702
|
+
return rvArray(result);
|
|
703
|
+
}
|
|
704
|
+
export function fnTAKE(args) {
|
|
705
|
+
const d = asArray(args[0]);
|
|
706
|
+
if (!d) {
|
|
707
|
+
return ERRORS.VALUE;
|
|
708
|
+
}
|
|
709
|
+
const rowsV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(d.height);
|
|
710
|
+
if (isError(rowsV)) {
|
|
711
|
+
return rowsV;
|
|
712
|
+
}
|
|
713
|
+
const colsV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(d.width);
|
|
714
|
+
if (isError(colsV)) {
|
|
715
|
+
return colsV;
|
|
716
|
+
}
|
|
717
|
+
const rS = rowsV.value >= 0 ? 0 : Math.max(0, d.height + rowsV.value);
|
|
718
|
+
const rE = rowsV.value >= 0 ? Math.min(rowsV.value, d.height) : d.height;
|
|
719
|
+
const cS = colsV.value >= 0 ? 0 : Math.max(0, d.width + colsV.value);
|
|
720
|
+
const cE = colsV.value >= 0 ? Math.min(colsV.value, d.width) : d.width;
|
|
721
|
+
const result = [];
|
|
722
|
+
for (let r = rS; r < rE; r++) {
|
|
723
|
+
const row = [];
|
|
724
|
+
for (let c = cS; c < cE; c++) {
|
|
725
|
+
row.push(getCell(d, r, c));
|
|
726
|
+
}
|
|
727
|
+
result.push(row);
|
|
728
|
+
}
|
|
729
|
+
return result.length > 0 ? rvArray(result) : ERRORS.CALC;
|
|
730
|
+
}
|
|
731
|
+
export function fnDROP(args) {
|
|
732
|
+
const d = asArray(args[0]);
|
|
733
|
+
if (!d) {
|
|
734
|
+
return ERRORS.VALUE;
|
|
735
|
+
}
|
|
736
|
+
const rowsV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
|
|
737
|
+
if (isError(rowsV)) {
|
|
738
|
+
return rowsV;
|
|
739
|
+
}
|
|
740
|
+
const colsV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(0);
|
|
741
|
+
if (isError(colsV)) {
|
|
742
|
+
return colsV;
|
|
743
|
+
}
|
|
744
|
+
const rS = rowsV.value >= 0 ? rowsV.value : 0;
|
|
745
|
+
const rE = rowsV.value >= 0 ? d.height : d.height + rowsV.value;
|
|
746
|
+
const cS = colsV.value >= 0 ? colsV.value : 0;
|
|
747
|
+
const cE = colsV.value >= 0 ? d.width : d.width + colsV.value;
|
|
748
|
+
const result = [];
|
|
749
|
+
for (let r = rS; r < rE; r++) {
|
|
750
|
+
const row = [];
|
|
751
|
+
for (let c = cS; c < cE; c++) {
|
|
752
|
+
row.push(getCell(d, r, c));
|
|
753
|
+
}
|
|
754
|
+
if (row.length > 0) {
|
|
755
|
+
result.push(row);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return result.length > 0 ? rvArray(result) : ERRORS.CALC;
|
|
759
|
+
}
|
|
760
|
+
export function fnWRAPROWS(args) {
|
|
761
|
+
if (!isArray(args[0])) {
|
|
762
|
+
return ERRORS.VALUE;
|
|
763
|
+
}
|
|
764
|
+
const arr = args[0];
|
|
765
|
+
const flat = [];
|
|
766
|
+
for (let r = 0; r < arr.height; r++) {
|
|
767
|
+
for (let c = 0; c < arr.width; c++) {
|
|
768
|
+
flat.push(getCell(arr, r, c));
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
const wcV = toNumberRV(args[1]);
|
|
772
|
+
if (isError(wcV)) {
|
|
773
|
+
return wcV;
|
|
774
|
+
}
|
|
775
|
+
if (wcV.value < 1) {
|
|
776
|
+
return ERRORS.VALUE;
|
|
777
|
+
}
|
|
778
|
+
const pad = args.length > 2 ? topLeft(args[2]) : ERRORS.NA;
|
|
779
|
+
const result = [];
|
|
780
|
+
for (let i = 0; i < flat.length; i += wcV.value) {
|
|
781
|
+
const row = flat.slice(i, i + wcV.value);
|
|
782
|
+
while (row.length < wcV.value) {
|
|
783
|
+
row.push(pad);
|
|
784
|
+
}
|
|
785
|
+
result.push(row);
|
|
786
|
+
}
|
|
787
|
+
return rvArray(result);
|
|
788
|
+
}
|
|
789
|
+
export function fnWRAPCOLS(args) {
|
|
790
|
+
if (!isArray(args[0])) {
|
|
791
|
+
return ERRORS.VALUE;
|
|
792
|
+
}
|
|
793
|
+
const arr = args[0];
|
|
794
|
+
const flat = [];
|
|
795
|
+
for (let r = 0; r < arr.height; r++) {
|
|
796
|
+
for (let c = 0; c < arr.width; c++) {
|
|
797
|
+
flat.push(getCell(arr, r, c));
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
const wcV = toNumberRV(args[1]);
|
|
801
|
+
if (isError(wcV)) {
|
|
802
|
+
return wcV;
|
|
803
|
+
}
|
|
804
|
+
if (wcV.value < 1) {
|
|
805
|
+
return ERRORS.VALUE;
|
|
806
|
+
}
|
|
807
|
+
const pad = args.length > 2 ? topLeft(args[2]) : ERRORS.NA;
|
|
808
|
+
const numCols = Math.ceil(flat.length / wcV.value);
|
|
809
|
+
const result = [];
|
|
810
|
+
for (let r = 0; r < wcV.value; r++) {
|
|
811
|
+
const row = [];
|
|
812
|
+
for (let c = 0; c < numCols; c++) {
|
|
813
|
+
const idx = c * wcV.value + r;
|
|
814
|
+
row.push(idx < flat.length ? flat[idx] : pad);
|
|
815
|
+
}
|
|
816
|
+
result.push(row);
|
|
817
|
+
}
|
|
818
|
+
return rvArray(result);
|
|
819
|
+
}
|
|
820
|
+
export function fnEXPAND(args) {
|
|
821
|
+
const d = asArray(args[0]);
|
|
822
|
+
if (!d) {
|
|
823
|
+
return ERRORS.VALUE;
|
|
824
|
+
}
|
|
825
|
+
const rowsV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(d.height);
|
|
826
|
+
if (isError(rowsV)) {
|
|
827
|
+
return rowsV;
|
|
828
|
+
}
|
|
829
|
+
const colsV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(d.width);
|
|
830
|
+
if (isError(colsV)) {
|
|
831
|
+
return colsV;
|
|
832
|
+
}
|
|
833
|
+
// Excel requires the target to be at least as large as the source, and
|
|
834
|
+
// both dimensions to be positive. Without Math.trunc the inner loop
|
|
835
|
+
// runs `c < rowsV.value` comparisons against a float, which produces
|
|
836
|
+
// an off-by-one depending on the fractional part (R6-P1-5).
|
|
837
|
+
const rowCount = Math.trunc(rowsV.value);
|
|
838
|
+
const colCount = Math.trunc(colsV.value);
|
|
839
|
+
if (!Number.isFinite(rowCount) ||
|
|
840
|
+
!Number.isFinite(colCount) ||
|
|
841
|
+
rowCount < d.height ||
|
|
842
|
+
colCount < d.width) {
|
|
843
|
+
return ERRORS.VALUE;
|
|
844
|
+
}
|
|
845
|
+
// Cap the output size to the same 10M-cell budget the other dynamic
|
|
846
|
+
// array producers use (see MAKEARRAY, broadcastBinaryOp).
|
|
847
|
+
if (rowCount * colCount > 10000000) {
|
|
848
|
+
return ERRORS.NUM;
|
|
849
|
+
}
|
|
850
|
+
const pad = args.length > 3 ? topLeft(args[3]) : ERRORS.NA;
|
|
851
|
+
const result = [];
|
|
852
|
+
for (let r = 0; r < rowCount; r++) {
|
|
853
|
+
const row = [];
|
|
854
|
+
for (let c = 0; c < colCount; c++) {
|
|
855
|
+
row.push(r < d.height && c < d.width ? getCell(d, r, c) : pad);
|
|
856
|
+
}
|
|
857
|
+
result.push(row);
|
|
858
|
+
}
|
|
859
|
+
return rvArray(result);
|
|
860
|
+
}
|