@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,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph for Formula Calculation
|
|
3
|
+
*
|
|
4
|
+
* Builds a dependency graph from compiled formulas' static dependencies,
|
|
5
|
+
* then produces a topological evaluation order with circular reference
|
|
6
|
+
* detection.
|
|
7
|
+
*
|
|
8
|
+
* Key exports:
|
|
9
|
+
* - `buildDependencyGraphFromDeps()` — build graph from CompiledFormula static deps
|
|
10
|
+
* - `topologicalSort()` — produce evaluation order, detecting circular refs
|
|
11
|
+
*/
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Cell Key Helpers
|
|
14
|
+
// ============================================================================
|
|
15
|
+
function makeKey(sheet, row, col) {
|
|
16
|
+
return `${sheet}!${row}:${col}`;
|
|
17
|
+
}
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Dependency Reference → Cell Key Expansion
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Type guard: is this a range reference (has `top` property)?
|
|
23
|
+
*/
|
|
24
|
+
function isRange(ref) {
|
|
25
|
+
return "top" in ref;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Expand a set of DepRefs into concrete cell keys.
|
|
29
|
+
* For single-cell refs, the key is produced directly.
|
|
30
|
+
* For range refs, we check which formula cells fall within the range rather
|
|
31
|
+
* than enumerating every cell (which would be prohibitively expensive for
|
|
32
|
+
* whole-column ranges like A:A).
|
|
33
|
+
*/
|
|
34
|
+
function expandRefsToKeys(refs, formulaKeySet, formulaCellCoordsBySheet) {
|
|
35
|
+
const keys = new Set();
|
|
36
|
+
for (const ref of refs) {
|
|
37
|
+
if (isRange(ref)) {
|
|
38
|
+
const rangeSize = (ref.bottom - ref.top + 1) * (ref.right - ref.left + 1);
|
|
39
|
+
if (rangeSize <= 10000) {
|
|
40
|
+
// Small-to-medium range: enumerate every cell
|
|
41
|
+
for (let r = ref.top; r <= ref.bottom; r++) {
|
|
42
|
+
for (let c = ref.left; c <= ref.right; c++) {
|
|
43
|
+
keys.add(makeKey(ref.sheet, r, c));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Large range (e.g. whole column A:A): scan formula cells in the
|
|
49
|
+
// referenced sheet only and check containment.
|
|
50
|
+
const sheetCoords = formulaCellCoordsBySheet.get(ref.sheet);
|
|
51
|
+
if (sheetCoords) {
|
|
52
|
+
for (const [fKey, coord] of sheetCoords) {
|
|
53
|
+
if (coord.row >= ref.top &&
|
|
54
|
+
coord.row <= ref.bottom &&
|
|
55
|
+
coord.col >= ref.left &&
|
|
56
|
+
coord.col <= ref.right) {
|
|
57
|
+
keys.add(fKey);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Single cell — always add
|
|
65
|
+
keys.add(makeKey(ref.sheet, ref.row, ref.col));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return keys;
|
|
69
|
+
}
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Build Dependency Graph from CompiledFormula StaticDeps
|
|
72
|
+
// ============================================================================
|
|
73
|
+
/**
|
|
74
|
+
* Build a dependency graph from compiled formulas' static dependencies.
|
|
75
|
+
*
|
|
76
|
+
* Operates on the already-resolved `StaticDependencySet` from each compiled
|
|
77
|
+
* formula. Since names and structured references are already resolved by
|
|
78
|
+
* the binder, the dependency edges are complete.
|
|
79
|
+
*
|
|
80
|
+
* @param compiled - Map from formula cell key to compiled formula with static deps
|
|
81
|
+
* @param producerMap - Optional map from cell key → formula key that produces
|
|
82
|
+
* that cell's value (via CSE distribution or dynamic-array spill). Allows
|
|
83
|
+
* dependency edges to be added to the producer even when the target cell
|
|
84
|
+
* isn't itself a formula.
|
|
85
|
+
* @returns The complete dependency graph
|
|
86
|
+
*/
|
|
87
|
+
export function buildDependencyGraphFromDeps(compiled, producerMap) {
|
|
88
|
+
// Build a lookup of all formula cell coordinates for range intersection.
|
|
89
|
+
// We group by sheet so that large-range containment scans only visit the
|
|
90
|
+
// relevant sheet's formula cells instead of the entire workbook.
|
|
91
|
+
const formulaKeySet = new Set();
|
|
92
|
+
const formulaCellCoordsBySheet = new Map();
|
|
93
|
+
const formulaKeys = [];
|
|
94
|
+
for (const [key, cf] of compiled) {
|
|
95
|
+
formulaKeySet.add(key);
|
|
96
|
+
// Use the instance's already-known coordinates instead of reverse-parsing
|
|
97
|
+
// the key string — saves two lastIndexOf calls and two parseInt calls
|
|
98
|
+
// per formula on cold-start.
|
|
99
|
+
const inst = cf.instance;
|
|
100
|
+
const coord = { sheet: inst.sheetName, row: inst.row, col: inst.col };
|
|
101
|
+
let list = formulaCellCoordsBySheet.get(inst.sheetName);
|
|
102
|
+
if (!list) {
|
|
103
|
+
list = [];
|
|
104
|
+
formulaCellCoordsBySheet.set(inst.sheetName, list);
|
|
105
|
+
}
|
|
106
|
+
list.push([key, coord]);
|
|
107
|
+
formulaKeys.push(key);
|
|
108
|
+
}
|
|
109
|
+
// Forward edges: formula key → set of keys it depends on
|
|
110
|
+
const dependsOn = new Map();
|
|
111
|
+
// Reverse edges: cell key → set of formula keys that depend on it
|
|
112
|
+
const dependedBy = new Map();
|
|
113
|
+
for (const [key, cf] of compiled) {
|
|
114
|
+
const deps = cf.staticDeps;
|
|
115
|
+
// Convert StaticDependencySet to DepRef[]
|
|
116
|
+
const refs = [];
|
|
117
|
+
// Direct cell deps always pass through verbatim.
|
|
118
|
+
for (const cell of deps.cells) {
|
|
119
|
+
refs.push({ sheet: cell.sheet, row: cell.row, col: cell.col });
|
|
120
|
+
}
|
|
121
|
+
// Area deps normally expand into every cell in the range. For areas
|
|
122
|
+
// that start at a dynamic-array master (e.g. the `A1:A5` in
|
|
123
|
+
// `SUM(A1:A5)` where A1 is a live `=SEQUENCE(5)`), we replace the
|
|
124
|
+
// expansion with a single dependency on the master. Evaluator-time
|
|
125
|
+
// `getCellValue` then reads the master's cached array result for
|
|
126
|
+
// the ghost positions, so downstream formulas see the full spill
|
|
127
|
+
// in the same calc pass. Without this, A2..A5 aren't yet in the
|
|
128
|
+
// snapshot on the first run and the SUM only picks up A1.
|
|
129
|
+
const dynMasterDeps = [];
|
|
130
|
+
for (const area of deps.areas) {
|
|
131
|
+
const topLeftKey = makeKey(area.sheet, area.top, area.left);
|
|
132
|
+
const masterCf = compiled.get(topLeftKey);
|
|
133
|
+
const isDynMaster = masterCf !== undefined &&
|
|
134
|
+
(masterCf.instance.isDynamicArray || masterCf.isDynamicArrayFunction);
|
|
135
|
+
if (isDynMaster) {
|
|
136
|
+
dynMasterDeps.push(topLeftKey);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
refs.push({
|
|
140
|
+
sheet: area.sheet,
|
|
141
|
+
top: area.top,
|
|
142
|
+
left: area.left,
|
|
143
|
+
bottom: area.bottom,
|
|
144
|
+
right: area.right
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// Expand to concrete cell keys
|
|
148
|
+
const depKeys = expandRefsToKeys(refs, formulaKeySet, formulaCellCoordsBySheet);
|
|
149
|
+
for (const mk of dynMasterDeps) {
|
|
150
|
+
depKeys.add(mk);
|
|
151
|
+
}
|
|
152
|
+
// Remap producer keys: if a dep points to a cell that's not a formula
|
|
153
|
+
// but IS produced by another formula (CSE target or spill target),
|
|
154
|
+
// depend on the producer instead.
|
|
155
|
+
if (producerMap && producerMap.size > 0) {
|
|
156
|
+
const remapped = new Set();
|
|
157
|
+
for (const depKey of depKeys) {
|
|
158
|
+
if (!formulaKeySet.has(depKey)) {
|
|
159
|
+
const producer = producerMap.get(depKey);
|
|
160
|
+
if (producer) {
|
|
161
|
+
remapped.add(producer);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
remapped.add(depKey);
|
|
166
|
+
}
|
|
167
|
+
dependsOn.set(key, remapped);
|
|
168
|
+
for (const depKey of remapped) {
|
|
169
|
+
let set = dependedBy.get(depKey);
|
|
170
|
+
if (!set) {
|
|
171
|
+
set = new Set();
|
|
172
|
+
dependedBy.set(depKey, set);
|
|
173
|
+
}
|
|
174
|
+
set.add(key);
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
dependsOn.set(key, depKeys);
|
|
179
|
+
// Build reverse index
|
|
180
|
+
for (const depKey of depKeys) {
|
|
181
|
+
let set = dependedBy.get(depKey);
|
|
182
|
+
if (!set) {
|
|
183
|
+
set = new Set();
|
|
184
|
+
dependedBy.set(depKey, set);
|
|
185
|
+
}
|
|
186
|
+
set.add(key);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Detect circular references
|
|
190
|
+
const { circularKeys } = detectCircularRefs(formulaKeys, dependsOn);
|
|
191
|
+
return {
|
|
192
|
+
dependsOn,
|
|
193
|
+
dependedBy,
|
|
194
|
+
formulaKeys,
|
|
195
|
+
circularKeys
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Merge Runtime Dynamic Dependencies
|
|
200
|
+
// ============================================================================
|
|
201
|
+
/**
|
|
202
|
+
* Merge runtime-discovered dynamic dependencies into a dependency graph.
|
|
203
|
+
*
|
|
204
|
+
* After evaluating formulas that contain INDIRECT/OFFSET, the runtime
|
|
205
|
+
* dependency recorder has collected the actual cell accesses. This function
|
|
206
|
+
* incorporates those dynamic edges into the graph and re-detects cycles.
|
|
207
|
+
*
|
|
208
|
+
* Returns a new graph if edges were added, or the original graph if no
|
|
209
|
+
* dynamic deps were recorded.
|
|
210
|
+
*/
|
|
211
|
+
export function mergeDynamicDeps(graph, dynamicDeps) {
|
|
212
|
+
if (dynamicDeps.size === 0) {
|
|
213
|
+
return { graph, changed: false };
|
|
214
|
+
}
|
|
215
|
+
// First pass: detect whether any new edges would actually be added.
|
|
216
|
+
// Cloning the full dependsOn/dependedBy maps is expensive for large
|
|
217
|
+
// workbooks; skip it entirely when there's no real work to do.
|
|
218
|
+
let needsClone = false;
|
|
219
|
+
for (const [formulaKey, accessedKeys] of dynamicDeps) {
|
|
220
|
+
const existing = graph.dependsOn.get(formulaKey);
|
|
221
|
+
for (const k of accessedKeys) {
|
|
222
|
+
if (!existing || !existing.has(k)) {
|
|
223
|
+
needsClone = true;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (needsClone) {
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!needsClone) {
|
|
232
|
+
return { graph, changed: false };
|
|
233
|
+
}
|
|
234
|
+
// Clone forward and reverse edges
|
|
235
|
+
const newDependsOn = new Map();
|
|
236
|
+
for (const [k, v] of graph.dependsOn) {
|
|
237
|
+
newDependsOn.set(k, new Set(v));
|
|
238
|
+
}
|
|
239
|
+
const newDependedBy = new Map();
|
|
240
|
+
for (const [k, v] of graph.dependedBy) {
|
|
241
|
+
newDependedBy.set(k, new Set(v));
|
|
242
|
+
}
|
|
243
|
+
// Add dynamic edges
|
|
244
|
+
for (const [formulaKey, accessedKeys] of dynamicDeps) {
|
|
245
|
+
let deps = newDependsOn.get(formulaKey);
|
|
246
|
+
if (!deps) {
|
|
247
|
+
deps = new Set();
|
|
248
|
+
newDependsOn.set(formulaKey, deps);
|
|
249
|
+
}
|
|
250
|
+
for (const accessedKey of accessedKeys) {
|
|
251
|
+
if (!deps.has(accessedKey)) {
|
|
252
|
+
deps.add(accessedKey);
|
|
253
|
+
// Update reverse edge
|
|
254
|
+
let rev = newDependedBy.get(accessedKey);
|
|
255
|
+
if (!rev) {
|
|
256
|
+
rev = new Set();
|
|
257
|
+
newDependedBy.set(accessedKey, rev);
|
|
258
|
+
}
|
|
259
|
+
rev.add(formulaKey);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Re-detect cycles with the augmented graph
|
|
264
|
+
const { circularKeys } = detectCircularRefs(graph.formulaKeys, newDependsOn);
|
|
265
|
+
return {
|
|
266
|
+
graph: {
|
|
267
|
+
dependsOn: newDependsOn,
|
|
268
|
+
dependedBy: newDependedBy,
|
|
269
|
+
formulaKeys: graph.formulaKeys,
|
|
270
|
+
circularKeys
|
|
271
|
+
},
|
|
272
|
+
changed: true
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// Circular Reference Detection
|
|
277
|
+
// ============================================================================
|
|
278
|
+
/**
|
|
279
|
+
* Detect circular references using Tarjan's SCC algorithm.
|
|
280
|
+
*
|
|
281
|
+
* A formula is "circular" if it belongs to a strongly connected component
|
|
282
|
+
* of size > 1, or if it has a direct self-loop (A = f(A)).
|
|
283
|
+
*
|
|
284
|
+
* This correctly identifies ALL nodes in cycles, including nodes reachable
|
|
285
|
+
* only through cross-edges to already-visited SCC members — a case that
|
|
286
|
+
* a simple 3-color DFS misses (e.g. diamond cycles like A→B→C→A plus A→D→C).
|
|
287
|
+
*/
|
|
288
|
+
function detectCircularRefs(formulaKeys, dependsOn) {
|
|
289
|
+
const circularKeys = new Set();
|
|
290
|
+
// Tarjan's iterative SCC
|
|
291
|
+
const index = new Map();
|
|
292
|
+
const lowlink = new Map();
|
|
293
|
+
const onStack = new Set();
|
|
294
|
+
const sccStack = [];
|
|
295
|
+
let nextIndex = 0;
|
|
296
|
+
for (const startKey of formulaKeys) {
|
|
297
|
+
if (index.has(startKey)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const dfsStack = [];
|
|
301
|
+
index.set(startKey, nextIndex);
|
|
302
|
+
lowlink.set(startKey, nextIndex);
|
|
303
|
+
nextIndex++;
|
|
304
|
+
sccStack.push(startKey);
|
|
305
|
+
onStack.add(startKey);
|
|
306
|
+
dfsStack.push({
|
|
307
|
+
key: startKey,
|
|
308
|
+
iter: (dependsOn.get(startKey) ?? new Set())[Symbol.iterator](),
|
|
309
|
+
pendingChild: null
|
|
310
|
+
});
|
|
311
|
+
while (dfsStack.length > 0) {
|
|
312
|
+
const frame = dfsStack[dfsStack.length - 1];
|
|
313
|
+
// If we just returned from a child, update our lowlink
|
|
314
|
+
if (frame.pendingChild !== null) {
|
|
315
|
+
const childLow = lowlink.get(frame.pendingChild);
|
|
316
|
+
lowlink.set(frame.key, Math.min(lowlink.get(frame.key), childLow));
|
|
317
|
+
frame.pendingChild = null;
|
|
318
|
+
}
|
|
319
|
+
const next = frame.iter.next();
|
|
320
|
+
if (next.done) {
|
|
321
|
+
// Finished processing all children — check if this is an SCC root
|
|
322
|
+
if (lowlink.get(frame.key) === index.get(frame.key)) {
|
|
323
|
+
const scc = [];
|
|
324
|
+
let node;
|
|
325
|
+
do {
|
|
326
|
+
node = sccStack.pop();
|
|
327
|
+
onStack.delete(node);
|
|
328
|
+
scc.push(node);
|
|
329
|
+
} while (node !== frame.key);
|
|
330
|
+
// Mark as circular if SCC has > 1 node, OR if it's a self-loop
|
|
331
|
+
const hasSelfLoop = scc.length === 1 && dependsOn.get(scc[0])?.has(scc[0]);
|
|
332
|
+
if (scc.length > 1 || hasSelfLoop) {
|
|
333
|
+
for (const k of scc) {
|
|
334
|
+
circularKeys.add(k);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
dfsStack.pop();
|
|
339
|
+
// Record returning to parent so it can update its lowlink
|
|
340
|
+
if (dfsStack.length > 0) {
|
|
341
|
+
dfsStack[dfsStack.length - 1].pendingChild = frame.key;
|
|
342
|
+
}
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
const depKey = next.value;
|
|
346
|
+
if (!index.has(depKey)) {
|
|
347
|
+
// Unvisited — push new frame
|
|
348
|
+
index.set(depKey, nextIndex);
|
|
349
|
+
lowlink.set(depKey, nextIndex);
|
|
350
|
+
nextIndex++;
|
|
351
|
+
sccStack.push(depKey);
|
|
352
|
+
onStack.add(depKey);
|
|
353
|
+
dfsStack.push({
|
|
354
|
+
key: depKey,
|
|
355
|
+
iter: (dependsOn.get(depKey) ?? new Set())[Symbol.iterator](),
|
|
356
|
+
pendingChild: null
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
else if (onStack.has(depKey)) {
|
|
360
|
+
// Back edge — update lowlink with dep's index
|
|
361
|
+
lowlink.set(frame.key, Math.min(lowlink.get(frame.key), index.get(depKey)));
|
|
362
|
+
}
|
|
363
|
+
// Cross edge to fully-processed SCC: skip (correct Tarjan behavior)
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return { circularKeys };
|
|
367
|
+
}
|
|
368
|
+
// ============================================================================
|
|
369
|
+
// Topological Sort (Kahn's Algorithm)
|
|
370
|
+
// ============================================================================
|
|
371
|
+
/**
|
|
372
|
+
* Produce a topological evaluation order for formula cells using Kahn's algorithm.
|
|
373
|
+
* Cells with no dependencies are evaluated first. Circular references are
|
|
374
|
+
* appended at the end in their original order.
|
|
375
|
+
*/
|
|
376
|
+
export function topologicalSort(graph) {
|
|
377
|
+
const { formulaKeys, dependsOn, circularKeys } = graph;
|
|
378
|
+
const formulaKeySet = new Set(formulaKeys);
|
|
379
|
+
const inDegree = new Map();
|
|
380
|
+
for (const key of formulaKeys) {
|
|
381
|
+
if (circularKeys.has(key)) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
const deps = dependsOn.get(key);
|
|
385
|
+
if (!deps) {
|
|
386
|
+
inDegree.set(key, 0);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
let count = 0;
|
|
390
|
+
for (const depKey of deps) {
|
|
391
|
+
if (formulaKeySet.has(depKey) && !circularKeys.has(depKey)) {
|
|
392
|
+
count++;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
inDegree.set(key, count);
|
|
396
|
+
}
|
|
397
|
+
const queue = [];
|
|
398
|
+
for (const key of formulaKeys) {
|
|
399
|
+
if (circularKeys.has(key)) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if ((inDegree.get(key) ?? 0) === 0) {
|
|
403
|
+
queue.push(key);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const sorted = [];
|
|
407
|
+
let head = 0;
|
|
408
|
+
while (head < queue.length) {
|
|
409
|
+
const key = queue[head++];
|
|
410
|
+
sorted.push(key);
|
|
411
|
+
const dependents = graph.dependedBy.get(key);
|
|
412
|
+
if (dependents) {
|
|
413
|
+
for (const depKey of dependents) {
|
|
414
|
+
if (circularKeys.has(depKey) || !formulaKeySet.has(depKey)) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const deg = (inDegree.get(depKey) ?? 1) - 1;
|
|
418
|
+
inDegree.set(depKey, deg);
|
|
419
|
+
if (deg === 0) {
|
|
420
|
+
queue.push(depKey);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Append circular reference cells at the end in original order
|
|
426
|
+
for (const key of formulaKeys) {
|
|
427
|
+
if (circularKeys.has(key)) {
|
|
428
|
+
sorted.push(key);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return sorted;
|
|
432
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for structured reference (table) row-range resolution.
|
|
3
|
+
*
|
|
4
|
+
* The row-range logic for structured references is needed in three places:
|
|
5
|
+
* - binder (compile-time range resolution)
|
|
6
|
+
* - compiled-formula (static dependency extraction)
|
|
7
|
+
* - evaluator (runtime evaluation)
|
|
8
|
+
*
|
|
9
|
+
* This module provides the canonical implementation to avoid triplication.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Minimum subset of table snapshot fields required to derive geometry
|
|
13
|
+
* and resolve structured-reference columns.
|
|
14
|
+
*
|
|
15
|
+
* Declared structurally (not as a nominal import of `TableSnapshot`) so
|
|
16
|
+
* this module stays dependency-free and can serve both compile- and
|
|
17
|
+
* runtime-side callers that carry their own table-shape types.
|
|
18
|
+
*/
|
|
19
|
+
export interface TableLike {
|
|
20
|
+
readonly topLeft: {
|
|
21
|
+
readonly row: number;
|
|
22
|
+
readonly col: number;
|
|
23
|
+
};
|
|
24
|
+
readonly dataRowCount: number;
|
|
25
|
+
readonly hasHeaderRow: boolean;
|
|
26
|
+
readonly hasTotalsRow: boolean;
|
|
27
|
+
readonly columns: readonly {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
}[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Table geometry needed for structured ref resolution.
|
|
33
|
+
*/
|
|
34
|
+
export interface TableGeometry {
|
|
35
|
+
/** Top-left row of the table (including header if present). */
|
|
36
|
+
readonly topLeftRow: number;
|
|
37
|
+
/** First row of the data body. */
|
|
38
|
+
readonly dataRowStart: number;
|
|
39
|
+
/** Last row of the data body. */
|
|
40
|
+
readonly dataRowEnd: number;
|
|
41
|
+
/** Whether the table has a header row. */
|
|
42
|
+
readonly hasHeaderRow: boolean;
|
|
43
|
+
/** Whether the table has a totals row. */
|
|
44
|
+
readonly hasTotalsRow: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Derive `TableGeometry` from a table's snapshot fields.
|
|
48
|
+
*
|
|
49
|
+
* The data row range excludes the header (if any) but also excludes the
|
|
50
|
+
* totals row — totals, when present, occupy `dataRowEnd + 1`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildTableGeometry(table: TableLike): TableGeometry;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve a list of structured-reference column names to a contiguous
|
|
55
|
+
* column range `[colLeft, colRight]` in absolute sheet coordinates.
|
|
56
|
+
*
|
|
57
|
+
* @param columns - Requested column names (case-insensitive match).
|
|
58
|
+
* @param table - Table whose columns are searched.
|
|
59
|
+
* @param mode -
|
|
60
|
+
* - `"strict"` — return `"error"` if any name is missing (used by
|
|
61
|
+
* binder and evaluator — unknown columns are `#REF!` errors).
|
|
62
|
+
* - `"permissive"` — ignore missing names; if ALL names are missing,
|
|
63
|
+
* falls back to the full table width (used by static-deps extraction,
|
|
64
|
+
* where a conservative over-estimate is acceptable).
|
|
65
|
+
* @returns `{ colLeft, colRight }`, or `"error"` in strict mode when a
|
|
66
|
+
* column name is not found. If `columns` is empty, returns the full
|
|
67
|
+
* table width.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveStructuredRefColumns(columns: readonly string[], table: TableLike, mode: "strict" | "permissive"): {
|
|
70
|
+
colLeft: number;
|
|
71
|
+
colRight: number;
|
|
72
|
+
} | "error";
|
|
73
|
+
/**
|
|
74
|
+
* Result of resolving structured reference specials to a row range.
|
|
75
|
+
*
|
|
76
|
+
* - `{rowTop, rowBottom}` — resolved range
|
|
77
|
+
* - `"thisRow"` — the `#This Row` special was used; caller must resolve
|
|
78
|
+
* using the current cell address
|
|
79
|
+
* - `"error"` — invalid special combination (e.g., #Totals on a table
|
|
80
|
+
* without a totals row)
|
|
81
|
+
*/
|
|
82
|
+
export type StructuredRefRowRange = {
|
|
83
|
+
rowTop: number;
|
|
84
|
+
rowBottom: number;
|
|
85
|
+
} | "thisRow" | "error";
|
|
86
|
+
/**
|
|
87
|
+
* Resolve structured reference specials to a row range.
|
|
88
|
+
*
|
|
89
|
+
* This is the single source of truth for the mapping from
|
|
90
|
+
* `#All`, `#Headers`, `#Data`, `#Totals`, `#This Row` (and their
|
|
91
|
+
* combinations) to concrete row numbers.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resolveStructuredRefRows(specials: readonly string[], geo: TableGeometry): StructuredRefRowRange;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for structured reference (table) row-range resolution.
|
|
3
|
+
*
|
|
4
|
+
* The row-range logic for structured references is needed in three places:
|
|
5
|
+
* - binder (compile-time range resolution)
|
|
6
|
+
* - compiled-formula (static dependency extraction)
|
|
7
|
+
* - evaluator (runtime evaluation)
|
|
8
|
+
*
|
|
9
|
+
* This module provides the canonical implementation to avoid triplication.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Derive `TableGeometry` from a table's snapshot fields.
|
|
13
|
+
*
|
|
14
|
+
* The data row range excludes the header (if any) but also excludes the
|
|
15
|
+
* totals row — totals, when present, occupy `dataRowEnd + 1`.
|
|
16
|
+
*/
|
|
17
|
+
export function buildTableGeometry(table) {
|
|
18
|
+
const topLeftRow = table.topLeft.row;
|
|
19
|
+
const dataRowStart = topLeftRow + (table.hasHeaderRow ? 1 : 0);
|
|
20
|
+
const dataRowEnd = dataRowStart + table.dataRowCount - 1;
|
|
21
|
+
return {
|
|
22
|
+
topLeftRow,
|
|
23
|
+
dataRowStart,
|
|
24
|
+
dataRowEnd,
|
|
25
|
+
hasHeaderRow: table.hasHeaderRow,
|
|
26
|
+
hasTotalsRow: table.hasTotalsRow
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a list of structured-reference column names to a contiguous
|
|
31
|
+
* column range `[colLeft, colRight]` in absolute sheet coordinates.
|
|
32
|
+
*
|
|
33
|
+
* @param columns - Requested column names (case-insensitive match).
|
|
34
|
+
* @param table - Table whose columns are searched.
|
|
35
|
+
* @param mode -
|
|
36
|
+
* - `"strict"` — return `"error"` if any name is missing (used by
|
|
37
|
+
* binder and evaluator — unknown columns are `#REF!` errors).
|
|
38
|
+
* - `"permissive"` — ignore missing names; if ALL names are missing,
|
|
39
|
+
* falls back to the full table width (used by static-deps extraction,
|
|
40
|
+
* where a conservative over-estimate is acceptable).
|
|
41
|
+
* @returns `{ colLeft, colRight }`, or `"error"` in strict mode when a
|
|
42
|
+
* column name is not found. If `columns` is empty, returns the full
|
|
43
|
+
* table width.
|
|
44
|
+
*/
|
|
45
|
+
export function resolveStructuredRefColumns(columns, table, mode) {
|
|
46
|
+
const tl = table.topLeft;
|
|
47
|
+
const width = table.columns.length;
|
|
48
|
+
if (columns.length === 0) {
|
|
49
|
+
return { colLeft: tl.col, colRight: tl.col + width - 1 };
|
|
50
|
+
}
|
|
51
|
+
const indices = [];
|
|
52
|
+
for (const colName of columns) {
|
|
53
|
+
const idx = table.columns.findIndex(c => c.name.toLowerCase() === colName.toLowerCase());
|
|
54
|
+
if (idx === -1) {
|
|
55
|
+
if (mode === "strict") {
|
|
56
|
+
return "error";
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
indices.push(idx);
|
|
61
|
+
}
|
|
62
|
+
if (indices.length === 0) {
|
|
63
|
+
// permissive + all names missing → conservative full-width fallback
|
|
64
|
+
return { colLeft: tl.col, colRight: tl.col + width - 1 };
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
colLeft: tl.col + Math.min(...indices),
|
|
68
|
+
colRight: tl.col + Math.max(...indices)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve structured reference specials to a row range.
|
|
73
|
+
*
|
|
74
|
+
* This is the single source of truth for the mapping from
|
|
75
|
+
* `#All`, `#Headers`, `#Data`, `#Totals`, `#This Row` (and their
|
|
76
|
+
* combinations) to concrete row numbers.
|
|
77
|
+
*/
|
|
78
|
+
export function resolveStructuredRefRows(specials, geo) {
|
|
79
|
+
// Tokenizer stashes unknown `[#Something]` tokens with a sentinel
|
|
80
|
+
// prefix. Surface them as errors rather than let them alias to the
|
|
81
|
+
// default-data-range path below.
|
|
82
|
+
for (const s of specials) {
|
|
83
|
+
if (s.startsWith("#__INVALID__")) {
|
|
84
|
+
return "error";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const hasAll = specials.includes("#All");
|
|
88
|
+
const hasHeaders = specials.includes("#Headers");
|
|
89
|
+
const hasTotals = specials.includes("#Totals");
|
|
90
|
+
const hasData = specials.includes("#Data");
|
|
91
|
+
const hasThisRow = specials.includes("#This Row");
|
|
92
|
+
if (hasAll) {
|
|
93
|
+
return {
|
|
94
|
+
rowTop: geo.topLeftRow,
|
|
95
|
+
rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (hasThisRow) {
|
|
99
|
+
return "thisRow";
|
|
100
|
+
}
|
|
101
|
+
if (hasHeaders && hasTotals) {
|
|
102
|
+
return {
|
|
103
|
+
rowTop: geo.topLeftRow,
|
|
104
|
+
rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (hasHeaders && hasData) {
|
|
108
|
+
return {
|
|
109
|
+
rowTop: geo.hasHeaderRow ? geo.topLeftRow : geo.dataRowStart,
|
|
110
|
+
rowBottom: geo.dataRowEnd
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (hasData && hasTotals) {
|
|
114
|
+
return {
|
|
115
|
+
rowTop: geo.dataRowStart,
|
|
116
|
+
rowBottom: geo.hasTotalsRow ? geo.dataRowEnd + 1 : geo.dataRowEnd
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (hasHeaders) {
|
|
120
|
+
if (geo.hasHeaderRow) {
|
|
121
|
+
return { rowTop: geo.topLeftRow, rowBottom: geo.topLeftRow };
|
|
122
|
+
}
|
|
123
|
+
// Table without a header row: Excel reports #REF! rather than silently
|
|
124
|
+
// aliasing to the first data row. Returning the data row here would
|
|
125
|
+
// route `Table1[#Headers]` to real data values, masking user mistakes.
|
|
126
|
+
return "error";
|
|
127
|
+
}
|
|
128
|
+
if (hasTotals) {
|
|
129
|
+
if (geo.hasTotalsRow) {
|
|
130
|
+
return { rowTop: geo.dataRowEnd + 1, rowBottom: geo.dataRowEnd + 1 };
|
|
131
|
+
}
|
|
132
|
+
return "error";
|
|
133
|
+
}
|
|
134
|
+
// #Data or no specials → data range
|
|
135
|
+
return { rowTop: geo.dataRowStart, rowBottom: geo.dataRowEnd };
|
|
136
|
+
}
|