@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
|
@@ -10,18 +10,21 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { ZipParser } from "../../archive/unzip/zip-parser.js";
|
|
12
12
|
import { StreamingZip, ZipDeflateFile } from "../../archive/zip/stream.js";
|
|
13
|
-
import { ExcelStreamStateError, ExcelFileError, ImageError, ExcelNotSupportedError, XmlParseError } from "../errors.js";
|
|
13
|
+
import { ExcelStreamStateError, ExcelFileError, ImageError, ExcelNotSupportedError, XmlParseError, TableError } from "../errors.js";
|
|
14
14
|
import { filterDrawingAnchors } from "../utils/drawing-utils.js";
|
|
15
|
-
import {
|
|
15
|
+
import { rewriteExternalRefs } from "../utils/external-link-formula.js";
|
|
16
|
+
import { commentsPath, commentsRelTargetFromWorksheetName, ctrlPropPath, drawingPath, drawingRelsPath, externalLinkPath, externalLinkRelsPath, externalLinkRelTargetFromWorkbook, OOXML_REL_TARGETS, pivotTableRelTargetFromWorksheetName, pivotCacheDefinitionRelTargetFromWorkbook, getCommentsIndexFromPath, getDrawingNameFromPath, getDrawingNameFromRelsPath, getExternalLinkIndexFromPath, getExternalLinkIndexFromRelsPath, getMediaFilenameFromPath, mediaPath, getPivotCacheDefinitionNameFromPath, getPivotCacheDefinitionNameFromRelsPath, getPivotCacheRecordsNameFromPath, getPivotTableNameFromPath, getPivotTableNameFromRelsPath, pivotCacheDefinitionPath, pivotCacheDefinitionRelsPath, pivotCacheDefinitionRelTargetFromPivotTable, pivotCacheRecordsPath, pivotCacheRecordsRelTarget, pivotTablePath, pivotTableRelsPath, getTableNameFromPath, tablePath, tableRelTargetFromWorksheetName, themePath, getThemeNameFromPath, getVmlDrawingNameFromPath, getVmlDrawingHFNameFromPath, getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, isBinaryEntryPath, normalizeZipPath, OOXML_PATHS, vmlDrawingRelTargetFromWorksheetName, vmlDrawingPath, vmlDrawingHFPath, vmlDrawingHFRelsPath, worksheetPath, worksheetRelsPath, worksheetRelTarget } from "../utils/ooxml-paths.js";
|
|
16
17
|
import { PassthroughManager } from "../utils/passthrough-manager.js";
|
|
17
18
|
import { StreamBuf } from "../utils/stream-buf.js";
|
|
18
19
|
import { RelType } from "./rel-type.js";
|
|
20
|
+
import { ExternalLinkXform } from "./xform/book/external-link-xform.js";
|
|
19
21
|
import { WorkbookXform } from "./xform/book/workbook-xform.js";
|
|
20
22
|
import { CommentsXform } from "./xform/comment/comments-xform.js";
|
|
21
23
|
import { AppXform } from "./xform/core/app-xform.js";
|
|
22
24
|
import { ContentTypesXform } from "./xform/core/content-types-xform.js";
|
|
23
25
|
import { CoreXform } from "./xform/core/core-xform.js";
|
|
24
26
|
import { FeaturePropertyBagXform } from "./xform/core/feature-property-bag-xform.js";
|
|
27
|
+
import { MetadataXform } from "./xform/core/metadata-xform.js";
|
|
25
28
|
import { RelationshipsXform } from "./xform/core/relationships-xform.js";
|
|
26
29
|
import { CtrlPropXform } from "./xform/drawing/ctrl-prop-xform.js";
|
|
27
30
|
import { DrawingXform } from "./xform/drawing/drawing-xform.js";
|
|
@@ -242,6 +245,31 @@ class StreamingZipWriterAdapter {
|
|
|
242
245
|
}
|
|
243
246
|
}
|
|
244
247
|
StreamingZipWriterAdapter.textEncoder = new TextEncoder();
|
|
248
|
+
/**
|
|
249
|
+
* Extract the trailing integer from a workbook-rels Target like
|
|
250
|
+
* `"externalLinks/externalLink12.xml"` (a path relative to `xl/`). Mirror
|
|
251
|
+
* of {@link getExternalLinkIndexFromPath} which takes the full
|
|
252
|
+
* `xl/externalLinks/…` form. Used during reconcile to bridge the
|
|
253
|
+
* workbook.xml.rels entry to the parsed externalLinkN.xml part.
|
|
254
|
+
*/
|
|
255
|
+
function externalLinkIndexFromRelTarget(target) {
|
|
256
|
+
const match = /(?:^|\/)externalLink(\d+)[.]xml$/.exec(target);
|
|
257
|
+
return match ? parseInt(match[1], 10) : undefined;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Add `sheetName` to an ExternalLinkModel's `sheetNames` list if it isn't
|
|
261
|
+
* already present. Ordering is preserved — the first-seen sheet wins
|
|
262
|
+
* position 0, which matches what Excel does when writing externalLinks
|
|
263
|
+
* itself.
|
|
264
|
+
*/
|
|
265
|
+
function upsertSheet(link, sheetName) {
|
|
266
|
+
if (!sheetName) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (!link.sheetNames.includes(sheetName)) {
|
|
270
|
+
link.sheetNames.push(sheetName);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
245
273
|
/**
|
|
246
274
|
* XLSX class - handles Excel file operations
|
|
247
275
|
* Works in both Node.js and Browser environments
|
|
@@ -310,10 +338,12 @@ class XLSX {
|
|
|
310
338
|
await this.addDrawings(zip, model);
|
|
311
339
|
await this.addTables(zip, model);
|
|
312
340
|
await this.addPivotTables(zip, model);
|
|
341
|
+
await this.addExternalLinks(zip, model);
|
|
313
342
|
this.addPassthrough(zip, model);
|
|
314
343
|
await this.addThemes(zip, model);
|
|
315
344
|
await this.addStyles(zip, model);
|
|
316
345
|
await this.addFeaturePropertyBag(zip, model);
|
|
346
|
+
await this.addMetadata(zip, model);
|
|
317
347
|
await this.addMedia(zip, model);
|
|
318
348
|
await this.addApp(zip, model);
|
|
319
349
|
await this.addCore(zip, model);
|
|
@@ -363,32 +393,44 @@ class XLSX {
|
|
|
363
393
|
return this._finalize(zip);
|
|
364
394
|
}
|
|
365
395
|
/**
|
|
366
|
-
* Load workbook from
|
|
396
|
+
* Load a workbook from binary data.
|
|
397
|
+
*
|
|
398
|
+
* Accepted inputs:
|
|
399
|
+
* - `Uint8Array` (and `Buffer`, which is a Uint8Array at runtime)
|
|
400
|
+
* - `ArrayBuffer` / `SharedArrayBuffer`
|
|
401
|
+
* - Any `ArrayBufferView` (DataView, Int8Array, Float32Array, …) — the
|
|
402
|
+
* underlying bytes are reinterpreted as a zip archive
|
|
403
|
+
* - `string` — treated as base64-encoded data when `options.base64 === true`;
|
|
404
|
+
* raw binary cannot be round-tripped through a JS string and is rejected
|
|
405
|
+
* to prevent silent corruption.
|
|
367
406
|
*/
|
|
368
407
|
async load(data, options) {
|
|
369
|
-
|
|
370
|
-
// Validate input
|
|
371
|
-
const isBuffer = typeof Buffer !== "undefined" ? Buffer.isBuffer(data) : false;
|
|
372
|
-
if (!data ||
|
|
373
|
-
(typeof data === "object" &&
|
|
374
|
-
!isBuffer &&
|
|
375
|
-
!(data instanceof Uint8Array) &&
|
|
376
|
-
!(data instanceof ArrayBuffer))) {
|
|
408
|
+
if (data === null || data === undefined) {
|
|
377
409
|
throw new ExcelFileError("<input>", "read", "Can't read the data of 'the loaded zip file'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?");
|
|
378
410
|
}
|
|
379
|
-
|
|
380
|
-
if (
|
|
381
|
-
|
|
411
|
+
let buffer;
|
|
412
|
+
if (typeof data === "string") {
|
|
413
|
+
// Strings must be base64-encoded — binary zip bytes cannot be round-tripped
|
|
414
|
+
// through a JS string without corruption. Require the explicit opt-in.
|
|
415
|
+
if (!options?.base64) {
|
|
416
|
+
throw new ExcelFileError("<input>", "read", "Can't read the data of 'the loaded zip file'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ? " +
|
|
417
|
+
"String input requires options.base64 === true (base64-encoded zip archive).");
|
|
418
|
+
}
|
|
419
|
+
buffer = base64ToUint8Array(data);
|
|
420
|
+
}
|
|
421
|
+
else if (data instanceof Uint8Array) {
|
|
422
|
+
// Covers Buffer (Node) and any typed-array view whose element size is 1.
|
|
423
|
+
buffer = data;
|
|
382
424
|
}
|
|
383
425
|
else if (data instanceof ArrayBuffer) {
|
|
384
426
|
buffer = new Uint8Array(data);
|
|
385
427
|
}
|
|
386
|
-
else if (data
|
|
387
|
-
|
|
428
|
+
else if (ArrayBuffer.isView(data)) {
|
|
429
|
+
// DataView, Int8Array, Float32Array, … — view onto an underlying buffer.
|
|
430
|
+
buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
388
431
|
}
|
|
389
432
|
else {
|
|
390
|
-
|
|
391
|
-
buffer = new Uint8Array(data);
|
|
433
|
+
throw new ExcelFileError("<input>", "read", "Can't read the data of 'the loaded zip file'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?");
|
|
392
434
|
}
|
|
393
435
|
return this.loadBuffer(buffer, options);
|
|
394
436
|
}
|
|
@@ -435,7 +477,15 @@ class XLSX {
|
|
|
435
477
|
pivotCacheDefinitions: {},
|
|
436
478
|
pivotCacheRecords: {},
|
|
437
479
|
// Passthrough storage for unknown/unsupported files (charts, etc.)
|
|
438
|
-
passthrough: {}
|
|
480
|
+
passthrough: {},
|
|
481
|
+
// External workbook links — parsed from xl/externalLinks/externalLinkN.xml
|
|
482
|
+
// during _processDefaultEntry, then reconciled into a dense
|
|
483
|
+
// ExternalLinkModel[] by reconcile() using workbookRels + <externalReferences>.
|
|
484
|
+
externalLinksByIndex: {},
|
|
485
|
+
// Raw rels from each externalLinkN.rels file, keyed by index.
|
|
486
|
+
// Contains the actual Target path (e.g. "测试.xlsx", "file:///...")
|
|
487
|
+
// and TargetMode ("External" / "Internal").
|
|
488
|
+
externalLinkRelsByIndex: {}
|
|
439
489
|
};
|
|
440
490
|
}
|
|
441
491
|
/**
|
|
@@ -495,8 +545,12 @@ class XLSX {
|
|
|
495
545
|
model.definedNames = workbook.definedNames;
|
|
496
546
|
model.views = workbook.views;
|
|
497
547
|
model.properties = workbook.properties;
|
|
548
|
+
model.protection = workbook.protection;
|
|
498
549
|
model.calcProperties = workbook.calcProperties;
|
|
499
550
|
model.pivotCaches = workbook.pivotCaches;
|
|
551
|
+
// Pass-through the ordered list of <externalReference> rIds. These
|
|
552
|
+
// get resolved into a dense externalLinks[] during reconcile().
|
|
553
|
+
model.externalReferences = workbook.externalReferences;
|
|
500
554
|
return true;
|
|
501
555
|
}
|
|
502
556
|
case OOXML_PATHS.xlSharedStrings:
|
|
@@ -525,6 +579,14 @@ class XLSX {
|
|
|
525
579
|
model.styles = new StylesXform();
|
|
526
580
|
await model.styles.parseStream(stream);
|
|
527
581
|
return true;
|
|
582
|
+
case OOXML_PATHS.xlMetadata: {
|
|
583
|
+
const metadataXform = new MetadataXform();
|
|
584
|
+
const metadataResult = await metadataXform.parseStream(stream);
|
|
585
|
+
if (metadataResult) {
|
|
586
|
+
model.metadata = metadataResult;
|
|
587
|
+
}
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
528
590
|
default:
|
|
529
591
|
return false;
|
|
530
592
|
}
|
|
@@ -695,12 +757,21 @@ class XLSX {
|
|
|
695
757
|
comments: model.comments,
|
|
696
758
|
tables: model.tables,
|
|
697
759
|
vmlDrawings: model.vmlDrawings,
|
|
698
|
-
pivotTables: model.pivotTablesIndexed
|
|
760
|
+
pivotTables: model.pivotTablesIndexed,
|
|
761
|
+
hasDynamicArrayMetadata: !!model.metadata?.hasDynamicArrays,
|
|
762
|
+
dynamicArrayCmIndices: model.metadata?.dynamicArrayCmIndices
|
|
699
763
|
};
|
|
700
764
|
model.worksheets.forEach((worksheet) => {
|
|
701
765
|
worksheet.relationships = model.worksheetRels[worksheet.sheetNo];
|
|
702
766
|
worksheetXform.reconcile(worksheet, sheetOptions);
|
|
703
767
|
});
|
|
768
|
+
// Reconcile external workbook links before workbookRels / externalReferences
|
|
769
|
+
// are dropped. Joins 3 sources:
|
|
770
|
+
// 1. model.externalReferences — ordered list of { rId } from workbook.xml
|
|
771
|
+
// 2. model.workbookRels — maps rId → target path (inside xl/)
|
|
772
|
+
// 3. model.externalLinksByIndex — parsed externalLinkN.xml parts
|
|
773
|
+
// 4. model.externalLinkRelsByIndex — parsed externalLinkN.xml.rels parts
|
|
774
|
+
this._reconcileExternalLinks(model);
|
|
704
775
|
// delete unnecessary parts
|
|
705
776
|
delete model.worksheetHash;
|
|
706
777
|
delete model.worksheetRels;
|
|
@@ -716,6 +787,180 @@ class XLSX {
|
|
|
716
787
|
delete model.drawingRels;
|
|
717
788
|
delete model.vmlDrawings;
|
|
718
789
|
delete model.pivotTableRels;
|
|
790
|
+
delete model.metadata;
|
|
791
|
+
// Internal-only scratch fields consumed by _reconcileExternalLinks.
|
|
792
|
+
delete model.externalReferences;
|
|
793
|
+
delete model.externalLinksByIndex;
|
|
794
|
+
delete model.externalLinkRelsByIndex;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Join the three on-disk sources that together describe external workbook
|
|
798
|
+
* references into a single dense `model.externalLinks: ExternalLinkModel[]`.
|
|
799
|
+
*
|
|
800
|
+
* Sources:
|
|
801
|
+
* - `<externalReferences>` list in workbook.xml (declaration order)
|
|
802
|
+
* - `xl/_rels/workbook.xml.rels` (rId → internal path)
|
|
803
|
+
* - `xl/externalLinks/externalLink{N}.xml` (sheet names, cached values)
|
|
804
|
+
* - `xl/externalLinks/_rels/externalLink{N}.xml.rels` (target, TargetMode)
|
|
805
|
+
*
|
|
806
|
+
* The 1-based index of each resulting ExternalLinkModel matches the `[N]`
|
|
807
|
+
* used in formula strings — this is the single source of truth formula
|
|
808
|
+
* code should rely on.
|
|
809
|
+
*/
|
|
810
|
+
_reconcileExternalLinks(model) {
|
|
811
|
+
const refs = model.externalReferences;
|
|
812
|
+
if (!refs || refs.length === 0) {
|
|
813
|
+
// Even when workbook.xml has no <externalReferences>, we may still
|
|
814
|
+
// have parsed externalLink parts (e.g. orphaned files); those are
|
|
815
|
+
// dropped silently rather than generating synthesised indices.
|
|
816
|
+
if (!model.externalLinks) {
|
|
817
|
+
model.externalLinks = [];
|
|
818
|
+
}
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
const rels = (model.workbookRels ?? []);
|
|
822
|
+
const relById = new Map();
|
|
823
|
+
for (const rel of rels) {
|
|
824
|
+
if (rel.Type === RelType.ExternalLink) {
|
|
825
|
+
relById.set(rel.Id, rel);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
const externalLinks = [];
|
|
829
|
+
for (let i = 0; i < refs.length; i++) {
|
|
830
|
+
const ref = refs[i];
|
|
831
|
+
const rel = relById.get(ref.rId);
|
|
832
|
+
if (!rel) {
|
|
833
|
+
// Broken reference — <externalReference> points at an rId that is
|
|
834
|
+
// not of type ExternalLink. We skip silently; the formula engine
|
|
835
|
+
// will see the now-missing index and fall back to #REF! as before.
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
// The rel Target is a path inside xl/ like "externalLinks/externalLink1.xml".
|
|
839
|
+
// Extract the trailing index to look up the parsed part.
|
|
840
|
+
const partIndex = externalLinkIndexFromRelTarget(rel.Target);
|
|
841
|
+
if (partIndex === undefined) {
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
const parsed = model.externalLinksByIndex[partIndex];
|
|
845
|
+
const partRels = (model.externalLinkRelsByIndex[partIndex] ?? []);
|
|
846
|
+
// Locate the externalLinkPath rel (should be unique within a part).
|
|
847
|
+
const pathRel = partRels.find(r => r.Type === RelType.ExternalLinkPath) ??
|
|
848
|
+
partRels.find(r => r.TargetMode === "External");
|
|
849
|
+
externalLinks.push({
|
|
850
|
+
index: i + 1,
|
|
851
|
+
rId: ref.rId,
|
|
852
|
+
target: pathRel?.Target ?? "",
|
|
853
|
+
targetMode: pathRel?.TargetMode ?? "External",
|
|
854
|
+
sheetNames: parsed?.sheetNames ?? [],
|
|
855
|
+
cachedValues: parsed?.cachedValues ?? {}
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
model.externalLinks = externalLinks;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Write-time pass that brings the workbook model into a shape the writer
|
|
862
|
+
* can serialise cleanly. Two concerns:
|
|
863
|
+
*
|
|
864
|
+
* 1. Build the final external-link list for this write, combining
|
|
865
|
+
* user-declared links (`wb.externalLinks`) with auto-discovered
|
|
866
|
+
* ones from previous writes (cached on the Workbook). The result
|
|
867
|
+
* is assigned to `model.externalLinks` and consumed by the writer;
|
|
868
|
+
* `wb.externalLinks` is **not** modified.
|
|
869
|
+
*
|
|
870
|
+
* 2. Scan every formula cell for `[Book]Sheet!` prefixes. Filename-form
|
|
871
|
+
* references that don't match an existing link trigger
|
|
872
|
+
* `_recordAutoExternalLink()` on the Workbook, which adds the target
|
|
873
|
+
* to the private writer cache (so subsequent writes are fixed-point
|
|
874
|
+
* stable) but leaves `wb.externalLinks` untouched.
|
|
875
|
+
*
|
|
876
|
+
* 3. Rewrite every external-ref formula so it uses the numeric `[N]`
|
|
877
|
+
* form, the canonical OOXML storage form. This mutation lands on
|
|
878
|
+
* the cell's model object — matching the library's existing
|
|
879
|
+
* write-time pattern for `ssId`, `styleId`, `si`, and `cm`.
|
|
880
|
+
* Subsequent writes see the `[N]` form directly and resolve it
|
|
881
|
+
* against `model.externalLinks`, giving idempotent output.
|
|
882
|
+
*/
|
|
883
|
+
_normaliseExternalLinks(model) {
|
|
884
|
+
// Start from user-declared links, honouring their declaration order.
|
|
885
|
+
const links = this.workbook._collectExternalLinksForWrite();
|
|
886
|
+
// Fast lookup: case-insensitive target → link object in `links`.
|
|
887
|
+
const byTarget = new Map();
|
|
888
|
+
for (const link of links) {
|
|
889
|
+
if (link.target) {
|
|
890
|
+
byTarget.set(link.target.toLowerCase(), link);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
const scratch = { links, byTarget, workbook: this.workbook };
|
|
894
|
+
for (const worksheet of model.worksheets ?? []) {
|
|
895
|
+
for (const row of worksheet.rows ?? []) {
|
|
896
|
+
for (const cell of row.cells ?? []) {
|
|
897
|
+
if (typeof cell?.formula === "string" && cell.formula.length > 0) {
|
|
898
|
+
cell.formula = this._normaliseFormulaExternalRefs(cell.formula, scratch);
|
|
899
|
+
}
|
|
900
|
+
if (typeof cell?.sharedFormula === "string" && cell.sharedFormula.length > 0) {
|
|
901
|
+
// Shared-formula clones typically carry the master's *address*
|
|
902
|
+
// here, not a formula body — they won't match the ref regex.
|
|
903
|
+
// Masters carry the formula on `.formula` (handled above).
|
|
904
|
+
// We rewrite defensively in case a caller stored an actual
|
|
905
|
+
// formula string here.
|
|
906
|
+
cell.sharedFormula = this._normaliseFormulaExternalRefs(cell.sharedFormula, scratch);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
model.externalLinks = links;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Rewrite a single formula so every external-ref prefix uses the numeric
|
|
915
|
+
* `[N]` form. When an unknown filename-form reference is found we record
|
|
916
|
+
* it on the workbook's private writer cache (so the next write can still
|
|
917
|
+
* resolve it) and append a local link to `scratch.links` so subsequent
|
|
918
|
+
* refs in the same formula see the freshly-assigned index.
|
|
919
|
+
*/
|
|
920
|
+
_normaliseFormulaExternalRefs(formula, scratch) {
|
|
921
|
+
// rewriteExternalRefs internally calls findExternalRefs and returns
|
|
922
|
+
// the original string unchanged when there are no matches — no need
|
|
923
|
+
// for a separate guard scan here.
|
|
924
|
+
return rewriteExternalRefs(formula, ref => {
|
|
925
|
+
// Numeric ref: accept if it resolves, otherwise preserve verbatim so
|
|
926
|
+
// Excel surfaces `#REF!` at load time — same as the old behaviour
|
|
927
|
+
// for truly broken references.
|
|
928
|
+
if (ref.numeric) {
|
|
929
|
+
if (ref.index !== null && ref.index >= 1 && ref.index <= scratch.links.length) {
|
|
930
|
+
upsertSheet(scratch.links[ref.index - 1], ref.sheet);
|
|
931
|
+
return ref.index;
|
|
932
|
+
}
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
// Filename form — look up or auto-register.
|
|
936
|
+
const key = ref.workbook.toLowerCase();
|
|
937
|
+
let link = scratch.byTarget.get(key);
|
|
938
|
+
if (!link) {
|
|
939
|
+
const index = scratch.workbook._recordAutoExternalLink(ref.workbook, ref.sheet);
|
|
940
|
+
link = {
|
|
941
|
+
index,
|
|
942
|
+
target: ref.workbook,
|
|
943
|
+
targetMode: "External",
|
|
944
|
+
sheetNames: ref.sheet ? [ref.sheet] : [],
|
|
945
|
+
cachedValues: {}
|
|
946
|
+
};
|
|
947
|
+
// Keep the local writer list dense: insert at its future position.
|
|
948
|
+
// `_recordAutoExternalLink` guarantees `index` is user.length + cache.size
|
|
949
|
+
// at the time of insertion, which equals `scratch.links.length + 1`
|
|
950
|
+
// whenever we walk formulas sequentially.
|
|
951
|
+
scratch.links.push(link);
|
|
952
|
+
scratch.byTarget.set(key, link);
|
|
953
|
+
}
|
|
954
|
+
else {
|
|
955
|
+
upsertSheet(link, ref.sheet);
|
|
956
|
+
// Keep the workbook cache's sheetNames in sync so subsequent
|
|
957
|
+
// writes see the accumulated set.
|
|
958
|
+
if (ref.sheet) {
|
|
959
|
+
scratch.workbook._recordAutoExternalLink(ref.workbook, ref.sheet);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return link.index;
|
|
963
|
+
});
|
|
719
964
|
}
|
|
720
965
|
/**
|
|
721
966
|
* Reconcile pivot tables by linking them to worksheets and their cache data.
|
|
@@ -971,6 +1216,29 @@ class XLSX {
|
|
|
971
1216
|
model.pivotCacheRecords[name] = cacheRecords;
|
|
972
1217
|
}
|
|
973
1218
|
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Parse `xl/externalLinks/externalLink{N}.xml` into the intermediate
|
|
1221
|
+
* ParsedExternalLink shape. Reconciliation (joining with the rels file
|
|
1222
|
+
* and the workbook's `<externalReferences>` list) happens later in
|
|
1223
|
+
* {@link reconcile}.
|
|
1224
|
+
*/
|
|
1225
|
+
async _processExternalLinkEntry(stream, model, index) {
|
|
1226
|
+
const xform = new ExternalLinkXform();
|
|
1227
|
+
const parsed = await xform.parseStream(stream);
|
|
1228
|
+
if (parsed) {
|
|
1229
|
+
model.externalLinksByIndex[index] = parsed;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Parse `xl/externalLinks/_rels/externalLink{N}.xml.rels`. The Target /
|
|
1234
|
+
* TargetMode carried here is what Excel uses to locate the actual external
|
|
1235
|
+
* file at open time, so we must preserve it verbatim (including relative
|
|
1236
|
+
* paths like `"测试.xlsx"`).
|
|
1237
|
+
*/
|
|
1238
|
+
async _processExternalLinkRelsEntry(stream, model, index) {
|
|
1239
|
+
const relationships = await this.parseRels(stream);
|
|
1240
|
+
model.externalLinkRelsByIndex[index] = relationships ?? [];
|
|
1241
|
+
}
|
|
974
1242
|
// ===========================================================================
|
|
975
1243
|
// loadFromFiles - shared logic for loading from pre-extracted ZIP data
|
|
976
1244
|
// ===========================================================================
|
|
@@ -1082,6 +1350,20 @@ class XLSX {
|
|
|
1082
1350
|
await this._processPivotCacheRecordsEntry(stream, model, pivotCacheRecordsName);
|
|
1083
1351
|
return true;
|
|
1084
1352
|
}
|
|
1353
|
+
// External workbook links: xl/externalLinks/externalLinkN.xml and its
|
|
1354
|
+
// sibling _rels file. Both parts are required to reconstruct the
|
|
1355
|
+
// ExternalLinkModel (the .xml carries sheet names + cached values; the
|
|
1356
|
+
// .rels carries the target path and TargetMode).
|
|
1357
|
+
const externalLinkIndex = getExternalLinkIndexFromPath(entryName);
|
|
1358
|
+
if (externalLinkIndex !== undefined) {
|
|
1359
|
+
await this._processExternalLinkEntry(stream, model, externalLinkIndex);
|
|
1360
|
+
return true;
|
|
1361
|
+
}
|
|
1362
|
+
const externalLinkRelsIndex = getExternalLinkIndexFromRelsPath(entryName);
|
|
1363
|
+
if (externalLinkRelsIndex !== undefined) {
|
|
1364
|
+
await this._processExternalLinkRelsEntry(stream, model, externalLinkRelsIndex);
|
|
1365
|
+
return true;
|
|
1366
|
+
}
|
|
1085
1367
|
// Store passthrough files (charts, etc.) for preservation
|
|
1086
1368
|
if (PassthroughManager.isPassthroughPath(entryName)) {
|
|
1087
1369
|
// If raw data is available (loadFromFiles path), use it directly
|
|
@@ -1163,6 +1445,14 @@ class XLSX {
|
|
|
1163
1445
|
Target: OOXML_REL_TARGETS.workbookFeaturePropertyBag
|
|
1164
1446
|
});
|
|
1165
1447
|
}
|
|
1448
|
+
// Add metadata relationship for dynamic array formulas
|
|
1449
|
+
if (model.hasDynamicArrayFormulas) {
|
|
1450
|
+
relationships.push({
|
|
1451
|
+
Id: `rId${count++}`,
|
|
1452
|
+
Type: XLSX.RelType.SheetMetadata,
|
|
1453
|
+
Target: OOXML_REL_TARGETS.workbookMetadata
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1166
1456
|
// R9-B6: Deduplicate pivot cache relationships by cacheId. When multiple pivot
|
|
1167
1457
|
// tables share the same cache, only one workbook relationship should be created.
|
|
1168
1458
|
// Also assigns rId to each pivot table (R9-B7: typed on PivotTable interface).
|
|
@@ -1192,6 +1482,26 @@ class XLSX {
|
|
|
1192
1482
|
Target: worksheetRelTarget(worksheet.fileIndex)
|
|
1193
1483
|
});
|
|
1194
1484
|
});
|
|
1485
|
+
// External workbook link rels are written AFTER worksheets on purpose:
|
|
1486
|
+
// Excel tolerates either order, but stable ordering (worksheets then
|
|
1487
|
+
// externalLinks) keeps the emitted workbook.xml.rels diff-friendly for
|
|
1488
|
+
// round-trip tests. Each external link becomes a regular Relationship
|
|
1489
|
+
// entry targeting `externalLinks/externalLinkN.xml` inside `xl/`; the
|
|
1490
|
+
// actual external file path is pointed at by the nested
|
|
1491
|
+
// externalLinkN.xml.rels part written by addExternalLinks().
|
|
1492
|
+
//
|
|
1493
|
+
// The list items here are the deep-copies produced by
|
|
1494
|
+
// `_normaliseExternalLinks` — assigning `link.rId` is safe and does not
|
|
1495
|
+
// leak into the user's Workbook.externalLinks.
|
|
1496
|
+
const externalLinks = (model.externalLinks ?? []);
|
|
1497
|
+
for (const link of externalLinks) {
|
|
1498
|
+
link.rId = `rId${count++}`;
|
|
1499
|
+
relationships.push({
|
|
1500
|
+
Id: link.rId,
|
|
1501
|
+
Type: XLSX.RelType.ExternalLink,
|
|
1502
|
+
Target: externalLinkRelTargetFromWorkbook(link.index)
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1195
1505
|
const xform = new RelationshipsXform();
|
|
1196
1506
|
await this._renderToZip(zip, OOXML_PATHS.xlWorkbookRels, xform, relationships);
|
|
1197
1507
|
}
|
|
@@ -1201,6 +1511,14 @@ class XLSX {
|
|
|
1201
1511
|
}
|
|
1202
1512
|
await this._renderToZip(zip, OOXML_PATHS.xlFeaturePropertyBag, new FeaturePropertyBagXform(), {});
|
|
1203
1513
|
}
|
|
1514
|
+
async addMetadata(zip, model) {
|
|
1515
|
+
if (!model.hasDynamicArrayFormulas) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
await this._renderToZip(zip, OOXML_PATHS.xlMetadata, new MetadataXform(), {
|
|
1519
|
+
dynamicArrayCount: model.dynamicArrayCount
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1204
1522
|
async addSharedStrings(zip, model) {
|
|
1205
1523
|
if (model.sharedStrings && model.sharedStrings.count) {
|
|
1206
1524
|
await this._renderToZip(zip, OOXML_PATHS.xlSharedStrings, model.sharedStrings, model.sharedStrings.model);
|
|
@@ -1316,6 +1634,41 @@ class XLSX {
|
|
|
1316
1634
|
}
|
|
1317
1635
|
}
|
|
1318
1636
|
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Write every external workbook reference into the archive. For each
|
|
1639
|
+
* {@link ExternalLinkModel} in `model.externalLinks` we emit two files:
|
|
1640
|
+
*
|
|
1641
|
+
* xl/externalLinks/externalLink{index}.xml — sheet names + cache
|
|
1642
|
+
* xl/externalLinks/_rels/externalLink{index}.xml.rels — target path
|
|
1643
|
+
*
|
|
1644
|
+
* The target-path rel carries `TargetMode="External"` with a **bare
|
|
1645
|
+
* relative** `Target` whenever the user supplied one. This is the single
|
|
1646
|
+
* line that makes Office / WPS resolve the referenced workbook relative
|
|
1647
|
+
* to the current file's directory (not the `%USERPROFILE%\Documents`
|
|
1648
|
+
* fallback) — the root of the behaviour reported in exceljs#3039.
|
|
1649
|
+
*/
|
|
1650
|
+
async addExternalLinks(zip, model) {
|
|
1651
|
+
const externalLinks = (model.externalLinks ?? []);
|
|
1652
|
+
if (externalLinks.length === 0) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
const externalLinkXform = new ExternalLinkXform();
|
|
1656
|
+
const relsXform = new RelationshipsXform();
|
|
1657
|
+
for (const link of externalLinks) {
|
|
1658
|
+
await this._renderToZip(zip, externalLinkPath(link.index), externalLinkXform, link);
|
|
1659
|
+
// Always rId1 — the externalLink part only ever has a single rel.
|
|
1660
|
+
// `TargetMode="External"` is what flags Office to look the file up
|
|
1661
|
+
// at workbook-open time rather than embed it.
|
|
1662
|
+
await this._renderToZip(zip, externalLinkRelsPath(link.index), relsXform, [
|
|
1663
|
+
{
|
|
1664
|
+
Id: "rId1",
|
|
1665
|
+
Type: XLSX.RelType.ExternalLinkPath,
|
|
1666
|
+
Target: link.target,
|
|
1667
|
+
TargetMode: link.targetMode ?? "External"
|
|
1668
|
+
}
|
|
1669
|
+
]);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1319
1672
|
/**
|
|
1320
1673
|
* Write passthrough files (charts, etc.) that were preserved during read.
|
|
1321
1674
|
* These files are written back unchanged to preserve unsupported features.
|
|
@@ -1409,6 +1762,18 @@ class XLSX {
|
|
|
1409
1762
|
const workbookXform = new WorkbookXform();
|
|
1410
1763
|
const worksheetXform = new WorkSheetXform();
|
|
1411
1764
|
workbookXform.prepare(model);
|
|
1765
|
+
// Normalise external-workbook references before any formula rendering.
|
|
1766
|
+
// Two jobs:
|
|
1767
|
+
// 1. Scan every formula cell and make sure each referenced workbook
|
|
1768
|
+
// has a matching ExternalLinkModel in `model.externalLinks`, with
|
|
1769
|
+
// a stable 1-based index.
|
|
1770
|
+
// 2. Rewrite formula strings from `[filename.xlsx]Sheet!A1` to
|
|
1771
|
+
// `[N]Sheet!A1`, which is the canonical on-disk form Excel
|
|
1772
|
+
// expects inside `<f>` elements.
|
|
1773
|
+
//
|
|
1774
|
+
// Done once up-front (not per cell) so the index assignment is
|
|
1775
|
+
// deterministic and every cell sees the final externalLinks list.
|
|
1776
|
+
this._normaliseExternalLinks(model);
|
|
1412
1777
|
const worksheetOptions = {
|
|
1413
1778
|
sharedStrings: model.sharedStrings,
|
|
1414
1779
|
styles: model.styles,
|
|
@@ -1422,6 +1787,7 @@ class XLSX {
|
|
|
1422
1787
|
model.hasHeaderWatermark = false;
|
|
1423
1788
|
let tableCount = 0;
|
|
1424
1789
|
model.tables = [];
|
|
1790
|
+
const tableNameMap = new Map(); // name (lowercase) → worksheet name
|
|
1425
1791
|
model.worksheets.forEach((worksheet, index) => {
|
|
1426
1792
|
// Assign fileIndex early so that worksheet-xform.prepare() can use it
|
|
1427
1793
|
// for comment/VML relationship targets and content type names.
|
|
@@ -1429,6 +1795,16 @@ class XLSX {
|
|
|
1429
1795
|
// using the same fileIndex.
|
|
1430
1796
|
worksheet.fileIndex = index + 1;
|
|
1431
1797
|
worksheet.tables.forEach((table) => {
|
|
1798
|
+
// OOXML requires table names to be unique across the entire workbook
|
|
1799
|
+
// (case-insensitive). Detect duplicates early to produce a clear error
|
|
1800
|
+
// instead of generating a corrupt file that Excel must repair.
|
|
1801
|
+
const nameKey = table.name.toLowerCase();
|
|
1802
|
+
const existingSheet = tableNameMap.get(nameKey);
|
|
1803
|
+
if (existingSheet !== undefined) {
|
|
1804
|
+
throw new TableError(`Duplicate table name "${table.name}": already used in worksheet "${existingSheet}". ` +
|
|
1805
|
+
`Table names must be unique across the entire workbook (case-insensitive).`);
|
|
1806
|
+
}
|
|
1807
|
+
tableNameMap.set(nameKey, worksheet.name);
|
|
1432
1808
|
tableCount++;
|
|
1433
1809
|
table.target = `table${tableCount}.xml`;
|
|
1434
1810
|
table.id = tableCount;
|
|
@@ -1438,6 +1814,20 @@ class XLSX {
|
|
|
1438
1814
|
});
|
|
1439
1815
|
// ContentTypesXform expects this flag
|
|
1440
1816
|
model.hasCheckboxes = model.styles.hasCheckboxes;
|
|
1817
|
+
// Scan all worksheets for dynamic array formulas.
|
|
1818
|
+
// cm=1 is assigned later by cell-xform.prepare() during worksheet rendering.
|
|
1819
|
+
let dynamicArrayCount = 0;
|
|
1820
|
+
model.worksheets.forEach((worksheet) => {
|
|
1821
|
+
(worksheet.rows ?? []).forEach((row) => {
|
|
1822
|
+
(row.cells ?? []).forEach((cell) => {
|
|
1823
|
+
if (cell.isDynamicArray) {
|
|
1824
|
+
dynamicArrayCount++;
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
});
|
|
1828
|
+
});
|
|
1829
|
+
model.hasDynamicArrayFormulas = dynamicArrayCount > 0;
|
|
1830
|
+
model.dynamicArrayCount = dynamicArrayCount;
|
|
1441
1831
|
// Propagate header watermark flag from worksheet prepare options
|
|
1442
1832
|
if (worksheetOptions.hasHeaderWatermark) {
|
|
1443
1833
|
model.hasHeaderWatermark = true;
|
|
@@ -100,7 +100,7 @@ class XLSX extends XLSXBase {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
catch (e) {
|
|
103
|
-
callback(e);
|
|
103
|
+
callback(toError(e));
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
106
|
final(callback) {
|
|
@@ -109,13 +109,13 @@ class XLSX extends XLSXBase {
|
|
|
109
109
|
callback();
|
|
110
110
|
}
|
|
111
111
|
catch (e) {
|
|
112
|
-
callback(e);
|
|
112
|
+
callback(toError(e));
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
});
|
|
116
116
|
const onParserError = (err) => {
|
|
117
117
|
try {
|
|
118
|
-
sink.destroy(err);
|
|
118
|
+
sink.destroy(toError(err));
|
|
119
119
|
}
|
|
120
120
|
catch {
|
|
121
121
|
// ignore
|
|
@@ -127,8 +127,7 @@ class XLSX extends XLSXBase {
|
|
|
127
127
|
for await (const entry of XLSX.iterateZipEntries(parser)) {
|
|
128
128
|
entry.on("error", swallowError);
|
|
129
129
|
const drain = async () => {
|
|
130
|
-
|
|
131
|
-
if (anyEntry?.readableEnded || anyEntry?.destroyed) {
|
|
130
|
+
if (entry.readableEnded || entry.destroyed) {
|
|
132
131
|
return;
|
|
133
132
|
}
|
|
134
133
|
const draining = entry.autodrain();
|