@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @cj-tech-master/excelts v9.
|
|
2
|
+
* @cj-tech-master/excelts v9.3.0
|
|
3
3
|
* Zero-dependency TypeScript toolkit — Excel (XLSX), PDF, CSV, Markdown, XML, ZIP/TAR, and streaming.
|
|
4
4
|
* (c) 2026 cjnoname
|
|
5
5
|
* Released under the MIT License
|
|
@@ -7364,7 +7364,8 @@ var ExcelTS = (function(exports) {
|
|
|
7364
7364
|
this._isSubclassTransform = false;
|
|
7365
7365
|
return false;
|
|
7366
7366
|
}
|
|
7367
|
-
|
|
7367
|
+
const proto = Object.getPrototypeOf(this);
|
|
7368
|
+
this._isSubclassTransform = proto._transform !== Transform.prototype._transform;
|
|
7368
7369
|
return this._isSubclassTransform;
|
|
7369
7370
|
}
|
|
7370
7371
|
_hasSubclassFlush() {
|
|
@@ -7739,34 +7740,36 @@ var ExcelTS = (function(exports) {
|
|
|
7739
7740
|
_getWebStream() {
|
|
7740
7741
|
if (this._webStream) return this._webStream;
|
|
7741
7742
|
const iterator = this[Symbol.asyncIterator]();
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
return;
|
|
7749
|
-
}
|
|
7750
|
-
controller.enqueue(value);
|
|
7751
|
-
},
|
|
7752
|
-
cancel: (reason) => {
|
|
7753
|
-
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
7743
|
+
const readable = new ReadableStream({
|
|
7744
|
+
pull: async (controller) => {
|
|
7745
|
+
const { done, value } = await iterator.next();
|
|
7746
|
+
if (done) {
|
|
7747
|
+
controller.close();
|
|
7748
|
+
return;
|
|
7754
7749
|
}
|
|
7750
|
+
controller.enqueue(value);
|
|
7751
|
+
},
|
|
7752
|
+
cancel: (reason) => {
|
|
7753
|
+
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
7754
|
+
}
|
|
7755
|
+
});
|
|
7756
|
+
const writable = new WritableStream({
|
|
7757
|
+
write: (chunk) => new Promise((resolve, reject) => {
|
|
7758
|
+
this.write(chunk, (err) => {
|
|
7759
|
+
if (err) reject(err);
|
|
7760
|
+
else resolve();
|
|
7761
|
+
});
|
|
7755
7762
|
}),
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
abort: (reason) => {
|
|
7767
|
-
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
7768
|
-
}
|
|
7769
|
-
})
|
|
7763
|
+
close: () => new Promise((resolve) => {
|
|
7764
|
+
this.end(() => resolve());
|
|
7765
|
+
}),
|
|
7766
|
+
abort: (reason) => {
|
|
7767
|
+
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
7768
|
+
}
|
|
7769
|
+
});
|
|
7770
|
+
this._webStream = {
|
|
7771
|
+
readable,
|
|
7772
|
+
writable
|
|
7770
7773
|
};
|
|
7771
7774
|
return this._webStream;
|
|
7772
7775
|
}
|
|
@@ -8461,7 +8464,8 @@ var ExcelTS = (function(exports) {
|
|
|
8461
8464
|
this.options = options;
|
|
8462
8465
|
this.chunkSize = options.chunkSize ?? 1e3;
|
|
8463
8466
|
this.decoder = new TextDecoder(options.encoding || "utf-8");
|
|
8464
|
-
|
|
8467
|
+
const delimiterOption = options.delimiter ?? ",";
|
|
8468
|
+
this.autoDetectDelimiter = delimiterOption === "";
|
|
8465
8469
|
const { config } = createParseConfig({ options });
|
|
8466
8470
|
this.parseConfig = config;
|
|
8467
8471
|
this.parseState = createParseState(config);
|
|
@@ -9611,6 +9615,11 @@ var ExcelTS = (function(exports) {
|
|
|
9611
9615
|
default: throw new InvalidAddressError(String(args.length), "Can only encode with 2 or 4 arguments");
|
|
9612
9616
|
}
|
|
9613
9617
|
},
|
|
9618
|
+
compareAddress(a, b) {
|
|
9619
|
+
const addrA = colCache.decodeAddress(a);
|
|
9620
|
+
const addrB = colCache.decodeAddress(b);
|
|
9621
|
+
return addrA.col - addrB.col || addrA.row - addrB.row;
|
|
9622
|
+
},
|
|
9614
9623
|
inRange(range, address) {
|
|
9615
9624
|
const [left, top, , right, bottom] = range;
|
|
9616
9625
|
const [col, row] = address;
|
|
@@ -9937,11 +9946,179 @@ var ExcelTS = (function(exports) {
|
|
|
9937
9946
|
}
|
|
9938
9947
|
};
|
|
9939
9948
|
//#endregion
|
|
9949
|
+
//#region src/modules/formula/default-syntax-probe.ts
|
|
9950
|
+
let defaultProbe = null;
|
|
9951
|
+
/**
|
|
9952
|
+
* Retrieve the currently-installed default probe, or `null` if none is
|
|
9953
|
+
* installed. Consumers (chiefly `DefinedNames`) should treat `null` as
|
|
9954
|
+
* a signal to use conservative (opaque) classification rather than
|
|
9955
|
+
* guessing.
|
|
9956
|
+
*/
|
|
9957
|
+
function getDefaultSyntaxProbe() {
|
|
9958
|
+
return defaultProbe;
|
|
9959
|
+
}
|
|
9960
|
+
//#endregion
|
|
9940
9961
|
//#region src/modules/excel/defined-names.ts
|
|
9941
9962
|
const rangeRegexp = /[$](\w+)[$](\d+)(:[$](\w+)[$](\d+))?/;
|
|
9963
|
+
const cellRangeRegexp = /^[$]?[A-Za-z]{1,3}[$]?\d+(:[$]?[A-Za-z]{1,3}[$]?\d+)?$/;
|
|
9964
|
+
const rowRangeRegexp = /^[$]?\d+:[$]?\d+$/;
|
|
9965
|
+
const colRangeRegexp = /^[$]?[A-Za-z]{1,3}:[$]?[A-Za-z]{1,3}$/;
|
|
9966
|
+
function isValidRange(range) {
|
|
9967
|
+
if (range.startsWith("{") || range.endsWith("}")) return false;
|
|
9968
|
+
const cellRef = range.split("!").pop() ?? "";
|
|
9969
|
+
if (!cellRangeRegexp.test(cellRef) && !rowRangeRegexp.test(cellRef) && !colRangeRegexp.test(cellRef)) return false;
|
|
9970
|
+
try {
|
|
9971
|
+
const decoded = colCache.decodeEx(range);
|
|
9972
|
+
if ("row" in decoded && typeof decoded.row === "number" || "top" in decoded && typeof decoded.top === "number" || "left" in decoded && typeof decoded.left === "number") return true;
|
|
9973
|
+
return false;
|
|
9974
|
+
} catch {
|
|
9975
|
+
return false;
|
|
9976
|
+
}
|
|
9977
|
+
}
|
|
9978
|
+
/**
|
|
9979
|
+
* Extract valid cell/range references from a raw defined name text string.
|
|
9980
|
+
* Handles comma-separated ranges and quoted sheet names that may contain commas.
|
|
9981
|
+
*/
|
|
9982
|
+
function extractRanges(parsedText) {
|
|
9983
|
+
const trimmed = parsedText.trim();
|
|
9984
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) return [];
|
|
9985
|
+
const ranges = [];
|
|
9986
|
+
let quotesOpened = false;
|
|
9987
|
+
let last = "";
|
|
9988
|
+
parsedText.split(",").forEach((item) => {
|
|
9989
|
+
if (!item) return;
|
|
9990
|
+
const quotes = (item.match(/'/g) ?? []).length;
|
|
9991
|
+
if (!quotes) {
|
|
9992
|
+
if (quotesOpened) last += `${item},`;
|
|
9993
|
+
else if (isValidRange(item)) ranges.push(item);
|
|
9994
|
+
return;
|
|
9995
|
+
}
|
|
9996
|
+
const quotesEven = quotes % 2 === 0;
|
|
9997
|
+
if (!quotesOpened && quotesEven && isValidRange(item)) ranges.push(item);
|
|
9998
|
+
else if (quotesOpened && !quotesEven) {
|
|
9999
|
+
quotesOpened = false;
|
|
10000
|
+
if (isValidRange(last + item)) ranges.push(last + item);
|
|
10001
|
+
last = "";
|
|
10002
|
+
} else {
|
|
10003
|
+
quotesOpened = true;
|
|
10004
|
+
last += `${item},`;
|
|
10005
|
+
}
|
|
10006
|
+
});
|
|
10007
|
+
return ranges;
|
|
10008
|
+
}
|
|
10009
|
+
/**
|
|
10010
|
+
* Check whether a string contains a '(' character outside of single-quoted
|
|
10011
|
+
* sheet name segments. Sheet names in cell references use single quotes:
|
|
10012
|
+
* e.g. `'Sheet (1)'!$A$1` — the '(' is inside quotes and does NOT indicate
|
|
10013
|
+
* a function call. A genuine formula like `OFFSET(Sheet1!$A$1,0,0,3,1)`
|
|
10014
|
+
* has '(' outside of any quotes.
|
|
10015
|
+
*/
|
|
10016
|
+
function hasUnquotedParen(s) {
|
|
10017
|
+
let inQuote = false;
|
|
10018
|
+
for (let i = 0; i < s.length; i++) {
|
|
10019
|
+
const ch = s[i];
|
|
10020
|
+
if (ch === "'") inQuote = !inQuote;
|
|
10021
|
+
else if (ch === "(" && !inQuote) return true;
|
|
10022
|
+
}
|
|
10023
|
+
return false;
|
|
10024
|
+
}
|
|
10025
|
+
/**
|
|
10026
|
+
* Classify a raw defined name text into one of three categories:
|
|
10027
|
+
* 1. **reference** — pure cell/range union (goes into matrixMap)
|
|
10028
|
+
* 2. **formula** — parseable expression (goes into formulaMap)
|
|
10029
|
+
* 3. **opaque** — unrecognised content preserved for round-trip
|
|
10030
|
+
*
|
|
10031
|
+
* Classification order matters:
|
|
10032
|
+
* - If the text contains an unquoted `(`, it is likely a formula — try the
|
|
10033
|
+
* formula parser first (this prevents `extractRanges` from misinterpreting
|
|
10034
|
+
* function arguments as partial range references).
|
|
10035
|
+
* - Otherwise try to extract ranges (pure cell references).
|
|
10036
|
+
* - If neither works, fall back to opaque.
|
|
10037
|
+
*
|
|
10038
|
+
* **Probe semantics:** `probe` is the formula tokenizer+parser oracle. It
|
|
10039
|
+
* is the *only* authority for deciding whether a non-range, non-wrapper
|
|
10040
|
+
* string is a formula. When `probe` is `null` (no formula engine
|
|
10041
|
+
* installed and no probe injected), any such string is classified as
|
|
10042
|
+
* **opaque** — we have no evidence it is a formula, and leaving it
|
|
10043
|
+
* opaque preserves round-trip bytes via `rawText`.
|
|
10044
|
+
*
|
|
10045
|
+
* This function is pure: the classification of a given input depends
|
|
10046
|
+
* entirely on (rawText, ranges, probe) and no global state. Two calls
|
|
10047
|
+
* with the same arguments always produce the same result.
|
|
10048
|
+
*/
|
|
10049
|
+
function classifyDefinedName(rawText, ranges, probe) {
|
|
10050
|
+
if (rawText === void 0) {
|
|
10051
|
+
if (ranges.length > 0) return {
|
|
10052
|
+
kind: "reference",
|
|
10053
|
+
ranges
|
|
10054
|
+
};
|
|
10055
|
+
return {
|
|
10056
|
+
kind: "opaque",
|
|
10057
|
+
ranges: []
|
|
10058
|
+
};
|
|
10059
|
+
}
|
|
10060
|
+
const trimmed = rawText.trim();
|
|
10061
|
+
if (trimmed.length === 0) return {
|
|
10062
|
+
kind: "opaque",
|
|
10063
|
+
ranges: []
|
|
10064
|
+
};
|
|
10065
|
+
const isArrayConst = trimmed.startsWith("{") && trimmed.endsWith("}");
|
|
10066
|
+
const isStringLit = trimmed.startsWith("\"") && trimmed.endsWith("\"");
|
|
10067
|
+
const isErrorVal = trimmed.startsWith("#");
|
|
10068
|
+
const isOpaqueWrapper = isArrayConst || isStringLit || isErrorVal;
|
|
10069
|
+
if (hasUnquotedParen(trimmed) && !isOpaqueWrapper) {
|
|
10070
|
+
if (probe && probe(trimmed)) return {
|
|
10071
|
+
kind: "formula",
|
|
10072
|
+
ranges: [trimmed],
|
|
10073
|
+
formulaExpression: trimmed
|
|
10074
|
+
};
|
|
10075
|
+
return {
|
|
10076
|
+
kind: "opaque",
|
|
10077
|
+
ranges: []
|
|
10078
|
+
};
|
|
10079
|
+
}
|
|
10080
|
+
const extracted = extractRanges(rawText);
|
|
10081
|
+
if (extracted.length > 0) return {
|
|
10082
|
+
kind: "reference",
|
|
10083
|
+
ranges: extracted
|
|
10084
|
+
};
|
|
10085
|
+
if (isOpaqueWrapper) return {
|
|
10086
|
+
kind: "opaque",
|
|
10087
|
+
ranges: []
|
|
10088
|
+
};
|
|
10089
|
+
if (probe && probe(trimmed)) return {
|
|
10090
|
+
kind: "formula",
|
|
10091
|
+
ranges: [trimmed],
|
|
10092
|
+
formulaExpression: trimmed
|
|
10093
|
+
};
|
|
10094
|
+
return {
|
|
10095
|
+
kind: "opaque",
|
|
10096
|
+
ranges: []
|
|
10097
|
+
};
|
|
10098
|
+
}
|
|
10099
|
+
/**
|
|
10100
|
+
* Build the internal storage key for a defined name entry.
|
|
10101
|
+
* Workbook-scoped: just the bare name.
|
|
10102
|
+
* Sheet-scoped: `"name\0sheetId"` (null char separator avoids collisions).
|
|
10103
|
+
*/
|
|
10104
|
+
function storageKey(name, localSheetId) {
|
|
10105
|
+
return localSheetId !== void 0 ? `${name}\0${localSheetId}` : name;
|
|
10106
|
+
}
|
|
9942
10107
|
var DefinedNames = class {
|
|
9943
|
-
|
|
10108
|
+
/**
|
|
10109
|
+
* @param probe Optional formula-syntax probe used when classifying
|
|
10110
|
+
* defined-name text. Injecting a probe here makes classification
|
|
10111
|
+
* deterministic for this instance regardless of process-global
|
|
10112
|
+
* `installFormulaEngine()` state. When omitted, the instance defers
|
|
10113
|
+
* to the default probe at classification time (see `set model`).
|
|
10114
|
+
*/
|
|
10115
|
+
constructor(probe) {
|
|
9944
10116
|
this.matrixMap = {};
|
|
10117
|
+
this.formulaMap = {};
|
|
10118
|
+
this.localSheetIdMap = {};
|
|
10119
|
+
this.opaqueMap = {};
|
|
10120
|
+
this.nameForKey = {};
|
|
10121
|
+
this._explicitProbe = probe ?? null;
|
|
9945
10122
|
}
|
|
9946
10123
|
getMatrix(name) {
|
|
9947
10124
|
return this.matrixMap[name] || (this.matrixMap[name] = new CellMatrix());
|
|
@@ -9949,6 +10126,9 @@ var ExcelTS = (function(exports) {
|
|
|
9949
10126
|
add(locStr, name) {
|
|
9950
10127
|
const location = colCache.decodeEx(locStr);
|
|
9951
10128
|
if ("error" in location) return;
|
|
10129
|
+
delete this.formulaMap[name];
|
|
10130
|
+
delete this.opaqueMap[name];
|
|
10131
|
+
this.nameForKey[name] = name;
|
|
9952
10132
|
this.addEx(location, name);
|
|
9953
10133
|
}
|
|
9954
10134
|
addEx(location, name) {
|
|
@@ -9964,6 +10144,22 @@ var ExcelTS = (function(exports) {
|
|
|
9964
10144
|
}
|
|
9965
10145
|
else matrix.addCellEx(location);
|
|
9966
10146
|
}
|
|
10147
|
+
/**
|
|
10148
|
+
* Register a formula-based defined name.
|
|
10149
|
+
*
|
|
10150
|
+
* Unlike `add()` which binds a name to a cell/range reference, this binds
|
|
10151
|
+
* a name to an arbitrary formula expression that will be evaluated at
|
|
10152
|
+
* calculation time.
|
|
10153
|
+
*
|
|
10154
|
+
* @param name - The defined name (e.g. "MyArray")
|
|
10155
|
+
* @param expression - The formula expression (e.g. "{1,2;3,4}", "LAMBDA(x,y,x+y)")
|
|
10156
|
+
*/
|
|
10157
|
+
addFormula(name, expression) {
|
|
10158
|
+
delete this.matrixMap[name];
|
|
10159
|
+
delete this.opaqueMap[name];
|
|
10160
|
+
this.nameForKey[name] = name;
|
|
10161
|
+
this.formulaMap[name] = expression;
|
|
10162
|
+
}
|
|
9967
10163
|
remove(locStr, name) {
|
|
9968
10164
|
const location = colCache.decodeEx(locStr);
|
|
9969
10165
|
if ("error" in location) return;
|
|
@@ -9991,9 +10187,10 @@ var ExcelTS = (function(exports) {
|
|
|
9991
10187
|
});
|
|
9992
10188
|
}
|
|
9993
10189
|
forEach(callback) {
|
|
9994
|
-
Object.entries(this.matrixMap).forEach(([
|
|
10190
|
+
Object.entries(this.matrixMap).forEach(([sKey, matrix]) => {
|
|
10191
|
+
const bareName = this.nameForKey[sKey] ?? sKey;
|
|
9995
10192
|
matrix.forEach((cell) => {
|
|
9996
|
-
callback(
|
|
10193
|
+
callback(bareName, cell);
|
|
9997
10194
|
});
|
|
9998
10195
|
});
|
|
9999
10196
|
}
|
|
@@ -10003,7 +10200,63 @@ var ExcelTS = (function(exports) {
|
|
|
10003
10200
|
return this.getNamesEx(location);
|
|
10004
10201
|
}
|
|
10005
10202
|
getNamesEx(address) {
|
|
10006
|
-
return Object.entries(this.matrixMap).map(([
|
|
10203
|
+
return Object.entries(this.matrixMap).map(([sKey, matrix]) => matrix.findCellEx(address, false) && (this.nameForKey[sKey] ?? sKey)).filter((name) => Boolean(name));
|
|
10204
|
+
}
|
|
10205
|
+
/**
|
|
10206
|
+
* Return all defined name entries in this collection, including scope info.
|
|
10207
|
+
* Each entry has the bare name and optional localSheetId.
|
|
10208
|
+
* Same bare name may appear multiple times with different scopes.
|
|
10209
|
+
*/
|
|
10210
|
+
getAllNames() {
|
|
10211
|
+
return this.getAllEntries().map((e) => e.localSheetId !== void 0 ? {
|
|
10212
|
+
name: e.name,
|
|
10213
|
+
localSheetId: e.localSheetId
|
|
10214
|
+
} : { name: e.name });
|
|
10215
|
+
}
|
|
10216
|
+
/**
|
|
10217
|
+
* Return all defined name entries with full details (name, ranges, scope).
|
|
10218
|
+
*
|
|
10219
|
+
* This is the primary enumeration API. Each entry is self-contained —
|
|
10220
|
+
* no second lookup is needed. Same bare name may appear multiple times
|
|
10221
|
+
* with different scopes.
|
|
10222
|
+
*/
|
|
10223
|
+
getAllEntries() {
|
|
10224
|
+
const result = [];
|
|
10225
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10226
|
+
for (const sKey of Object.keys(this.matrixMap)) {
|
|
10227
|
+
if (seen.has(sKey)) continue;
|
|
10228
|
+
seen.add(sKey);
|
|
10229
|
+
const model = this.getRanges(sKey);
|
|
10230
|
+
const localSheetId = this.localSheetIdMap[sKey];
|
|
10231
|
+
result.push(localSheetId !== void 0 ? {
|
|
10232
|
+
...model,
|
|
10233
|
+
localSheetId
|
|
10234
|
+
} : model);
|
|
10235
|
+
}
|
|
10236
|
+
for (const sKey of Object.keys(this.formulaMap)) {
|
|
10237
|
+
if (seen.has(sKey)) continue;
|
|
10238
|
+
seen.add(sKey);
|
|
10239
|
+
const model = this.getRanges(sKey);
|
|
10240
|
+
const localSheetId = this.localSheetIdMap[sKey];
|
|
10241
|
+
result.push(localSheetId !== void 0 ? {
|
|
10242
|
+
...model,
|
|
10243
|
+
localSheetId
|
|
10244
|
+
} : model);
|
|
10245
|
+
}
|
|
10246
|
+
for (const sKey of Object.keys(this.opaqueMap)) {
|
|
10247
|
+
if (seen.has(sKey)) continue;
|
|
10248
|
+
seen.add(sKey);
|
|
10249
|
+
const bareName = this.nameForKey[sKey] ?? sKey;
|
|
10250
|
+
const entry = this.opaqueMap[sKey];
|
|
10251
|
+
result.push({
|
|
10252
|
+
name: bareName,
|
|
10253
|
+
ranges: [],
|
|
10254
|
+
rawText: entry.rawText,
|
|
10255
|
+
localSheetId: entry.localSheetId,
|
|
10256
|
+
kind: "opaque"
|
|
10257
|
+
});
|
|
10258
|
+
}
|
|
10259
|
+
return result;
|
|
10007
10260
|
}
|
|
10008
10261
|
_explore(matrix, cell) {
|
|
10009
10262
|
cell.mark = false;
|
|
@@ -10038,17 +10291,37 @@ var ExcelTS = (function(exports) {
|
|
|
10038
10291
|
for (x = cell.col + 1; hGrow(x, "right"); x++);
|
|
10039
10292
|
return range;
|
|
10040
10293
|
}
|
|
10294
|
+
/**
|
|
10295
|
+
* Get ranges for a specific scoped entry.
|
|
10296
|
+
*
|
|
10297
|
+
* Unlike `getRanges(name)` which uses the bare name (and may hit the
|
|
10298
|
+
* wrong scope when the same name exists both globally and locally),
|
|
10299
|
+
* this method uses the internal `storageKey` to look up the exact entry.
|
|
10300
|
+
*/
|
|
10301
|
+
getRangesScoped(name, localSheetId) {
|
|
10302
|
+
const sKey = storageKey(name, localSheetId);
|
|
10303
|
+
return this.getRanges(sKey);
|
|
10304
|
+
}
|
|
10041
10305
|
getRanges(name, matrix) {
|
|
10306
|
+
const formula = this.formulaMap[name];
|
|
10042
10307
|
matrix = matrix || this.matrixMap[name];
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10308
|
+
const bareName = this.nameForKey[name] ?? name;
|
|
10309
|
+
if (!matrix) {
|
|
10310
|
+
if (formula) return {
|
|
10311
|
+
name: bareName,
|
|
10312
|
+
ranges: [formula],
|
|
10313
|
+
formulaExpression: formula
|
|
10314
|
+
};
|
|
10315
|
+
return {
|
|
10316
|
+
name: bareName,
|
|
10317
|
+
ranges: []
|
|
10318
|
+
};
|
|
10319
|
+
}
|
|
10047
10320
|
matrix.forEach((cell) => {
|
|
10048
10321
|
cell.mark = true;
|
|
10049
10322
|
});
|
|
10050
10323
|
return {
|
|
10051
|
-
name,
|
|
10324
|
+
name: bareName,
|
|
10052
10325
|
ranges: matrix.map((cell) => cell.mark && this._explore(matrix, cell)).filter((range) => Boolean(range)).map((range) => range.$shortRange)
|
|
10053
10326
|
};
|
|
10054
10327
|
}
|
|
@@ -10076,16 +10349,84 @@ var ExcelTS = (function(exports) {
|
|
|
10076
10349
|
});
|
|
10077
10350
|
}
|
|
10078
10351
|
get model() {
|
|
10079
|
-
|
|
10352
|
+
const cellNames = Object.entries(this.matrixMap).map(([sKey, matrix]) => {
|
|
10353
|
+
const result = this.getRanges(sKey, matrix);
|
|
10354
|
+
const localSheetId = this.localSheetIdMap[sKey];
|
|
10355
|
+
if (localSheetId !== void 0) return {
|
|
10356
|
+
...result,
|
|
10357
|
+
localSheetId
|
|
10358
|
+
};
|
|
10359
|
+
return result;
|
|
10360
|
+
}).filter((definedName) => definedName.ranges.length);
|
|
10361
|
+
const formulaNames = Object.entries(this.formulaMap).filter(([sKey]) => !this.matrixMap[sKey]).map(([sKey, expression]) => {
|
|
10362
|
+
const result = {
|
|
10363
|
+
name: this.nameForKey[sKey] ?? sKey,
|
|
10364
|
+
ranges: [expression],
|
|
10365
|
+
formulaExpression: expression
|
|
10366
|
+
};
|
|
10367
|
+
const localSheetId = this.localSheetIdMap[sKey];
|
|
10368
|
+
if (localSheetId !== void 0) return {
|
|
10369
|
+
...result,
|
|
10370
|
+
localSheetId
|
|
10371
|
+
};
|
|
10372
|
+
return result;
|
|
10373
|
+
});
|
|
10374
|
+
const opaqueNames = Object.entries(this.opaqueMap).map(([sKey, entry]) => {
|
|
10375
|
+
return {
|
|
10376
|
+
name: this.nameForKey[sKey] ?? sKey,
|
|
10377
|
+
ranges: [],
|
|
10378
|
+
rawText: entry.rawText,
|
|
10379
|
+
localSheetId: entry.localSheetId,
|
|
10380
|
+
kind: "opaque"
|
|
10381
|
+
};
|
|
10382
|
+
});
|
|
10383
|
+
return [
|
|
10384
|
+
...cellNames,
|
|
10385
|
+
...formulaNames,
|
|
10386
|
+
...opaqueNames
|
|
10387
|
+
];
|
|
10080
10388
|
}
|
|
10389
|
+
/**
|
|
10390
|
+
* Deserialise an array of `DefinedNameModel` entries (typically from XLSX parsing).
|
|
10391
|
+
*
|
|
10392
|
+
* Stage 2 of the two-phase design: each entry's `rawText` is classified
|
|
10393
|
+
* into reference / formula / opaque by `classifyDefinedName()`. Entries
|
|
10394
|
+
* that arrive without `rawText` (programmatic API) fall back to inspecting
|
|
10395
|
+
* the existing `ranges` and `formulaExpression` fields for compatibility.
|
|
10396
|
+
*/
|
|
10081
10397
|
set model(value) {
|
|
10082
10398
|
const matrixMap = this.matrixMap = {};
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10399
|
+
const formulaMap = this.formulaMap = {};
|
|
10400
|
+
const localSheetIdMap = this.localSheetIdMap = {};
|
|
10401
|
+
const opaqueMap = this.opaqueMap = {};
|
|
10402
|
+
const nameForKeyMap = this.nameForKey = {};
|
|
10403
|
+
const probe = this._explicitProbe ?? getDefaultSyntaxProbe();
|
|
10404
|
+
for (const definedName of value) {
|
|
10405
|
+
const sKey = storageKey(definedName.name, definedName.localSheetId);
|
|
10406
|
+
nameForKeyMap[sKey] = definedName.name;
|
|
10407
|
+
if (definedName.localSheetId !== void 0) localSheetIdMap[sKey] = definedName.localSheetId;
|
|
10408
|
+
if (definedName.formulaExpression && definedName.rawText === void 0) {
|
|
10409
|
+
formulaMap[sKey] = definedName.formulaExpression;
|
|
10410
|
+
continue;
|
|
10411
|
+
}
|
|
10412
|
+
const classified = classifyDefinedName(definedName.rawText, definedName.ranges, probe);
|
|
10413
|
+
switch (classified.kind) {
|
|
10414
|
+
case "reference": {
|
|
10415
|
+
const matrix = matrixMap[sKey] = new CellMatrix();
|
|
10416
|
+
for (const rangeStr of classified.ranges) if (rangeRegexp.test(rangeStr.split("!").pop() ?? "")) matrix.addCell(rangeStr);
|
|
10417
|
+
break;
|
|
10418
|
+
}
|
|
10419
|
+
case "formula":
|
|
10420
|
+
formulaMap[sKey] = classified.formulaExpression;
|
|
10421
|
+
break;
|
|
10422
|
+
case "opaque":
|
|
10423
|
+
if (definedName.rawText) opaqueMap[sKey] = {
|
|
10424
|
+
rawText: definedName.rawText,
|
|
10425
|
+
localSheetId: definedName.localSheetId
|
|
10426
|
+
};
|
|
10427
|
+
break;
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10089
10430
|
}
|
|
10090
10431
|
};
|
|
10091
10432
|
//#endregion
|
|
@@ -15225,7 +15566,10 @@ onmessage = async (ev) => {
|
|
|
15225
15566
|
PivotCacheRecords: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords",
|
|
15226
15567
|
PivotTable: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable",
|
|
15227
15568
|
FeaturePropertyBag: "http://schemas.microsoft.com/office/2022/11/relationships/FeaturePropertyBag",
|
|
15228
|
-
CtrlProp: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp"
|
|
15569
|
+
CtrlProp: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp",
|
|
15570
|
+
SheetMetadata: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
|
|
15571
|
+
ExternalLink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
|
|
15572
|
+
ExternalLinkPath: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath"
|
|
15229
15573
|
};
|
|
15230
15574
|
//#endregion
|
|
15231
15575
|
//#region src/modules/xml/errors.ts
|
|
@@ -16643,7 +16987,7 @@ onmessage = async (ev) => {
|
|
|
16643
16987
|
const attributes = node.attributes;
|
|
16644
16988
|
if (attributes.Type !== RelType.Hyperlink) return;
|
|
16645
16989
|
const relationship = {
|
|
16646
|
-
type:
|
|
16990
|
+
type: 7,
|
|
16647
16991
|
rId: attributes.Id,
|
|
16648
16992
|
target: attributes.Target,
|
|
16649
16993
|
targetMode: attributes.TargetMode
|
|
@@ -16939,7 +17283,7 @@ onmessage = async (ev) => {
|
|
|
16939
17283
|
get values() {
|
|
16940
17284
|
const v = [];
|
|
16941
17285
|
this.eachCell((cell, rowNumber) => {
|
|
16942
|
-
if (cell && cell.type !==
|
|
17286
|
+
if (cell && cell.type !== 0) v[rowNumber] = cell.value;
|
|
16943
17287
|
});
|
|
16944
17288
|
return v;
|
|
16945
17289
|
}
|
|
@@ -17151,6 +17495,40 @@ onmessage = async (ev) => {
|
|
|
17151
17495
|
//#endregion
|
|
17152
17496
|
//#region src/modules/excel/cell.ts
|
|
17153
17497
|
const hasOwnKeys = (v) => !!v && (typeof v !== "object" || Object.keys(v).length > 0);
|
|
17498
|
+
/**
|
|
17499
|
+
* Flatten a rich-text array into its plain-text representation by
|
|
17500
|
+
* concatenating each run's `text`. Missing/null runs contribute "".
|
|
17501
|
+
*/
|
|
17502
|
+
function flattenRichText(runs) {
|
|
17503
|
+
let out = "";
|
|
17504
|
+
for (const run of runs) if (run && typeof run.text === "string") out += run.text;
|
|
17505
|
+
return out;
|
|
17506
|
+
}
|
|
17507
|
+
/**
|
|
17508
|
+
* Normalize a CellHyperlinkValue so the {@link NormalizedHyperlink} invariants
|
|
17509
|
+
* hold.
|
|
17510
|
+
*
|
|
17511
|
+
* - If the caller supplied `richText` but no `text`, text is derived.
|
|
17512
|
+
* - If the caller supplied `text` but no `richText`, richText stays absent.
|
|
17513
|
+
* - If both are supplied, `richText` wins and `text` is regenerated
|
|
17514
|
+
* (to keep `text === flatten(richText)`).
|
|
17515
|
+
* - An empty `richText: []` is dropped (treated as "no rich text").
|
|
17516
|
+
*/
|
|
17517
|
+
function normalizeHyperlinkValue(value) {
|
|
17518
|
+
let text;
|
|
17519
|
+
let richText;
|
|
17520
|
+
if (Array.isArray(value.richText) && value.richText.length > 0) {
|
|
17521
|
+
richText = value.richText;
|
|
17522
|
+
text = flattenRichText(richText);
|
|
17523
|
+
} else text = typeof value.text === "string" ? value.text : "";
|
|
17524
|
+
const out = {
|
|
17525
|
+
text,
|
|
17526
|
+
hyperlink: typeof value.hyperlink === "string" ? value.hyperlink : ""
|
|
17527
|
+
};
|
|
17528
|
+
if (richText) out.richText = richText;
|
|
17529
|
+
if (typeof value.tooltip === "string" && value.tooltip.length > 0) out.tooltip = value.tooltip;
|
|
17530
|
+
return out;
|
|
17531
|
+
}
|
|
17154
17532
|
var Cell = class Cell {
|
|
17155
17533
|
static {
|
|
17156
17534
|
this.Types = Enums.ValueType;
|
|
@@ -17322,10 +17700,25 @@ onmessage = async (ev) => {
|
|
|
17322
17700
|
}
|
|
17323
17701
|
/** @internal */
|
|
17324
17702
|
_upgradeToHyperlink(hyperlink) {
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
|
|
17328
|
-
|
|
17703
|
+
switch (this.type) {
|
|
17704
|
+
case Cell.Types.String:
|
|
17705
|
+
this._value = Value.create(Cell.Types.Hyperlink, this, {
|
|
17706
|
+
text: String(this._value.value),
|
|
17707
|
+
hyperlink
|
|
17708
|
+
});
|
|
17709
|
+
break;
|
|
17710
|
+
case Cell.Types.RichText: {
|
|
17711
|
+
const current = this._value.value;
|
|
17712
|
+
const runs = current && Array.isArray(current.richText) ? current.richText : [];
|
|
17713
|
+
this._value = Value.create(Cell.Types.Hyperlink, this, {
|
|
17714
|
+
text: flattenRichText(runs),
|
|
17715
|
+
richText: runs.length > 0 ? runs : void 0,
|
|
17716
|
+
hyperlink
|
|
17717
|
+
});
|
|
17718
|
+
break;
|
|
17719
|
+
}
|
|
17720
|
+
default: break;
|
|
17721
|
+
}
|
|
17329
17722
|
}
|
|
17330
17723
|
get formula() {
|
|
17331
17724
|
return this._value.formula;
|
|
@@ -17333,8 +17726,11 @@ onmessage = async (ev) => {
|
|
|
17333
17726
|
get result() {
|
|
17334
17727
|
return this._value.result;
|
|
17335
17728
|
}
|
|
17729
|
+
set result(value) {
|
|
17730
|
+
if (this.type === Cell.Types.Formula) this._value.result = value;
|
|
17731
|
+
}
|
|
17336
17732
|
get formulaType() {
|
|
17337
|
-
return this._value.formulaType ??
|
|
17733
|
+
return this._value.formulaType ?? 0;
|
|
17338
17734
|
}
|
|
17339
17735
|
get fullAddress() {
|
|
17340
17736
|
const { worksheet } = this._row;
|
|
@@ -17572,30 +17968,60 @@ onmessage = async (ev) => {
|
|
|
17572
17968
|
constructor(cell, value) {
|
|
17573
17969
|
this.model = {
|
|
17574
17970
|
address: cell.address,
|
|
17575
|
-
type: Cell.Types.Hyperlink
|
|
17576
|
-
text: value ? value.text : void 0,
|
|
17577
|
-
hyperlink: value ? value.hyperlink : void 0
|
|
17971
|
+
type: Cell.Types.Hyperlink
|
|
17578
17972
|
};
|
|
17579
|
-
if (value
|
|
17973
|
+
if (value) {
|
|
17974
|
+
if ("formula" in value && typeof value.formula === "string") {
|
|
17975
|
+
const fh = value;
|
|
17976
|
+
const display = fh.result === void 0 || fh.result === null ? "" : String(fh.result);
|
|
17977
|
+
this.model.text = display;
|
|
17978
|
+
this.model.hyperlink = fh.hyperlink ?? "";
|
|
17979
|
+
if (fh.tooltip !== void 0) this.model.tooltip = fh.tooltip;
|
|
17980
|
+
this.model.formula = fh.formula;
|
|
17981
|
+
if (fh.result !== void 0) this.model.result = fh.result;
|
|
17982
|
+
return;
|
|
17983
|
+
}
|
|
17984
|
+
const normalized = normalizeHyperlinkValue(value);
|
|
17985
|
+
this.model.text = normalized.text;
|
|
17986
|
+
this.model.hyperlink = normalized.hyperlink;
|
|
17987
|
+
if (normalized.richText) this.model.richText = normalized.richText;
|
|
17988
|
+
if (normalized.tooltip !== void 0) this.model.tooltip = normalized.tooltip;
|
|
17989
|
+
}
|
|
17580
17990
|
}
|
|
17581
17991
|
get value() {
|
|
17582
|
-
|
|
17992
|
+
const out = {
|
|
17583
17993
|
text: this.model.text ?? "",
|
|
17584
|
-
hyperlink: this.model.hyperlink ?? ""
|
|
17585
|
-
tooltip: this.model.tooltip
|
|
17994
|
+
hyperlink: this.model.hyperlink ?? ""
|
|
17586
17995
|
};
|
|
17996
|
+
if (this.model.richText && this.model.richText.length > 0) out.richText = this.model.richText;
|
|
17997
|
+
if (this.model.tooltip !== void 0) out.tooltip = this.model.tooltip;
|
|
17998
|
+
return out;
|
|
17587
17999
|
}
|
|
17588
18000
|
set value(value) {
|
|
17589
|
-
|
|
17590
|
-
this.model.
|
|
17591
|
-
|
|
18001
|
+
const normalized = normalizeHyperlinkValue(value);
|
|
18002
|
+
this.model.text = normalized.text;
|
|
18003
|
+
this.model.hyperlink = normalized.hyperlink;
|
|
18004
|
+
if (normalized.richText) this.model.richText = normalized.richText;
|
|
18005
|
+
else delete this.model.richText;
|
|
18006
|
+
if (normalized.tooltip !== void 0) this.model.tooltip = normalized.tooltip;
|
|
18007
|
+
else delete this.model.tooltip;
|
|
17592
18008
|
}
|
|
17593
18009
|
get text() {
|
|
17594
18010
|
return this.model.text;
|
|
17595
18011
|
}
|
|
17596
18012
|
set text(value) {
|
|
18013
|
+
if (this.model.richText) delete this.model.richText;
|
|
17597
18014
|
this.model.text = value;
|
|
17598
18015
|
}
|
|
18016
|
+
get richText() {
|
|
18017
|
+
return this.model.richText;
|
|
18018
|
+
}
|
|
18019
|
+
set richText(value) {
|
|
18020
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
18021
|
+
this.model.richText = value;
|
|
18022
|
+
this.model.text = flattenRichText(value);
|
|
18023
|
+
} else delete this.model.richText;
|
|
18024
|
+
}
|
|
17599
18025
|
get hyperlink() {
|
|
17600
18026
|
return this.model.hyperlink;
|
|
17601
18027
|
}
|
|
@@ -17680,7 +18106,8 @@ onmessage = async (ev) => {
|
|
|
17680
18106
|
ref: value ? value.ref : void 0,
|
|
17681
18107
|
formula: value ? value.formula : void 0,
|
|
17682
18108
|
sharedFormula: value ? value.sharedFormula : void 0,
|
|
17683
|
-
result: value ? value.result : void 0
|
|
18109
|
+
result: value ? value.result : void 0,
|
|
18110
|
+
isDynamicArray: value ? value.isDynamicArray : void 0
|
|
17684
18111
|
};
|
|
17685
18112
|
}
|
|
17686
18113
|
_copyModel(model) {
|
|
@@ -17690,6 +18117,7 @@ onmessage = async (ev) => {
|
|
|
17690
18117
|
if (model.ref) copy.ref = model.ref;
|
|
17691
18118
|
if (model.shareType) copy.shareType = model.shareType;
|
|
17692
18119
|
if (model.sharedFormula) copy.sharedFormula = model.sharedFormula;
|
|
18120
|
+
if (model.isDynamicArray) copy.isDynamicArray = model.isDynamicArray;
|
|
17693
18121
|
return copy;
|
|
17694
18122
|
}
|
|
17695
18123
|
get value() {
|
|
@@ -17701,6 +18129,7 @@ onmessage = async (ev) => {
|
|
|
17701
18129
|
if (value.ref) this.model.ref = value.ref;
|
|
17702
18130
|
if (value.shareType) this.model.shareType = value.shareType;
|
|
17703
18131
|
if (value.sharedFormula) this.model.sharedFormula = value.sharedFormula;
|
|
18132
|
+
if (value.isDynamicArray !== void 0) this.model.isDynamicArray = value.isDynamicArray;
|
|
17704
18133
|
}
|
|
17705
18134
|
validate(value) {
|
|
17706
18135
|
switch (Value.getType(value)) {
|
|
@@ -17726,9 +18155,9 @@ onmessage = async (ev) => {
|
|
|
17726
18155
|
this.model.formula = value;
|
|
17727
18156
|
}
|
|
17728
18157
|
get formulaType() {
|
|
17729
|
-
if (this.model.formula) return
|
|
17730
|
-
if (this.model.sharedFormula) return
|
|
17731
|
-
return
|
|
18158
|
+
if (this.model.formula) return 1;
|
|
18159
|
+
if (this.model.sharedFormula) return 2;
|
|
18160
|
+
return 0;
|
|
17732
18161
|
}
|
|
17733
18162
|
get result() {
|
|
17734
18163
|
return this.model.result;
|
|
@@ -17741,12 +18170,12 @@ onmessage = async (ev) => {
|
|
|
17741
18170
|
}
|
|
17742
18171
|
get effectiveType() {
|
|
17743
18172
|
const v = this.model.result;
|
|
17744
|
-
if (v === null || v === void 0) return
|
|
17745
|
-
if (typeof v === "string") return
|
|
17746
|
-
if (typeof v === "number") return
|
|
17747
|
-
if (v instanceof Date) return
|
|
17748
|
-
if (typeof v === "object" && "error" in v) return
|
|
17749
|
-
return
|
|
18173
|
+
if (v === null || v === void 0) return 0;
|
|
18174
|
+
if (typeof v === "string") return 3;
|
|
18175
|
+
if (typeof v === "number") return 2;
|
|
18176
|
+
if (v instanceof Date) return 4;
|
|
18177
|
+
if (typeof v === "object" && "error" in v) return 10;
|
|
18178
|
+
return 0;
|
|
17750
18179
|
}
|
|
17751
18180
|
get address() {
|
|
17752
18181
|
return this.model.address;
|
|
@@ -17951,9 +18380,14 @@ onmessage = async (ev) => {
|
|
|
17951
18380
|
if (value instanceof Date) return Cell.Types.Date;
|
|
17952
18381
|
if (typeof value === "object") {
|
|
17953
18382
|
if ("checkbox" in value && typeof value.checkbox === "boolean") return Cell.Types.Checkbox;
|
|
17954
|
-
if ("
|
|
18383
|
+
if ("hyperlink" in value && typeof value.hyperlink === "string" && value.hyperlink) {
|
|
18384
|
+
const hasText = "text" in value && typeof value.text === "string" && value.text.length > 0;
|
|
18385
|
+
const hasRichText = "richText" in value && Array.isArray(value.richText) && value.richText.length > 0;
|
|
18386
|
+
const hasFormula = "formula" in value && typeof value.formula === "string";
|
|
18387
|
+
if (hasText || hasRichText || hasFormula) return Cell.Types.Hyperlink;
|
|
18388
|
+
}
|
|
17955
18389
|
if ("formula" in value && value.formula || "sharedFormula" in value && value.sharedFormula) return Cell.Types.Formula;
|
|
17956
|
-
if ("richText" in value && value.richText) return Cell.Types.RichText;
|
|
18390
|
+
if ("richText" in value && Array.isArray(value.richText) && value.richText.length > 0) return Cell.Types.RichText;
|
|
17957
18391
|
if ("sharedString" in value && value.sharedString) return Cell.Types.SharedString;
|
|
17958
18392
|
if ("error" in value && value.error) return Cell.Types.Error;
|
|
17959
18393
|
}
|
|
@@ -18142,7 +18576,7 @@ onmessage = async (ev) => {
|
|
|
18142
18576
|
const n = this._cells.length;
|
|
18143
18577
|
for (let i = 1; i <= n; i++) callback(this.getCell(i), i);
|
|
18144
18578
|
} else this._cells.forEach((cell, index) => {
|
|
18145
|
-
if (cell && cell.type !==
|
|
18579
|
+
if (cell && cell.type !== 0) callback(cell, index + 1);
|
|
18146
18580
|
});
|
|
18147
18581
|
}
|
|
18148
18582
|
addPageBreak(lft, rght) {
|
|
@@ -18163,7 +18597,7 @@ onmessage = async (ev) => {
|
|
|
18163
18597
|
get values() {
|
|
18164
18598
|
const values = [];
|
|
18165
18599
|
this._cells.forEach((cell) => {
|
|
18166
|
-
if (cell && cell.type !==
|
|
18600
|
+
if (cell && cell.type !== 0) values[cell.col] = cell.value;
|
|
18167
18601
|
});
|
|
18168
18602
|
return values;
|
|
18169
18603
|
}
|
|
@@ -18199,7 +18633,7 @@ onmessage = async (ev) => {
|
|
|
18199
18633
|
getValues() {
|
|
18200
18634
|
const values = [];
|
|
18201
18635
|
this._cells.forEach((cell) => {
|
|
18202
|
-
if (cell && cell.type !==
|
|
18636
|
+
if (cell && cell.type !== 0) values[cell.col - 1] = cell.value;
|
|
18203
18637
|
});
|
|
18204
18638
|
return values;
|
|
18205
18639
|
}
|
|
@@ -18215,7 +18649,7 @@ onmessage = async (ev) => {
|
|
|
18215
18649
|
* Returns true if the row includes at least one cell with a value
|
|
18216
18650
|
*/
|
|
18217
18651
|
get hasValues() {
|
|
18218
|
-
return this._cells.some((cell) => cell && cell.type !==
|
|
18652
|
+
return this._cells.some((cell) => cell && cell.type !== 0);
|
|
18219
18653
|
}
|
|
18220
18654
|
/**
|
|
18221
18655
|
* Number of cells including empty ones
|
|
@@ -18240,7 +18674,7 @@ onmessage = async (ev) => {
|
|
|
18240
18674
|
let min = 0;
|
|
18241
18675
|
let max = 0;
|
|
18242
18676
|
this._cells.forEach((cell) => {
|
|
18243
|
-
if (cell && cell.type !==
|
|
18677
|
+
if (cell && cell.type !== 0) {
|
|
18244
18678
|
if (!min || min > cell.col) min = cell.col;
|
|
18245
18679
|
if (max < cell.col) max = cell.col;
|
|
18246
18680
|
}
|
|
@@ -18944,10 +19378,12 @@ onmessage = async (ev) => {
|
|
|
18944
19378
|
case "c":
|
|
18945
19379
|
if (row) {
|
|
18946
19380
|
const styleAttr = node.attributes.s;
|
|
19381
|
+
const cmAttr = node.attributes.cm;
|
|
18947
19382
|
c = {
|
|
18948
19383
|
ref: node.attributes.r,
|
|
18949
19384
|
s: styleAttr !== void 0 ? parseInt(styleAttr, 10) : void 0,
|
|
18950
|
-
t: node.attributes.t
|
|
19385
|
+
t: node.attributes.t,
|
|
19386
|
+
cm: cmAttr !== void 0 ? parseInt(cmAttr, 10) : void 0
|
|
18951
19387
|
};
|
|
18952
19388
|
}
|
|
18953
19389
|
break;
|
|
@@ -19025,6 +19461,12 @@ onmessage = async (ev) => {
|
|
|
19025
19461
|
const cellValue = { formula: c.f.text };
|
|
19026
19462
|
if (c.v) if (c.t === "str") cellValue.result = c.v.text;
|
|
19027
19463
|
else cellValue.result = parseFloat(c.v.text);
|
|
19464
|
+
if (c.cm !== void 0) {
|
|
19465
|
+
const { workbook: wb } = this;
|
|
19466
|
+
if (wb.dynamicArrayCmIndices) {
|
|
19467
|
+
if (wb.dynamicArrayCmIndices.has(c.cm)) cellValue.isDynamicArray = true;
|
|
19468
|
+
} else if (wb.hasDynamicArrayMetadata) cellValue.isDynamicArray = true;
|
|
19469
|
+
}
|
|
19028
19470
|
cell.value = cellValue;
|
|
19029
19471
|
} else if (c.v) switch (c.t) {
|
|
19030
19472
|
case "s": {
|
|
@@ -19130,7 +19572,8 @@ onmessage = async (ev) => {
|
|
|
19130
19572
|
});
|
|
19131
19573
|
} else {
|
|
19132
19574
|
stream.pause();
|
|
19133
|
-
|
|
19575
|
+
const data = contents.shift();
|
|
19576
|
+
if (data !== void 0) yield data;
|
|
19134
19577
|
}
|
|
19135
19578
|
if (error) throw toError(error);
|
|
19136
19579
|
}
|
|
@@ -19152,7 +19595,8 @@ onmessage = async (ev) => {
|
|
|
19152
19595
|
xlSharedStrings: "xl/sharedStrings.xml",
|
|
19153
19596
|
xlStyles: "xl/styles.xml",
|
|
19154
19597
|
xlTheme1: "xl/theme/theme1.xml",
|
|
19155
|
-
xlFeaturePropertyBag: "xl/featurePropertyBag/featurePropertyBag.xml"
|
|
19598
|
+
xlFeaturePropertyBag: "xl/featurePropertyBag/featurePropertyBag.xml",
|
|
19599
|
+
xlMetadata: "xl/metadata.xml"
|
|
19156
19600
|
};
|
|
19157
19601
|
const worksheetXmlRegex = /^xl\/worksheets\/sheet(\d+)[.]xml$/;
|
|
19158
19602
|
const worksheetRelsXmlRegex = /^xl\/worksheets\/_rels\/sheet(\d+)[.]xml[.]rels$/;
|
|
@@ -19169,6 +19613,8 @@ onmessage = async (ev) => {
|
|
|
19169
19613
|
const pivotCacheDefinitionXmlRegex = /^xl\/pivotCache\/(pivotCacheDefinition\d+)[.]xml$/;
|
|
19170
19614
|
const pivotCacheDefinitionRelsXmlRegex = /^xl\/pivotCache\/_rels\/(pivotCacheDefinition\d+)[.]xml[.]rels$/;
|
|
19171
19615
|
const pivotCacheRecordsXmlRegex = /^xl\/pivotCache\/(pivotCacheRecords\d+)[.]xml$/;
|
|
19616
|
+
const externalLinkXmlRegex = /^xl\/externalLinks\/externalLink(\d+)[.]xml$/;
|
|
19617
|
+
const externalLinkRelsXmlRegex = /^xl\/externalLinks\/_rels\/externalLink(\d+)[.]xml[.]rels$/;
|
|
19172
19618
|
function normalizeZipPath$1(path) {
|
|
19173
19619
|
return path.startsWith("/") ? path.slice(1) : path;
|
|
19174
19620
|
}
|
|
@@ -19243,6 +19689,22 @@ onmessage = async (ev) => {
|
|
|
19243
19689
|
const match = pivotCacheRecordsXmlRegex.exec(path);
|
|
19244
19690
|
return match ? match[1] : void 0;
|
|
19245
19691
|
}
|
|
19692
|
+
/**
|
|
19693
|
+
* Extract the 1-based index `N` from `xl/externalLinks/externalLink{N}.xml`.
|
|
19694
|
+
* Returns the raw integer (e.g. `1` for externalLink1.xml) or undefined.
|
|
19695
|
+
*/
|
|
19696
|
+
function getExternalLinkIndexFromPath(path) {
|
|
19697
|
+
const match = externalLinkXmlRegex.exec(path);
|
|
19698
|
+
return match ? parseInt(match[1], 10) : void 0;
|
|
19699
|
+
}
|
|
19700
|
+
/**
|
|
19701
|
+
* Extract the 1-based index `N` from
|
|
19702
|
+
* `xl/externalLinks/_rels/externalLink{N}.xml.rels`.
|
|
19703
|
+
*/
|
|
19704
|
+
function getExternalLinkIndexFromRelsPath(path) {
|
|
19705
|
+
const match = externalLinkRelsXmlRegex.exec(path);
|
|
19706
|
+
return match ? parseInt(match[1], 10) : void 0;
|
|
19707
|
+
}
|
|
19246
19708
|
function toContentTypesPartName(zipPath) {
|
|
19247
19709
|
return zipPath.startsWith("/") ? zipPath : `/${zipPath}`;
|
|
19248
19710
|
}
|
|
@@ -19303,6 +19765,19 @@ onmessage = async (ev) => {
|
|
|
19303
19765
|
function pivotTableRelsPath(n) {
|
|
19304
19766
|
return `xl/pivotTables/_rels/pivotTable${n}.xml.rels`;
|
|
19305
19767
|
}
|
|
19768
|
+
function externalLinkPath(n) {
|
|
19769
|
+
return `xl/externalLinks/externalLink${n}.xml`;
|
|
19770
|
+
}
|
|
19771
|
+
function externalLinkRelsPath(n) {
|
|
19772
|
+
return `xl/externalLinks/_rels/externalLink${n}.xml.rels`;
|
|
19773
|
+
}
|
|
19774
|
+
/**
|
|
19775
|
+
* Build the `Target` value for an externalLink relationship inside
|
|
19776
|
+
* `xl/_rels/workbook.xml.rels` (base: `xl/`).
|
|
19777
|
+
*/
|
|
19778
|
+
function externalLinkRelTargetFromWorkbook(n) {
|
|
19779
|
+
return `externalLinks/externalLink${n}.xml`;
|
|
19780
|
+
}
|
|
19306
19781
|
function pivotCacheDefinitionRelTargetFromPivotTable(n) {
|
|
19307
19782
|
return `../pivotCache/pivotCacheDefinition${n}.xml`;
|
|
19308
19783
|
}
|
|
@@ -19310,7 +19785,8 @@ onmessage = async (ev) => {
|
|
|
19310
19785
|
workbookStyles: "styles.xml",
|
|
19311
19786
|
workbookSharedStrings: "sharedStrings.xml",
|
|
19312
19787
|
workbookTheme1: "theme/theme1.xml",
|
|
19313
|
-
workbookFeaturePropertyBag: "featurePropertyBag/featurePropertyBag.xml"
|
|
19788
|
+
workbookFeaturePropertyBag: "featurePropertyBag/featurePropertyBag.xml",
|
|
19789
|
+
workbookMetadata: "metadata.xml"
|
|
19314
19790
|
};
|
|
19315
19791
|
function pivotCacheDefinitionRelTargetFromWorkbook(n) {
|
|
19316
19792
|
return `pivotCache/pivotCacheDefinition${n}.xml`;
|
|
@@ -19788,7 +20264,8 @@ onmessage = async (ev) => {
|
|
|
19788
20264
|
name: model.name,
|
|
19789
20265
|
localSheetId: model.localSheetId
|
|
19790
20266
|
});
|
|
19791
|
-
xmlStream.writeText(model.
|
|
20267
|
+
if (model.kind === "opaque" && model.rawText) xmlStream.writeText(model.rawText);
|
|
20268
|
+
else xmlStream.writeText(model.ranges.join(","));
|
|
19792
20269
|
xmlStream.closeNode();
|
|
19793
20270
|
}
|
|
19794
20271
|
parseOpen(node) {
|
|
@@ -19804,57 +20281,47 @@ onmessage = async (ev) => {
|
|
|
19804
20281
|
parseText(text) {
|
|
19805
20282
|
this._parsedText.push(text);
|
|
19806
20283
|
}
|
|
20284
|
+
/**
|
|
20285
|
+
* Stage 1 of the two-phase defined name design: the XLSX layer only
|
|
20286
|
+
* preserves the raw XML text. Semantic classification (reference vs
|
|
20287
|
+
* formula vs opaque) is deferred to `DefinedNames.set model()`.
|
|
20288
|
+
*/
|
|
19807
20289
|
parseClose() {
|
|
19808
|
-
|
|
20290
|
+
const rawText = this._parsedText.join("");
|
|
20291
|
+
const model = {
|
|
19809
20292
|
name: this._parsedName,
|
|
19810
|
-
ranges:
|
|
20293
|
+
ranges: [],
|
|
20294
|
+
rawText: rawText.trim() || void 0
|
|
19811
20295
|
};
|
|
19812
|
-
if (this._parsedLocalSheetId !== void 0)
|
|
20296
|
+
if (this._parsedLocalSheetId !== void 0) model.localSheetId = parseInt(this._parsedLocalSheetId, 10);
|
|
20297
|
+
this.model = model;
|
|
19813
20298
|
return false;
|
|
19814
20299
|
}
|
|
19815
20300
|
};
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
|
|
19819
|
-
|
|
19820
|
-
|
|
19821
|
-
|
|
19822
|
-
|
|
19823
|
-
|
|
19824
|
-
|
|
19825
|
-
|
|
20301
|
+
//#endregion
|
|
20302
|
+
//#region src/modules/excel/xlsx/xform/book/external-reference-xform.ts
|
|
20303
|
+
/**
|
|
20304
|
+
* Xform for a single `<externalReference r:id="..."/>` element inside
|
|
20305
|
+
* `<externalReferences>` in `xl/workbook.xml`. Each `<externalReference>`
|
|
20306
|
+
* maps positionally (in document order, 1-based) to an `[N]Sheet!Ref`
|
|
20307
|
+
* prefix in formula strings.
|
|
20308
|
+
*/
|
|
20309
|
+
var ExternalReferenceXform = class extends BaseXform {
|
|
20310
|
+
render(xmlStream, model) {
|
|
20311
|
+
xmlStream.leafNode("externalReference", { "r:id": model.rId });
|
|
20312
|
+
}
|
|
20313
|
+
parseOpen(node) {
|
|
20314
|
+
if (node.name === "externalReference") {
|
|
20315
|
+
this.model = { rId: node.attributes["r:id"] ?? "" };
|
|
20316
|
+
return true;
|
|
20317
|
+
}
|
|
19826
20318
|
return false;
|
|
19827
|
-
}
|
|
20319
|
+
}
|
|
20320
|
+
parseText() {}
|
|
20321
|
+
parseClose() {
|
|
19828
20322
|
return false;
|
|
19829
20323
|
}
|
|
19830
|
-
}
|
|
19831
|
-
function extractRanges(parsedText) {
|
|
19832
|
-
const trimmed = parsedText.trim();
|
|
19833
|
-
if (trimmed.startsWith("{") && trimmed.endsWith("}")) return [];
|
|
19834
|
-
const ranges = [];
|
|
19835
|
-
let quotesOpened = false;
|
|
19836
|
-
let last = "";
|
|
19837
|
-
parsedText.split(",").forEach((item) => {
|
|
19838
|
-
if (!item) return;
|
|
19839
|
-
const quotes = (item.match(/'/g) ?? []).length;
|
|
19840
|
-
if (!quotes) {
|
|
19841
|
-
if (quotesOpened) last += `${item},`;
|
|
19842
|
-
else if (isValidRange(item)) ranges.push(item);
|
|
19843
|
-
return;
|
|
19844
|
-
}
|
|
19845
|
-
const quotesEven = quotes % 2 === 0;
|
|
19846
|
-
if (!quotesOpened && quotesEven && isValidRange(item)) ranges.push(item);
|
|
19847
|
-
else if (quotesOpened && !quotesEven) {
|
|
19848
|
-
quotesOpened = false;
|
|
19849
|
-
if (isValidRange(last + item)) ranges.push(last + item);
|
|
19850
|
-
last = "";
|
|
19851
|
-
} else {
|
|
19852
|
-
quotesOpened = true;
|
|
19853
|
-
last += `${item},`;
|
|
19854
|
-
}
|
|
19855
|
-
});
|
|
19856
|
-
return ranges;
|
|
19857
|
-
}
|
|
20324
|
+
};
|
|
19858
20325
|
//#endregion
|
|
19859
20326
|
//#region src/modules/excel/xlsx/xform/book/sheet-xform.ts
|
|
19860
20327
|
const VALID_STATES = new Set([
|
|
@@ -19898,12 +20365,21 @@ onmessage = async (ev) => {
|
|
|
19898
20365
|
render(xmlStream, model) {
|
|
19899
20366
|
xmlStream.leafNode("calcPr", {
|
|
19900
20367
|
calcId: 171027,
|
|
19901
|
-
fullCalcOnLoad: model.fullCalcOnLoad ? 1 : void 0
|
|
20368
|
+
fullCalcOnLoad: model.fullCalcOnLoad ? 1 : void 0,
|
|
20369
|
+
iterate: model.iterate ? 1 : void 0,
|
|
20370
|
+
iterateCount: model.iterateCount !== void 0 ? model.iterateCount : void 0,
|
|
20371
|
+
iterateDelta: model.iterateDelta !== void 0 ? model.iterateDelta : void 0
|
|
19902
20372
|
});
|
|
19903
20373
|
}
|
|
19904
20374
|
parseOpen(node) {
|
|
19905
20375
|
if (node.name === "calcPr") {
|
|
19906
|
-
|
|
20376
|
+
const attrs = node.attributes ?? {};
|
|
20377
|
+
this.model = {
|
|
20378
|
+
fullCalcOnLoad: attrs.fullCalcOnLoad === "1",
|
|
20379
|
+
iterate: attrs.iterate === "1" ? true : void 0,
|
|
20380
|
+
iterateCount: attrs.iterateCount !== void 0 ? parseInt(attrs.iterateCount, 10) : void 0,
|
|
20381
|
+
iterateDelta: attrs.iterateDelta !== void 0 ? parseFloat(attrs.iterateDelta) : void 0
|
|
20382
|
+
};
|
|
19907
20383
|
return true;
|
|
19908
20384
|
}
|
|
19909
20385
|
return false;
|
|
@@ -19959,6 +20435,55 @@ onmessage = async (ev) => {
|
|
|
19959
20435
|
}
|
|
19960
20436
|
};
|
|
19961
20437
|
//#endregion
|
|
20438
|
+
//#region src/modules/excel/xlsx/xform/book/workbook-protection-xform.ts
|
|
20439
|
+
var WorkbookProtectionXform = class extends BaseXform {
|
|
20440
|
+
get tag() {
|
|
20441
|
+
return "workbookProtection";
|
|
20442
|
+
}
|
|
20443
|
+
render(xmlStream, model) {
|
|
20444
|
+
if (!model) return;
|
|
20445
|
+
const attributes = {};
|
|
20446
|
+
if (model.lockStructure) attributes.lockStructure = "1";
|
|
20447
|
+
if (model.lockWindows) attributes.lockWindows = "1";
|
|
20448
|
+
if (model.lockRevision) attributes.lockRevision = "1";
|
|
20449
|
+
if (model.workbookPassword) attributes.workbookPassword = model.workbookPassword;
|
|
20450
|
+
if (model.revisionsPassword) attributes.revisionsPassword = model.revisionsPassword;
|
|
20451
|
+
if (model.algorithmName) {
|
|
20452
|
+
attributes.workbookAlgorithmName = model.algorithmName;
|
|
20453
|
+
attributes.workbookHashValue = model.hashValue;
|
|
20454
|
+
attributes.workbookSaltValue = model.saltValue;
|
|
20455
|
+
attributes.workbookSpinCount = model.spinCount?.toString();
|
|
20456
|
+
}
|
|
20457
|
+
if (Object.values(attributes).some((v) => v !== void 0)) xmlStream.leafNode(this.tag, attributes);
|
|
20458
|
+
}
|
|
20459
|
+
parseOpen(node) {
|
|
20460
|
+
switch (node.name) {
|
|
20461
|
+
case this.tag: {
|
|
20462
|
+
const a = node.attributes;
|
|
20463
|
+
this.model = {
|
|
20464
|
+
lockStructure: a.lockStructure === "1" || void 0,
|
|
20465
|
+
lockWindows: a.lockWindows === "1" || void 0,
|
|
20466
|
+
lockRevision: a.lockRevision === "1" || void 0,
|
|
20467
|
+
workbookPassword: a.workbookPassword || void 0,
|
|
20468
|
+
revisionsPassword: a.revisionsPassword || void 0
|
|
20469
|
+
};
|
|
20470
|
+
if (a.workbookAlgorithmName) {
|
|
20471
|
+
this.model.algorithmName = a.workbookAlgorithmName;
|
|
20472
|
+
this.model.hashValue = a.workbookHashValue;
|
|
20473
|
+
this.model.saltValue = a.workbookSaltValue;
|
|
20474
|
+
this.model.spinCount = a.workbookSpinCount ? parseInt(a.workbookSpinCount, 10) : void 0;
|
|
20475
|
+
}
|
|
20476
|
+
return true;
|
|
20477
|
+
}
|
|
20478
|
+
default: return false;
|
|
20479
|
+
}
|
|
20480
|
+
}
|
|
20481
|
+
parseText() {}
|
|
20482
|
+
parseClose() {
|
|
20483
|
+
return false;
|
|
20484
|
+
}
|
|
20485
|
+
};
|
|
20486
|
+
//#endregion
|
|
19962
20487
|
//#region src/modules/excel/xlsx/xform/book/workbook-view-xform.ts
|
|
19963
20488
|
var WorkbookViewXform = class extends BaseXform {
|
|
19964
20489
|
render(xmlStream, model) {
|
|
@@ -20115,6 +20640,7 @@ onmessage = async (ev) => {
|
|
|
20115
20640
|
this.map = {
|
|
20116
20641
|
fileVersion: WorkbookXform.STATIC_XFORMS.fileVersion,
|
|
20117
20642
|
workbookPr: new WorkbookPropertiesXform(),
|
|
20643
|
+
workbookProtection: new WorkbookProtectionXform(),
|
|
20118
20644
|
bookViews: new ListXform({
|
|
20119
20645
|
tag: "bookViews",
|
|
20120
20646
|
count: false,
|
|
@@ -20135,6 +20661,11 @@ onmessage = async (ev) => {
|
|
|
20135
20661
|
tag: "pivotCaches",
|
|
20136
20662
|
count: false,
|
|
20137
20663
|
childXform: new WorkbookPivotCacheXform()
|
|
20664
|
+
}),
|
|
20665
|
+
externalReferences: new ListXform({
|
|
20666
|
+
tag: "externalReferences",
|
|
20667
|
+
count: false,
|
|
20668
|
+
childXform: new ExternalReferenceXform()
|
|
20138
20669
|
})
|
|
20139
20670
|
};
|
|
20140
20671
|
}
|
|
@@ -20187,6 +20718,7 @@ onmessage = async (ev) => {
|
|
|
20187
20718
|
xmlStream.openNode("workbook", WorkbookXform.WORKBOOK_ATTRIBUTES);
|
|
20188
20719
|
this.map.fileVersion.render(xmlStream);
|
|
20189
20720
|
this.map.workbookPr.render(xmlStream, model.properties);
|
|
20721
|
+
this.map.workbookProtection.render(xmlStream, model.protection);
|
|
20190
20722
|
this.map.bookViews.render(xmlStream, model.views);
|
|
20191
20723
|
this.map.sheets.render(xmlStream, model.sheets);
|
|
20192
20724
|
this.map.definedNames.render(xmlStream, model.definedNames);
|
|
@@ -20199,6 +20731,11 @@ onmessage = async (ev) => {
|
|
|
20199
20731
|
return true;
|
|
20200
20732
|
});
|
|
20201
20733
|
this.map.pivotCaches.render(xmlStream, uniquePivotCaches);
|
|
20734
|
+
const externalLinks = model.externalLinks ?? [];
|
|
20735
|
+
if (externalLinks.length > 0) {
|
|
20736
|
+
const externalReferenceModels = externalLinks.map((link) => ({ rId: link.rId }));
|
|
20737
|
+
this.map.externalReferences.render(xmlStream, externalReferenceModels);
|
|
20738
|
+
}
|
|
20202
20739
|
xmlStream.closeNode();
|
|
20203
20740
|
}
|
|
20204
20741
|
parseOpen(node) {
|
|
@@ -20227,11 +20764,13 @@ onmessage = async (ev) => {
|
|
|
20227
20764
|
this.model = {
|
|
20228
20765
|
sheets: this.map.sheets.model,
|
|
20229
20766
|
properties: this.map.workbookPr.model || {},
|
|
20767
|
+
protection: this.map.workbookProtection.model,
|
|
20230
20768
|
views: this.map.bookViews.model,
|
|
20231
|
-
calcProperties: {}
|
|
20769
|
+
calcProperties: this.map.calcPr.model || {}
|
|
20232
20770
|
};
|
|
20233
20771
|
if (this.map.definedNames.model) this.model.definedNames = this.map.definedNames.model;
|
|
20234
20772
|
if (this.map.pivotCaches.model && this.map.pivotCaches.model.length > 0) this.model.pivotCaches = this.map.pivotCaches.model;
|
|
20773
|
+
if (this.map.externalReferences.model && this.map.externalReferences.model.length > 0) this.model.externalReferences = this.map.externalReferences.model;
|
|
20235
20774
|
return false;
|
|
20236
20775
|
default: return true;
|
|
20237
20776
|
}
|
|
@@ -20257,18 +20796,19 @@ onmessage = async (ev) => {
|
|
|
20257
20796
|
});
|
|
20258
20797
|
const definedNames = [];
|
|
20259
20798
|
if (model.definedNames) model.definedNames.forEach((definedName) => {
|
|
20799
|
+
const effectiveRanges = definedName.ranges?.length > 0 ? definedName.ranges : definedName.rawText ? [definedName.rawText] : [];
|
|
20260
20800
|
if (definedName.name === "_xlnm.Print_Area") {
|
|
20261
20801
|
worksheet = worksheets[definedName.localSheetId];
|
|
20262
|
-
if (worksheet &&
|
|
20802
|
+
if (worksheet && effectiveRanges.length > 0) {
|
|
20263
20803
|
if (!worksheet.pageSetup) worksheet.pageSetup = {};
|
|
20264
|
-
const range = colCache.decodeEx(
|
|
20804
|
+
const range = colCache.decodeEx(effectiveRanges[0]);
|
|
20265
20805
|
worksheet.pageSetup.printArea = worksheet.pageSetup.printArea ? `${worksheet.pageSetup.printArea}&&${range.dimensions}` : range.dimensions;
|
|
20266
20806
|
}
|
|
20267
20807
|
} else if (definedName.name === "_xlnm.Print_Titles") {
|
|
20268
20808
|
worksheet = worksheets[definedName.localSheetId];
|
|
20269
|
-
if (worksheet &&
|
|
20809
|
+
if (worksheet && effectiveRanges.length > 0) {
|
|
20270
20810
|
if (!worksheet.pageSetup) worksheet.pageSetup = {};
|
|
20271
|
-
const rangeString =
|
|
20811
|
+
const rangeString = effectiveRanges.join(",");
|
|
20272
20812
|
const dollarRegex = /\$/g;
|
|
20273
20813
|
const rowRangeMatches = rangeString.match(/\$\d+:\$\d+/);
|
|
20274
20814
|
if (rowRangeMatches && rowRangeMatches.length) {
|
|
@@ -20310,6 +20850,135 @@ onmessage = async (ev) => {
|
|
|
20310
20850
|
}
|
|
20311
20851
|
};
|
|
20312
20852
|
//#endregion
|
|
20853
|
+
//#region src/modules/excel/xlsx/xform/core/metadata-xform.ts
|
|
20854
|
+
const NS_SPREADSHEETML = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
|
20855
|
+
const NS_DYNAMIC_ARRAY = "http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray";
|
|
20856
|
+
const XLDAPR_EXT_URI = "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}";
|
|
20857
|
+
var MetadataXform = class extends BaseXform {
|
|
20858
|
+
constructor(..._args) {
|
|
20859
|
+
super(..._args);
|
|
20860
|
+
this._metadataTypeNames = [];
|
|
20861
|
+
this._cellMetadataTypeRefs = [];
|
|
20862
|
+
this._inCellMetadata = false;
|
|
20863
|
+
this._currentRcType = void 0;
|
|
20864
|
+
}
|
|
20865
|
+
get tag() {
|
|
20866
|
+
return "metadata";
|
|
20867
|
+
}
|
|
20868
|
+
/**
|
|
20869
|
+
* Render xl/metadata.xml for the given model.
|
|
20870
|
+
* Only emits content when dynamicArrayCount > 0.
|
|
20871
|
+
*/
|
|
20872
|
+
render(xmlStream, model) {
|
|
20873
|
+
if (!model || model.dynamicArrayCount <= 0) return;
|
|
20874
|
+
xmlStream.openXml(StdDocAttributes);
|
|
20875
|
+
xmlStream.openNode("metadata", {
|
|
20876
|
+
xmlns: NS_SPREADSHEETML,
|
|
20877
|
+
"xmlns:xda": NS_DYNAMIC_ARRAY
|
|
20878
|
+
});
|
|
20879
|
+
xmlStream.openNode("metadataTypes", { count: "1" });
|
|
20880
|
+
xmlStream.leafNode("metadataType", {
|
|
20881
|
+
name: "XLDAPR",
|
|
20882
|
+
minSupportedVersion: "120000",
|
|
20883
|
+
copy: "1",
|
|
20884
|
+
pasteAll: "1",
|
|
20885
|
+
pasteValues: "1",
|
|
20886
|
+
merge: "1",
|
|
20887
|
+
splitFirst: "1",
|
|
20888
|
+
rowColShift: "1",
|
|
20889
|
+
clearFormats: "1",
|
|
20890
|
+
clearComments: "1",
|
|
20891
|
+
assign: "1",
|
|
20892
|
+
coerce: "1",
|
|
20893
|
+
adjust: "1",
|
|
20894
|
+
cellMeta: "1"
|
|
20895
|
+
});
|
|
20896
|
+
xmlStream.closeNode();
|
|
20897
|
+
xmlStream.openNode("futureMetadata", {
|
|
20898
|
+
name: "XLDAPR",
|
|
20899
|
+
count: "1"
|
|
20900
|
+
});
|
|
20901
|
+
xmlStream.openNode("bk");
|
|
20902
|
+
xmlStream.openNode("extLst");
|
|
20903
|
+
xmlStream.openNode("ext", { uri: XLDAPR_EXT_URI });
|
|
20904
|
+
xmlStream.leafNode("xda:dynamicArrayProperties", {
|
|
20905
|
+
fDynamic: "1",
|
|
20906
|
+
fCollapsed: "0"
|
|
20907
|
+
});
|
|
20908
|
+
xmlStream.closeNode();
|
|
20909
|
+
xmlStream.closeNode();
|
|
20910
|
+
xmlStream.closeNode();
|
|
20911
|
+
xmlStream.closeNode();
|
|
20912
|
+
xmlStream.openNode("cellMetadata", { count: "1" });
|
|
20913
|
+
xmlStream.openNode("bk");
|
|
20914
|
+
xmlStream.leafNode("rc", {
|
|
20915
|
+
t: "1",
|
|
20916
|
+
v: "0"
|
|
20917
|
+
});
|
|
20918
|
+
xmlStream.closeNode();
|
|
20919
|
+
xmlStream.closeNode();
|
|
20920
|
+
xmlStream.closeNode();
|
|
20921
|
+
}
|
|
20922
|
+
reset() {
|
|
20923
|
+
this._metadataTypeNames = [];
|
|
20924
|
+
this._cellMetadataTypeRefs = [];
|
|
20925
|
+
this._inCellMetadata = false;
|
|
20926
|
+
this._currentRcType = void 0;
|
|
20927
|
+
}
|
|
20928
|
+
parseOpen(node) {
|
|
20929
|
+
switch (node.name) {
|
|
20930
|
+
case "metadata":
|
|
20931
|
+
this.reset();
|
|
20932
|
+
return true;
|
|
20933
|
+
case "metadataType":
|
|
20934
|
+
this._metadataTypeNames.push(node.attributes.name || "");
|
|
20935
|
+
return true;
|
|
20936
|
+
case "cellMetadata":
|
|
20937
|
+
this._inCellMetadata = true;
|
|
20938
|
+
return true;
|
|
20939
|
+
case "bk":
|
|
20940
|
+
if (this._inCellMetadata) this._currentRcType = void 0;
|
|
20941
|
+
return true;
|
|
20942
|
+
case "rc":
|
|
20943
|
+
if (this._inCellMetadata && node.attributes.t !== void 0) this._currentRcType = parseInt(node.attributes.t, 10);
|
|
20944
|
+
return true;
|
|
20945
|
+
case "metadataTypes":
|
|
20946
|
+
case "futureMetadata":
|
|
20947
|
+
case "extLst":
|
|
20948
|
+
case "ext":
|
|
20949
|
+
case "xda:dynamicArrayProperties": return true;
|
|
20950
|
+
default: return false;
|
|
20951
|
+
}
|
|
20952
|
+
}
|
|
20953
|
+
parseText() {}
|
|
20954
|
+
parseClose(name) {
|
|
20955
|
+
switch (name) {
|
|
20956
|
+
case "bk":
|
|
20957
|
+
if (this._inCellMetadata) {
|
|
20958
|
+
this._cellMetadataTypeRefs.push(this._currentRcType ?? 0);
|
|
20959
|
+
this._currentRcType = void 0;
|
|
20960
|
+
}
|
|
20961
|
+
return true;
|
|
20962
|
+
case "cellMetadata":
|
|
20963
|
+
this._inCellMetadata = false;
|
|
20964
|
+
return true;
|
|
20965
|
+
case "metadata": {
|
|
20966
|
+
const dynamicArrayCmIndices = /* @__PURE__ */ new Set();
|
|
20967
|
+
for (let i = 0; i < this._cellMetadataTypeRefs.length; i++) {
|
|
20968
|
+
const typeIndex = this._cellMetadataTypeRefs[i];
|
|
20969
|
+
if (this._metadataTypeNames[typeIndex - 1] === "XLDAPR") dynamicArrayCmIndices.add(i + 1);
|
|
20970
|
+
}
|
|
20971
|
+
this.model = {
|
|
20972
|
+
hasDynamicArrays: dynamicArrayCmIndices.size > 0,
|
|
20973
|
+
dynamicArrayCmIndices
|
|
20974
|
+
};
|
|
20975
|
+
return false;
|
|
20976
|
+
}
|
|
20977
|
+
default: return true;
|
|
20978
|
+
}
|
|
20979
|
+
}
|
|
20980
|
+
};
|
|
20981
|
+
//#endregion
|
|
20313
20982
|
//#region src/modules/excel/xlsx/xform/core/relationship-xform.ts
|
|
20314
20983
|
var RelationshipXform = class extends BaseXform {
|
|
20315
20984
|
render(xmlStream, model) {
|
|
@@ -20564,11 +21233,13 @@ onmessage = async (ev) => {
|
|
|
20564
21233
|
return true;
|
|
20565
21234
|
}
|
|
20566
21235
|
if (name === "border") {
|
|
20567
|
-
const model =
|
|
21236
|
+
const model = {};
|
|
21237
|
+
let hasContent = false;
|
|
20568
21238
|
const add = (key, edgeModel, extensions) => {
|
|
20569
21239
|
if (edgeModel) {
|
|
20570
21240
|
if (extensions) Object.assign(edgeModel, extensions);
|
|
20571
21241
|
model[key] = edgeModel;
|
|
21242
|
+
hasContent = true;
|
|
20572
21243
|
}
|
|
20573
21244
|
};
|
|
20574
21245
|
add("left", this.map.left.model);
|
|
@@ -20579,6 +21250,7 @@ onmessage = async (ev) => {
|
|
|
20579
21250
|
up: this.diagonalUp,
|
|
20580
21251
|
down: this.diagonalDown
|
|
20581
21252
|
});
|
|
21253
|
+
this.model = hasContent ? model : void 0;
|
|
20582
21254
|
}
|
|
20583
21255
|
return false;
|
|
20584
21256
|
}
|
|
@@ -21507,7 +22179,8 @@ onmessage = async (ev) => {
|
|
|
21507
22179
|
locked: !(node.attributes.locked === "0"),
|
|
21508
22180
|
hidden: node.attributes.hidden === "1"
|
|
21509
22181
|
};
|
|
21510
|
-
|
|
22182
|
+
const isSignificant = !model.locked || model.hidden;
|
|
22183
|
+
this.model = isSignificant ? model : null;
|
|
21511
22184
|
}
|
|
21512
22185
|
parseText() {}
|
|
21513
22186
|
parseClose() {
|
|
@@ -21911,15 +22584,15 @@ onmessage = async (ev) => {
|
|
|
21911
22584
|
family: 2,
|
|
21912
22585
|
scheme: "minor"
|
|
21913
22586
|
});
|
|
21914
|
-
const type = cellType ||
|
|
21915
|
-
if (type !==
|
|
22587
|
+
const type = cellType || 2;
|
|
22588
|
+
if (type !== 12 && this.weakMap && this.weakMap.has(model)) return this.weakMap.get(model);
|
|
21916
22589
|
const style = {};
|
|
21917
22590
|
if (model.numFmt) style.numFmtId = this._addNumFmtStr(model.numFmt);
|
|
21918
22591
|
else switch (type) {
|
|
21919
|
-
case
|
|
22592
|
+
case 2:
|
|
21920
22593
|
style.numFmtId = this._addNumFmtStr("General");
|
|
21921
22594
|
break;
|
|
21922
|
-
case
|
|
22595
|
+
case 4:
|
|
21923
22596
|
style.numFmtId = this._addNumFmtStr("mm-dd-yy");
|
|
21924
22597
|
break;
|
|
21925
22598
|
default: break;
|
|
@@ -21938,14 +22611,14 @@ onmessage = async (ev) => {
|
|
|
21938
22611
|
"applyAlignment",
|
|
21939
22612
|
"applyProtection"
|
|
21940
22613
|
]) if (model[flag]) style[flag] = true;
|
|
21941
|
-
if (type ===
|
|
22614
|
+
if (type === 12) {
|
|
21942
22615
|
this._hasCheckboxes = true;
|
|
21943
22616
|
style.alignment = style.alignment || {};
|
|
21944
22617
|
style.checkbox = true;
|
|
21945
22618
|
style.xfComplementIndex = 0;
|
|
21946
22619
|
}
|
|
21947
22620
|
const styleId = this._addStyle(style);
|
|
21948
|
-
if (type !==
|
|
22621
|
+
if (type !== 12 && this.weakMap) this.weakMap.set(model, styleId);
|
|
21949
22622
|
return styleId;
|
|
21950
22623
|
}
|
|
21951
22624
|
getStyleModel(id) {
|
|
@@ -22137,8 +22810,8 @@ onmessage = async (ev) => {
|
|
|
22137
22810
|
}
|
|
22138
22811
|
addStyleModel(model, cellType) {
|
|
22139
22812
|
switch (cellType) {
|
|
22140
|
-
case
|
|
22141
|
-
case
|
|
22813
|
+
case 12: throw new ExcelNotSupportedError("Checkbox cells", "require styles to be enabled (useStyles: true)");
|
|
22814
|
+
case 4: return this.dateStyleId;
|
|
22142
22815
|
default: return 0;
|
|
22143
22816
|
}
|
|
22144
22817
|
}
|
|
@@ -22182,6 +22855,7 @@ onmessage = async (ev) => {
|
|
|
22182
22855
|
}
|
|
22183
22856
|
constructor(input, options, WorksheetReaderClass, HyperlinkReaderClass) {
|
|
22184
22857
|
super();
|
|
22858
|
+
this.hasDynamicArrayMetadata = false;
|
|
22185
22859
|
this._totalBufferedBytes = 0;
|
|
22186
22860
|
this.input = input;
|
|
22187
22861
|
this.WorksheetReaderClass = WorksheetReaderClass;
|
|
@@ -22275,7 +22949,8 @@ onmessage = async (ev) => {
|
|
|
22275
22949
|
if (this.options.entries === "emit") this.emit("entry", payload);
|
|
22276
22950
|
}
|
|
22277
22951
|
async _parseRels(entry) {
|
|
22278
|
-
|
|
22952
|
+
const xform = new RelationshipsXform();
|
|
22953
|
+
this.workbookRels = await xform.parseStream(iterateStream(entry));
|
|
22279
22954
|
this._workbookRelIdByTarget = Object.create(null);
|
|
22280
22955
|
for (const rel of this.workbookRels ?? []) if (rel?.Target && rel?.Id) this._workbookRelIdByTarget[rel.Target] = rel.Id;
|
|
22281
22956
|
}
|
|
@@ -22516,6 +23191,13 @@ onmessage = async (ev) => {
|
|
|
22516
23191
|
await this.styles.parseStream(iterateStream(entry));
|
|
22517
23192
|
}
|
|
22518
23193
|
}
|
|
23194
|
+
async _parseMetadata(entry) {
|
|
23195
|
+
const result = await new MetadataXform().parseStream(iterateStream(entry));
|
|
23196
|
+
if (result) {
|
|
23197
|
+
this.hasDynamicArrayMetadata = !!result.hasDynamicArrays;
|
|
23198
|
+
this.dynamicArrayCmIndices = result.dynamicArrayCmIndices;
|
|
23199
|
+
}
|
|
23200
|
+
}
|
|
22519
23201
|
*_parseWorksheet(iterator, sheetNo) {
|
|
22520
23202
|
this._emitEntry({
|
|
22521
23203
|
type: "worksheet",
|
|
@@ -22586,6 +23268,9 @@ onmessage = async (ev) => {
|
|
|
22586
23268
|
case OOXML_PATHS.xlStyles:
|
|
22587
23269
|
await this._parseStyles(entry);
|
|
22588
23270
|
break;
|
|
23271
|
+
case OOXML_PATHS.xlMetadata:
|
|
23272
|
+
await this._parseMetadata(entry);
|
|
23273
|
+
break;
|
|
22589
23274
|
default:
|
|
22590
23275
|
sheetNo = getWorksheetNoFromWorksheetPath(normalizedPath)?.toString();
|
|
22591
23276
|
if (sheetNo) if (!!this.workbookRels && !!this.model && (this.options.sharedStrings !== "cache" || !!this.sharedStrings)) {
|
|
@@ -24638,13 +25323,14 @@ self.onmessage = async function(event) {
|
|
|
24638
25323
|
this._localHeader = null;
|
|
24639
25324
|
return;
|
|
24640
25325
|
}
|
|
24641
|
-
|
|
25326
|
+
const store = isProbablyIncompressibleChunks((function* (pending, current) {
|
|
24642
25327
|
for (const c of pending) if (c.length) yield c;
|
|
24643
25328
|
if (current.length) yield current;
|
|
24644
25329
|
})(this._pendingChunks, dataForDecision), {
|
|
24645
25330
|
sampleBytes: SMART_STORE_DECIDE_BYTES,
|
|
24646
25331
|
minDecisionBytes: SMART_STORE_DECIDE_BYTES
|
|
24647
25332
|
});
|
|
25333
|
+
this._deflateWanted = !store;
|
|
24648
25334
|
this._sampleLen = 0;
|
|
24649
25335
|
this._compressionMethod = this._buildCompressionMethod(this._deflateWanted);
|
|
24650
25336
|
this._localHeader = null;
|
|
@@ -24892,7 +25578,8 @@ self.onmessage = async function(event) {
|
|
|
24892
25578
|
if (this._inputPos > 0) {
|
|
24893
25579
|
const flushData = this._inputBuf.slice(0, this._inputPos);
|
|
24894
25580
|
this._inputPos = 0;
|
|
24895
|
-
const
|
|
25581
|
+
const flushPromise = this._pushAsync(flushData, false);
|
|
25582
|
+
const promise = this._pushChain = flushPromise.then(() => this._pushUnchained(data, final, callback), () => this._pushUnchained(data, final, callback));
|
|
24896
25583
|
promise.catch(() => {});
|
|
24897
25584
|
return promise;
|
|
24898
25585
|
}
|
|
@@ -26049,6 +26736,7 @@ self.onmessage = async function(event) {
|
|
|
26049
26736
|
function filterDrawingAnchors(anchors) {
|
|
26050
26737
|
return anchors.filter((a) => {
|
|
26051
26738
|
if (a == null) return false;
|
|
26739
|
+
if (a.range?.pos !== void 0) return !!a.picture;
|
|
26052
26740
|
if (a.range?.br && a.shape) return true;
|
|
26053
26741
|
if (!a.range?.br && !a.picture) return false;
|
|
26054
26742
|
if (a.range?.br && !a.picture && !a.shape) return false;
|
|
@@ -26984,7 +27672,7 @@ self.onmessage = async function(event) {
|
|
|
26984
27672
|
address,
|
|
26985
27673
|
dataValidation,
|
|
26986
27674
|
marked: false
|
|
26987
|
-
})).sort((a, b) => a.address
|
|
27675
|
+
})).sort((a, b) => colCache.compareAddress(a.address, b.address));
|
|
26988
27676
|
const dvMap = Object.fromEntries(dvList.map((dv) => [dv.address, dv]));
|
|
26989
27677
|
const matchCol = (addr, height, col) => {
|
|
26990
27678
|
for (let i = 0; i < height; i++) {
|
|
@@ -27712,6 +28400,69 @@ self.onmessage = async function(event) {
|
|
|
27712
28400
|
}
|
|
27713
28401
|
};
|
|
27714
28402
|
//#endregion
|
|
28403
|
+
//#region src/modules/excel/xlsx/xform/sheet/ignored-errors-xform.ts
|
|
28404
|
+
/**
|
|
28405
|
+
* Boolean attribute names supported on <ignoredError> elements.
|
|
28406
|
+
* These correspond to the OOXML spec CT_IgnoredError attributes.
|
|
28407
|
+
*/
|
|
28408
|
+
const BOOL_ATTRS = [
|
|
28409
|
+
"numberStoredAsText",
|
|
28410
|
+
"formula",
|
|
28411
|
+
"formulaRange",
|
|
28412
|
+
"unlockedFormula",
|
|
28413
|
+
"emptyCellReference",
|
|
28414
|
+
"listDataValidation",
|
|
28415
|
+
"calculatedColumn",
|
|
28416
|
+
"evalError",
|
|
28417
|
+
"twoDigitTextYear"
|
|
28418
|
+
];
|
|
28419
|
+
/**
|
|
28420
|
+
* Xform for the <ignoredErrors> element in a worksheet.
|
|
28421
|
+
*
|
|
28422
|
+
* Renders:
|
|
28423
|
+
* ```xml
|
|
28424
|
+
* <ignoredErrors>
|
|
28425
|
+
* <ignoredError sqref="A1:B10" numberStoredAsText="1" />
|
|
28426
|
+
* </ignoredErrors>
|
|
28427
|
+
* ```
|
|
28428
|
+
*/
|
|
28429
|
+
var IgnoredErrorsXform = class extends BaseXform {
|
|
28430
|
+
get tag() {
|
|
28431
|
+
return "ignoredErrors";
|
|
28432
|
+
}
|
|
28433
|
+
render(xmlStream, model) {
|
|
28434
|
+
if (!model || model.length === 0) return;
|
|
28435
|
+
xmlStream.openNode("ignoredErrors");
|
|
28436
|
+
for (const entry of model) {
|
|
28437
|
+
const attrs = { sqref: entry.ref };
|
|
28438
|
+
for (const attr of BOOL_ATTRS) if (entry[attr]) attrs[attr] = 1;
|
|
28439
|
+
xmlStream.leafNode("ignoredError", attrs);
|
|
28440
|
+
}
|
|
28441
|
+
xmlStream.closeNode();
|
|
28442
|
+
}
|
|
28443
|
+
parseOpen(node) {
|
|
28444
|
+
switch (node.name) {
|
|
28445
|
+
case "ignoredErrors":
|
|
28446
|
+
this.model = [];
|
|
28447
|
+
return true;
|
|
28448
|
+
case "ignoredError": {
|
|
28449
|
+
const entry = { ref: node.attributes.sqref ?? "" };
|
|
28450
|
+
for (const attr of BOOL_ATTRS) if (node.attributes[attr] === "1" || node.attributes[attr] === "true") entry[attr] = true;
|
|
28451
|
+
this.model.push(entry);
|
|
28452
|
+
return true;
|
|
28453
|
+
}
|
|
28454
|
+
default: return true;
|
|
28455
|
+
}
|
|
28456
|
+
}
|
|
28457
|
+
parseText() {}
|
|
28458
|
+
parseClose(name) {
|
|
28459
|
+
switch (name) {
|
|
28460
|
+
case "ignoredErrors": return false;
|
|
28461
|
+
default: return true;
|
|
28462
|
+
}
|
|
28463
|
+
}
|
|
28464
|
+
};
|
|
28465
|
+
//#endregion
|
|
27715
28466
|
//#region src/modules/excel/xlsx/xform/sheet/page-margins-xform.ts
|
|
27716
28467
|
var PageMarginsXform = class extends BaseXform {
|
|
27717
28468
|
get tag() {
|
|
@@ -27892,22 +28643,62 @@ self.onmessage = async function(event) {
|
|
|
27892
28643
|
//#endregion
|
|
27893
28644
|
//#region src/modules/excel/xlsx/xform/sheet/cell-xform.ts
|
|
27894
28645
|
function getValueType(v) {
|
|
27895
|
-
if (v === null || v === void 0) return
|
|
27896
|
-
if (v instanceof String || typeof v === "string") return
|
|
27897
|
-
if (typeof v === "number") return
|
|
27898
|
-
if (typeof v === "boolean") return
|
|
27899
|
-
if (v instanceof Date) return
|
|
27900
|
-
if (v.text && v.hyperlink) return
|
|
27901
|
-
if (v.formula) return
|
|
27902
|
-
if (v.error) return
|
|
28646
|
+
if (v === null || v === void 0) return 0;
|
|
28647
|
+
if (v instanceof String || typeof v === "string") return 3;
|
|
28648
|
+
if (typeof v === "number") return 2;
|
|
28649
|
+
if (typeof v === "boolean") return 9;
|
|
28650
|
+
if (v instanceof Date) return 4;
|
|
28651
|
+
if (v.text && v.hyperlink) return 5;
|
|
28652
|
+
if (v.formula) return 6;
|
|
28653
|
+
if (v.error) return 10;
|
|
27903
28654
|
throw new InvalidValueTypeError(typeof v, "Could not understand type of value");
|
|
27904
28655
|
}
|
|
27905
28656
|
function getEffectiveCellType(cell) {
|
|
27906
28657
|
switch (cell.type) {
|
|
27907
|
-
case
|
|
28658
|
+
case 6: return getValueType(cell.result);
|
|
27908
28659
|
default: return cell.type;
|
|
27909
28660
|
}
|
|
27910
28661
|
}
|
|
28662
|
+
/**
|
|
28663
|
+
* Extract the display form of a hyperlink cell value that came either from
|
|
28664
|
+
* a shared-string rich-text payload (`{ richText: [...] }`) or from a
|
|
28665
|
+
* plain scalar.
|
|
28666
|
+
*
|
|
28667
|
+
* Input comes from the XML parser (`raw: unknown`), so every nested value is
|
|
28668
|
+
* treated defensively — the public `RichText` shape is only produced after
|
|
28669
|
+
* runtime validation, never asserted.
|
|
28670
|
+
*
|
|
28671
|
+
* Returns:
|
|
28672
|
+
* - `text`: always a string (flattened rich-text or `String(raw)`)
|
|
28673
|
+
* - `richText`: preserved if the source was a rich-text payload, else undefined
|
|
28674
|
+
*
|
|
28675
|
+
* This keeps the CellHyperlinkValue.text: string public contract intact while
|
|
28676
|
+
* also letting the Hyperlink value class retain the formatted runs
|
|
28677
|
+
* (see https://github.com/cjnoname/excelts/issues/142).
|
|
28678
|
+
*/
|
|
28679
|
+
function extractHyperlinkDisplay(raw) {
|
|
28680
|
+
if (raw === null || raw === void 0) return { text: "" };
|
|
28681
|
+
if (typeof raw === "string") return { text: raw };
|
|
28682
|
+
if (typeof raw === "number" || typeof raw === "boolean") return { text: String(raw) };
|
|
28683
|
+
if (typeof raw === "object") {
|
|
28684
|
+
const obj = raw;
|
|
28685
|
+
if (Array.isArray(obj.richText)) {
|
|
28686
|
+
if (obj.richText.length === 0) return { text: "" };
|
|
28687
|
+
const runs = obj.richText.map((rawRun) => {
|
|
28688
|
+
const run = rawRun;
|
|
28689
|
+
const normalized = { text: typeof run?.text === "string" ? run.text : "" };
|
|
28690
|
+
if (run?.font !== null && typeof run?.font === "object") normalized.font = run.font;
|
|
28691
|
+
return normalized;
|
|
28692
|
+
});
|
|
28693
|
+
return {
|
|
28694
|
+
text: runs.map((r) => r.text).join(""),
|
|
28695
|
+
richText: runs
|
|
28696
|
+
};
|
|
28697
|
+
}
|
|
28698
|
+
if (typeof obj.error === "string") return { text: obj.error };
|
|
28699
|
+
}
|
|
28700
|
+
return { text: String(raw) };
|
|
28701
|
+
}
|
|
27911
28702
|
var CellXform = class extends BaseXform {
|
|
27912
28703
|
constructor() {
|
|
27913
28704
|
super();
|
|
@@ -27924,26 +28715,35 @@ self.onmessage = async function(event) {
|
|
|
27924
28715
|
ref: model.address
|
|
27925
28716
|
});
|
|
27926
28717
|
switch (model.type) {
|
|
27927
|
-
case
|
|
27928
|
-
case
|
|
28718
|
+
case 3:
|
|
28719
|
+
case 8:
|
|
27929
28720
|
if (options.sharedStrings) model.ssId = options.sharedStrings.add(model.value);
|
|
27930
28721
|
break;
|
|
27931
|
-
case
|
|
28722
|
+
case 4:
|
|
27932
28723
|
if (options.date1904) model.date1904 = true;
|
|
27933
28724
|
break;
|
|
27934
|
-
case
|
|
27935
|
-
if (options.sharedStrings
|
|
28725
|
+
case 5:
|
|
28726
|
+
if (options.sharedStrings) {
|
|
28727
|
+
if (Array.isArray(model.richText) && model.richText.length > 0) model.ssId = options.sharedStrings.add({ richText: model.richText });
|
|
28728
|
+
else if (model.text !== void 0 && model.text !== null) model.ssId = options.sharedStrings.add(model.text);
|
|
28729
|
+
}
|
|
27936
28730
|
options.hyperlinks.push({
|
|
27937
28731
|
address: model.address,
|
|
27938
28732
|
target: model.hyperlink,
|
|
27939
28733
|
tooltip: model.tooltip
|
|
27940
28734
|
});
|
|
27941
28735
|
break;
|
|
27942
|
-
case
|
|
28736
|
+
case 1:
|
|
27943
28737
|
options.merges.add(model);
|
|
27944
28738
|
break;
|
|
27945
|
-
case
|
|
28739
|
+
case 6:
|
|
27946
28740
|
if (options.date1904) model.date1904 = true;
|
|
28741
|
+
if (model.isDynamicArray) model.cm = 1;
|
|
28742
|
+
if (model.hyperlink) options.hyperlinks.push({
|
|
28743
|
+
address: model.address,
|
|
28744
|
+
target: model.hyperlink,
|
|
28745
|
+
tooltip: model.tooltip
|
|
28746
|
+
});
|
|
27947
28747
|
if (model.shareType === "shared") model.si = options.siFormulae++;
|
|
27948
28748
|
if (model.formula) options.formulae[model.address] = model;
|
|
27949
28749
|
else if (model.sharedFormula) {
|
|
@@ -27984,29 +28784,29 @@ self.onmessage = async function(event) {
|
|
|
27984
28784
|
break;
|
|
27985
28785
|
}
|
|
27986
28786
|
switch (getValueType(model.result)) {
|
|
27987
|
-
case
|
|
28787
|
+
case 0:
|
|
27988
28788
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
27989
28789
|
break;
|
|
27990
|
-
case
|
|
28790
|
+
case 3:
|
|
27991
28791
|
xmlStream.addAttribute("t", "str");
|
|
27992
28792
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
27993
28793
|
xmlStream.leafNode("v", null, model.result);
|
|
27994
28794
|
break;
|
|
27995
|
-
case
|
|
28795
|
+
case 2:
|
|
27996
28796
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
27997
28797
|
xmlStream.leafNode("v", null, model.result);
|
|
27998
28798
|
break;
|
|
27999
|
-
case
|
|
28799
|
+
case 9:
|
|
28000
28800
|
xmlStream.addAttribute("t", "b");
|
|
28001
28801
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
28002
28802
|
xmlStream.leafNode("v", null, model.result ? 1 : 0);
|
|
28003
28803
|
break;
|
|
28004
|
-
case
|
|
28804
|
+
case 10:
|
|
28005
28805
|
xmlStream.addAttribute("t", "e");
|
|
28006
28806
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
28007
28807
|
xmlStream.leafNode("v", null, model.result.error);
|
|
28008
28808
|
break;
|
|
28009
|
-
case
|
|
28809
|
+
case 4:
|
|
28010
28810
|
xmlStream.leafNode("f", attrs, model.formula);
|
|
28011
28811
|
xmlStream.leafNode("v", null, dateToExcel(model.result, model.date1904));
|
|
28012
28812
|
break;
|
|
@@ -28014,29 +28814,30 @@ self.onmessage = async function(event) {
|
|
|
28014
28814
|
}
|
|
28015
28815
|
}
|
|
28016
28816
|
render(xmlStream, model) {
|
|
28017
|
-
if (model.type ===
|
|
28817
|
+
if (model.type === 0 && !model.styleId) return;
|
|
28018
28818
|
xmlStream.openNode("c");
|
|
28019
28819
|
xmlStream.addAttribute("r", model.address);
|
|
28020
28820
|
if (model.styleId) xmlStream.addAttribute("s", model.styleId);
|
|
28821
|
+
if (model.cm) xmlStream.addAttribute("cm", model.cm);
|
|
28021
28822
|
switch (model.type) {
|
|
28022
|
-
case
|
|
28023
|
-
case
|
|
28823
|
+
case 0: break;
|
|
28824
|
+
case 2:
|
|
28024
28825
|
xmlStream.leafNode("v", null, model.value);
|
|
28025
28826
|
break;
|
|
28026
|
-
case
|
|
28827
|
+
case 9:
|
|
28027
28828
|
xmlStream.addAttribute("t", "b");
|
|
28028
28829
|
xmlStream.leafNode("v", null, model.value ? "1" : "0");
|
|
28029
28830
|
break;
|
|
28030
|
-
case
|
|
28831
|
+
case 12:
|
|
28031
28832
|
xmlStream.addAttribute("t", "b");
|
|
28032
28833
|
xmlStream.leafNode("v", null, model.value ? "1" : "0");
|
|
28033
28834
|
break;
|
|
28034
|
-
case
|
|
28835
|
+
case 10:
|
|
28035
28836
|
xmlStream.addAttribute("t", "e");
|
|
28036
28837
|
xmlStream.leafNode("v", null, model.value.error);
|
|
28037
28838
|
break;
|
|
28038
|
-
case
|
|
28039
|
-
case
|
|
28839
|
+
case 3:
|
|
28840
|
+
case 8:
|
|
28040
28841
|
if (model.ssId !== void 0) {
|
|
28041
28842
|
xmlStream.addAttribute("t", "s");
|
|
28042
28843
|
xmlStream.leafNode("v", null, model.ssId);
|
|
@@ -28052,22 +28853,30 @@ self.onmessage = async function(event) {
|
|
|
28052
28853
|
xmlStream.leafNode("v", null, model.value);
|
|
28053
28854
|
}
|
|
28054
28855
|
break;
|
|
28055
|
-
case
|
|
28856
|
+
case 4:
|
|
28056
28857
|
xmlStream.leafNode("v", null, dateToExcel(model.value, model.date1904));
|
|
28057
28858
|
break;
|
|
28058
|
-
case
|
|
28059
|
-
if (model.
|
|
28859
|
+
case 5:
|
|
28860
|
+
if (model.formula || model.sharedFormula) this.renderFormula(xmlStream, model);
|
|
28861
|
+
else if (model.ssId !== void 0) {
|
|
28060
28862
|
xmlStream.addAttribute("t", "s");
|
|
28061
28863
|
xmlStream.leafNode("v", null, model.ssId);
|
|
28864
|
+
} else if (Array.isArray(model.richText) && model.richText.length > 0) {
|
|
28865
|
+
xmlStream.addAttribute("t", "inlineStr");
|
|
28866
|
+
xmlStream.openNode("is");
|
|
28867
|
+
model.richText.forEach((text) => {
|
|
28868
|
+
this.richTextXform.render(xmlStream, text);
|
|
28869
|
+
});
|
|
28870
|
+
xmlStream.closeNode("is");
|
|
28062
28871
|
} else {
|
|
28063
28872
|
xmlStream.addAttribute("t", "str");
|
|
28064
28873
|
xmlStream.leafNode("v", null, model.text);
|
|
28065
28874
|
}
|
|
28066
28875
|
break;
|
|
28067
|
-
case
|
|
28876
|
+
case 6:
|
|
28068
28877
|
this.renderFormula(xmlStream, model);
|
|
28069
28878
|
break;
|
|
28070
|
-
case
|
|
28879
|
+
case 1: break;
|
|
28071
28880
|
default: break;
|
|
28072
28881
|
}
|
|
28073
28882
|
xmlStream.closeNode();
|
|
@@ -28082,6 +28891,7 @@ self.onmessage = async function(event) {
|
|
|
28082
28891
|
this.model = { address: node.attributes.r };
|
|
28083
28892
|
this.t = node.attributes.t;
|
|
28084
28893
|
if (node.attributes.s) this.model.styleId = parseInt(node.attributes.s, 10);
|
|
28894
|
+
if (node.attributes.cm) this.model.cm = parseInt(node.attributes.cm, 10);
|
|
28085
28895
|
return true;
|
|
28086
28896
|
case "f":
|
|
28087
28897
|
this.currentNode = "f";
|
|
@@ -28124,7 +28934,7 @@ self.onmessage = async function(event) {
|
|
|
28124
28934
|
case "c": {
|
|
28125
28935
|
const { model } = this;
|
|
28126
28936
|
if (model.formula || model.shareType) {
|
|
28127
|
-
model.type =
|
|
28937
|
+
model.type = 6;
|
|
28128
28938
|
if (model.value) {
|
|
28129
28939
|
if (this.t === "str") model.result = model.value;
|
|
28130
28940
|
else if (this.t === "b") model.result = parseInt(model.value, 10) !== 0;
|
|
@@ -28134,35 +28944,35 @@ self.onmessage = async function(event) {
|
|
|
28134
28944
|
}
|
|
28135
28945
|
} else if (model.value !== void 0) switch (this.t) {
|
|
28136
28946
|
case "s":
|
|
28137
|
-
model.type =
|
|
28947
|
+
model.type = 3;
|
|
28138
28948
|
model.value = parseInt(model.value, 10);
|
|
28139
28949
|
break;
|
|
28140
28950
|
case "str":
|
|
28141
|
-
model.type =
|
|
28951
|
+
model.type = 3;
|
|
28142
28952
|
break;
|
|
28143
28953
|
case "inlineStr":
|
|
28144
|
-
model.type =
|
|
28954
|
+
model.type = 3;
|
|
28145
28955
|
if (typeof model.value === "string" && model.value.includes("_x")) model.value = decodeOoxmlEscape(model.value);
|
|
28146
28956
|
break;
|
|
28147
28957
|
case "b":
|
|
28148
|
-
model.type =
|
|
28958
|
+
model.type = 9;
|
|
28149
28959
|
model.value = parseInt(model.value, 10) !== 0;
|
|
28150
28960
|
break;
|
|
28151
28961
|
case "e":
|
|
28152
|
-
model.type =
|
|
28962
|
+
model.type = 10;
|
|
28153
28963
|
model.value = { error: model.value };
|
|
28154
28964
|
break;
|
|
28155
28965
|
case "d":
|
|
28156
|
-
model.type =
|
|
28966
|
+
model.type = 4;
|
|
28157
28967
|
model.value = new Date(model.value);
|
|
28158
28968
|
break;
|
|
28159
28969
|
default:
|
|
28160
|
-
model.type =
|
|
28970
|
+
model.type = 2;
|
|
28161
28971
|
model.value = parseFloat(model.value);
|
|
28162
28972
|
break;
|
|
28163
28973
|
}
|
|
28164
|
-
else if (model.styleId) model.type =
|
|
28165
|
-
else model.type =
|
|
28974
|
+
else if (model.styleId) model.type = 0;
|
|
28975
|
+
else model.type = 1;
|
|
28166
28976
|
return false;
|
|
28167
28977
|
}
|
|
28168
28978
|
case "f":
|
|
@@ -28197,19 +29007,23 @@ self.onmessage = async function(event) {
|
|
|
28197
29007
|
if (style) model.style = style;
|
|
28198
29008
|
if (model.styleId !== void 0) model.styleId = void 0;
|
|
28199
29009
|
switch (model.type) {
|
|
28200
|
-
case
|
|
29010
|
+
case 3:
|
|
28201
29011
|
if (typeof model.value === "number") {
|
|
28202
|
-
if (options.sharedStrings)
|
|
29012
|
+
if (options.sharedStrings) {
|
|
29013
|
+
const ssIndex = model.value;
|
|
29014
|
+
model.value = options.sharedStrings.getString(ssIndex);
|
|
29015
|
+
if (model.value === void 0) throw new ExcelError(`Invalid shared string index ${ssIndex} in cell ${model.address}: the xlsx file appears to be corrupted`);
|
|
29016
|
+
}
|
|
28203
29017
|
}
|
|
28204
|
-
if (model.value.richText) model.type =
|
|
29018
|
+
if (model.value && model.value.richText) model.type = 8;
|
|
28205
29019
|
break;
|
|
28206
|
-
case
|
|
29020
|
+
case 2:
|
|
28207
29021
|
if (style && isDateFmt(style.numFmt)) {
|
|
28208
|
-
model.type =
|
|
29022
|
+
model.type = 4;
|
|
28209
29023
|
model.value = excelToDate(model.value, options.date1904);
|
|
28210
29024
|
}
|
|
28211
29025
|
break;
|
|
28212
|
-
case
|
|
29026
|
+
case 6:
|
|
28213
29027
|
if (model.result !== void 0 && typeof model.result === "number" && style && isDateFmt(style.numFmt)) model.result = excelToDate(model.result, options.date1904);
|
|
28214
29028
|
if (model.shareType === "shared") {
|
|
28215
29029
|
if (model.ref) options.formulae[model.si] = model.address;
|
|
@@ -28219,19 +29033,28 @@ self.onmessage = async function(event) {
|
|
|
28219
29033
|
}
|
|
28220
29034
|
delete model.si;
|
|
28221
29035
|
}
|
|
29036
|
+
if (model.cm) {
|
|
29037
|
+
if (options.dynamicArrayCmIndices) {
|
|
29038
|
+
if (options.dynamicArrayCmIndices.has(model.cm)) model.isDynamicArray = true;
|
|
29039
|
+
} else if (options.hasDynamicArrayMetadata) model.isDynamicArray = true;
|
|
29040
|
+
}
|
|
29041
|
+
delete model.cm;
|
|
28222
29042
|
break;
|
|
28223
29043
|
default: break;
|
|
28224
29044
|
}
|
|
28225
29045
|
const hyperlink = options.hyperlinkMap[model.address];
|
|
28226
29046
|
if (hyperlink) {
|
|
28227
|
-
|
|
28228
|
-
|
|
28229
|
-
|
|
28230
|
-
|
|
28231
|
-
model.text = model.value;
|
|
29047
|
+
let source;
|
|
29048
|
+
if (model.type === 6) source = model.result;
|
|
29049
|
+
else {
|
|
29050
|
+
source = model.value;
|
|
28232
29051
|
model.value = void 0;
|
|
28233
29052
|
}
|
|
28234
|
-
|
|
29053
|
+
const display = extractHyperlinkDisplay(source);
|
|
29054
|
+
model.text = display.text;
|
|
29055
|
+
if (display.richText) model.richText = display.richText;
|
|
29056
|
+
else delete model.richText;
|
|
29057
|
+
model.type = 5;
|
|
28235
29058
|
model.hyperlink = hyperlink;
|
|
28236
29059
|
}
|
|
28237
29060
|
const comment = options.commentsMap && options.commentsMap[model.address];
|
|
@@ -28301,8 +29124,9 @@ self.onmessage = async function(event) {
|
|
|
28301
29124
|
spanMin = parseInt(spans, 10);
|
|
28302
29125
|
spanMax = colonIdx > -1 ? parseInt(spans.substring(colonIdx + 1), 10) : void 0;
|
|
28303
29126
|
}
|
|
29127
|
+
const rowNumber = node.attributes.r ? parseInt(node.attributes.r, 10) : this.numRowsSeen;
|
|
28304
29128
|
const model = this.model = {
|
|
28305
|
-
number:
|
|
29129
|
+
number: rowNumber,
|
|
28306
29130
|
min: spanMin,
|
|
28307
29131
|
max: spanMax,
|
|
28308
29132
|
cells: []
|
|
@@ -28786,6 +29610,7 @@ self.onmessage = async function(event) {
|
|
|
28786
29610
|
drawing: new DrawingXform$1(),
|
|
28787
29611
|
conditionalFormattings: new ConditionalFormattingsXform(),
|
|
28788
29612
|
extLst: new ExtLstXform$1(),
|
|
29613
|
+
ignoredErrors: new IgnoredErrorsXform(),
|
|
28789
29614
|
headerFooter: new HeaderFooterXform(),
|
|
28790
29615
|
rowBreaks: new RowBreaksXform(),
|
|
28791
29616
|
colBreaks: new ColBreaksXform()
|
|
@@ -28810,6 +29635,7 @@ self.onmessage = async function(event) {
|
|
|
28810
29635
|
this._formulae = {};
|
|
28811
29636
|
this._siFormulae = 0;
|
|
28812
29637
|
this.conditionalFormatting = [];
|
|
29638
|
+
this.ignoredErrors = [];
|
|
28813
29639
|
this.rowBreaks = [];
|
|
28814
29640
|
this.colBreaks = [];
|
|
28815
29641
|
this.properties = Object.assign({}, {
|
|
@@ -28900,6 +29726,7 @@ self.onmessage = async function(event) {
|
|
|
28900
29726
|
this._writeDrawing();
|
|
28901
29727
|
this._writeBackground();
|
|
28902
29728
|
this._writeLegacyData();
|
|
29729
|
+
this._writeIgnoredErrors();
|
|
28903
29730
|
this._writeExtLst();
|
|
28904
29731
|
this._writeCloseWorksheet();
|
|
28905
29732
|
this.stream.end();
|
|
@@ -29146,17 +29973,33 @@ self.onmessage = async function(event) {
|
|
|
29146
29973
|
};
|
|
29147
29974
|
throw new Error(`Invalid image range: "${range}". Expected a range like "A1:C3".`);
|
|
29148
29975
|
}
|
|
29149
|
-
return {
|
|
29976
|
+
if ("pos" in range && range.pos) return {
|
|
29150
29977
|
type: "image",
|
|
29151
29978
|
imageId,
|
|
29152
29979
|
range: {
|
|
29153
|
-
tl:
|
|
29154
|
-
|
|
29980
|
+
tl: {
|
|
29981
|
+
nativeCol: 0,
|
|
29982
|
+
nativeColOff: 0,
|
|
29983
|
+
nativeRow: 0,
|
|
29984
|
+
nativeRowOff: 0
|
|
29985
|
+
},
|
|
29155
29986
|
ext: range.ext,
|
|
29156
|
-
|
|
29987
|
+
pos: range.pos
|
|
29157
29988
|
},
|
|
29158
29989
|
hyperlinks: range.hyperlinks
|
|
29159
29990
|
};
|
|
29991
|
+
const cellRange = range;
|
|
29992
|
+
return {
|
|
29993
|
+
type: "image",
|
|
29994
|
+
imageId,
|
|
29995
|
+
range: {
|
|
29996
|
+
tl: new Anchor(this, cellRange.tl, 0).model,
|
|
29997
|
+
br: cellRange.br ? new Anchor(this, cellRange.br, 0).model : void 0,
|
|
29998
|
+
ext: cellRange.ext,
|
|
29999
|
+
editAs: cellRange.editAs
|
|
30000
|
+
},
|
|
30001
|
+
hyperlinks: cellRange.hyperlinks
|
|
30002
|
+
};
|
|
29160
30003
|
}
|
|
29161
30004
|
async protect(password, options) {
|
|
29162
30005
|
this.sheetProtection = { sheet: true };
|
|
@@ -29215,6 +30058,7 @@ self.onmessage = async function(event) {
|
|
|
29215
30058
|
}
|
|
29216
30059
|
if (row.hasValues || row.height != null) {
|
|
29217
30060
|
const { model } = row;
|
|
30061
|
+
if (!model) return;
|
|
29218
30062
|
const options = {
|
|
29219
30063
|
styles: this._workbook.styles,
|
|
29220
30064
|
sharedStrings: this.useSharedStrings ? this._workbook.sharedStrings : void 0,
|
|
@@ -29226,6 +30070,9 @@ self.onmessage = async function(event) {
|
|
|
29226
30070
|
};
|
|
29227
30071
|
xform.row.prepare(model, options);
|
|
29228
30072
|
this.stream.write(xform.row.toXml(model));
|
|
30073
|
+
if (model.cells) {
|
|
30074
|
+
for (const cell of model.cells) if (cell && cell.isDynamicArray) this._workbook.dynamicArrayCount++;
|
|
30075
|
+
}
|
|
29229
30076
|
if (options.comments.length) {
|
|
29230
30077
|
this.hasComments = true;
|
|
29231
30078
|
this._sheetCommentsWriter.addComments(options.comments);
|
|
@@ -29268,6 +30115,9 @@ self.onmessage = async function(event) {
|
|
|
29268
30115
|
const model = { conditionalFormattings: this.conditionalFormatting };
|
|
29269
30116
|
this.stream.write(xform.extLst.toXml(model));
|
|
29270
30117
|
}
|
|
30118
|
+
_writeIgnoredErrors() {
|
|
30119
|
+
if (this.ignoredErrors.length > 0) this.stream.write(xform.ignoredErrors.toXml(this.ignoredErrors));
|
|
30120
|
+
}
|
|
29271
30121
|
_writeRowBreaks() {
|
|
29272
30122
|
this.stream.write(xform.rowBreaks.toXml(this.rowBreaks));
|
|
29273
30123
|
}
|
|
@@ -29330,6 +30180,7 @@ self.onmessage = async function(event) {
|
|
|
29330
30180
|
if (this._background) {
|
|
29331
30181
|
if (this._background.imageId !== void 0) {
|
|
29332
30182
|
const image = this._workbook.getImage(this._background.imageId);
|
|
30183
|
+
if (!image) return;
|
|
29333
30184
|
const pictureId = this._sheetRelsWriter.addMedia({
|
|
29334
30185
|
Target: mediaRelTargetFromRels(image.name),
|
|
29335
30186
|
Type: RelType.Image
|
|
@@ -29356,6 +30207,20 @@ self.onmessage = async function(event) {
|
|
|
29356
30207
|
};
|
|
29357
30208
|
//#endregion
|
|
29358
30209
|
//#region src/modules/excel/utils/shared-strings.ts
|
|
30210
|
+
/**
|
|
30211
|
+
* Canonical JSON serializer with sorted object keys.
|
|
30212
|
+
*
|
|
30213
|
+
* Used to derive an insertion-order-independent dedupe key for rich-text
|
|
30214
|
+
* shared-string entries. Two semantically identical run/font objects must
|
|
30215
|
+
* map to the same key regardless of the order their properties were assigned.
|
|
30216
|
+
*/
|
|
30217
|
+
function canonicalStringify(value) {
|
|
30218
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
30219
|
+
if (Array.isArray(value)) return `[${value.map(canonicalStringify).join(",")}]`;
|
|
30220
|
+
const keys = Object.keys(value).sort();
|
|
30221
|
+
const obj = value;
|
|
30222
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalStringify(obj[k])}`).join(",")}}`;
|
|
30223
|
+
}
|
|
29359
30224
|
var SharedStrings = class {
|
|
29360
30225
|
constructor() {
|
|
29361
30226
|
this._values = [];
|
|
@@ -29375,9 +30240,10 @@ self.onmessage = async function(event) {
|
|
|
29375
30240
|
return this._values[index];
|
|
29376
30241
|
}
|
|
29377
30242
|
add(value) {
|
|
29378
|
-
|
|
30243
|
+
const key = typeof value === "string" ? `s:${value}` : `r:${canonicalStringify(value.richText)}`;
|
|
30244
|
+
let index = this._hash[key];
|
|
29379
30245
|
if (index === void 0) {
|
|
29380
|
-
index = this._hash[
|
|
30246
|
+
index = this._hash[key] = this._values.length;
|
|
29381
30247
|
this._values.push(value);
|
|
29382
30248
|
}
|
|
29383
30249
|
this._totalRefs++;
|
|
@@ -29773,6 +30639,33 @@ self.onmessage = async function(event) {
|
|
|
29773
30639
|
return result;
|
|
29774
30640
|
}
|
|
29775
30641
|
//#endregion
|
|
30642
|
+
//#region src/modules/excel/utils/workbook-protection.ts
|
|
30643
|
+
/**
|
|
30644
|
+
* Build a workbook-protection object with optional password hashing.
|
|
30645
|
+
*
|
|
30646
|
+
* This is the shared implementation used by both `Workbook.protect()` and
|
|
30647
|
+
* `WorkbookWriter.protect()`. The caller is responsible for assigning the
|
|
30648
|
+
* result to its own `protection` field.
|
|
30649
|
+
*
|
|
30650
|
+
* @param password - Optional password to hash
|
|
30651
|
+
* @param options - Optional protection flags (lockStructure, lockWindows, lockRevision, spinCount)
|
|
30652
|
+
* @returns A fully-populated workbook-protection object
|
|
30653
|
+
*/
|
|
30654
|
+
async function buildWorkbookProtection(password, options) {
|
|
30655
|
+
const protection = {
|
|
30656
|
+
lockStructure: options?.lockStructure ?? true,
|
|
30657
|
+
lockWindows: options?.lockWindows,
|
|
30658
|
+
lockRevision: options?.lockRevision
|
|
30659
|
+
};
|
|
30660
|
+
if (password) {
|
|
30661
|
+
protection.algorithmName = "SHA-512";
|
|
30662
|
+
protection.saltValue = uint8ArrayToBase64(Encryptor.randomBytes(16));
|
|
30663
|
+
protection.spinCount = options?.spinCount != null && Number.isFinite(options.spinCount) ? Math.round(Math.max(0, options.spinCount)) : 1e5;
|
|
30664
|
+
protection.hashValue = await Encryptor.convertPasswordToHash(password, "SHA-512", protection.saltValue, protection.spinCount);
|
|
30665
|
+
}
|
|
30666
|
+
return protection;
|
|
30667
|
+
}
|
|
30668
|
+
//#endregion
|
|
29776
30669
|
//#region src/modules/excel/xlsx/xform/core/app-heading-pairs-xform.ts
|
|
29777
30670
|
var AppHeadingPairsXform = class extends BaseXform {
|
|
29778
30671
|
render(xmlStream, model) {
|
|
@@ -29966,10 +30859,18 @@ self.onmessage = async function(event) {
|
|
|
29966
30859
|
PartName: toContentTypesPartName(OOXML_PATHS.xlStyles),
|
|
29967
30860
|
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"
|
|
29968
30861
|
});
|
|
30862
|
+
if (model.externalLinks && model.externalLinks.length > 0) for (const link of model.externalLinks) xmlStream.leafNode("Override", {
|
|
30863
|
+
PartName: toContentTypesPartName(externalLinkPath(link.index)),
|
|
30864
|
+
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml"
|
|
30865
|
+
});
|
|
29969
30866
|
if (model.hasCheckboxes) xmlStream.leafNode("Override", {
|
|
29970
30867
|
PartName: toContentTypesPartName(OOXML_PATHS.xlFeaturePropertyBag),
|
|
29971
30868
|
ContentType: "application/vnd.ms-excel.featurepropertybag+xml"
|
|
29972
30869
|
});
|
|
30870
|
+
if (model.hasDynamicArrayFormulas) xmlStream.leafNode("Override", {
|
|
30871
|
+
PartName: toContentTypesPartName(OOXML_PATHS.xlMetadata),
|
|
30872
|
+
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml"
|
|
30873
|
+
});
|
|
29973
30874
|
if (model.sharedStrings && model.sharedStrings.count) xmlStream.leafNode("Override", {
|
|
29974
30875
|
PartName: toContentTypesPartName(OOXML_PATHS.xlSharedStrings),
|
|
29975
30876
|
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"
|
|
@@ -30236,7 +31137,9 @@ self.onmessage = async function(event) {
|
|
|
30236
31137
|
}
|
|
30237
31138
|
reconcilePicture(model, options) {
|
|
30238
31139
|
if (model && model.rId) {
|
|
30239
|
-
const
|
|
31140
|
+
const rel = options.rels[model.rId];
|
|
31141
|
+
if (!rel) return;
|
|
31142
|
+
const match = rel.Target.match(/.*\/media\/(.+[.][a-zA-Z]{3,4})/);
|
|
30240
31143
|
if (match) {
|
|
30241
31144
|
const name = match[1];
|
|
30242
31145
|
const mediaId = options.mediaIndex[name];
|
|
@@ -30251,85 +31154,9 @@ self.onmessage = async function(event) {
|
|
|
30251
31154
|
}
|
|
30252
31155
|
};
|
|
30253
31156
|
//#endregion
|
|
30254
|
-
//#region src/modules/excel/xlsx/xform/drawing/cell-position-xform.ts
|
|
30255
|
-
var CellPositionXform = class extends BaseXform {
|
|
30256
|
-
constructor(options) {
|
|
30257
|
-
super();
|
|
30258
|
-
this.tag = options.tag;
|
|
30259
|
-
this.map = {
|
|
30260
|
-
"xdr:col": new IntegerXform({
|
|
30261
|
-
tag: "xdr:col",
|
|
30262
|
-
zero: true
|
|
30263
|
-
}),
|
|
30264
|
-
"xdr:colOff": new IntegerXform({
|
|
30265
|
-
tag: "xdr:colOff",
|
|
30266
|
-
zero: true
|
|
30267
|
-
}),
|
|
30268
|
-
"xdr:row": new IntegerXform({
|
|
30269
|
-
tag: "xdr:row",
|
|
30270
|
-
zero: true
|
|
30271
|
-
}),
|
|
30272
|
-
"xdr:rowOff": new IntegerXform({
|
|
30273
|
-
tag: "xdr:rowOff",
|
|
30274
|
-
zero: true
|
|
30275
|
-
})
|
|
30276
|
-
};
|
|
30277
|
-
this.model = {
|
|
30278
|
-
nativeCol: 0,
|
|
30279
|
-
nativeColOff: 0,
|
|
30280
|
-
nativeRow: 0,
|
|
30281
|
-
nativeRowOff: 0
|
|
30282
|
-
};
|
|
30283
|
-
}
|
|
30284
|
-
render(xmlStream, model) {
|
|
30285
|
-
xmlStream.openNode(this.tag);
|
|
30286
|
-
this.map["xdr:col"].render(xmlStream, model.nativeCol);
|
|
30287
|
-
this.map["xdr:colOff"].render(xmlStream, model.nativeColOff);
|
|
30288
|
-
this.map["xdr:row"].render(xmlStream, model.nativeRow);
|
|
30289
|
-
this.map["xdr:rowOff"].render(xmlStream, model.nativeRowOff);
|
|
30290
|
-
xmlStream.closeNode();
|
|
30291
|
-
}
|
|
30292
|
-
parseOpen(node) {
|
|
30293
|
-
if (this.parser) {
|
|
30294
|
-
this.parser.parseOpen(node);
|
|
30295
|
-
return true;
|
|
30296
|
-
}
|
|
30297
|
-
switch (node.name) {
|
|
30298
|
-
case this.tag:
|
|
30299
|
-
this.reset();
|
|
30300
|
-
break;
|
|
30301
|
-
default:
|
|
30302
|
-
this.parser = this.map[node.name];
|
|
30303
|
-
if (this.parser) this.parser.parseOpen(node);
|
|
30304
|
-
break;
|
|
30305
|
-
}
|
|
30306
|
-
return true;
|
|
30307
|
-
}
|
|
30308
|
-
parseText(text) {
|
|
30309
|
-
if (this.parser) this.parser.parseText(text);
|
|
30310
|
-
}
|
|
30311
|
-
parseClose(name) {
|
|
30312
|
-
if (this.parser) {
|
|
30313
|
-
if (!this.parser.parseClose(name)) this.parser = void 0;
|
|
30314
|
-
return true;
|
|
30315
|
-
}
|
|
30316
|
-
switch (name) {
|
|
30317
|
-
case this.tag:
|
|
30318
|
-
this.model = {
|
|
30319
|
-
nativeCol: this.map["xdr:col"].model,
|
|
30320
|
-
nativeColOff: this.map["xdr:colOff"].model,
|
|
30321
|
-
nativeRow: this.map["xdr:row"].model,
|
|
30322
|
-
nativeRowOff: this.map["xdr:rowOff"].model
|
|
30323
|
-
};
|
|
30324
|
-
return false;
|
|
30325
|
-
default: return true;
|
|
30326
|
-
}
|
|
30327
|
-
}
|
|
30328
|
-
};
|
|
30329
|
-
//#endregion
|
|
30330
31157
|
//#region src/modules/excel/xlsx/xform/drawing/ext-xform.ts
|
|
30331
31158
|
/** https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML */
|
|
30332
|
-
const EMU_PER_PIXEL_AT_96_DPI = 9525;
|
|
31159
|
+
const EMU_PER_PIXEL_AT_96_DPI$1 = 9525;
|
|
30333
31160
|
var ExtXform = class extends BaseXform {
|
|
30334
31161
|
constructor(options) {
|
|
30335
31162
|
super();
|
|
@@ -30342,8 +31169,8 @@ self.onmessage = async function(event) {
|
|
|
30342
31169
|
}
|
|
30343
31170
|
render(xmlStream, model) {
|
|
30344
31171
|
xmlStream.openNode(this.tag);
|
|
30345
|
-
const width = Math.floor(model.width * EMU_PER_PIXEL_AT_96_DPI);
|
|
30346
|
-
const height = Math.floor(model.height * EMU_PER_PIXEL_AT_96_DPI);
|
|
31172
|
+
const width = Math.floor(model.width * EMU_PER_PIXEL_AT_96_DPI$1);
|
|
31173
|
+
const height = Math.floor(model.height * EMU_PER_PIXEL_AT_96_DPI$1);
|
|
30347
31174
|
xmlStream.addAttribute("cx", width);
|
|
30348
31175
|
xmlStream.addAttribute("cy", height);
|
|
30349
31176
|
xmlStream.closeNode();
|
|
@@ -30351,8 +31178,8 @@ self.onmessage = async function(event) {
|
|
|
30351
31178
|
parseOpen(node) {
|
|
30352
31179
|
if (node.name === this.tag) {
|
|
30353
31180
|
this.model = {
|
|
30354
|
-
width: parseInt(node.attributes.cx ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI,
|
|
30355
|
-
height: parseInt(node.attributes.cy ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI
|
|
31181
|
+
width: parseInt(node.attributes.cx ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI$1,
|
|
31182
|
+
height: parseInt(node.attributes.cy ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI$1
|
|
30356
31183
|
};
|
|
30357
31184
|
return true;
|
|
30358
31185
|
}
|
|
@@ -30729,6 +31556,182 @@ self.onmessage = async function(event) {
|
|
|
30729
31556
|
}
|
|
30730
31557
|
};
|
|
30731
31558
|
//#endregion
|
|
31559
|
+
//#region src/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.ts
|
|
31560
|
+
/** https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML */
|
|
31561
|
+
const EMU_PER_PIXEL_AT_96_DPI = 9525;
|
|
31562
|
+
/**
|
|
31563
|
+
* Xform for the <xdr:pos> element (absolute position in EMU).
|
|
31564
|
+
* Converts between EMU (in XML) and pixels (in model).
|
|
31565
|
+
*/
|
|
31566
|
+
var PosXform = class extends BaseXform {
|
|
31567
|
+
constructor() {
|
|
31568
|
+
super();
|
|
31569
|
+
this.map = {};
|
|
31570
|
+
this.model = {
|
|
31571
|
+
x: 0,
|
|
31572
|
+
y: 0
|
|
31573
|
+
};
|
|
31574
|
+
}
|
|
31575
|
+
get tag() {
|
|
31576
|
+
return "xdr:pos";
|
|
31577
|
+
}
|
|
31578
|
+
render(xmlStream, model) {
|
|
31579
|
+
xmlStream.leafNode(this.tag, {
|
|
31580
|
+
x: Math.floor(model.x * EMU_PER_PIXEL_AT_96_DPI),
|
|
31581
|
+
y: Math.floor(model.y * EMU_PER_PIXEL_AT_96_DPI)
|
|
31582
|
+
});
|
|
31583
|
+
}
|
|
31584
|
+
parseOpen(node) {
|
|
31585
|
+
if (node.name === this.tag) {
|
|
31586
|
+
this.model = {
|
|
31587
|
+
x: parseInt(node.attributes.x ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI,
|
|
31588
|
+
y: parseInt(node.attributes.y ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI
|
|
31589
|
+
};
|
|
31590
|
+
return true;
|
|
31591
|
+
}
|
|
31592
|
+
return false;
|
|
31593
|
+
}
|
|
31594
|
+
parseText() {}
|
|
31595
|
+
parseClose() {
|
|
31596
|
+
return false;
|
|
31597
|
+
}
|
|
31598
|
+
};
|
|
31599
|
+
/**
|
|
31600
|
+
* Xform for <xdr:absoluteAnchor> — images positioned by absolute coordinates
|
|
31601
|
+
* rather than cell references.
|
|
31602
|
+
*
|
|
31603
|
+
* Structure:
|
|
31604
|
+
* ```xml
|
|
31605
|
+
* <xdr:absoluteAnchor>
|
|
31606
|
+
* <xdr:pos x="0" y="0"/>
|
|
31607
|
+
* <xdr:ext cx="1000000" cy="1000000"/>
|
|
31608
|
+
* <xdr:pic>...</xdr:pic>
|
|
31609
|
+
* <xdr:clientData/>
|
|
31610
|
+
* </xdr:absoluteAnchor>
|
|
31611
|
+
* ```
|
|
31612
|
+
*/
|
|
31613
|
+
var AbsoluteAnchorXform = class extends BaseCellAnchorXform {
|
|
31614
|
+
constructor() {
|
|
31615
|
+
super();
|
|
31616
|
+
this.map = {
|
|
31617
|
+
"xdr:pos": new PosXform(),
|
|
31618
|
+
"xdr:ext": new ExtXform({ tag: "xdr:ext" }),
|
|
31619
|
+
"xdr:pic": new PicXform(),
|
|
31620
|
+
"xdr:clientData": new StaticXform({ tag: "xdr:clientData" })
|
|
31621
|
+
};
|
|
31622
|
+
}
|
|
31623
|
+
get tag() {
|
|
31624
|
+
return "xdr:absoluteAnchor";
|
|
31625
|
+
}
|
|
31626
|
+
prepare(model, options) {
|
|
31627
|
+
if (model.picture) this.map["xdr:pic"].prepare(model.picture, options);
|
|
31628
|
+
}
|
|
31629
|
+
render(xmlStream, model) {
|
|
31630
|
+
xmlStream.openNode(this.tag);
|
|
31631
|
+
this.map["xdr:pos"].render(xmlStream, model.range.pos ?? {
|
|
31632
|
+
x: 0,
|
|
31633
|
+
y: 0
|
|
31634
|
+
});
|
|
31635
|
+
this.map["xdr:ext"].render(xmlStream, model.range.ext);
|
|
31636
|
+
if (model.picture) this.map["xdr:pic"].render(xmlStream, model.picture);
|
|
31637
|
+
this.map["xdr:clientData"].render(xmlStream, {});
|
|
31638
|
+
xmlStream.closeNode();
|
|
31639
|
+
}
|
|
31640
|
+
parseClose(name) {
|
|
31641
|
+
if (this.parser) {
|
|
31642
|
+
if (!this.parser.parseClose(name)) this.parser = void 0;
|
|
31643
|
+
return true;
|
|
31644
|
+
}
|
|
31645
|
+
switch (name) {
|
|
31646
|
+
case this.tag:
|
|
31647
|
+
this.model.range.pos = this.map["xdr:pos"].model;
|
|
31648
|
+
this.model.range.ext = this.map["xdr:ext"].model;
|
|
31649
|
+
this.model.picture = this.map["xdr:pic"].model;
|
|
31650
|
+
return false;
|
|
31651
|
+
default: return true;
|
|
31652
|
+
}
|
|
31653
|
+
}
|
|
31654
|
+
reconcile(model, options) {
|
|
31655
|
+
model.medium = this.reconcilePicture(model.picture, options);
|
|
31656
|
+
}
|
|
31657
|
+
};
|
|
31658
|
+
//#endregion
|
|
31659
|
+
//#region src/modules/excel/xlsx/xform/drawing/cell-position-xform.ts
|
|
31660
|
+
var CellPositionXform = class extends BaseXform {
|
|
31661
|
+
constructor(options) {
|
|
31662
|
+
super();
|
|
31663
|
+
this.tag = options.tag;
|
|
31664
|
+
this.map = {
|
|
31665
|
+
"xdr:col": new IntegerXform({
|
|
31666
|
+
tag: "xdr:col",
|
|
31667
|
+
zero: true
|
|
31668
|
+
}),
|
|
31669
|
+
"xdr:colOff": new IntegerXform({
|
|
31670
|
+
tag: "xdr:colOff",
|
|
31671
|
+
zero: true
|
|
31672
|
+
}),
|
|
31673
|
+
"xdr:row": new IntegerXform({
|
|
31674
|
+
tag: "xdr:row",
|
|
31675
|
+
zero: true
|
|
31676
|
+
}),
|
|
31677
|
+
"xdr:rowOff": new IntegerXform({
|
|
31678
|
+
tag: "xdr:rowOff",
|
|
31679
|
+
zero: true
|
|
31680
|
+
})
|
|
31681
|
+
};
|
|
31682
|
+
this.model = {
|
|
31683
|
+
nativeCol: 0,
|
|
31684
|
+
nativeColOff: 0,
|
|
31685
|
+
nativeRow: 0,
|
|
31686
|
+
nativeRowOff: 0
|
|
31687
|
+
};
|
|
31688
|
+
}
|
|
31689
|
+
render(xmlStream, model) {
|
|
31690
|
+
xmlStream.openNode(this.tag);
|
|
31691
|
+
this.map["xdr:col"].render(xmlStream, model.nativeCol);
|
|
31692
|
+
this.map["xdr:colOff"].render(xmlStream, model.nativeColOff);
|
|
31693
|
+
this.map["xdr:row"].render(xmlStream, model.nativeRow);
|
|
31694
|
+
this.map["xdr:rowOff"].render(xmlStream, model.nativeRowOff);
|
|
31695
|
+
xmlStream.closeNode();
|
|
31696
|
+
}
|
|
31697
|
+
parseOpen(node) {
|
|
31698
|
+
if (this.parser) {
|
|
31699
|
+
this.parser.parseOpen(node);
|
|
31700
|
+
return true;
|
|
31701
|
+
}
|
|
31702
|
+
switch (node.name) {
|
|
31703
|
+
case this.tag:
|
|
31704
|
+
this.reset();
|
|
31705
|
+
break;
|
|
31706
|
+
default:
|
|
31707
|
+
this.parser = this.map[node.name];
|
|
31708
|
+
if (this.parser) this.parser.parseOpen(node);
|
|
31709
|
+
break;
|
|
31710
|
+
}
|
|
31711
|
+
return true;
|
|
31712
|
+
}
|
|
31713
|
+
parseText(text) {
|
|
31714
|
+
if (this.parser) this.parser.parseText(text);
|
|
31715
|
+
}
|
|
31716
|
+
parseClose(name) {
|
|
31717
|
+
if (this.parser) {
|
|
31718
|
+
if (!this.parser.parseClose(name)) this.parser = void 0;
|
|
31719
|
+
return true;
|
|
31720
|
+
}
|
|
31721
|
+
switch (name) {
|
|
31722
|
+
case this.tag:
|
|
31723
|
+
this.model = {
|
|
31724
|
+
nativeCol: this.map["xdr:col"].model,
|
|
31725
|
+
nativeColOff: this.map["xdr:colOff"].model,
|
|
31726
|
+
nativeRow: this.map["xdr:row"].model,
|
|
31727
|
+
nativeRowOff: this.map["xdr:rowOff"].model
|
|
31728
|
+
};
|
|
31729
|
+
return false;
|
|
31730
|
+
default: return true;
|
|
31731
|
+
}
|
|
31732
|
+
}
|
|
31733
|
+
};
|
|
31734
|
+
//#endregion
|
|
30732
31735
|
//#region src/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.ts
|
|
30733
31736
|
var OneCellAnchorXform = class extends BaseCellAnchorXform {
|
|
30734
31737
|
constructor() {
|
|
@@ -30961,14 +31964,17 @@ self.onmessage = async function(event) {
|
|
|
30961
31964
|
//#endregion
|
|
30962
31965
|
//#region src/modules/excel/xlsx/xform/drawing/drawing-xform.ts
|
|
30963
31966
|
function getAnchorType(model) {
|
|
30964
|
-
|
|
31967
|
+
const range = typeof model.range === "string" ? colCache.decode(model.range) : model.range;
|
|
31968
|
+
if (range.pos !== void 0) return "xdr:absoluteAnchor";
|
|
31969
|
+
return range.br ? "xdr:twoCellAnchor" : "xdr:oneCellAnchor";
|
|
30965
31970
|
}
|
|
30966
31971
|
var DrawingXform = class DrawingXform extends BaseXform {
|
|
30967
31972
|
constructor() {
|
|
30968
31973
|
super();
|
|
30969
31974
|
this.map = {
|
|
30970
31975
|
"xdr:twoCellAnchor": new TwoCellAnchorXform(),
|
|
30971
|
-
"xdr:oneCellAnchor": new OneCellAnchorXform()
|
|
31976
|
+
"xdr:oneCellAnchor": new OneCellAnchorXform(),
|
|
31977
|
+
"xdr:absoluteAnchor": new AbsoluteAnchorXform()
|
|
30972
31978
|
};
|
|
30973
31979
|
this.model = { anchors: [] };
|
|
30974
31980
|
}
|
|
@@ -31025,7 +32031,8 @@ self.onmessage = async function(event) {
|
|
|
31025
32031
|
}
|
|
31026
32032
|
reconcile(model, options) {
|
|
31027
32033
|
model.anchors.forEach((anchor) => {
|
|
31028
|
-
if (anchor.
|
|
32034
|
+
if (anchor.range?.pos !== void 0) this.map["xdr:absoluteAnchor"].reconcile(anchor, options);
|
|
32035
|
+
else if (anchor.br) this.map["xdr:twoCellAnchor"].reconcile(anchor, options);
|
|
31029
32036
|
else this.map["xdr:oneCellAnchor"].reconcile(anchor, options);
|
|
31030
32037
|
});
|
|
31031
32038
|
}
|
|
@@ -31308,6 +32315,7 @@ self.onmessage = async function(event) {
|
|
|
31308
32315
|
this.compressionLevel = Math.max(0, Math.min(9, level));
|
|
31309
32316
|
this.media = [];
|
|
31310
32317
|
this.commentRefs = [];
|
|
32318
|
+
this.dynamicArrayCount = 0;
|
|
31311
32319
|
this._trueStreaming = options.trueStreaming ?? false;
|
|
31312
32320
|
this.zip = new StreamingZip((err, data, final) => {
|
|
31313
32321
|
if (err) this.stream.emit("error", err);
|
|
@@ -31329,6 +32337,16 @@ self.onmessage = async function(event) {
|
|
|
31329
32337
|
get definedNames() {
|
|
31330
32338
|
return this._definedNames;
|
|
31331
32339
|
}
|
|
32340
|
+
/**
|
|
32341
|
+
* The default font for the workbook (fontId=0 / "Normal" style).
|
|
32342
|
+
* Must be set before any worksheet rows are committed.
|
|
32343
|
+
*/
|
|
32344
|
+
get defaultFont() {
|
|
32345
|
+
return this.styles.defaultFont;
|
|
32346
|
+
}
|
|
32347
|
+
set defaultFont(font) {
|
|
32348
|
+
if (this.styles.setDefaultFont) this.styles.setDefaultFont(font);
|
|
32349
|
+
}
|
|
31332
32350
|
/** @internal */
|
|
31333
32351
|
_openStream(path) {
|
|
31334
32352
|
const stream = new StreamBuf({
|
|
@@ -31380,6 +32398,7 @@ self.onmessage = async function(event) {
|
|
|
31380
32398
|
this.addSharedStrings(),
|
|
31381
32399
|
this.addStyles(),
|
|
31382
32400
|
this.addFeaturePropertyBag(),
|
|
32401
|
+
this.addMetadata(),
|
|
31383
32402
|
this.addWorkbookRels()
|
|
31384
32403
|
]);
|
|
31385
32404
|
await this.addWorkbook();
|
|
@@ -31402,6 +32421,19 @@ self.onmessage = async function(event) {
|
|
|
31402
32421
|
getImage(id) {
|
|
31403
32422
|
return this.media[id];
|
|
31404
32423
|
}
|
|
32424
|
+
/**
|
|
32425
|
+
* Protect the workbook structure with an optional password.
|
|
32426
|
+
* Prevents users from adding, deleting, renaming, moving, or copying worksheets.
|
|
32427
|
+
*/
|
|
32428
|
+
async protect(password, options) {
|
|
32429
|
+
this.protection = await buildWorkbookProtection(password, options);
|
|
32430
|
+
}
|
|
32431
|
+
/**
|
|
32432
|
+
* Remove workbook structure protection.
|
|
32433
|
+
*/
|
|
32434
|
+
unprotect() {
|
|
32435
|
+
this.protection = void 0;
|
|
32436
|
+
}
|
|
31405
32437
|
addWorksheet(name, options) {
|
|
31406
32438
|
const opts = options || {};
|
|
31407
32439
|
const useSharedStrings = opts.useSharedStrings !== void 0 ? opts.useSharedStrings : this.useSharedStrings;
|
|
@@ -31485,7 +32517,8 @@ self.onmessage = async function(event) {
|
|
|
31485
32517
|
commentRefs: this.commentRefs,
|
|
31486
32518
|
media: this.media,
|
|
31487
32519
|
drawings,
|
|
31488
|
-
hasCheckboxes: this.styles.hasCheckboxes
|
|
32520
|
+
hasCheckboxes: this.styles.hasCheckboxes,
|
|
32521
|
+
hasDynamicArrayFormulas: this.dynamicArrayCount > 0
|
|
31489
32522
|
};
|
|
31490
32523
|
const xform = new ContentTypesXform();
|
|
31491
32524
|
this._addFile(xform.toXml(model), OOXML_PATHS.contentTypes);
|
|
@@ -31565,6 +32598,12 @@ self.onmessage = async function(event) {
|
|
|
31565
32598
|
}
|
|
31566
32599
|
return Promise.resolve();
|
|
31567
32600
|
}
|
|
32601
|
+
addMetadata() {
|
|
32602
|
+
if (this.dynamicArrayCount <= 0) return Promise.resolve();
|
|
32603
|
+
const xform = new MetadataXform();
|
|
32604
|
+
this._addFile(xform.toXml({ dynamicArrayCount: this.dynamicArrayCount }), OOXML_PATHS.xlMetadata);
|
|
32605
|
+
return Promise.resolve();
|
|
32606
|
+
}
|
|
31568
32607
|
addWorkbookRels() {
|
|
31569
32608
|
let count = 1;
|
|
31570
32609
|
const relationships = [{
|
|
@@ -31586,6 +32625,11 @@ self.onmessage = async function(event) {
|
|
|
31586
32625
|
Type: RelType.FeaturePropertyBag,
|
|
31587
32626
|
Target: OOXML_REL_TARGETS.workbookFeaturePropertyBag
|
|
31588
32627
|
});
|
|
32628
|
+
if (this.dynamicArrayCount > 0) relationships.push({
|
|
32629
|
+
Id: `rId${count++}`,
|
|
32630
|
+
Type: RelType.SheetMetadata,
|
|
32631
|
+
Target: OOXML_REL_TARGETS.workbookMetadata
|
|
32632
|
+
});
|
|
31589
32633
|
this._worksheets.forEach((ws) => {
|
|
31590
32634
|
if (ws) {
|
|
31591
32635
|
ws.rId = `rId${count++}`;
|
|
@@ -31608,6 +32652,7 @@ self.onmessage = async function(event) {
|
|
|
31608
32652
|
definedNames: this._definedNames.model,
|
|
31609
32653
|
views: this.views,
|
|
31610
32654
|
properties: {},
|
|
32655
|
+
protection: this.protection,
|
|
31611
32656
|
calcProperties: {}
|
|
31612
32657
|
};
|
|
31613
32658
|
return new Promise((resolve) => {
|
|
@@ -31922,6 +32967,21 @@ self.onmessage = async function(event) {
|
|
|
31922
32967
|
case "image": {
|
|
31923
32968
|
const range = this.range;
|
|
31924
32969
|
if (!range) throw new ImageError("Image has no range");
|
|
32970
|
+
if (range.pos) return {
|
|
32971
|
+
type: this.type,
|
|
32972
|
+
imageId: this.imageId ?? "",
|
|
32973
|
+
hyperlinks: range.hyperlinks,
|
|
32974
|
+
range: {
|
|
32975
|
+
tl: {
|
|
32976
|
+
nativeCol: 0,
|
|
32977
|
+
nativeColOff: 0,
|
|
32978
|
+
nativeRow: 0,
|
|
32979
|
+
nativeRowOff: 0
|
|
32980
|
+
},
|
|
32981
|
+
ext: range.ext,
|
|
32982
|
+
pos: range.pos
|
|
32983
|
+
}
|
|
32984
|
+
};
|
|
31925
32985
|
return {
|
|
31926
32986
|
type: this.type,
|
|
31927
32987
|
imageId: this.imageId ?? "",
|
|
@@ -31958,7 +33018,13 @@ self.onmessage = async function(event) {
|
|
|
31958
33018
|
}, 0),
|
|
31959
33019
|
editAs: "oneCell"
|
|
31960
33020
|
};
|
|
31961
|
-
} else if (range) this.range = {
|
|
33021
|
+
} else if (range && "pos" in range && range.pos) this.range = {
|
|
33022
|
+
tl: new Anchor(this.worksheet, null, 0),
|
|
33023
|
+
ext: range.ext,
|
|
33024
|
+
hyperlinks: hyperlinks || ("hyperlinks" in range ? range.hyperlinks : void 0),
|
|
33025
|
+
pos: range.pos
|
|
33026
|
+
};
|
|
33027
|
+
else if (range) this.range = {
|
|
31962
33028
|
tl: new Anchor(this.worksheet, range.tl, 0),
|
|
31963
33029
|
br: range.br ? new Anchor(this.worksheet, range.br, 0) : void 0,
|
|
31964
33030
|
ext: range.ext,
|
|
@@ -31981,7 +33047,8 @@ self.onmessage = async function(event) {
|
|
|
31981
33047
|
br: this.range.br ? this.range.br.clone(target) : void 0,
|
|
31982
33048
|
ext: this.range.ext ? { ...this.range.ext } : void 0,
|
|
31983
33049
|
editAs: this.range.editAs,
|
|
31984
|
-
hyperlinks: this.range.hyperlinks ? { ...this.range.hyperlinks } : void 0
|
|
33050
|
+
hyperlinks: this.range.hyperlinks ? { ...this.range.hyperlinks } : void 0,
|
|
33051
|
+
pos: this.range.pos ? { ...this.range.pos } : void 0
|
|
31985
33052
|
};
|
|
31986
33053
|
return cloned;
|
|
31987
33054
|
}
|
|
@@ -32436,8 +33503,8 @@ self.onmessage = async function(event) {
|
|
|
32436
33503
|
count: 103,
|
|
32437
33504
|
max: 104,
|
|
32438
33505
|
min: 105,
|
|
32439
|
-
stdDev:
|
|
32440
|
-
var:
|
|
33506
|
+
stdDev: 107,
|
|
33507
|
+
var: 110,
|
|
32441
33508
|
sum: 109
|
|
32442
33509
|
};
|
|
32443
33510
|
}
|
|
@@ -37779,7 +38846,7 @@ self.onmessage = async function(event) {
|
|
|
37779
38846
|
function getCellTextWidthPx(cell) {
|
|
37780
38847
|
const cellType = cell.effectiveType;
|
|
37781
38848
|
const font = cell.font;
|
|
37782
|
-
if (cellType ===
|
|
38849
|
+
if (cellType === 8) {
|
|
37783
38850
|
const value = cell.value;
|
|
37784
38851
|
if (value && typeof value === "object" && "richText" in value) return measureRichTextWidthPx(value.richText, font);
|
|
37785
38852
|
}
|
|
@@ -37799,7 +38866,7 @@ self.onmessage = async function(event) {
|
|
|
37799
38866
|
function getCellHeightPt(cell, mdw, columnWidthPx) {
|
|
37800
38867
|
const font = cell.font;
|
|
37801
38868
|
const alignment = cell.alignment;
|
|
37802
|
-
if (cell.effectiveType ===
|
|
38869
|
+
if (cell.effectiveType === 8) {
|
|
37803
38870
|
const value = cell.value;
|
|
37804
38871
|
if (value && typeof value === "object" && "richText" in value) return calculateRichTextAutoFitHeight(value.richText, font, alignment, columnWidthPx);
|
|
37805
38872
|
}
|
|
@@ -37879,6 +38946,7 @@ self.onmessage = async function(event) {
|
|
|
37879
38946
|
this.pivotTables = [];
|
|
37880
38947
|
this.conditionalFormattings = [];
|
|
37881
38948
|
this.formControls = [];
|
|
38949
|
+
this.ignoredErrors = [];
|
|
37882
38950
|
this._watermark = null;
|
|
37883
38951
|
}
|
|
37884
38952
|
get name() {
|
|
@@ -37992,7 +39060,7 @@ self.onmessage = async function(event) {
|
|
|
37992
39060
|
spliceColumns(start, count, ...inserts) {
|
|
37993
39061
|
for (const merge of Object.values(this._merges)) for (let r = merge.top; r <= merge.bottom; r++) for (let c = merge.left; c <= merge.right; c++) {
|
|
37994
39062
|
const cell = this.findCell(r, c);
|
|
37995
|
-
if (cell && cell.type ===
|
|
39063
|
+
if (cell && cell.type === 1) cell.unmerge();
|
|
37996
39064
|
}
|
|
37997
39065
|
const nRows = this._rows.length;
|
|
37998
39066
|
if (inserts.length > 0) for (let i = 0; i < nRows; i++) {
|
|
@@ -38215,7 +39283,7 @@ self.onmessage = async function(event) {
|
|
|
38215
39283
|
spliceRows(start, count, ...inserts) {
|
|
38216
39284
|
for (const merge of Object.values(this._merges)) for (let r = merge.top; r <= merge.bottom; r++) for (let c = merge.left; c <= merge.right; c++) {
|
|
38217
39285
|
const cell = this.findCell(r, c);
|
|
38218
|
-
if (cell && cell.type ===
|
|
39286
|
+
if (cell && cell.type === 1) cell.unmerge();
|
|
38219
39287
|
}
|
|
38220
39288
|
const nKeep = start + count;
|
|
38221
39289
|
const nInserts = inserts.length;
|
|
@@ -38403,7 +39471,7 @@ self.onmessage = async function(event) {
|
|
|
38403
39471
|
for (let i = dimensions.top; i <= dimensions.bottom; i++) for (let j = dimensions.left; j <= dimensions.right; j++) {
|
|
38404
39472
|
const cell = this.findCell(i, j);
|
|
38405
39473
|
if (cell) {
|
|
38406
|
-
if (cell.type ===
|
|
39474
|
+
if (cell.type === 1) this._unMergeMaster(cell.master);
|
|
38407
39475
|
else if (this._merges[cell.address]) this._unMergeMaster(cell);
|
|
38408
39476
|
}
|
|
38409
39477
|
}
|
|
@@ -38578,7 +39646,11 @@ self.onmessage = async function(event) {
|
|
|
38578
39646
|
*/
|
|
38579
39647
|
addTable(model) {
|
|
38580
39648
|
const table = new Table(this, model);
|
|
39649
|
+
const nameKey = table.name.toLowerCase();
|
|
39650
|
+
if (this.tables[table.name]) throw new TableError(`Table name "${table.name}" already exists in worksheet "${this.name}".`);
|
|
39651
|
+
if (this.workbook._tableNames.has(nameKey)) throw new TableError(`Table name "${table.name}" already exists in another worksheet. Table names must be unique across the entire workbook (case-insensitive).`);
|
|
38581
39652
|
this.tables[table.name] = table;
|
|
39653
|
+
this.workbook._tableNames.add(nameKey);
|
|
38582
39654
|
return table;
|
|
38583
39655
|
}
|
|
38584
39656
|
/**
|
|
@@ -38591,6 +39663,7 @@ self.onmessage = async function(event) {
|
|
|
38591
39663
|
* Delete table by name
|
|
38592
39664
|
*/
|
|
38593
39665
|
removeTable(name) {
|
|
39666
|
+
if (this.tables[name]) this.workbook._tableNames.delete(name.toLowerCase());
|
|
38594
39667
|
delete this.tables[name];
|
|
38595
39668
|
}
|
|
38596
39669
|
/**
|
|
@@ -38684,7 +39757,7 @@ self.onmessage = async function(event) {
|
|
|
38684
39757
|
if (row.hidden) return;
|
|
38685
39758
|
const cell = row.findCell(colNum);
|
|
38686
39759
|
if (!cell) return;
|
|
38687
|
-
if (cell.type ===
|
|
39760
|
+
if (cell.type === 1) return;
|
|
38688
39761
|
if (cell.isMerged) {
|
|
38689
39762
|
const mergeRange = this._merges[cell.address];
|
|
38690
39763
|
if (mergeRange && mergeRange.left !== mergeRange.right) return;
|
|
@@ -38711,7 +39784,7 @@ self.onmessage = async function(event) {
|
|
|
38711
39784
|
const mdw = getMaxDigitWidth();
|
|
38712
39785
|
let maxHeightPt = 0;
|
|
38713
39786
|
row.eachCell((cell) => {
|
|
38714
|
-
if (cell.type ===
|
|
39787
|
+
if (cell.type === 1) return;
|
|
38715
39788
|
if (cell.isMerged) {
|
|
38716
39789
|
const mergeRange = this._merges[cell.address];
|
|
38717
39790
|
if (mergeRange && mergeRange.top !== mergeRange.bottom) return;
|
|
@@ -38765,6 +39838,7 @@ self.onmessage = async function(event) {
|
|
|
38765
39838
|
pivotTables: this.pivotTables,
|
|
38766
39839
|
conditionalFormattings: this.conditionalFormattings,
|
|
38767
39840
|
formControls: this.formControls.map((fc) => fc.model),
|
|
39841
|
+
ignoredErrors: this.ignoredErrors,
|
|
38768
39842
|
watermark: this._watermark,
|
|
38769
39843
|
drawing: this._drawing
|
|
38770
39844
|
};
|
|
@@ -38833,10 +39907,12 @@ self.onmessage = async function(event) {
|
|
|
38833
39907
|
const t = new Table(this, table);
|
|
38834
39908
|
t.model = table;
|
|
38835
39909
|
tables[table.name] = t;
|
|
39910
|
+
this.workbook._tableNames.add(table.name.toLowerCase());
|
|
38836
39911
|
return tables;
|
|
38837
39912
|
}, {});
|
|
38838
39913
|
this.pivotTables = value.pivotTables;
|
|
38839
39914
|
this.conditionalFormattings = value.conditionalFormattings;
|
|
39915
|
+
this.ignoredErrors = value.ignoredErrors ?? [];
|
|
38840
39916
|
this.formControls = [];
|
|
38841
39917
|
this._drawing = value.drawing;
|
|
38842
39918
|
}
|
|
@@ -39673,6 +40749,144 @@ self.onmessage = async function(event) {
|
|
|
39673
40749
|
}
|
|
39674
40750
|
};
|
|
39675
40751
|
//#endregion
|
|
40752
|
+
//#region src/modules/excel/utils/external-link-formula.ts
|
|
40753
|
+
/**
|
|
40754
|
+
* Utilities for manipulating the external-workbook prefix in formula strings.
|
|
40755
|
+
*
|
|
40756
|
+
* Excel formula strings containing external workbook references have the
|
|
40757
|
+
* shape `[<workbook>]Sheet!Ref` where `<workbook>` is either
|
|
40758
|
+
*
|
|
40759
|
+
* - a 1-based numeric index — `[1]Sheet1!A1` (the canonical on-disk form
|
|
40760
|
+
* stored inside `<f>` elements of worksheet XML), or
|
|
40761
|
+
* - a filename / relative path — `[测试.xlsx]Sheet1!A1` (what Excel
|
|
40762
|
+
* displays in the formula bar; not part of the OOXML storage contract,
|
|
40763
|
+
* but produced by hand-written formulas and some older tools).
|
|
40764
|
+
*
|
|
40765
|
+
* When writing, excelts always emits the numeric form — indices map
|
|
40766
|
+
* positionally into the workbook's `<externalReferences>` list. When a
|
|
40767
|
+
* formula arrives with the filename form, the writer assigns (or reuses) an
|
|
40768
|
+
* ExternalLinkModel with that filename as its `target` and rewrites the
|
|
40769
|
+
* formula to the numeric form. This matches how Excel itself stores formulas
|
|
40770
|
+
* and makes them round-trippable.
|
|
40771
|
+
*
|
|
40772
|
+
* The quoted variant `'[file.xlsx]Sheet with space'!A1` is handled too — Excel
|
|
40773
|
+
* wraps the `[name]Sheet` segment in single quotes when the sheet name needs
|
|
40774
|
+
* quoting. The matching logic here recognises both the unquoted and quoted
|
|
40775
|
+
* forms, rewriting inside the quotes when needed.
|
|
40776
|
+
*
|
|
40777
|
+
* Edge cases we explicitly *do not* treat as external refs:
|
|
40778
|
+
* - `[@Column]`, `[#Headers]`, `[Column Name]` — table structured refs
|
|
40779
|
+
* (no `]Sheet!` tail). The regex requires the `]<sheet>!` follow-up,
|
|
40780
|
+
* which structured refs never have.
|
|
40781
|
+
* - Array literals `{1,2;3,4}` use `{}`, not `[]`.
|
|
40782
|
+
* - String literals `"[Book]Sheet!A1"` — handled by scanning only outside
|
|
40783
|
+
* string literal regions.
|
|
40784
|
+
*/
|
|
40785
|
+
const UNQUOTED_EXTERNAL_REF = /\[([^\]\\/:*?"<>|\s]+)\]([A-Za-z_\u00A1-\uFFFF][A-Za-z0-9_\u00A1-\uFFFF.]*)!/g;
|
|
40786
|
+
const QUOTED_EXTERNAL_REF = /'\[([^\]]+)\]((?:''|[^'])+)'!/g;
|
|
40787
|
+
/**
|
|
40788
|
+
* Scan a formula string for all external-workbook references. String
|
|
40789
|
+
* literals (inside `"..."`) are skipped so that a string value like
|
|
40790
|
+
* `"[Book]Sheet!A1"` is not misidentified as a ref.
|
|
40791
|
+
*
|
|
40792
|
+
* The returned matches are in source order. If a formula contains no
|
|
40793
|
+
* external refs, the array is empty.
|
|
40794
|
+
*/
|
|
40795
|
+
function findExternalRefs(formula) {
|
|
40796
|
+
if (formula.indexOf("[") === -1) return [];
|
|
40797
|
+
const matches = [];
|
|
40798
|
+
const safeRegions = stringLiteralRegions(formula);
|
|
40799
|
+
const addMatch = (start, end, workbook, sheet, quoted, match) => {
|
|
40800
|
+
if (insideAnyRegion(start, safeRegions)) return;
|
|
40801
|
+
const numeric = /^\d+$/.test(workbook);
|
|
40802
|
+
matches.push({
|
|
40803
|
+
match,
|
|
40804
|
+
workbook,
|
|
40805
|
+
numeric,
|
|
40806
|
+
index: numeric ? parseInt(workbook, 10) : null,
|
|
40807
|
+
sheet: unquoteSheetName(sheet),
|
|
40808
|
+
quoted,
|
|
40809
|
+
start,
|
|
40810
|
+
end
|
|
40811
|
+
});
|
|
40812
|
+
};
|
|
40813
|
+
UNQUOTED_EXTERNAL_REF.lastIndex = 0;
|
|
40814
|
+
let m;
|
|
40815
|
+
while ((m = UNQUOTED_EXTERNAL_REF.exec(formula)) !== null) addMatch(m.index, m.index + m[0].length, m[1], m[2], false, m[0]);
|
|
40816
|
+
QUOTED_EXTERNAL_REF.lastIndex = 0;
|
|
40817
|
+
while ((m = QUOTED_EXTERNAL_REF.exec(formula)) !== null) addMatch(m.index, m.index + m[0].length, m[1], m[2], true, m[0]);
|
|
40818
|
+
matches.sort((a, b) => a.start - b.start);
|
|
40819
|
+
const out = [];
|
|
40820
|
+
let lastEnd = -1;
|
|
40821
|
+
for (const ref of matches) if (ref.start >= lastEnd) {
|
|
40822
|
+
out.push(ref);
|
|
40823
|
+
lastEnd = ref.end;
|
|
40824
|
+
}
|
|
40825
|
+
return out;
|
|
40826
|
+
}
|
|
40827
|
+
/**
|
|
40828
|
+
* Replace every external-workbook token in `formula` using the supplied
|
|
40829
|
+
* resolver. The resolver is called once per match and returns the numeric
|
|
40830
|
+
* index to substitute; returning `null` leaves the match unchanged (useful
|
|
40831
|
+
* when the caller cannot resolve a particular filename).
|
|
40832
|
+
*
|
|
40833
|
+
* Returns the rewritten formula. Offsets inside the original formula are
|
|
40834
|
+
* adjusted correctly even when multiple rewrites change the total length.
|
|
40835
|
+
*/
|
|
40836
|
+
function rewriteExternalRefs(formula, resolve) {
|
|
40837
|
+
const refs = findExternalRefs(formula);
|
|
40838
|
+
if (refs.length === 0) return formula;
|
|
40839
|
+
let out = "";
|
|
40840
|
+
let cursor = 0;
|
|
40841
|
+
for (const ref of refs) {
|
|
40842
|
+
const index = resolve(ref);
|
|
40843
|
+
if (index === null) continue;
|
|
40844
|
+
out += formula.slice(cursor, ref.start);
|
|
40845
|
+
if (ref.quoted) {
|
|
40846
|
+
const inner = formula.slice(ref.start + 1, ref.end - 2);
|
|
40847
|
+
out += "'" + inner.replace(/^\[[^\]]*\]/, `[${index}]`) + "'!";
|
|
40848
|
+
} else out += `[${index}]${ref.match.slice(ref.match.indexOf("]") + 1)}`;
|
|
40849
|
+
cursor = ref.end;
|
|
40850
|
+
}
|
|
40851
|
+
out += formula.slice(cursor);
|
|
40852
|
+
return out;
|
|
40853
|
+
}
|
|
40854
|
+
/**
|
|
40855
|
+
* Return the spans of string literal regions in a formula, as half-open
|
|
40856
|
+
* [start, end) intervals (exclusive of the surrounding quotes themselves).
|
|
40857
|
+
* Used to skip external-ref matches that fall inside a string value.
|
|
40858
|
+
*/
|
|
40859
|
+
function stringLiteralRegions(formula) {
|
|
40860
|
+
if (formula.indexOf("\"") === -1) return [];
|
|
40861
|
+
const regions = [];
|
|
40862
|
+
const len = formula.length;
|
|
40863
|
+
let i = 0;
|
|
40864
|
+
while (i < len) if (formula[i] === "\"") {
|
|
40865
|
+
const start = i;
|
|
40866
|
+
i++;
|
|
40867
|
+
while (i < len) {
|
|
40868
|
+
if (formula[i] === "\"") {
|
|
40869
|
+
if (i + 1 < len && formula[i + 1] === "\"") {
|
|
40870
|
+
i += 2;
|
|
40871
|
+
continue;
|
|
40872
|
+
}
|
|
40873
|
+
i++;
|
|
40874
|
+
break;
|
|
40875
|
+
}
|
|
40876
|
+
i++;
|
|
40877
|
+
}
|
|
40878
|
+
regions.push([start, i]);
|
|
40879
|
+
} else i++;
|
|
40880
|
+
return regions;
|
|
40881
|
+
}
|
|
40882
|
+
function insideAnyRegion(pos, regions) {
|
|
40883
|
+
for (const [a, b] of regions) if (pos >= a && pos < b) return true;
|
|
40884
|
+
return false;
|
|
40885
|
+
}
|
|
40886
|
+
function unquoteSheetName(sheet) {
|
|
40887
|
+
return sheet.replace(/''/g, "'");
|
|
40888
|
+
}
|
|
40889
|
+
//#endregion
|
|
39676
40890
|
//#region src/modules/excel/utils/passthrough-manager.ts
|
|
39677
40891
|
/**
|
|
39678
40892
|
* Content type definitions for passthrough files
|
|
@@ -39781,6 +40995,232 @@ self.onmessage = async function(event) {
|
|
|
39781
40995
|
}
|
|
39782
40996
|
};
|
|
39783
40997
|
//#endregion
|
|
40998
|
+
//#region src/modules/excel/xlsx/xform/book/external-link-xform.ts
|
|
40999
|
+
/** Pretty attribute constant used on the root element. */
|
|
41000
|
+
const ROOT_ATTRIBUTES = {
|
|
41001
|
+
xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
|
41002
|
+
"xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
41003
|
+
};
|
|
41004
|
+
var ExternalLinkXform = class extends BaseXform {
|
|
41005
|
+
constructor(..._args) {
|
|
41006
|
+
super(..._args);
|
|
41007
|
+
this.sheetNamesByIndex = [];
|
|
41008
|
+
this.currentSheetCells = null;
|
|
41009
|
+
this.currentSheetName = null;
|
|
41010
|
+
this.currentCellAddress = null;
|
|
41011
|
+
this.currentCellType = "n";
|
|
41012
|
+
this.currentCellValue = null;
|
|
41013
|
+
this.inV = false;
|
|
41014
|
+
}
|
|
41015
|
+
get tag() {
|
|
41016
|
+
return "externalLink";
|
|
41017
|
+
}
|
|
41018
|
+
reset() {
|
|
41019
|
+
super.reset();
|
|
41020
|
+
this.sheetNamesByIndex = [];
|
|
41021
|
+
this.currentSheetCells = null;
|
|
41022
|
+
this.currentSheetName = null;
|
|
41023
|
+
this.currentCellAddress = null;
|
|
41024
|
+
this.currentCellType = "n";
|
|
41025
|
+
this.currentCellValue = null;
|
|
41026
|
+
this.inV = false;
|
|
41027
|
+
}
|
|
41028
|
+
render(xmlStream, model) {
|
|
41029
|
+
xmlStream.openXml(StdDocAttributes);
|
|
41030
|
+
xmlStream.openNode("externalLink", ROOT_ATTRIBUTES);
|
|
41031
|
+
xmlStream.openNode("externalBook", { "r:id": "rId1" });
|
|
41032
|
+
if (model.sheetNames.length > 0) {
|
|
41033
|
+
xmlStream.openNode("sheetNames");
|
|
41034
|
+
for (const name of model.sheetNames) xmlStream.leafNode("sheetName", { val: name });
|
|
41035
|
+
xmlStream.closeNode();
|
|
41036
|
+
}
|
|
41037
|
+
const cache = model.cachedValues ?? {};
|
|
41038
|
+
if (Object.keys(cache).some((name) => {
|
|
41039
|
+
const sheet = cache[name];
|
|
41040
|
+
return sheet && Object.keys(sheet).length > 0;
|
|
41041
|
+
})) {
|
|
41042
|
+
xmlStream.openNode("sheetDataSet");
|
|
41043
|
+
for (let i = 0; i < model.sheetNames.length; i++) {
|
|
41044
|
+
const cells = cache[model.sheetNames[i]];
|
|
41045
|
+
if (!cells || Object.keys(cells).length === 0) continue;
|
|
41046
|
+
renderSheetData(xmlStream, i, cells);
|
|
41047
|
+
}
|
|
41048
|
+
xmlStream.closeNode();
|
|
41049
|
+
}
|
|
41050
|
+
xmlStream.closeNode();
|
|
41051
|
+
xmlStream.closeNode();
|
|
41052
|
+
}
|
|
41053
|
+
parseOpen(node) {
|
|
41054
|
+
switch (node.name) {
|
|
41055
|
+
case "externalLink":
|
|
41056
|
+
this.model = {
|
|
41057
|
+
externalBookRId: "",
|
|
41058
|
+
sheetNames: [],
|
|
41059
|
+
cachedValues: {}
|
|
41060
|
+
};
|
|
41061
|
+
this.sheetNamesByIndex = [];
|
|
41062
|
+
return true;
|
|
41063
|
+
case "externalBook":
|
|
41064
|
+
if (this.model) this.model.externalBookRId = node.attributes["r:id"] ?? "";
|
|
41065
|
+
return true;
|
|
41066
|
+
case "sheetName":
|
|
41067
|
+
if (this.model) {
|
|
41068
|
+
const val = node.attributes.val ?? "";
|
|
41069
|
+
this.model.sheetNames.push(val);
|
|
41070
|
+
this.sheetNamesByIndex.push(val);
|
|
41071
|
+
}
|
|
41072
|
+
return true;
|
|
41073
|
+
case "sheetData": {
|
|
41074
|
+
const sheetIdRaw = node.attributes.sheetId;
|
|
41075
|
+
const sheetId = sheetIdRaw !== void 0 ? parseInt(sheetIdRaw, 10) : NaN;
|
|
41076
|
+
this.currentSheetName = Number.isFinite(sheetId) ? this.sheetNamesByIndex[sheetId] ?? null : null;
|
|
41077
|
+
this.currentSheetCells = this.currentSheetName ? {} : null;
|
|
41078
|
+
return true;
|
|
41079
|
+
}
|
|
41080
|
+
case "cell":
|
|
41081
|
+
this.currentCellAddress = node.attributes.r ?? null;
|
|
41082
|
+
this.currentCellType = node.attributes.t ?? "n";
|
|
41083
|
+
this.currentCellValue = null;
|
|
41084
|
+
return true;
|
|
41085
|
+
case "v":
|
|
41086
|
+
this.inV = true;
|
|
41087
|
+
this.currentCellValue = "";
|
|
41088
|
+
return true;
|
|
41089
|
+
default: return false;
|
|
41090
|
+
}
|
|
41091
|
+
}
|
|
41092
|
+
parseText(text) {
|
|
41093
|
+
if (this.inV) this.currentCellValue = (this.currentCellValue ?? "") + text;
|
|
41094
|
+
}
|
|
41095
|
+
parseClose(name) {
|
|
41096
|
+
switch (name) {
|
|
41097
|
+
case "v":
|
|
41098
|
+
this.inV = false;
|
|
41099
|
+
return true;
|
|
41100
|
+
case "cell":
|
|
41101
|
+
if (this.model && this.currentSheetCells && this.currentCellAddress) this.currentSheetCells[this.currentCellAddress.toUpperCase()] = decodePrimitive(this.currentCellType, this.currentCellValue);
|
|
41102
|
+
this.currentCellAddress = null;
|
|
41103
|
+
this.currentCellType = "n";
|
|
41104
|
+
this.currentCellValue = null;
|
|
41105
|
+
return true;
|
|
41106
|
+
case "sheetData":
|
|
41107
|
+
if (this.model && this.currentSheetName && this.currentSheetCells && Object.keys(this.currentSheetCells).length > 0) this.model.cachedValues[this.currentSheetName] = this.currentSheetCells;
|
|
41108
|
+
this.currentSheetName = null;
|
|
41109
|
+
this.currentSheetCells = null;
|
|
41110
|
+
return true;
|
|
41111
|
+
case "externalLink": return false;
|
|
41112
|
+
default: return true;
|
|
41113
|
+
}
|
|
41114
|
+
}
|
|
41115
|
+
};
|
|
41116
|
+
function renderSheetData(xmlStream, sheetIdx, cells) {
|
|
41117
|
+
const rows = groupByRow(cells);
|
|
41118
|
+
xmlStream.openNode("sheetData", { sheetId: sheetIdx });
|
|
41119
|
+
for (const row of rows) {
|
|
41120
|
+
xmlStream.openNode("row", { r: row.rowNum });
|
|
41121
|
+
for (const { address, value } of row.cells) renderCell(xmlStream, address, value);
|
|
41122
|
+
xmlStream.closeNode();
|
|
41123
|
+
}
|
|
41124
|
+
xmlStream.closeNode();
|
|
41125
|
+
}
|
|
41126
|
+
function groupByRow(cells) {
|
|
41127
|
+
const byRow = /* @__PURE__ */ new Map();
|
|
41128
|
+
for (const rawAddress of Object.keys(cells)) {
|
|
41129
|
+
const address = rawAddress.toUpperCase();
|
|
41130
|
+
const rowNum = extractRowNumber(address);
|
|
41131
|
+
if (rowNum === void 0) continue;
|
|
41132
|
+
let bucket = byRow.get(rowNum);
|
|
41133
|
+
if (!bucket) {
|
|
41134
|
+
bucket = {
|
|
41135
|
+
rowNum,
|
|
41136
|
+
cells: []
|
|
41137
|
+
};
|
|
41138
|
+
byRow.set(rowNum, bucket);
|
|
41139
|
+
}
|
|
41140
|
+
bucket.cells.push({
|
|
41141
|
+
address: stripAbsoluteMarkers(address),
|
|
41142
|
+
value: cells[rawAddress]
|
|
41143
|
+
});
|
|
41144
|
+
}
|
|
41145
|
+
return [...byRow.values()].sort((a, b) => a.rowNum - b.rowNum);
|
|
41146
|
+
}
|
|
41147
|
+
function extractRowNumber(address) {
|
|
41148
|
+
const match = /^\$?[A-Z]+\$?(\d+)$/.exec(address);
|
|
41149
|
+
return match ? parseInt(match[1], 10) : void 0;
|
|
41150
|
+
}
|
|
41151
|
+
function stripAbsoluteMarkers(address) {
|
|
41152
|
+
return address.replace(/\$/g, "");
|
|
41153
|
+
}
|
|
41154
|
+
function renderCell(xmlStream, address, value) {
|
|
41155
|
+
if (value === null || value === void 0) {
|
|
41156
|
+
xmlStream.leafNode("cell", { r: address });
|
|
41157
|
+
return;
|
|
41158
|
+
}
|
|
41159
|
+
if (typeof value === "number") {
|
|
41160
|
+
xmlStream.openNode("cell", { r: address });
|
|
41161
|
+
xmlStream.leafNode("v", void 0, String(value));
|
|
41162
|
+
xmlStream.closeNode();
|
|
41163
|
+
return;
|
|
41164
|
+
}
|
|
41165
|
+
if (typeof value === "boolean") {
|
|
41166
|
+
xmlStream.openNode("cell", {
|
|
41167
|
+
r: address,
|
|
41168
|
+
t: "b"
|
|
41169
|
+
});
|
|
41170
|
+
xmlStream.leafNode("v", void 0, value ? "1" : "0");
|
|
41171
|
+
xmlStream.closeNode();
|
|
41172
|
+
return;
|
|
41173
|
+
}
|
|
41174
|
+
if (isErrorLiteral(value)) {
|
|
41175
|
+
xmlStream.openNode("cell", {
|
|
41176
|
+
r: address,
|
|
41177
|
+
t: "e"
|
|
41178
|
+
});
|
|
41179
|
+
xmlStream.leafNode("v", void 0, value);
|
|
41180
|
+
xmlStream.closeNode();
|
|
41181
|
+
return;
|
|
41182
|
+
}
|
|
41183
|
+
xmlStream.openNode("cell", {
|
|
41184
|
+
r: address,
|
|
41185
|
+
t: "str"
|
|
41186
|
+
});
|
|
41187
|
+
xmlStream.leafNode("v", void 0, value);
|
|
41188
|
+
xmlStream.closeNode();
|
|
41189
|
+
}
|
|
41190
|
+
/** Excel error literals that should be written with `t="e"`. */
|
|
41191
|
+
const ERROR_LITERALS = new Set([
|
|
41192
|
+
"#NULL!",
|
|
41193
|
+
"#DIV/0!",
|
|
41194
|
+
"#VALUE!",
|
|
41195
|
+
"#REF!",
|
|
41196
|
+
"#NAME?",
|
|
41197
|
+
"#NUM!",
|
|
41198
|
+
"#N/A",
|
|
41199
|
+
"#GETTING_DATA",
|
|
41200
|
+
"#SPILL!",
|
|
41201
|
+
"#CALC!",
|
|
41202
|
+
"#CONNECT!",
|
|
41203
|
+
"#BLOCKED!",
|
|
41204
|
+
"#UNKNOWN!",
|
|
41205
|
+
"#FIELD!",
|
|
41206
|
+
"#PYTHON!"
|
|
41207
|
+
]);
|
|
41208
|
+
function isErrorLiteral(value) {
|
|
41209
|
+
return ERROR_LITERALS.has(value);
|
|
41210
|
+
}
|
|
41211
|
+
function decodePrimitive(type, raw) {
|
|
41212
|
+
if (raw === null || raw === "") return null;
|
|
41213
|
+
switch (type) {
|
|
41214
|
+
case "b": return raw !== "0" && raw.toLowerCase() !== "false";
|
|
41215
|
+
case "e": return raw;
|
|
41216
|
+
case "str": return raw;
|
|
41217
|
+
default: {
|
|
41218
|
+
const n = Number(raw);
|
|
41219
|
+
return Number.isFinite(n) ? n : raw;
|
|
41220
|
+
}
|
|
41221
|
+
}
|
|
41222
|
+
}
|
|
41223
|
+
//#endregion
|
|
39784
41224
|
//#region src/modules/excel/xlsx/xform/comment/comments-xform.ts
|
|
39785
41225
|
var CommentsXform = class CommentsXform extends BaseXform {
|
|
39786
41226
|
constructor() {
|
|
@@ -41897,10 +43337,10 @@ self.onmessage = async function(event) {
|
|
|
41897
43337
|
for (let j = dimensions.left; j <= dimensions.right; j++) {
|
|
41898
43338
|
const cell = row.cells[j - 1];
|
|
41899
43339
|
if (!cell) row.cells[j] = {
|
|
41900
|
-
type:
|
|
43340
|
+
type: 0,
|
|
41901
43341
|
address: colCache.encodeAddress(i, j)
|
|
41902
43342
|
};
|
|
41903
|
-
else if (cell.type ===
|
|
43343
|
+
else if (cell.type === 1) cell.master = dimensions.tl;
|
|
41904
43344
|
}
|
|
41905
43345
|
}
|
|
41906
43346
|
});
|
|
@@ -42066,7 +43506,8 @@ self.onmessage = async function(event) {
|
|
|
42066
43506
|
childXform: new TablePartXform()
|
|
42067
43507
|
}),
|
|
42068
43508
|
conditionalFormatting: new ConditionalFormattingsXform(),
|
|
42069
|
-
extLst: new ExtLstXform$1()
|
|
43509
|
+
extLst: new ExtLstXform$1(),
|
|
43510
|
+
ignoredErrors: new IgnoredErrorsXform()
|
|
42070
43511
|
};
|
|
42071
43512
|
}
|
|
42072
43513
|
prepare(model, options) {
|
|
@@ -42449,6 +43890,7 @@ self.onmessage = async function(event) {
|
|
|
42449
43890
|
xmlStream.leafNode("mc:Fallback");
|
|
42450
43891
|
xmlStream.closeNode();
|
|
42451
43892
|
}
|
|
43893
|
+
this.map.ignoredErrors.render(xmlStream, model.ignoredErrors);
|
|
42452
43894
|
this.map.tableParts.render(xmlStream, model.tables);
|
|
42453
43895
|
this.map.extLst.render(xmlStream, model);
|
|
42454
43896
|
xmlStream.closeNode();
|
|
@@ -42505,7 +43947,8 @@ self.onmessage = async function(event) {
|
|
|
42505
43947
|
tables: this.map.tableParts.model,
|
|
42506
43948
|
conditionalFormattings,
|
|
42507
43949
|
rowBreaks: this.map.rowBreaks.model ?? [],
|
|
42508
|
-
colBreaks: this.map.colBreaks.model ?? []
|
|
43950
|
+
colBreaks: this.map.colBreaks.model ?? [],
|
|
43951
|
+
ignoredErrors: this.map.ignoredErrors.model ?? []
|
|
42509
43952
|
};
|
|
42510
43953
|
if (this.map.autoFilter.model) this.model.autoFilter = this.map.autoFilter.model;
|
|
42511
43954
|
if (this.map.sheetProtection.model) this.model.sheetProtection = this.map.sheetProtection.model;
|
|
@@ -43335,6 +44778,27 @@ self.onmessage = async function(event) {
|
|
|
43335
44778
|
}
|
|
43336
44779
|
};
|
|
43337
44780
|
/**
|
|
44781
|
+
* Extract the trailing integer from a workbook-rels Target like
|
|
44782
|
+
* `"externalLinks/externalLink12.xml"` (a path relative to `xl/`). Mirror
|
|
44783
|
+
* of {@link getExternalLinkIndexFromPath} which takes the full
|
|
44784
|
+
* `xl/externalLinks/…` form. Used during reconcile to bridge the
|
|
44785
|
+
* workbook.xml.rels entry to the parsed externalLinkN.xml part.
|
|
44786
|
+
*/
|
|
44787
|
+
function externalLinkIndexFromRelTarget(target) {
|
|
44788
|
+
const match = /(?:^|\/)externalLink(\d+)[.]xml$/.exec(target);
|
|
44789
|
+
return match ? parseInt(match[1], 10) : void 0;
|
|
44790
|
+
}
|
|
44791
|
+
/**
|
|
44792
|
+
* Add `sheetName` to an ExternalLinkModel's `sheetNames` list if it isn't
|
|
44793
|
+
* already present. Ordering is preserved — the first-seen sheet wins
|
|
44794
|
+
* position 0, which matches what Excel does when writing externalLinks
|
|
44795
|
+
* itself.
|
|
44796
|
+
*/
|
|
44797
|
+
function upsertSheet(link, sheetName) {
|
|
44798
|
+
if (!sheetName) return;
|
|
44799
|
+
if (!link.sheetNames.includes(sheetName)) link.sheetNames.push(sheetName);
|
|
44800
|
+
}
|
|
44801
|
+
/**
|
|
43338
44802
|
* XLSX class - handles Excel file operations
|
|
43339
44803
|
* Works in both Node.js and Browser environments
|
|
43340
44804
|
*/
|
|
@@ -43396,10 +44860,12 @@ self.onmessage = async function(event) {
|
|
|
43396
44860
|
await this.addDrawings(zip, model);
|
|
43397
44861
|
await this.addTables(zip, model);
|
|
43398
44862
|
await this.addPivotTables(zip, model);
|
|
44863
|
+
await this.addExternalLinks(zip, model);
|
|
43399
44864
|
this.addPassthrough(zip, model);
|
|
43400
44865
|
await this.addThemes(zip, model);
|
|
43401
44866
|
await this.addStyles(zip, model);
|
|
43402
44867
|
await this.addFeaturePropertyBag(zip, model);
|
|
44868
|
+
await this.addMetadata(zip, model);
|
|
43403
44869
|
await this.addMedia(zip, model);
|
|
43404
44870
|
await this.addApp(zip, model);
|
|
43405
44871
|
await this.addCore(zip, model);
|
|
@@ -43444,16 +44910,27 @@ self.onmessage = async function(event) {
|
|
|
43444
44910
|
return this._finalize(zip);
|
|
43445
44911
|
}
|
|
43446
44912
|
/**
|
|
43447
|
-
* Load workbook from
|
|
44913
|
+
* Load a workbook from binary data.
|
|
44914
|
+
*
|
|
44915
|
+
* Accepted inputs:
|
|
44916
|
+
* - `Uint8Array` (and `Buffer`, which is a Uint8Array at runtime)
|
|
44917
|
+
* - `ArrayBuffer` / `SharedArrayBuffer`
|
|
44918
|
+
* - Any `ArrayBufferView` (DataView, Int8Array, Float32Array, …) — the
|
|
44919
|
+
* underlying bytes are reinterpreted as a zip archive
|
|
44920
|
+
* - `string` — treated as base64-encoded data when `options.base64 === true`;
|
|
44921
|
+
* raw binary cannot be round-tripped through a JS string and is rejected
|
|
44922
|
+
* to prevent silent corruption.
|
|
43448
44923
|
*/
|
|
43449
44924
|
async load(data, options) {
|
|
44925
|
+
if (data === null || data === void 0) 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) ?");
|
|
43450
44926
|
let buffer;
|
|
43451
|
-
|
|
43452
|
-
|
|
43453
|
-
|
|
44927
|
+
if (typeof data === "string") {
|
|
44928
|
+
if (!options?.base64) 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) ? String input requires options.base64 === true (base64-encoded zip archive).");
|
|
44929
|
+
buffer = base64ToUint8Array(data);
|
|
44930
|
+
} else if (data instanceof Uint8Array) buffer = data;
|
|
43454
44931
|
else if (data instanceof ArrayBuffer) buffer = new Uint8Array(data);
|
|
43455
|
-
else if (data
|
|
43456
|
-
else
|
|
44932
|
+
else if (ArrayBuffer.isView(data)) buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
44933
|
+
else 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) ?");
|
|
43457
44934
|
return this.loadBuffer(buffer, options);
|
|
43458
44935
|
}
|
|
43459
44936
|
/**
|
|
@@ -43493,7 +44970,9 @@ self.onmessage = async function(event) {
|
|
|
43493
44970
|
pivotTableRels: {},
|
|
43494
44971
|
pivotCacheDefinitions: {},
|
|
43495
44972
|
pivotCacheRecords: {},
|
|
43496
|
-
passthrough: {}
|
|
44973
|
+
passthrough: {},
|
|
44974
|
+
externalLinksByIndex: {},
|
|
44975
|
+
externalLinkRelsByIndex: {}
|
|
43497
44976
|
};
|
|
43498
44977
|
}
|
|
43499
44978
|
/**
|
|
@@ -43546,8 +45025,10 @@ self.onmessage = async function(event) {
|
|
|
43546
45025
|
model.definedNames = workbook.definedNames;
|
|
43547
45026
|
model.views = workbook.views;
|
|
43548
45027
|
model.properties = workbook.properties;
|
|
45028
|
+
model.protection = workbook.protection;
|
|
43549
45029
|
model.calcProperties = workbook.calcProperties;
|
|
43550
45030
|
model.pivotCaches = workbook.pivotCaches;
|
|
45031
|
+
model.externalReferences = workbook.externalReferences;
|
|
43551
45032
|
return true;
|
|
43552
45033
|
}
|
|
43553
45034
|
case OOXML_PATHS.xlSharedStrings:
|
|
@@ -43574,6 +45055,11 @@ self.onmessage = async function(event) {
|
|
|
43574
45055
|
model.styles = new StylesXform();
|
|
43575
45056
|
await model.styles.parseStream(stream);
|
|
43576
45057
|
return true;
|
|
45058
|
+
case OOXML_PATHS.xlMetadata: {
|
|
45059
|
+
const metadataResult = await new MetadataXform().parseStream(stream);
|
|
45060
|
+
if (metadataResult) model.metadata = metadataResult;
|
|
45061
|
+
return true;
|
|
45062
|
+
}
|
|
43577
45063
|
default: return false;
|
|
43578
45064
|
}
|
|
43579
45065
|
}
|
|
@@ -43703,12 +45189,15 @@ self.onmessage = async function(event) {
|
|
|
43703
45189
|
comments: model.comments,
|
|
43704
45190
|
tables: model.tables,
|
|
43705
45191
|
vmlDrawings: model.vmlDrawings,
|
|
43706
|
-
pivotTables: model.pivotTablesIndexed
|
|
45192
|
+
pivotTables: model.pivotTablesIndexed,
|
|
45193
|
+
hasDynamicArrayMetadata: !!model.metadata?.hasDynamicArrays,
|
|
45194
|
+
dynamicArrayCmIndices: model.metadata?.dynamicArrayCmIndices
|
|
43707
45195
|
};
|
|
43708
45196
|
model.worksheets.forEach((worksheet) => {
|
|
43709
45197
|
worksheet.relationships = model.worksheetRels[worksheet.sheetNo];
|
|
43710
45198
|
worksheetXform.reconcile(worksheet, sheetOptions);
|
|
43711
45199
|
});
|
|
45200
|
+
this._reconcileExternalLinks(model);
|
|
43712
45201
|
delete model.worksheetHash;
|
|
43713
45202
|
delete model.worksheetRels;
|
|
43714
45203
|
delete model.globalRels;
|
|
@@ -43722,6 +45211,127 @@ self.onmessage = async function(event) {
|
|
|
43722
45211
|
delete model.drawingRels;
|
|
43723
45212
|
delete model.vmlDrawings;
|
|
43724
45213
|
delete model.pivotTableRels;
|
|
45214
|
+
delete model.metadata;
|
|
45215
|
+
delete model.externalReferences;
|
|
45216
|
+
delete model.externalLinksByIndex;
|
|
45217
|
+
delete model.externalLinkRelsByIndex;
|
|
45218
|
+
}
|
|
45219
|
+
/**
|
|
45220
|
+
* Join the three on-disk sources that together describe external workbook
|
|
45221
|
+
* references into a single dense `model.externalLinks: ExternalLinkModel[]`.
|
|
45222
|
+
*
|
|
45223
|
+
* Sources:
|
|
45224
|
+
* - `<externalReferences>` list in workbook.xml (declaration order)
|
|
45225
|
+
* - `xl/_rels/workbook.xml.rels` (rId → internal path)
|
|
45226
|
+
* - `xl/externalLinks/externalLink{N}.xml` (sheet names, cached values)
|
|
45227
|
+
* - `xl/externalLinks/_rels/externalLink{N}.xml.rels` (target, TargetMode)
|
|
45228
|
+
*
|
|
45229
|
+
* The 1-based index of each resulting ExternalLinkModel matches the `[N]`
|
|
45230
|
+
* used in formula strings — this is the single source of truth formula
|
|
45231
|
+
* code should rely on.
|
|
45232
|
+
*/
|
|
45233
|
+
_reconcileExternalLinks(model) {
|
|
45234
|
+
const refs = model.externalReferences;
|
|
45235
|
+
if (!refs || refs.length === 0) {
|
|
45236
|
+
if (!model.externalLinks) model.externalLinks = [];
|
|
45237
|
+
return;
|
|
45238
|
+
}
|
|
45239
|
+
const rels = model.workbookRels ?? [];
|
|
45240
|
+
const relById = /* @__PURE__ */ new Map();
|
|
45241
|
+
for (const rel of rels) if (rel.Type === RelType.ExternalLink) relById.set(rel.Id, rel);
|
|
45242
|
+
const externalLinks = [];
|
|
45243
|
+
for (let i = 0; i < refs.length; i++) {
|
|
45244
|
+
const ref = refs[i];
|
|
45245
|
+
const rel = relById.get(ref.rId);
|
|
45246
|
+
if (!rel) continue;
|
|
45247
|
+
const partIndex = externalLinkIndexFromRelTarget(rel.Target);
|
|
45248
|
+
if (partIndex === void 0) continue;
|
|
45249
|
+
const parsed = model.externalLinksByIndex[partIndex];
|
|
45250
|
+
const partRels = model.externalLinkRelsByIndex[partIndex] ?? [];
|
|
45251
|
+
const pathRel = partRels.find((r) => r.Type === RelType.ExternalLinkPath) ?? partRels.find((r) => r.TargetMode === "External");
|
|
45252
|
+
externalLinks.push({
|
|
45253
|
+
index: i + 1,
|
|
45254
|
+
rId: ref.rId,
|
|
45255
|
+
target: pathRel?.Target ?? "",
|
|
45256
|
+
targetMode: pathRel?.TargetMode ?? "External",
|
|
45257
|
+
sheetNames: parsed?.sheetNames ?? [],
|
|
45258
|
+
cachedValues: parsed?.cachedValues ?? {}
|
|
45259
|
+
});
|
|
45260
|
+
}
|
|
45261
|
+
model.externalLinks = externalLinks;
|
|
45262
|
+
}
|
|
45263
|
+
/**
|
|
45264
|
+
* Write-time pass that brings the workbook model into a shape the writer
|
|
45265
|
+
* can serialise cleanly. Two concerns:
|
|
45266
|
+
*
|
|
45267
|
+
* 1. Build the final external-link list for this write, combining
|
|
45268
|
+
* user-declared links (`wb.externalLinks`) with auto-discovered
|
|
45269
|
+
* ones from previous writes (cached on the Workbook). The result
|
|
45270
|
+
* is assigned to `model.externalLinks` and consumed by the writer;
|
|
45271
|
+
* `wb.externalLinks` is **not** modified.
|
|
45272
|
+
*
|
|
45273
|
+
* 2. Scan every formula cell for `[Book]Sheet!` prefixes. Filename-form
|
|
45274
|
+
* references that don't match an existing link trigger
|
|
45275
|
+
* `_recordAutoExternalLink()` on the Workbook, which adds the target
|
|
45276
|
+
* to the private writer cache (so subsequent writes are fixed-point
|
|
45277
|
+
* stable) but leaves `wb.externalLinks` untouched.
|
|
45278
|
+
*
|
|
45279
|
+
* 3. Rewrite every external-ref formula so it uses the numeric `[N]`
|
|
45280
|
+
* form, the canonical OOXML storage form. This mutation lands on
|
|
45281
|
+
* the cell's model object — matching the library's existing
|
|
45282
|
+
* write-time pattern for `ssId`, `styleId`, `si`, and `cm`.
|
|
45283
|
+
* Subsequent writes see the `[N]` form directly and resolve it
|
|
45284
|
+
* against `model.externalLinks`, giving idempotent output.
|
|
45285
|
+
*/
|
|
45286
|
+
_normaliseExternalLinks(model) {
|
|
45287
|
+
const links = this.workbook._collectExternalLinksForWrite();
|
|
45288
|
+
const byTarget = /* @__PURE__ */ new Map();
|
|
45289
|
+
for (const link of links) if (link.target) byTarget.set(link.target.toLowerCase(), link);
|
|
45290
|
+
const scratch = {
|
|
45291
|
+
links,
|
|
45292
|
+
byTarget,
|
|
45293
|
+
workbook: this.workbook
|
|
45294
|
+
};
|
|
45295
|
+
for (const worksheet of model.worksheets ?? []) for (const row of worksheet.rows ?? []) for (const cell of row.cells ?? []) {
|
|
45296
|
+
if (typeof cell?.formula === "string" && cell.formula.length > 0) cell.formula = this._normaliseFormulaExternalRefs(cell.formula, scratch);
|
|
45297
|
+
if (typeof cell?.sharedFormula === "string" && cell.sharedFormula.length > 0) cell.sharedFormula = this._normaliseFormulaExternalRefs(cell.sharedFormula, scratch);
|
|
45298
|
+
}
|
|
45299
|
+
model.externalLinks = links;
|
|
45300
|
+
}
|
|
45301
|
+
/**
|
|
45302
|
+
* Rewrite a single formula so every external-ref prefix uses the numeric
|
|
45303
|
+
* `[N]` form. When an unknown filename-form reference is found we record
|
|
45304
|
+
* it on the workbook's private writer cache (so the next write can still
|
|
45305
|
+
* resolve it) and append a local link to `scratch.links` so subsequent
|
|
45306
|
+
* refs in the same formula see the freshly-assigned index.
|
|
45307
|
+
*/
|
|
45308
|
+
_normaliseFormulaExternalRefs(formula, scratch) {
|
|
45309
|
+
return rewriteExternalRefs(formula, (ref) => {
|
|
45310
|
+
if (ref.numeric) {
|
|
45311
|
+
if (ref.index !== null && ref.index >= 1 && ref.index <= scratch.links.length) {
|
|
45312
|
+
upsertSheet(scratch.links[ref.index - 1], ref.sheet);
|
|
45313
|
+
return ref.index;
|
|
45314
|
+
}
|
|
45315
|
+
return null;
|
|
45316
|
+
}
|
|
45317
|
+
const key = ref.workbook.toLowerCase();
|
|
45318
|
+
let link = scratch.byTarget.get(key);
|
|
45319
|
+
if (!link) {
|
|
45320
|
+
link = {
|
|
45321
|
+
index: scratch.workbook._recordAutoExternalLink(ref.workbook, ref.sheet),
|
|
45322
|
+
target: ref.workbook,
|
|
45323
|
+
targetMode: "External",
|
|
45324
|
+
sheetNames: ref.sheet ? [ref.sheet] : [],
|
|
45325
|
+
cachedValues: {}
|
|
45326
|
+
};
|
|
45327
|
+
scratch.links.push(link);
|
|
45328
|
+
scratch.byTarget.set(key, link);
|
|
45329
|
+
} else {
|
|
45330
|
+
upsertSheet(link, ref.sheet);
|
|
45331
|
+
if (ref.sheet) scratch.workbook._recordAutoExternalLink(ref.workbook, ref.sheet);
|
|
45332
|
+
}
|
|
45333
|
+
return link.index;
|
|
45334
|
+
});
|
|
43725
45335
|
}
|
|
43726
45336
|
/**
|
|
43727
45337
|
* Reconcile pivot tables by linking them to worksheets and their cache data.
|
|
@@ -43931,6 +45541,26 @@ self.onmessage = async function(event) {
|
|
|
43931
45541
|
const cacheRecords = await new PivotCacheRecordsXform().parseStream(stream);
|
|
43932
45542
|
if (cacheRecords) model.pivotCacheRecords[name] = cacheRecords;
|
|
43933
45543
|
}
|
|
45544
|
+
/**
|
|
45545
|
+
* Parse `xl/externalLinks/externalLink{N}.xml` into the intermediate
|
|
45546
|
+
* ParsedExternalLink shape. Reconciliation (joining with the rels file
|
|
45547
|
+
* and the workbook's `<externalReferences>` list) happens later in
|
|
45548
|
+
* {@link reconcile}.
|
|
45549
|
+
*/
|
|
45550
|
+
async _processExternalLinkEntry(stream, model, index) {
|
|
45551
|
+
const parsed = await new ExternalLinkXform().parseStream(stream);
|
|
45552
|
+
if (parsed) model.externalLinksByIndex[index] = parsed;
|
|
45553
|
+
}
|
|
45554
|
+
/**
|
|
45555
|
+
* Parse `xl/externalLinks/_rels/externalLink{N}.xml.rels`. The Target /
|
|
45556
|
+
* TargetMode carried here is what Excel uses to locate the actual external
|
|
45557
|
+
* file at open time, so we must preserve it verbatim (including relative
|
|
45558
|
+
* paths like `"测试.xlsx"`).
|
|
45559
|
+
*/
|
|
45560
|
+
async _processExternalLinkRelsEntry(stream, model, index) {
|
|
45561
|
+
const relationships = await this.parseRels(stream);
|
|
45562
|
+
model.externalLinkRelsByIndex[index] = relationships ?? [];
|
|
45563
|
+
}
|
|
43934
45564
|
async loadFromFiles(zipData, options) {
|
|
43935
45565
|
const model = this.createEmptyModel();
|
|
43936
45566
|
const entries = Object.keys(zipData).map((name) => ({
|
|
@@ -44018,6 +45648,16 @@ self.onmessage = async function(event) {
|
|
|
44018
45648
|
await this._processPivotCacheRecordsEntry(stream, model, pivotCacheRecordsName);
|
|
44019
45649
|
return true;
|
|
44020
45650
|
}
|
|
45651
|
+
const externalLinkIndex = getExternalLinkIndexFromPath(entryName);
|
|
45652
|
+
if (externalLinkIndex !== void 0) {
|
|
45653
|
+
await this._processExternalLinkEntry(stream, model, externalLinkIndex);
|
|
45654
|
+
return true;
|
|
45655
|
+
}
|
|
45656
|
+
const externalLinkRelsIndex = getExternalLinkIndexFromRelsPath(entryName);
|
|
45657
|
+
if (externalLinkRelsIndex !== void 0) {
|
|
45658
|
+
await this._processExternalLinkRelsEntry(stream, model, externalLinkRelsIndex);
|
|
45659
|
+
return true;
|
|
45660
|
+
}
|
|
44021
45661
|
if (PassthroughManager.isPassthroughPath(entryName)) {
|
|
44022
45662
|
if (rawData) model.passthrough[entryName] = rawData;
|
|
44023
45663
|
else await this._processPassthroughEntry(stream, model, entryName);
|
|
@@ -44101,6 +45741,11 @@ self.onmessage = async function(event) {
|
|
|
44101
45741
|
Type: XLSX.RelType.FeaturePropertyBag,
|
|
44102
45742
|
Target: OOXML_REL_TARGETS.workbookFeaturePropertyBag
|
|
44103
45743
|
});
|
|
45744
|
+
if (model.hasDynamicArrayFormulas) relationships.push({
|
|
45745
|
+
Id: `rId${count++}`,
|
|
45746
|
+
Type: XLSX.RelType.SheetMetadata,
|
|
45747
|
+
Target: OOXML_REL_TARGETS.workbookMetadata
|
|
45748
|
+
});
|
|
44104
45749
|
const seenCacheIds = /* @__PURE__ */ new Map();
|
|
44105
45750
|
(model.pivotTables ?? []).forEach((pivotTable) => {
|
|
44106
45751
|
const existing = seenCacheIds.get(pivotTable.cacheId);
|
|
@@ -44123,6 +45768,15 @@ self.onmessage = async function(event) {
|
|
|
44123
45768
|
Target: worksheetRelTarget(worksheet.fileIndex)
|
|
44124
45769
|
});
|
|
44125
45770
|
});
|
|
45771
|
+
const externalLinks = model.externalLinks ?? [];
|
|
45772
|
+
for (const link of externalLinks) {
|
|
45773
|
+
link.rId = `rId${count++}`;
|
|
45774
|
+
relationships.push({
|
|
45775
|
+
Id: link.rId,
|
|
45776
|
+
Type: XLSX.RelType.ExternalLink,
|
|
45777
|
+
Target: externalLinkRelTargetFromWorkbook(link.index)
|
|
45778
|
+
});
|
|
45779
|
+
}
|
|
44126
45780
|
const xform = new RelationshipsXform();
|
|
44127
45781
|
await this._renderToZip(zip, OOXML_PATHS.xlWorkbookRels, xform, relationships);
|
|
44128
45782
|
}
|
|
@@ -44130,6 +45784,10 @@ self.onmessage = async function(event) {
|
|
|
44130
45784
|
if (!model.hasCheckboxes) return;
|
|
44131
45785
|
await this._renderToZip(zip, OOXML_PATHS.xlFeaturePropertyBag, new FeaturePropertyBagXform(), {});
|
|
44132
45786
|
}
|
|
45787
|
+
async addMetadata(zip, model) {
|
|
45788
|
+
if (!model.hasDynamicArrayFormulas) return;
|
|
45789
|
+
await this._renderToZip(zip, OOXML_PATHS.xlMetadata, new MetadataXform(), { dynamicArrayCount: model.dynamicArrayCount });
|
|
45790
|
+
}
|
|
44133
45791
|
async addSharedStrings(zip, model) {
|
|
44134
45792
|
if (model.sharedStrings && model.sharedStrings.count) await this._renderToZip(zip, OOXML_PATHS.xlSharedStrings, model.sharedStrings, model.sharedStrings.model);
|
|
44135
45793
|
}
|
|
@@ -44211,6 +45869,34 @@ self.onmessage = async function(event) {
|
|
|
44211
45869
|
}
|
|
44212
45870
|
}
|
|
44213
45871
|
/**
|
|
45872
|
+
* Write every external workbook reference into the archive. For each
|
|
45873
|
+
* {@link ExternalLinkModel} in `model.externalLinks` we emit two files:
|
|
45874
|
+
*
|
|
45875
|
+
* xl/externalLinks/externalLink{index}.xml — sheet names + cache
|
|
45876
|
+
* xl/externalLinks/_rels/externalLink{index}.xml.rels — target path
|
|
45877
|
+
*
|
|
45878
|
+
* The target-path rel carries `TargetMode="External"` with a **bare
|
|
45879
|
+
* relative** `Target` whenever the user supplied one. This is the single
|
|
45880
|
+
* line that makes Office / WPS resolve the referenced workbook relative
|
|
45881
|
+
* to the current file's directory (not the `%USERPROFILE%\Documents`
|
|
45882
|
+
* fallback) — the root of the behaviour reported in exceljs#3039.
|
|
45883
|
+
*/
|
|
45884
|
+
async addExternalLinks(zip, model) {
|
|
45885
|
+
const externalLinks = model.externalLinks ?? [];
|
|
45886
|
+
if (externalLinks.length === 0) return;
|
|
45887
|
+
const externalLinkXform = new ExternalLinkXform();
|
|
45888
|
+
const relsXform = new RelationshipsXform();
|
|
45889
|
+
for (const link of externalLinks) {
|
|
45890
|
+
await this._renderToZip(zip, externalLinkPath(link.index), externalLinkXform, link);
|
|
45891
|
+
await this._renderToZip(zip, externalLinkRelsPath(link.index), relsXform, [{
|
|
45892
|
+
Id: "rId1",
|
|
45893
|
+
Type: XLSX.RelType.ExternalLinkPath,
|
|
45894
|
+
Target: link.target,
|
|
45895
|
+
TargetMode: link.targetMode ?? "External"
|
|
45896
|
+
}]);
|
|
45897
|
+
}
|
|
45898
|
+
}
|
|
45899
|
+
/**
|
|
44214
45900
|
* Write passthrough files (charts, etc.) that were preserved during read.
|
|
44215
45901
|
* These files are written back unchanged to preserve unsupported features.
|
|
44216
45902
|
*/
|
|
@@ -44280,6 +45966,7 @@ self.onmessage = async function(event) {
|
|
|
44280
45966
|
const workbookXform = new WorkbookXform();
|
|
44281
45967
|
const worksheetXform = new WorkSheetXform();
|
|
44282
45968
|
workbookXform.prepare(model);
|
|
45969
|
+
this._normaliseExternalLinks(model);
|
|
44283
45970
|
const worksheetOptions = {
|
|
44284
45971
|
sharedStrings: model.sharedStrings,
|
|
44285
45972
|
styles: model.styles,
|
|
@@ -44293,9 +45980,14 @@ self.onmessage = async function(event) {
|
|
|
44293
45980
|
model.hasHeaderWatermark = false;
|
|
44294
45981
|
let tableCount = 0;
|
|
44295
45982
|
model.tables = [];
|
|
45983
|
+
const tableNameMap = /* @__PURE__ */ new Map();
|
|
44296
45984
|
model.worksheets.forEach((worksheet, index) => {
|
|
44297
45985
|
worksheet.fileIndex = index + 1;
|
|
44298
45986
|
worksheet.tables.forEach((table) => {
|
|
45987
|
+
const nameKey = table.name.toLowerCase();
|
|
45988
|
+
const existingSheet = tableNameMap.get(nameKey);
|
|
45989
|
+
if (existingSheet !== void 0) throw new TableError(`Duplicate table name "${table.name}": already used in worksheet "${existingSheet}". Table names must be unique across the entire workbook (case-insensitive).`);
|
|
45990
|
+
tableNameMap.set(nameKey, worksheet.name);
|
|
44299
45991
|
tableCount++;
|
|
44300
45992
|
table.target = `table${tableCount}.xml`;
|
|
44301
45993
|
table.id = tableCount;
|
|
@@ -44304,6 +45996,16 @@ self.onmessage = async function(event) {
|
|
|
44304
45996
|
worksheetXform.prepare(worksheet, worksheetOptions);
|
|
44305
45997
|
});
|
|
44306
45998
|
model.hasCheckboxes = model.styles.hasCheckboxes;
|
|
45999
|
+
let dynamicArrayCount = 0;
|
|
46000
|
+
model.worksheets.forEach((worksheet) => {
|
|
46001
|
+
(worksheet.rows ?? []).forEach((row) => {
|
|
46002
|
+
(row.cells ?? []).forEach((cell) => {
|
|
46003
|
+
if (cell.isDynamicArray) dynamicArrayCount++;
|
|
46004
|
+
});
|
|
46005
|
+
});
|
|
46006
|
+
});
|
|
46007
|
+
model.hasDynamicArrayFormulas = dynamicArrayCount > 0;
|
|
46008
|
+
model.dynamicArrayCount = dynamicArrayCount;
|
|
44307
46009
|
if (worksheetOptions.hasHeaderWatermark) model.hasHeaderWatermark = true;
|
|
44308
46010
|
const passthrough = model.passthrough || {};
|
|
44309
46011
|
const passthroughManager = new PassthroughManager();
|
|
@@ -44311,6 +46013,22 @@ self.onmessage = async function(event) {
|
|
|
44311
46013
|
model.passthroughContentTypes = passthroughManager.getContentTypes();
|
|
44312
46014
|
}
|
|
44313
46015
|
};
|
|
46016
|
+
/**
|
|
46017
|
+
* Invoke the registered engine on `workbook`. Throws a descriptive error
|
|
46018
|
+
* if no engine has been installed.
|
|
46019
|
+
*/
|
|
46020
|
+
function invokeFormulaEngine(workbook) {
|
|
46021
|
+
throw new Error("No formula engine is installed. Call `installFormulaEngine()` from `@cj-tech-master/excelts/formula` once at startup to enable `Workbook.calculateFormulas()` and automatic recalculation during `excelToPdf()`.");
|
|
46022
|
+
}
|
|
46023
|
+
/**
|
|
46024
|
+
* Like {@link invokeFormulaEngine} but returns silently when no engine is
|
|
46025
|
+
* installed. Used by `excelToPdf()` so that PDF export still works for
|
|
46026
|
+
* workbooks whose cached formula results are already up to date (the
|
|
46027
|
+
* common case when the XLSX was saved by Excel itself).
|
|
46028
|
+
*/
|
|
46029
|
+
function tryInvokeFormulaEngine(workbook) {
|
|
46030
|
+
return false;
|
|
46031
|
+
}
|
|
44314
46032
|
//#endregion
|
|
44315
46033
|
//#region src/modules/markdown/constants.ts
|
|
44316
46034
|
/**
|
|
@@ -44950,29 +46668,48 @@ self.onmessage = async function(event) {
|
|
|
44950
46668
|
const datumNumber = Number(datum);
|
|
44951
46669
|
if (!Number.isNaN(datumNumber) && datumNumber !== Infinity) return datumNumber;
|
|
44952
46670
|
}
|
|
44953
|
-
|
|
44954
|
-
|
|
44955
|
-
|
|
44956
|
-
|
|
46671
|
+
if (typeof datum === "string") {
|
|
46672
|
+
const date = dateParser.parse(datum);
|
|
46673
|
+
if (date) return date;
|
|
46674
|
+
const special = SpecialValues[datum];
|
|
46675
|
+
if (special !== void 0) return special;
|
|
46676
|
+
}
|
|
44957
46677
|
return datum;
|
|
44958
46678
|
};
|
|
44959
46679
|
}
|
|
44960
46680
|
/**
|
|
44961
46681
|
* Create a value mapper for writing Excel values to CSV format.
|
|
44962
|
-
*
|
|
46682
|
+
*
|
|
46683
|
+
* Branches below correspond to each member of the `CellValue` union, in an
|
|
46684
|
+
* order that prefers the most specific shape:
|
|
46685
|
+
* 1. Hyperlink — emit the URL (falling back to display text)
|
|
46686
|
+
* 2. Formula / SharedFormula / ArrayFormula — emit the evaluated `result`
|
|
46687
|
+
* 3. RichText — flatten runs to plain text
|
|
46688
|
+
* 4. Checkbox — emit the boolean state
|
|
46689
|
+
* 5. Error — emit the Excel error token (e.g. "#N/A")
|
|
46690
|
+
* 6. Date — format via the configured DateFormatter
|
|
46691
|
+
* 7. Primitive — pass through (`string | number | boolean | null | undefined`)
|
|
46692
|
+
*
|
|
46693
|
+
* An object that does not match any of the above is stringified as JSON so
|
|
46694
|
+
* the CSV remains round-trippable rather than producing `[object Object]`.
|
|
44963
46695
|
*/
|
|
44964
46696
|
function createDefaultWriteMapper(dateFormat, dateUTC) {
|
|
44965
46697
|
const formatter = dateFormat ? DateFormatter.create(dateFormat, { utc: dateUTC }) : DateFormatter.iso(dateUTC);
|
|
44966
46698
|
return function mapValue(value) {
|
|
44967
|
-
if (value)
|
|
44968
|
-
|
|
44969
|
-
|
|
44970
|
-
|
|
44971
|
-
|
|
44972
|
-
|
|
44973
|
-
|
|
44974
|
-
|
|
44975
|
-
|
|
46699
|
+
if (value === null || value === void 0) return value;
|
|
46700
|
+
if (value instanceof Date) return formatter.format(value);
|
|
46701
|
+
if (typeof value !== "object") return value;
|
|
46702
|
+
const maybeLink = value;
|
|
46703
|
+
if (typeof maybeLink.hyperlink === "string" || typeof maybeLink.text === "string") {
|
|
46704
|
+
const url = typeof maybeLink.hyperlink === "string" ? maybeLink.hyperlink : "";
|
|
46705
|
+
const text = typeof maybeLink.text === "string" ? maybeLink.text : "";
|
|
46706
|
+
return url || text || "";
|
|
46707
|
+
}
|
|
46708
|
+
if ("formula" in value || "sharedFormula" in value) return value.result ?? "";
|
|
46709
|
+
if ("richText" in value && Array.isArray(value.richText)) return value.richText.map((r) => r.text).join("");
|
|
46710
|
+
if ("checkbox" in value && typeof value.checkbox === "boolean") return value.checkbox;
|
|
46711
|
+
if ("error" in value && typeof value.error === "string") return value.error;
|
|
46712
|
+
return JSON.stringify(value);
|
|
44976
46713
|
};
|
|
44977
46714
|
}
|
|
44978
46715
|
/**
|
|
@@ -45064,7 +46801,17 @@ self.onmessage = async function(event) {
|
|
|
45064
46801
|
static {
|
|
45065
46802
|
this.Reader = WorkbookReader;
|
|
45066
46803
|
}
|
|
45067
|
-
|
|
46804
|
+
/**
|
|
46805
|
+
* @param options Optional construction options.
|
|
46806
|
+
* - `formulaSyntaxProbe`: An explicit tokenizer+parser probe used to
|
|
46807
|
+
* classify defined-name text during XLSX load. Providing this makes
|
|
46808
|
+
* classification deterministic for *this* workbook regardless of
|
|
46809
|
+
* whether `installFormulaEngine()` has been called. Most callers
|
|
46810
|
+
* don't need it — `installFormulaEngine()` registers a
|
|
46811
|
+
* process-wide default probe that is picked up automatically.
|
|
46812
|
+
*/
|
|
46813
|
+
constructor(options) {
|
|
46814
|
+
this._tableNames = /* @__PURE__ */ new Set();
|
|
45068
46815
|
this.category = "";
|
|
45069
46816
|
this.company = "";
|
|
45070
46817
|
this.created = /* @__PURE__ */ new Date();
|
|
@@ -45080,9 +46827,30 @@ self.onmessage = async function(event) {
|
|
|
45080
46827
|
this.views = [];
|
|
45081
46828
|
this.media = [];
|
|
45082
46829
|
this.pivotTables = [];
|
|
46830
|
+
this.externalLinks = [];
|
|
45083
46831
|
this._passthrough = {};
|
|
45084
46832
|
this._rawDrawings = {};
|
|
45085
|
-
this.
|
|
46833
|
+
this._writerExternalLinkCache = /* @__PURE__ */ new Map();
|
|
46834
|
+
this._definedNames = new DefinedNames(options?.formulaSyntaxProbe);
|
|
46835
|
+
}
|
|
46836
|
+
/**
|
|
46837
|
+
* The default font for the workbook (fontId=0 / "Normal" style).
|
|
46838
|
+
* Cells without explicit font styles will inherit this font in Excel.
|
|
46839
|
+
*
|
|
46840
|
+
* @example
|
|
46841
|
+
* ```ts
|
|
46842
|
+
* wb.defaultFont = { name: "Arial", size: 12 };
|
|
46843
|
+
* ```
|
|
46844
|
+
*
|
|
46845
|
+
* When reading an existing XLSX file, this preserves the original default font
|
|
46846
|
+
* for round-trip fidelity. Setting it on a new workbook changes the default
|
|
46847
|
+
* from Calibri 11 to your chosen font.
|
|
46848
|
+
*/
|
|
46849
|
+
get defaultFont() {
|
|
46850
|
+
return this._defaultFont;
|
|
46851
|
+
}
|
|
46852
|
+
set defaultFont(font) {
|
|
46853
|
+
this._defaultFont = font;
|
|
45086
46854
|
}
|
|
45087
46855
|
/**
|
|
45088
46856
|
* Import a worksheet from another workbook (or a standalone worksheet).
|
|
@@ -45105,6 +46873,22 @@ self.onmessage = async function(event) {
|
|
|
45105
46873
|
return newWs;
|
|
45106
46874
|
}
|
|
45107
46875
|
/**
|
|
46876
|
+
* Protect the workbook structure with an optional password.
|
|
46877
|
+
* Prevents users from adding, deleting, renaming, moving, or copying worksheets.
|
|
46878
|
+
*
|
|
46879
|
+
* @param password - Optional password to protect the structure
|
|
46880
|
+
* @param options - Optional protection flags (lockStructure, lockWindows, lockRevision)
|
|
46881
|
+
*/
|
|
46882
|
+
async protect(password, options) {
|
|
46883
|
+
this.protection = await buildWorkbookProtection(password, options);
|
|
46884
|
+
}
|
|
46885
|
+
/**
|
|
46886
|
+
* Remove workbook structure protection.
|
|
46887
|
+
*/
|
|
46888
|
+
unprotect() {
|
|
46889
|
+
this.protection = void 0;
|
|
46890
|
+
}
|
|
46891
|
+
/**
|
|
45108
46892
|
* xlsx file format operations
|
|
45109
46893
|
* Node.js: readFile, writeFile, read (stream), write (stream), load (buffer), writeBuffer
|
|
45110
46894
|
* Browser: load (buffer), writeBuffer
|
|
@@ -45615,6 +47399,47 @@ self.onmessage = async function(event) {
|
|
|
45615
47399
|
get definedNames() {
|
|
45616
47400
|
return this._definedNames;
|
|
45617
47401
|
}
|
|
47402
|
+
/**
|
|
47403
|
+
* Recalculate all formula cells in this workbook.
|
|
47404
|
+
*
|
|
47405
|
+
* Evaluates every formula cell using the built-in calculation engine and updates
|
|
47406
|
+
* each cell's cached `result` value in-place. Formulas are evaluated with
|
|
47407
|
+
* recursive dependency resolution, memoization, and circular reference detection.
|
|
47408
|
+
*
|
|
47409
|
+
* Call this after programmatically modifying cell values that are referenced by
|
|
47410
|
+
* formulas, to ensure formula results reflect the latest data.
|
|
47411
|
+
*
|
|
47412
|
+
* Unsupported functions preserve their original cached result if one exists.
|
|
47413
|
+
*
|
|
47414
|
+
* ## Tree-shaking note
|
|
47415
|
+
*
|
|
47416
|
+
* The formula engine ships ~200KB of code (433 Excel functions, parser,
|
|
47417
|
+
* evaluator, dependency graph, spill materialiser). To keep it out of
|
|
47418
|
+
* bundles that don't need it, the engine is registered at runtime
|
|
47419
|
+
* rather than imported by the core `Workbook` module. Call
|
|
47420
|
+
* {@link installFormulaEngine} once at startup before the first call
|
|
47421
|
+
* to this method, or a clear error will be thrown explaining what to do.
|
|
47422
|
+
*
|
|
47423
|
+
* ```ts
|
|
47424
|
+
* import { installFormulaEngine } from "@cj-tech-master/excelts/formula";
|
|
47425
|
+
*
|
|
47426
|
+
* installFormulaEngine(); // once, at startup
|
|
47427
|
+
*
|
|
47428
|
+
* sheet.getCell("A1").value = 100;
|
|
47429
|
+
* workbook.calculateFormulas(); // now works
|
|
47430
|
+
* ```
|
|
47431
|
+
*
|
|
47432
|
+
* Callers who prefer a zero-side-effect, tree-shakeable surface can
|
|
47433
|
+
* use the functional equivalent directly:
|
|
47434
|
+
*
|
|
47435
|
+
* ```ts
|
|
47436
|
+
* import { calculateFormulas } from "@cj-tech-master/excelts/formula";
|
|
47437
|
+
* calculateFormulas(workbook);
|
|
47438
|
+
* ```
|
|
47439
|
+
*/
|
|
47440
|
+
calculateFormulas() {
|
|
47441
|
+
invokeFormulaEngine(this);
|
|
47442
|
+
}
|
|
45618
47443
|
clearThemes() {
|
|
45619
47444
|
this._themes = void 0;
|
|
45620
47445
|
}
|
|
@@ -45632,6 +47457,119 @@ self.onmessage = async function(event) {
|
|
|
45632
47457
|
getImage(id) {
|
|
45633
47458
|
return this.media[Number(id)];
|
|
45634
47459
|
}
|
|
47460
|
+
/**
|
|
47461
|
+
* Declare that formulas in this workbook may reference an external
|
|
47462
|
+
* workbook. Registers the target so the output file contains the required
|
|
47463
|
+
* `xl/externalLinks/externalLink{N}.xml` part plus its `.rels` sibling
|
|
47464
|
+
* and Office/WPS can resolve the reference correctly.
|
|
47465
|
+
*
|
|
47466
|
+
* When Office opens the file, it resolves a relative `target` like
|
|
47467
|
+
* `"测试.xlsx"` **relative to the current workbook's directory** — which
|
|
47468
|
+
* is the exact behaviour the user expects when they write
|
|
47469
|
+
* `=[测试.xlsx]Sheet1!A1`. Absolute `file:///…` or `http(s)://…` URIs
|
|
47470
|
+
* are accepted and written through unchanged.
|
|
47471
|
+
*
|
|
47472
|
+
* @returns the registered {@link ExternalLinkModel}. Its `index` field is
|
|
47473
|
+
* the 1-based number used inside the `[N]` prefix of on-disk formula
|
|
47474
|
+
* strings (the library rewrites `[target]` forms to `[index]` at write
|
|
47475
|
+
* time automatically).
|
|
47476
|
+
*
|
|
47477
|
+
* @example
|
|
47478
|
+
* ```ts
|
|
47479
|
+
* const wb = new Workbook();
|
|
47480
|
+
* const ws = wb.addWorksheet("Main");
|
|
47481
|
+
*
|
|
47482
|
+
* // Declare the link once — sheet names and cached values are optional
|
|
47483
|
+
* // but improve interoperability (Excel displays cached values when the
|
|
47484
|
+
* // external file is unavailable).
|
|
47485
|
+
* wb.addExternalLink({
|
|
47486
|
+
* target: "测试.xlsx",
|
|
47487
|
+
* sheetNames: ["Sheet1"],
|
|
47488
|
+
* cachedValues: { Sheet1: { A1: 42 } }
|
|
47489
|
+
* });
|
|
47490
|
+
*
|
|
47491
|
+
* // Write the formula using either the target name OR the numeric index;
|
|
47492
|
+
* // the library normalises both to the on-disk `[N]` form.
|
|
47493
|
+
* ws.getCell("A1").value = { formula: "=[测试.xlsx]Sheet1!A1", result: 42 };
|
|
47494
|
+
* ```
|
|
47495
|
+
*/
|
|
47496
|
+
addExternalLink(input) {
|
|
47497
|
+
const link = {
|
|
47498
|
+
index: this.externalLinks.length + 1,
|
|
47499
|
+
target: input.target,
|
|
47500
|
+
targetMode: input.targetMode ?? "External",
|
|
47501
|
+
sheetNames: input.sheetNames ? [...input.sheetNames] : [],
|
|
47502
|
+
cachedValues: input.cachedValues ? { ...input.cachedValues } : {}
|
|
47503
|
+
};
|
|
47504
|
+
this.externalLinks.push(link);
|
|
47505
|
+
return link;
|
|
47506
|
+
}
|
|
47507
|
+
/**
|
|
47508
|
+
* Retrieve an external link by its 1-based on-disk index (the number
|
|
47509
|
+
* inside the `[N]` formula prefix) or by matching target path.
|
|
47510
|
+
*/
|
|
47511
|
+
getExternalLink(indexOrTarget) {
|
|
47512
|
+
if (typeof indexOrTarget === "number") return this.externalLinks[indexOrTarget - 1];
|
|
47513
|
+
const lower = indexOrTarget.toLowerCase();
|
|
47514
|
+
return this.externalLinks.find((link) => link.target.toLowerCase() === lower);
|
|
47515
|
+
}
|
|
47516
|
+
/**
|
|
47517
|
+
* @internal — used by the writer to obtain the full list of external
|
|
47518
|
+
* links to serialise, including entries auto-discovered from formula
|
|
47519
|
+
* strings during earlier writes. User-visible `externalLinks` always
|
|
47520
|
+
* comes first (in declaration order) so explicit `addExternalLink()`
|
|
47521
|
+
* indices are stable across writes.
|
|
47522
|
+
*/
|
|
47523
|
+
_collectExternalLinksForWrite() {
|
|
47524
|
+
const userLower = new Set(this.externalLinks.map((l) => l.target.toLowerCase()));
|
|
47525
|
+
const combined = this.externalLinks.map((link, i) => ({
|
|
47526
|
+
...link,
|
|
47527
|
+
index: i + 1,
|
|
47528
|
+
sheetNames: [...link.sheetNames ?? []],
|
|
47529
|
+
cachedValues: { ...link.cachedValues ?? {} },
|
|
47530
|
+
targetMode: link.targetMode ?? "External"
|
|
47531
|
+
}));
|
|
47532
|
+
for (const cached of this._writerExternalLinkCache.values()) {
|
|
47533
|
+
if (userLower.has(cached.target.toLowerCase())) continue;
|
|
47534
|
+
combined.push({
|
|
47535
|
+
...cached,
|
|
47536
|
+
index: combined.length + 1,
|
|
47537
|
+
sheetNames: [...cached.sheetNames],
|
|
47538
|
+
cachedValues: { ...cached.cachedValues }
|
|
47539
|
+
});
|
|
47540
|
+
}
|
|
47541
|
+
return combined;
|
|
47542
|
+
}
|
|
47543
|
+
/**
|
|
47544
|
+
* @internal — record an auto-discovered external link (seen in a
|
|
47545
|
+
* formula but not explicitly declared). Idempotent by target; the
|
|
47546
|
+
* sheet name is upserted onto the existing cached entry when present.
|
|
47547
|
+
* Returns the 1-based index the link will carry in the output file.
|
|
47548
|
+
*/
|
|
47549
|
+
_recordAutoExternalLink(target, sheetName) {
|
|
47550
|
+
const lower = target.toLowerCase();
|
|
47551
|
+
const existingUserIdx = this.externalLinks.findIndex((l) => l.target.toLowerCase() === lower);
|
|
47552
|
+
if (existingUserIdx !== -1) return existingUserIdx + 1;
|
|
47553
|
+
let cached = this._writerExternalLinkCache.get(lower);
|
|
47554
|
+
if (!cached) {
|
|
47555
|
+
cached = {
|
|
47556
|
+
index: 0,
|
|
47557
|
+
target,
|
|
47558
|
+
targetMode: "External",
|
|
47559
|
+
sheetNames: [],
|
|
47560
|
+
cachedValues: {}
|
|
47561
|
+
};
|
|
47562
|
+
this._writerExternalLinkCache.set(lower, cached);
|
|
47563
|
+
}
|
|
47564
|
+
if (sheetName && !cached.sheetNames.includes(sheetName)) cached.sheetNames.push(sheetName);
|
|
47565
|
+
const userCount = this.externalLinks.length;
|
|
47566
|
+
let cacheIdx = 0;
|
|
47567
|
+
for (const key of this._writerExternalLinkCache.keys()) {
|
|
47568
|
+
cacheIdx++;
|
|
47569
|
+
if (key === lower) return userCount + cacheIdx;
|
|
47570
|
+
}
|
|
47571
|
+
return userCount + this._writerExternalLinkCache.size;
|
|
47572
|
+
}
|
|
45635
47573
|
get model() {
|
|
45636
47574
|
return {
|
|
45637
47575
|
creator: this.creator || "Unknown",
|
|
@@ -45640,6 +47578,7 @@ self.onmessage = async function(event) {
|
|
|
45640
47578
|
created: this.created,
|
|
45641
47579
|
modified: this.modified,
|
|
45642
47580
|
properties: this.properties,
|
|
47581
|
+
protection: this.protection,
|
|
45643
47582
|
worksheets: this.worksheets.map((worksheet) => worksheet.model),
|
|
45644
47583
|
sheets: this.worksheets.map((ws) => ws.model).filter(Boolean),
|
|
45645
47584
|
definedNames: this._definedNames.model,
|
|
@@ -45660,7 +47599,8 @@ self.onmessage = async function(event) {
|
|
|
45660
47599
|
calcProperties: this.calcProperties,
|
|
45661
47600
|
passthrough: this._passthrough,
|
|
45662
47601
|
rawDrawings: this._rawDrawings,
|
|
45663
|
-
defaultFont: this._defaultFont
|
|
47602
|
+
defaultFont: this._defaultFont,
|
|
47603
|
+
externalLinks: this.externalLinks
|
|
45664
47604
|
};
|
|
45665
47605
|
}
|
|
45666
47606
|
set model(value) {
|
|
@@ -45680,8 +47620,10 @@ self.onmessage = async function(event) {
|
|
|
45680
47620
|
this.revision = value.revision;
|
|
45681
47621
|
this.contentStatus = value.contentStatus;
|
|
45682
47622
|
this.properties = value.properties;
|
|
47623
|
+
this.protection = value.protection;
|
|
45683
47624
|
this.calcProperties = value.calcProperties;
|
|
45684
47625
|
this._worksheets = [];
|
|
47626
|
+
this._tableNames.clear();
|
|
45685
47627
|
value.worksheets.forEach((worksheetModel) => {
|
|
45686
47628
|
const { id, name, state } = worksheetModel;
|
|
45687
47629
|
const orderNo = value.sheets && value.sheets.findIndex((ws) => ws.id === id);
|
|
@@ -45702,6 +47644,8 @@ self.onmessage = async function(event) {
|
|
|
45702
47644
|
this._passthrough = value.passthrough || {};
|
|
45703
47645
|
this._rawDrawings = value.rawDrawings || {};
|
|
45704
47646
|
this._defaultFont = value.defaultFont;
|
|
47647
|
+
this.externalLinks = value.externalLinks ? [...value.externalLinks] : [];
|
|
47648
|
+
this._writerExternalLinkCache = /* @__PURE__ */ new Map();
|
|
45705
47649
|
}
|
|
45706
47650
|
};
|
|
45707
47651
|
//#endregion
|
|
@@ -52434,22 +54378,6 @@ self.onmessage = async function(event) {
|
|
|
52434
54378
|
//#endregion
|
|
52435
54379
|
//#region src/modules/pdf/excel-bridge.ts
|
|
52436
54380
|
/**
|
|
52437
|
-
* Excel-to-PDF Bridge
|
|
52438
|
-
*
|
|
52439
|
-
* Converts Excel Workbook data into the PDF module's independent data model.
|
|
52440
|
-
* This is the ONLY file in the PDF module that imports from @excel.
|
|
52441
|
-
*
|
|
52442
|
-
* @example
|
|
52443
|
-
* ```typescript
|
|
52444
|
-
* import { Workbook } from "excelts";
|
|
52445
|
-
* import { excelToPdf } from "excelts/pdf";
|
|
52446
|
-
*
|
|
52447
|
-
* const workbook = new Workbook();
|
|
52448
|
-
* // ... build workbook ...
|
|
52449
|
-
* const pdf = await excelToPdf(workbook);
|
|
52450
|
-
* ```
|
|
52451
|
-
*/
|
|
52452
|
-
/**
|
|
52453
54381
|
* Export an Excel Workbook directly to PDF.
|
|
52454
54382
|
*
|
|
52455
54383
|
* This is a convenience function that converts the Workbook to the PDF module's
|
|
@@ -52461,6 +54389,7 @@ self.onmessage = async function(event) {
|
|
|
52461
54389
|
* @returns Promise of PDF file as a Uint8Array
|
|
52462
54390
|
*/
|
|
52463
54391
|
async function excelToPdf(workbook, options) {
|
|
54392
|
+
tryInvokeFormulaEngine(workbook);
|
|
52464
54393
|
return exportPdf(excelWorkbookToPdf(workbook), options);
|
|
52465
54394
|
}
|
|
52466
54395
|
/**
|
|
@@ -52502,7 +54431,7 @@ self.onmessage = async function(event) {
|
|
|
52502
54431
|
if (!row) continue;
|
|
52503
54432
|
const cells = /* @__PURE__ */ new Map();
|
|
52504
54433
|
row.eachCell({ includeEmpty: true }, (cell) => {
|
|
52505
|
-
const hasValue = cell.type !==
|
|
54434
|
+
const hasValue = cell.type !== 0 && cell.type !== 1;
|
|
52506
54435
|
const hasStyle = cell.style && (cell.style.border && (cell.style.border.top || cell.style.border.right || cell.style.border.bottom || cell.style.border.left) || cell.style.fill || cell.style.font);
|
|
52507
54436
|
if (hasValue || hasStyle) cells.set(cell.col, convertCell(cell));
|
|
52508
54437
|
});
|
|
@@ -52589,17 +54518,17 @@ self.onmessage = async function(event) {
|
|
|
52589
54518
|
}
|
|
52590
54519
|
function mapValueType(vt) {
|
|
52591
54520
|
switch (vt) {
|
|
52592
|
-
case
|
|
52593
|
-
case
|
|
52594
|
-
case
|
|
52595
|
-
case
|
|
52596
|
-
case
|
|
52597
|
-
case
|
|
52598
|
-
case
|
|
52599
|
-
case
|
|
52600
|
-
case
|
|
52601
|
-
case
|
|
52602
|
-
case
|
|
54521
|
+
case 0: return PdfCellType.Empty;
|
|
54522
|
+
case 1: return PdfCellType.Merge;
|
|
54523
|
+
case 2: return PdfCellType.Number;
|
|
54524
|
+
case 3:
|
|
54525
|
+
case 7: return PdfCellType.String;
|
|
54526
|
+
case 4: return PdfCellType.Date;
|
|
54527
|
+
case 5: return PdfCellType.Hyperlink;
|
|
54528
|
+
case 6: return PdfCellType.Formula;
|
|
54529
|
+
case 8: return PdfCellType.RichText;
|
|
54530
|
+
case 9: return PdfCellType.Boolean;
|
|
54531
|
+
case 10: return PdfCellType.Error;
|
|
52603
54532
|
default: return PdfCellType.String;
|
|
52604
54533
|
}
|
|
52605
54534
|
}
|
|
@@ -52609,12 +54538,12 @@ self.onmessage = async function(event) {
|
|
|
52609
54538
|
function getCellDisplayText(cell) {
|
|
52610
54539
|
if (!cell) return "";
|
|
52611
54540
|
switch (cell.type) {
|
|
52612
|
-
case
|
|
52613
|
-
case
|
|
52614
|
-
case
|
|
52615
|
-
case
|
|
52616
|
-
case
|
|
52617
|
-
case
|
|
54541
|
+
case 0:
|
|
54542
|
+
case 1: return "";
|
|
54543
|
+
case 8:
|
|
54544
|
+
case 5: return cell.text ?? "";
|
|
54545
|
+
case 10: return cell.value?.error ?? cell.text ?? "";
|
|
54546
|
+
case 6: {
|
|
52618
54547
|
const result = cell.result;
|
|
52619
54548
|
if (result !== void 0 && result !== null) {
|
|
52620
54549
|
if (typeof result === "object" && "error" in result) return result.error;
|
|
@@ -52638,7 +54567,7 @@ self.onmessage = async function(event) {
|
|
|
52638
54567
|
return String(value);
|
|
52639
54568
|
}
|
|
52640
54569
|
function convertCellValue(cell) {
|
|
52641
|
-
if (cell.type ===
|
|
54570
|
+
if (cell.type === 8) {
|
|
52642
54571
|
const rtValue = cell.value;
|
|
52643
54572
|
if (rtValue?.richText) return { richText: rtValue.richText.map((run) => ({
|
|
52644
54573
|
text: run.text,
|