@cj-tech-master/excelts 1.6.3 → 2.0.0-canary.20251228013952.4f2c3c6
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 +139 -24
- package/README_zh.md +140 -26
- package/dist/browser/excelts.esm.js +18468 -0
- package/dist/browser/excelts.esm.js.map +1 -0
- package/dist/browser/excelts.esm.min.js +125 -0
- package/dist/browser/excelts.iife.js +13107 -47146
- package/dist/browser/excelts.iife.js.map +1 -1
- package/dist/browser/excelts.iife.min.js +24 -106
- package/dist/cjs/csv/csv-core.js +701 -0
- package/dist/cjs/csv/csv-stream.js +646 -0
- package/dist/cjs/csv/csv.base.js +137 -0
- package/dist/cjs/csv/csv.browser.js +68 -0
- package/dist/cjs/csv/csv.js +218 -162
- package/dist/cjs/doc/anchor.js +2 -2
- package/dist/cjs/doc/cell.js +22 -22
- package/dist/cjs/doc/column.js +28 -7
- package/dist/cjs/doc/data-validations.js +3 -3
- package/dist/cjs/doc/defined-names.js +13 -13
- package/dist/cjs/doc/image.js +7 -7
- package/dist/cjs/doc/modelcontainer.js +2 -2
- package/dist/cjs/doc/note.js +2 -2
- package/dist/cjs/doc/pivot-table.js +5 -5
- package/dist/cjs/doc/range.js +11 -11
- package/dist/cjs/doc/row.js +16 -16
- package/dist/cjs/doc/table.js +5 -5
- package/dist/cjs/doc/workbook.base.js +211 -0
- package/dist/cjs/doc/workbook.browser.js +62 -0
- package/dist/cjs/doc/workbook.js +68 -179
- package/dist/cjs/doc/worksheet.js +45 -41
- package/dist/cjs/index.js +49 -32
- package/dist/cjs/stream/xlsx/hyperlink-reader.js +6 -6
- package/dist/cjs/stream/xlsx/sheet-comments-writer.js +12 -12
- package/dist/cjs/stream/xlsx/sheet-rels-writer.js +4 -4
- package/dist/cjs/stream/xlsx/workbook-reader.js +22 -22
- package/dist/cjs/stream/xlsx/workbook-writer.js +38 -38
- package/dist/cjs/stream/xlsx/worksheet-reader.js +17 -17
- package/dist/cjs/stream/xlsx/worksheet-writer.js +67 -60
- package/dist/cjs/utils/browser-buffer.js +75 -0
- package/dist/cjs/utils/cell-format.js +2 -2
- package/dist/cjs/utils/cell-matrix.js +5 -5
- package/dist/cjs/utils/datetime.js +499 -0
- package/dist/cjs/utils/encryptor.browser.js +240 -0
- package/dist/cjs/utils/parse-sax.js +1191 -13
- package/dist/cjs/utils/shared-formula.js +5 -5
- package/dist/cjs/utils/sheet-utils.js +13 -13
- package/dist/cjs/utils/stream-buf.browser.js +355 -0
- package/dist/cjs/utils/stream-buf.js +5 -5
- package/dist/cjs/utils/unzip/extract.js +11 -11
- package/dist/cjs/utils/unzip/index.js +21 -21
- package/dist/cjs/utils/unzip/parse-extra-field.js +3 -3
- package/dist/cjs/utils/unzip/parse.js +16 -16
- package/dist/cjs/utils/unzip/zip-parser.js +14 -3
- package/dist/cjs/utils/utils.base.js +161 -0
- package/dist/cjs/utils/utils.browser.js +89 -0
- package/dist/cjs/utils/utils.js +46 -154
- package/dist/cjs/utils/xml-stream.js +3 -3
- package/dist/cjs/utils/zip/compress.base.js +88 -0
- package/dist/cjs/utils/zip/compress.browser.js +127 -0
- package/dist/cjs/utils/zip/compress.js +18 -198
- package/dist/cjs/utils/zip/crc32.browser.js +88 -0
- package/dist/cjs/utils/zip/deflate-fallback.js +575 -0
- package/dist/cjs/utils/zip/index.js +17 -17
- package/dist/cjs/utils/zip/streaming-zip.js +264 -0
- package/dist/cjs/utils/zip/zip-builder.js +10 -10
- package/dist/cjs/utils/zip-stream.browser.js +135 -0
- package/dist/cjs/utils/zip-stream.js +4 -4
- package/dist/cjs/xlsx/xform/base-xform.js +4 -4
- package/dist/cjs/xlsx/xform/book/defined-name-xform.js +4 -4
- package/dist/cjs/xlsx/xform/book/sheet-xform.js +4 -4
- package/dist/cjs/xlsx/xform/book/workbook-calc-properties-xform.js +2 -2
- package/dist/cjs/xlsx/xform/book/workbook-pivot-cache-xform.js +2 -2
- package/dist/cjs/xlsx/xform/book/workbook-properties-xform.js +2 -2
- package/dist/cjs/xlsx/xform/book/workbook-view-xform.js +2 -2
- package/dist/cjs/xlsx/xform/book/workbook-xform.js +24 -24
- package/dist/cjs/xlsx/xform/comment/comment-xform.js +4 -4
- package/dist/cjs/xlsx/xform/comment/comments-xform.js +6 -6
- package/dist/cjs/xlsx/xform/comment/style/vml-position-xform.js +2 -2
- package/dist/cjs/xlsx/xform/comment/style/vml-protection-xform.js +2 -2
- package/dist/cjs/xlsx/xform/comment/vml-anchor-xform.js +2 -2
- package/dist/cjs/xlsx/xform/comment/vml-client-data-xform.js +10 -10
- package/dist/cjs/xlsx/xform/comment/vml-notes-xform.js +6 -6
- package/dist/cjs/xlsx/xform/comment/vml-shape-xform.js +6 -6
- package/dist/cjs/xlsx/xform/comment/vml-textbox-xform.js +2 -2
- package/dist/cjs/xlsx/xform/composite-xform.js +2 -2
- package/dist/cjs/xlsx/xform/core/app-heading-pairs-xform.js +2 -2
- package/dist/cjs/xlsx/xform/core/app-titles-of-parts-xform.js +2 -2
- package/dist/cjs/xlsx/xform/core/app-xform.js +11 -11
- package/dist/cjs/xlsx/xform/core/content-types-xform.js +4 -4
- package/dist/cjs/xlsx/xform/core/core-xform.js +23 -23
- package/dist/cjs/xlsx/xform/core/relationship-xform.js +2 -2
- package/dist/cjs/xlsx/xform/core/relationships-xform.js +6 -6
- package/dist/cjs/xlsx/xform/drawing/base-cell-anchor-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/blip-fill-xform.js +4 -4
- package/dist/cjs/xlsx/xform/drawing/blip-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/c-nv-pic-pr-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/c-nv-pr-xform.js +6 -6
- package/dist/cjs/xlsx/xform/drawing/cell-position-xform.js +7 -7
- package/dist/cjs/xlsx/xform/drawing/drawing-xform.js +10 -10
- package/dist/cjs/xlsx/xform/drawing/ext-lst-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/ext-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/hlink-click-xform.js +2 -2
- package/dist/cjs/xlsx/xform/drawing/nv-pic-pr-xform.js +6 -6
- package/dist/cjs/xlsx/xform/drawing/one-cell-anchor-xform.js +10 -10
- package/dist/cjs/xlsx/xform/drawing/pic-xform.js +9 -9
- package/dist/cjs/xlsx/xform/drawing/two-cell-anchor-xform.js +9 -9
- package/dist/cjs/xlsx/xform/list-xform.js +2 -2
- package/dist/cjs/xlsx/xform/pivot-table/cache-field-xform.js +5 -5
- package/dist/cjs/xlsx/xform/pivot-table/cache-field.js +3 -3
- package/dist/cjs/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +10 -10
- package/dist/cjs/xlsx/xform/pivot-table/pivot-cache-records-xform.js +9 -9
- package/dist/cjs/xlsx/xform/pivot-table/pivot-table-xform.js +10 -11
- package/dist/cjs/xlsx/xform/sheet/auto-filter-xform.js +4 -4
- package/dist/cjs/xlsx/xform/sheet/cell-xform.js +65 -65
- package/dist/cjs/xlsx/xform/sheet/cf/cf-rule-xform.js +27 -27
- package/dist/cjs/xlsx/xform/sheet/cf/cfvo-xform.js +3 -3
- package/dist/cjs/xlsx/xform/sheet/cf/color-scale-xform.js +6 -6
- package/dist/cjs/xlsx/xform/sheet/cf/conditional-formatting-xform.js +6 -6
- package/dist/cjs/xlsx/xform/sheet/cf/conditional-formattings-xform.js +4 -4
- package/dist/cjs/xlsx/xform/sheet/cf/databar-xform.js +6 -6
- package/dist/cjs/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +5 -5
- package/dist/cjs/xlsx/xform/sheet/cf/formula-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/cf/icon-set-xform.js +11 -11
- package/dist/cjs/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +3 -3
- package/dist/cjs/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +11 -12
- package/dist/cjs/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +4 -4
- package/dist/cjs/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +8 -8
- package/dist/cjs/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +6 -6
- package/dist/cjs/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +26 -26
- package/dist/cjs/xlsx/xform/sheet/cf-ext/f-ext-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +14 -14
- package/dist/cjs/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/col-breaks-xform.js +38 -0
- package/dist/cjs/xlsx/xform/sheet/col-xform.js +6 -6
- package/dist/cjs/xlsx/xform/sheet/data-validations-xform.js +18 -18
- package/dist/cjs/xlsx/xform/sheet/dimension-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/drawing-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/ext-lst-xform.js +5 -5
- package/dist/cjs/xlsx/xform/sheet/header-footer-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/hyperlink-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/merge-cell-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/merges.js +8 -8
- package/dist/cjs/xlsx/xform/sheet/outline-properties-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/page-breaks-xform.js +15 -3
- package/dist/cjs/xlsx/xform/sheet/page-margins-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/page-setup-properties-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/page-setup-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/picture-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/print-options-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/row-breaks-xform.js +15 -17
- package/dist/cjs/xlsx/xform/sheet/row-xform.js +11 -11
- package/dist/cjs/xlsx/xform/sheet/sheet-format-properties-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/sheet-properties-xform.js +8 -8
- package/dist/cjs/xlsx/xform/sheet/sheet-protection-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/sheet-view-xform.js +4 -4
- package/dist/cjs/xlsx/xform/sheet/table-part-xform.js +2 -2
- package/dist/cjs/xlsx/xform/sheet/worksheet-xform.js +75 -70
- package/dist/cjs/xlsx/xform/simple/boolean-xform.js +2 -2
- package/dist/cjs/xlsx/xform/simple/date-xform.js +2 -2
- package/dist/cjs/xlsx/xform/simple/float-xform.js +2 -2
- package/dist/cjs/xlsx/xform/simple/integer-xform.js +2 -2
- package/dist/cjs/xlsx/xform/simple/string-xform.js +2 -2
- package/dist/cjs/xlsx/xform/static-xform.js +4 -4
- package/dist/cjs/xlsx/xform/strings/phonetic-text-xform.js +6 -6
- package/dist/cjs/xlsx/xform/strings/rich-text-xform.js +6 -6
- package/dist/cjs/xlsx/xform/strings/shared-string-xform.js +8 -8
- package/dist/cjs/xlsx/xform/strings/shared-strings-xform.js +6 -6
- package/dist/cjs/xlsx/xform/strings/text-xform.js +2 -2
- package/dist/cjs/xlsx/xform/style/alignment-xform.js +8 -8
- package/dist/cjs/xlsx/xform/style/border-xform.js +8 -8
- package/dist/cjs/xlsx/xform/style/color-xform.js +2 -2
- package/dist/cjs/xlsx/xform/style/dxf-xform.js +14 -14
- package/dist/cjs/xlsx/xform/style/fill-xform.js +9 -9
- package/dist/cjs/xlsx/xform/style/font-xform.js +22 -22
- package/dist/cjs/xlsx/xform/style/numfmt-xform.js +5 -5
- package/dist/cjs/xlsx/xform/style/protection-xform.js +2 -2
- package/dist/cjs/xlsx/xform/style/style-xform.js +6 -6
- package/dist/cjs/xlsx/xform/style/styles-xform.js +39 -39
- package/dist/cjs/xlsx/xform/style/underline-xform.js +2 -2
- package/dist/cjs/xlsx/xform/table/auto-filter-xform.js +4 -4
- package/dist/cjs/xlsx/xform/table/custom-filter-xform.js +2 -2
- package/dist/cjs/xlsx/xform/table/filter-column-xform.js +9 -9
- package/dist/cjs/xlsx/xform/table/filter-xform.js +2 -2
- package/dist/cjs/xlsx/xform/table/table-column-xform.js +2 -2
- package/dist/cjs/xlsx/xform/table/table-style-info-xform.js +2 -2
- package/dist/cjs/xlsx/xform/table/table-xform.js +12 -12
- package/dist/cjs/xlsx/xlsx.base.js +742 -0
- package/dist/cjs/xlsx/xlsx.browser.js +162 -0
- package/dist/cjs/xlsx/xlsx.js +118 -892
- package/dist/esm/csv/csv-core.js +694 -0
- package/dist/esm/csv/csv-stream.js +638 -0
- package/dist/esm/csv/csv.base.js +127 -0
- package/dist/esm/csv/csv.browser.js +65 -0
- package/dist/esm/csv/csv.js +181 -159
- package/dist/esm/doc/column.js +21 -0
- package/dist/esm/doc/workbook.base.js +207 -0
- package/dist/esm/doc/workbook.browser.js +59 -0
- package/dist/esm/doc/workbook.js +64 -175
- package/dist/esm/doc/worksheet.js +4 -0
- package/dist/esm/index.browser.js +33 -1
- package/dist/esm/index.js +23 -8
- package/dist/esm/local.js +0 -1
- package/dist/esm/stream/xlsx/workbook-writer.js +1 -1
- package/dist/esm/stream/xlsx/worksheet-writer.js +8 -1
- package/dist/esm/utils/browser-buffer.js +67 -0
- package/dist/esm/utils/datetime.js +493 -0
- package/dist/esm/utils/encryptor.browser.js +237 -0
- package/dist/esm/utils/parse-sax.js +1188 -12
- package/dist/esm/utils/stream-buf.browser.js +352 -0
- package/dist/esm/utils/unzip/zip-parser.js +11 -0
- package/dist/esm/utils/utils.base.js +142 -0
- package/dist/esm/utils/utils.browser.js +68 -0
- package/dist/esm/utils/utils.js +15 -123
- package/dist/esm/utils/zip/compress.base.js +83 -0
- package/dist/esm/utils/zip/compress.browser.js +121 -0
- package/dist/esm/utils/zip/compress.js +16 -164
- package/dist/esm/utils/zip/crc32.browser.js +82 -0
- package/dist/esm/utils/zip/deflate-fallback.js +570 -0
- package/dist/esm/utils/zip/streaming-zip.js +259 -0
- package/dist/esm/utils/zip-stream.browser.js +132 -0
- package/dist/esm/xlsx/xform/pivot-table/pivot-table-xform.js +2 -3
- package/dist/esm/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +2 -3
- package/dist/esm/xlsx/xform/sheet/col-breaks-xform.js +35 -0
- package/dist/esm/xlsx/xform/sheet/page-breaks-xform.js +13 -1
- package/dist/esm/xlsx/xform/sheet/row-breaks-xform.js +11 -13
- package/dist/esm/xlsx/xform/sheet/worksheet-xform.js +7 -2
- package/dist/esm/xlsx/xlsx.base.js +739 -0
- package/dist/esm/xlsx/xlsx.browser.js +159 -0
- package/dist/esm/xlsx/xlsx.js +114 -888
- package/dist/types/csv/csv-core.d.ts +207 -0
- package/dist/types/csv/csv-stream.d.ts +114 -0
- package/dist/types/csv/csv.base.d.ts +62 -0
- package/dist/types/csv/csv.browser.d.ts +33 -0
- package/dist/types/csv/csv.d.ts +97 -71
- package/dist/types/doc/anchor.d.ts +1 -1
- package/dist/types/doc/cell.d.ts +7 -7
- package/dist/types/doc/column.d.ts +9 -3
- package/dist/types/doc/defined-names.d.ts +4 -4
- package/dist/types/doc/image.d.ts +2 -2
- package/dist/types/doc/modelcontainer.d.ts +1 -1
- package/dist/types/doc/pivot-table.d.ts +1 -1
- package/dist/types/doc/range.d.ts +1 -1
- package/dist/types/doc/row.d.ts +3 -3
- package/dist/types/doc/table.d.ts +2 -2
- package/dist/types/doc/workbook.base.d.ts +111 -0
- package/dist/types/doc/workbook.browser.d.ts +38 -0
- package/dist/types/doc/workbook.d.ts +62 -92
- package/dist/types/doc/worksheet.d.ts +12 -10
- package/dist/types/index.browser.d.ts +19 -5
- package/dist/types/index.d.ts +24 -23
- package/dist/types/local.d.ts +0 -1
- package/dist/types/stream/xlsx/hyperlink-reader.d.ts +1 -1
- package/dist/types/stream/xlsx/workbook-reader.d.ts +4 -4
- package/dist/types/stream/xlsx/workbook-writer.d.ts +7 -7
- package/dist/types/stream/xlsx/worksheet-reader.d.ts +5 -5
- package/dist/types/stream/xlsx/worksheet-writer.d.ts +11 -9
- package/dist/types/types.d.ts +6 -0
- package/dist/types/utils/browser-buffer.d.ts +28 -0
- package/dist/types/utils/col-cache.d.ts +1 -1
- package/dist/types/utils/datetime.d.ts +56 -0
- package/dist/types/utils/encryptor.browser.d.ts +28 -0
- package/dist/types/utils/parse-sax.d.ts +108 -1
- package/dist/types/utils/sheet-utils.d.ts +3 -3
- package/dist/types/utils/stream-buf.browser.d.ts +41 -0
- package/dist/types/utils/unzip/extract.d.ts +6 -6
- package/dist/types/utils/unzip/index.d.ts +8 -8
- package/dist/types/utils/unzip/parse.d.ts +3 -3
- package/dist/types/utils/unzip/zip-parser.d.ts +5 -0
- package/dist/types/utils/utils.base.d.ts +29 -0
- package/dist/types/utils/utils.browser.d.ts +29 -0
- package/dist/types/utils/utils.d.ts +6 -25
- package/dist/types/utils/zip/compress.base.d.ts +45 -0
- package/dist/types/utils/zip/compress.browser.d.ts +63 -0
- package/dist/types/utils/zip/compress.d.ts +13 -45
- package/dist/types/utils/zip/crc32.browser.d.ts +52 -0
- package/dist/types/utils/zip/deflate-fallback.d.ts +39 -0
- package/dist/types/utils/zip/index.d.ts +5 -5
- package/dist/types/utils/zip/streaming-zip.d.ts +96 -0
- package/dist/types/utils/zip/zip-builder.d.ts +1 -1
- package/dist/types/utils/zip-stream.browser.d.ts +39 -0
- package/dist/types/xlsx/xform/base-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/defined-name-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/sheet-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/workbook-calc-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/workbook-pivot-cache-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/workbook-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/workbook-view-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/book/workbook-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/comment/comment-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/comment/comments-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/comment/style/vml-position-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/style/vml-protection-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/vml-anchor-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/vml-client-data-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/vml-notes-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/vml-shape-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/comment/vml-textbox-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/composite-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/app-heading-pairs-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/app-titles-of-parts-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/app-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/content-types-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/core-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/relationship-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/core/relationships-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/base-cell-anchor-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/blip-fill-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/drawing/blip-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/c-nv-pic-pr-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/c-nv-pr-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/cell-position-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/drawing/drawing-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/ext-lst-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/ext-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/hlink-click-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/nv-pic-pr-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/pic-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/list-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/pivot-table/cache-field-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/pivot-table/pivot-cache-definition-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/pivot-table/pivot-cache-records-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/pivot-table/pivot-table-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/auto-filter-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cell-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf/cf-rule-xform.d.ts +6 -6
- package/dist/types/xlsx/xform/sheet/cf/cfvo-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf/color-scale-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf/conditional-formatting-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf/conditional-formattings-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/sheet/cf/databar-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf/ext-lst-ref-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf/formula-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf/icon-set-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/sheet/cf-ext/databar-ext-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf-ext/f-ext-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/sheet/cf-ext/sqref-ext-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/col-breaks-xform.d.ts +16 -0
- package/dist/types/xlsx/xform/sheet/col-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/data-validations-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/dimension-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/drawing-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/header-footer-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/hyperlink-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/merge-cell-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/outline-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/page-breaks-xform.d.ts +5 -1
- package/dist/types/xlsx/xform/sheet/page-margins-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/page-setup-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/page-setup-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/picture-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/print-options-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/row-breaks-xform.d.ts +5 -1
- package/dist/types/xlsx/xform/sheet/row-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/sheet-format-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/sheet-properties-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/sheet-protection-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/sheet-view-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/table-part-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/sheet/worksheet-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/simple/boolean-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/simple/date-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/simple/float-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/simple/integer-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/simple/string-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/static-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/strings/phonetic-text-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/strings/rich-text-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/strings/shared-string-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/strings/shared-strings-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/strings/text-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/alignment-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/border-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/style/color-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/dxf-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/fill-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/style/font-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/numfmt-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/protection-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/style/style-xform.d.ts +3 -3
- package/dist/types/xlsx/xform/style/styles-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/style/underline-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/table/auto-filter-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/table/custom-filter-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/table/filter-column-xform.d.ts +2 -2
- package/dist/types/xlsx/xform/table/filter-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/table/table-column-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/table/table-style-info-xform.d.ts +1 -1
- package/dist/types/xlsx/xform/table/table-xform.d.ts +1 -1
- package/dist/types/xlsx/xlsx.base.d.ts +134 -0
- package/dist/types/xlsx/xlsx.browser.d.ts +31 -0
- package/dist/types/xlsx/xlsx.d.ts +20 -80
- package/package.json +16 -39
package/dist/cjs/xlsx/xlsx.js
CHANGED
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XLSX - Node.js version with full functionality
|
|
4
|
+
*
|
|
5
|
+
* Extends XLSXBase with:
|
|
6
|
+
* - readFile: Read from file path
|
|
7
|
+
* - writeFile: Write to file path
|
|
8
|
+
* - read: Read from stream
|
|
9
|
+
* - write: Write to stream
|
|
10
|
+
* - load: Load from buffer
|
|
11
|
+
* - writeBuffer: Write to buffer
|
|
12
|
+
*/
|
|
2
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
17
|
exports.XLSX = void 0;
|
|
7
18
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const fflate_1 = require("fflate");
|
|
9
19
|
const stream_1 = require("stream");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const core_xform_js_1 = require("./xform/core/core-xform");
|
|
16
|
-
const shared_strings_xform_js_1 = require("./xform/strings/shared-strings-xform");
|
|
17
|
-
const relationships_xform_js_1 = require("./xform/core/relationships-xform");
|
|
18
|
-
const content_types_xform_js_1 = require("./xform/core/content-types-xform");
|
|
19
|
-
const app_xform_js_1 = require("./xform/core/app-xform");
|
|
20
|
-
const workbook_xform_js_1 = require("./xform/book/workbook-xform");
|
|
21
|
-
const worksheet_xform_js_1 = require("./xform/sheet/worksheet-xform");
|
|
22
|
-
const drawing_xform_js_1 = require("./xform/drawing/drawing-xform");
|
|
23
|
-
const table_xform_js_1 = require("./xform/table/table-xform");
|
|
24
|
-
const pivot_cache_records_xform_js_1 = require("./xform/pivot-table/pivot-cache-records-xform");
|
|
25
|
-
const pivot_cache_definition_xform_js_1 = require("./xform/pivot-table/pivot-cache-definition-xform");
|
|
26
|
-
const pivot_table_xform_js_1 = require("./xform/pivot-table/pivot-table-xform");
|
|
27
|
-
const comments_xform_js_1 = require("./xform/comment/comments-xform");
|
|
28
|
-
const vml_notes_xform_js_1 = require("./xform/comment/vml-notes-xform");
|
|
29
|
-
const theme1_js_1 = require("./xml/theme1");
|
|
30
|
-
const rel_type_js_1 = require("./rel-type");
|
|
20
|
+
const zip_parser_1 = require("../utils/unzip/zip-parser");
|
|
21
|
+
const zip_stream_1 = require("../utils/zip-stream");
|
|
22
|
+
const stream_buf_1 = require("../utils/stream-buf");
|
|
23
|
+
const utils_1 = require("../utils/utils");
|
|
24
|
+
const xlsx_base_1 = require("./xlsx.base");
|
|
31
25
|
function fsReadFileAsync(filename, options) {
|
|
32
26
|
return new Promise((resolve, reject) => {
|
|
33
27
|
fs_1.default.readFile(filename, options, (error, data) => {
|
|
@@ -40,16 +34,34 @@ function fsReadFileAsync(filename, options) {
|
|
|
40
34
|
});
|
|
41
35
|
});
|
|
42
36
|
}
|
|
43
|
-
class XLSX {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
class XLSX extends xlsx_base_1.XLSXBase {
|
|
38
|
+
// ===========================================================================
|
|
39
|
+
// Abstract method implementations
|
|
40
|
+
// ===========================================================================
|
|
41
|
+
createStreamBuf() {
|
|
42
|
+
return new stream_buf_1.StreamBuf();
|
|
43
|
+
}
|
|
44
|
+
createBinaryStream(data) {
|
|
45
|
+
const stream = new stream_1.PassThrough();
|
|
46
|
+
stream.end(Buffer.from(data));
|
|
47
|
+
return stream;
|
|
48
|
+
}
|
|
49
|
+
createTextStream(content) {
|
|
50
|
+
const stream = new stream_1.PassThrough({
|
|
51
|
+
readableObjectMode: true,
|
|
52
|
+
writableObjectMode: true
|
|
53
|
+
});
|
|
54
|
+
stream.end(content);
|
|
55
|
+
return stream;
|
|
56
|
+
}
|
|
57
|
+
bufferToString(data) {
|
|
58
|
+
return (0, utils_1.bufferToString)(data);
|
|
59
|
+
}
|
|
60
|
+
// ===========================================================================
|
|
61
|
+
// Node.js specific: File operations
|
|
62
|
+
// ===========================================================================
|
|
51
63
|
async readFile(filename, options) {
|
|
52
|
-
if (!(await (0,
|
|
64
|
+
if (!(await (0, utils_1.fileExists)(filename))) {
|
|
53
65
|
throw new Error(`File not found: ${filename}`);
|
|
54
66
|
}
|
|
55
67
|
const stream = fs_1.default.createReadStream(filename);
|
|
@@ -63,425 +75,102 @@ class XLSX {
|
|
|
63
75
|
throw error;
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
parseWorkbook(stream) {
|
|
71
|
-
const xform = new workbook_xform_js_1.WorkbookXform();
|
|
72
|
-
return xform.parseStream(stream);
|
|
73
|
-
}
|
|
74
|
-
parseSharedStrings(stream) {
|
|
75
|
-
const xform = new shared_strings_xform_js_1.SharedStringsXform();
|
|
76
|
-
return xform.parseStream(stream);
|
|
77
|
-
}
|
|
78
|
-
reconcile(model, options) {
|
|
79
|
-
const workbookXform = new workbook_xform_js_1.WorkbookXform();
|
|
80
|
-
const worksheetXform = new worksheet_xform_js_1.WorkSheetXform(options);
|
|
81
|
-
const drawingXform = new drawing_xform_js_1.DrawingXform();
|
|
82
|
-
const tableXform = new table_xform_js_1.TableXform();
|
|
83
|
-
workbookXform.reconcile(model);
|
|
84
|
-
// reconcile drawings with their rels
|
|
85
|
-
const drawingOptions = {
|
|
86
|
-
media: model.media,
|
|
87
|
-
mediaIndex: model.mediaIndex
|
|
88
|
-
};
|
|
89
|
-
Object.keys(model.drawings).forEach(name => {
|
|
90
|
-
const drawing = model.drawings[name];
|
|
91
|
-
const drawingRel = model.drawingRels[name];
|
|
92
|
-
if (drawingRel) {
|
|
93
|
-
drawingOptions.rels = drawingRel.reduce((o, rel) => {
|
|
94
|
-
o[rel.Id] = rel;
|
|
95
|
-
return o;
|
|
96
|
-
}, {});
|
|
97
|
-
(drawing.anchors || []).forEach((anchor) => {
|
|
98
|
-
const hyperlinks = anchor.picture && anchor.picture.hyperlinks;
|
|
99
|
-
if (hyperlinks && drawingOptions.rels[hyperlinks.rId]) {
|
|
100
|
-
hyperlinks.hyperlink = drawingOptions.rels[hyperlinks.rId].Target;
|
|
101
|
-
delete hyperlinks.rId;
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
drawingXform.reconcile(drawing, drawingOptions);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
// reconcile tables with the default styles
|
|
108
|
-
const tableOptions = {
|
|
109
|
-
styles: model.styles
|
|
110
|
-
};
|
|
111
|
-
Object.values(model.tables).forEach((table) => {
|
|
112
|
-
tableXform.reconcile(table, tableOptions);
|
|
113
|
-
});
|
|
114
|
-
// Reconcile pivot tables - link pivot tables to worksheets and cache data
|
|
115
|
-
this._reconcilePivotTables(model);
|
|
116
|
-
const sheetOptions = {
|
|
117
|
-
styles: model.styles,
|
|
118
|
-
sharedStrings: model.sharedStrings,
|
|
119
|
-
media: model.media,
|
|
120
|
-
mediaIndex: model.mediaIndex,
|
|
121
|
-
date1904: model.properties && model.properties.date1904,
|
|
122
|
-
drawings: model.drawings,
|
|
123
|
-
comments: model.comments,
|
|
124
|
-
tables: model.tables,
|
|
125
|
-
vmlDrawings: model.vmlDrawings,
|
|
126
|
-
pivotTables: model.pivotTablesIndexed
|
|
127
|
-
};
|
|
128
|
-
model.worksheets.forEach((worksheet) => {
|
|
129
|
-
worksheet.relationships = model.worksheetRels[worksheet.sheetNo];
|
|
130
|
-
worksheetXform.reconcile(worksheet, sheetOptions);
|
|
131
|
-
});
|
|
132
|
-
// delete unnecessary parts
|
|
133
|
-
delete model.worksheetHash;
|
|
134
|
-
delete model.worksheetRels;
|
|
135
|
-
delete model.globalRels;
|
|
136
|
-
delete model.sharedStrings;
|
|
137
|
-
delete model.workbookRels;
|
|
138
|
-
delete model.sheetDefs;
|
|
139
|
-
delete model.styles;
|
|
140
|
-
delete model.mediaIndex;
|
|
141
|
-
delete model.drawings;
|
|
142
|
-
delete model.drawingRels;
|
|
143
|
-
delete model.vmlDrawings;
|
|
144
|
-
// Clean up raw pivot table data after reconciliation
|
|
145
|
-
delete model.pivotTableRels;
|
|
146
|
-
delete model.pivotCacheDefinitionRels;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Reconcile pivot tables by linking them to worksheets and their cache data.
|
|
150
|
-
* This builds a complete pivot table model ready for writing.
|
|
151
|
-
*/
|
|
152
|
-
_reconcilePivotTables(model) {
|
|
153
|
-
// Skip if no pivot tables were loaded (object is empty or undefined)
|
|
154
|
-
const rawPivotTables = model.pivotTables || {};
|
|
155
|
-
if (typeof rawPivotTables !== "object" || Object.keys(rawPivotTables).length === 0) {
|
|
156
|
-
// Ensure pivotTables is an empty array (not an object)
|
|
157
|
-
model.pivotTables = [];
|
|
158
|
-
// Also create an empty indexed object for worksheet reconciliation
|
|
159
|
-
model.pivotTablesIndexed = {};
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
// Build mapping from definition name to cacheId
|
|
163
|
-
const definitionToCacheId = this._buildDefinitionToCacheIdMap(model);
|
|
164
|
-
// Build a map of cache IDs to their definitions and records
|
|
165
|
-
const cacheMap = new Map();
|
|
166
|
-
// Process cache definitions
|
|
167
|
-
Object.entries(model.pivotCacheDefinitions || {}).forEach(([name, definition]) => {
|
|
168
|
-
// Get the cacheId from the mapping (derived from workbook.xml pivotCaches)
|
|
169
|
-
const cacheId = definitionToCacheId.get(name);
|
|
170
|
-
if (cacheId !== undefined) {
|
|
171
|
-
const recordsName = name.replace("Definition", "Records");
|
|
172
|
-
cacheMap.set(cacheId, {
|
|
173
|
-
definition,
|
|
174
|
-
records: model.pivotCacheRecords?.[recordsName],
|
|
175
|
-
definitionName: name
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// Process pivot tables and link to worksheets
|
|
180
|
-
const loadedPivotTables = [];
|
|
181
|
-
// Create indexed object for worksheet reconciliation (keyed by relative path)
|
|
182
|
-
const pivotTablesIndexed = {};
|
|
183
|
-
Object.entries(rawPivotTables).forEach(([pivotName, pivotTable]) => {
|
|
184
|
-
const pt = pivotTable;
|
|
185
|
-
const tableNumber = this._extractTableNumber(pivotName);
|
|
186
|
-
// Get cache data for this pivot table
|
|
187
|
-
const cacheData = cacheMap.get(pt.cacheId);
|
|
188
|
-
// Build complete pivot table model
|
|
189
|
-
const completePivotTable = {
|
|
190
|
-
// Core model data
|
|
191
|
-
...pt,
|
|
192
|
-
tableNumber,
|
|
193
|
-
// Link to cache data
|
|
194
|
-
cacheDefinition: cacheData?.definition,
|
|
195
|
-
cacheRecords: cacheData?.records,
|
|
196
|
-
// Reconstruct cacheFields from definition for compatibility
|
|
197
|
-
cacheFields: cacheData?.definition?.cacheFields || [],
|
|
198
|
-
// Determine rows, columns, values from parsed data
|
|
199
|
-
rows: pt.rowFields.filter(f => f >= 0),
|
|
200
|
-
columns: pt.colFields.filter(f => f >= 0 && f !== -2),
|
|
201
|
-
values: pt.dataFields.map(df => df.fld),
|
|
202
|
-
// Determine metric from dataFields
|
|
203
|
-
metric: this._determineMetric(pt.dataFields),
|
|
204
|
-
// Preserve formatting options
|
|
205
|
-
applyWidthHeightFormats: pt.applyWidthHeightFormats || "0"
|
|
206
|
-
};
|
|
207
|
-
loadedPivotTables.push(completePivotTable);
|
|
208
|
-
// Index by relative path for worksheet reconciliation
|
|
209
|
-
pivotTablesIndexed[`../pivotTables/${pivotName}.xml`] = completePivotTable;
|
|
210
|
-
});
|
|
211
|
-
// Sort by table number to maintain order
|
|
212
|
-
loadedPivotTables.sort((a, b) => a.tableNumber - b.tableNumber);
|
|
213
|
-
// Replace pivotTables object with the processed array
|
|
214
|
-
// This is what the Workbook model setter expects
|
|
215
|
-
model.pivotTables = loadedPivotTables;
|
|
216
|
-
// Also keep indexed version for worksheet reconciliation
|
|
217
|
-
model.pivotTablesIndexed = pivotTablesIndexed;
|
|
218
|
-
// Also keep as loadedPivotTables for backward compatibility
|
|
219
|
-
model.loadedPivotTables = loadedPivotTables;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Extract table number from pivot table name (e.g., "pivotTable1" -> 1)
|
|
223
|
-
*/
|
|
224
|
-
_extractTableNumber(name) {
|
|
225
|
-
const match = name.match(/pivotTable(\d+)/);
|
|
226
|
-
return match ? parseInt(match[1], 10) : 1;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Build a mapping from rId to cacheId using pivotCaches from workbook.xml
|
|
230
|
-
* and workbookRels to determine which definition file corresponds to which cacheId
|
|
231
|
-
*/
|
|
232
|
-
_buildCacheIdMap(model) {
|
|
233
|
-
const rIdToCacheId = new Map();
|
|
234
|
-
// pivotCaches from workbook.xml contains {cacheId, rId} mappings
|
|
235
|
-
const pivotCaches = model.pivotCaches || [];
|
|
236
|
-
for (const cache of pivotCaches) {
|
|
237
|
-
if (cache.cacheId && cache.rId) {
|
|
238
|
-
rIdToCacheId.set(cache.rId, parseInt(cache.cacheId, 10));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return rIdToCacheId;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Build a mapping from definition name to cacheId
|
|
245
|
-
*/
|
|
246
|
-
_buildDefinitionToCacheIdMap(model) {
|
|
247
|
-
const definitionToCacheId = new Map();
|
|
248
|
-
const rIdToCacheId = this._buildCacheIdMap(model);
|
|
249
|
-
const workbookRels = model.workbookRels || [];
|
|
250
|
-
// Map workbook rels to get definitionNumber -> cacheId mapping
|
|
251
|
-
for (const rel of workbookRels) {
|
|
252
|
-
if (rel.Type === XLSX.RelType.PivotCacheDefinition && rel.Target) {
|
|
253
|
-
// Extract definition number from target (e.g., "pivotCache/pivotCacheDefinition1.xml" -> 1)
|
|
254
|
-
const match = rel.Target.match(/pivotCacheDefinition(\d+)\.xml/);
|
|
255
|
-
if (match) {
|
|
256
|
-
const defName = `pivotCacheDefinition${match[1]}`;
|
|
257
|
-
const cacheId = rIdToCacheId.get(rel.Id);
|
|
258
|
-
if (cacheId !== undefined) {
|
|
259
|
-
definitionToCacheId.set(defName, cacheId);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return definitionToCacheId;
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Determine the aggregation metric from dataFields
|
|
268
|
-
*/
|
|
269
|
-
_determineMetric(dataFields) {
|
|
270
|
-
if (dataFields.length > 0 && dataFields[0].subtotal === "count") {
|
|
271
|
-
return "count";
|
|
272
|
-
}
|
|
273
|
-
return "sum";
|
|
274
|
-
}
|
|
275
|
-
async _processWorksheetEntry(stream, model, sheetNo, options, path) {
|
|
276
|
-
const xform = new worksheet_xform_js_1.WorkSheetXform(options);
|
|
277
|
-
const worksheet = await xform.parseStream(stream);
|
|
278
|
-
if (!worksheet) {
|
|
279
|
-
throw new Error(`Failed to parse worksheet ${path}`);
|
|
280
|
-
}
|
|
281
|
-
worksheet.sheetNo = sheetNo;
|
|
282
|
-
model.worksheetHash[path] = worksheet;
|
|
283
|
-
model.worksheets.push(worksheet);
|
|
284
|
-
}
|
|
285
|
-
async _processCommentEntry(stream, model, name) {
|
|
286
|
-
const xform = new comments_xform_js_1.CommentsXform();
|
|
287
|
-
const comments = await xform.parseStream(stream);
|
|
288
|
-
model.comments[`../${name}.xml`] = comments;
|
|
289
|
-
}
|
|
290
|
-
async _processTableEntry(stream, model, name) {
|
|
291
|
-
const xform = new table_xform_js_1.TableXform();
|
|
292
|
-
const table = await xform.parseStream(stream);
|
|
293
|
-
model.tables[`../tables/${name}.xml`] = table;
|
|
294
|
-
}
|
|
295
|
-
async _processWorksheetRelsEntry(stream, model, sheetNo) {
|
|
296
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
297
|
-
const relationships = await xform.parseStream(stream);
|
|
298
|
-
model.worksheetRels[sheetNo] = relationships;
|
|
299
|
-
}
|
|
300
|
-
async _processMediaEntry(stream, model, filename) {
|
|
301
|
-
const lastDot = filename.lastIndexOf(".");
|
|
302
|
-
// if we can't determine extension, ignore it
|
|
303
|
-
if (lastDot >= 1) {
|
|
304
|
-
const extension = filename.substr(lastDot + 1);
|
|
305
|
-
const name = filename.substr(0, lastDot);
|
|
306
|
-
await new Promise((resolve, reject) => {
|
|
307
|
-
const streamBuf = new stream_buf_js_1.StreamBuf();
|
|
308
|
-
const cleanup = () => {
|
|
309
|
-
stream.removeListener("error", onError);
|
|
310
|
-
streamBuf.removeListener("error", onError);
|
|
311
|
-
streamBuf.removeListener("finish", onFinish);
|
|
312
|
-
};
|
|
313
|
-
const onFinish = () => {
|
|
314
|
-
cleanup();
|
|
315
|
-
model.mediaIndex[filename] = model.media.length;
|
|
316
|
-
model.mediaIndex[name] = model.media.length;
|
|
317
|
-
const medium = {
|
|
318
|
-
type: "image",
|
|
319
|
-
name,
|
|
320
|
-
extension,
|
|
321
|
-
buffer: streamBuf.toBuffer()
|
|
322
|
-
};
|
|
323
|
-
model.media.push(medium);
|
|
324
|
-
resolve();
|
|
325
|
-
};
|
|
326
|
-
const onError = (error) => {
|
|
327
|
-
cleanup();
|
|
328
|
-
reject(error);
|
|
329
|
-
};
|
|
330
|
-
streamBuf.once("finish", onFinish);
|
|
331
|
-
stream.on("error", onError);
|
|
332
|
-
streamBuf.on("error", onError);
|
|
333
|
-
stream.pipe(streamBuf);
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
async _processDrawingEntry(entry, model, name) {
|
|
338
|
-
const xform = new drawing_xform_js_1.DrawingXform();
|
|
339
|
-
const drawing = await xform.parseStream(entry);
|
|
340
|
-
model.drawings[name] = drawing;
|
|
341
|
-
}
|
|
342
|
-
async _processDrawingRelsEntry(entry, model, name) {
|
|
343
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
344
|
-
const relationships = await xform.parseStream(entry);
|
|
345
|
-
model.drawingRels[name] = relationships;
|
|
346
|
-
}
|
|
347
|
-
async _processVmlDrawingEntry(entry, model, name) {
|
|
348
|
-
const xform = new vml_notes_xform_js_1.VmlNotesXform();
|
|
349
|
-
const vmlDrawing = await xform.parseStream(entry);
|
|
350
|
-
model.vmlDrawings[`../drawings/${name}.vml`] = vmlDrawing;
|
|
351
|
-
}
|
|
352
|
-
async _processThemeEntry(stream, model, name) {
|
|
353
|
-
await new Promise((resolve, reject) => {
|
|
354
|
-
// TODO: stream entry into buffer and store the xml in the model.themes[]
|
|
355
|
-
const streamBuf = new stream_buf_js_1.StreamBuf();
|
|
78
|
+
writeFile(filename, options) {
|
|
79
|
+
const stream = fs_1.default.createWriteStream(filename);
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
356
81
|
const cleanup = () => {
|
|
82
|
+
stream.removeListener("finish", onFinish);
|
|
357
83
|
stream.removeListener("error", onError);
|
|
358
|
-
streamBuf.removeListener("error", onError);
|
|
359
|
-
streamBuf.removeListener("finish", onFinish);
|
|
360
84
|
};
|
|
361
85
|
const onFinish = () => {
|
|
362
86
|
cleanup();
|
|
363
|
-
model.themes[name] = streamBuf.read().toString();
|
|
364
87
|
resolve();
|
|
365
88
|
};
|
|
366
|
-
const onError = (
|
|
89
|
+
const onError = (error) => {
|
|
367
90
|
cleanup();
|
|
368
|
-
reject(
|
|
91
|
+
reject(error);
|
|
369
92
|
};
|
|
370
|
-
|
|
93
|
+
stream.once("finish", onFinish);
|
|
371
94
|
stream.on("error", onError);
|
|
372
|
-
|
|
373
|
-
|
|
95
|
+
this.write(stream, options)
|
|
96
|
+
.then(() => {
|
|
97
|
+
stream.end();
|
|
98
|
+
})
|
|
99
|
+
.catch(err => {
|
|
100
|
+
cleanup();
|
|
101
|
+
reject(err);
|
|
102
|
+
});
|
|
374
103
|
});
|
|
375
104
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
if (pivotTable) {
|
|
380
|
-
model.pivotTables[name] = pivotTable;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
async _processPivotTableRelsEntry(stream, model, name) {
|
|
384
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
385
|
-
const relationships = await xform.parseStream(stream);
|
|
386
|
-
model.pivotTableRels[name] = relationships;
|
|
387
|
-
}
|
|
388
|
-
async _processPivotCacheDefinitionEntry(stream, model, name) {
|
|
389
|
-
const xform = new pivot_cache_definition_xform_js_1.PivotCacheDefinitionXform();
|
|
390
|
-
const cacheDefinition = await xform.parseStream(stream);
|
|
391
|
-
if (cacheDefinition) {
|
|
392
|
-
model.pivotCacheDefinitions[name] = cacheDefinition;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
async _processPivotCacheDefinitionRelsEntry(stream, model, name) {
|
|
396
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
397
|
-
const relationships = await xform.parseStream(stream);
|
|
398
|
-
model.pivotCacheDefinitionRels[name] = relationships;
|
|
399
|
-
}
|
|
400
|
-
async _processPivotCacheRecordsEntry(stream, model, name) {
|
|
401
|
-
const xform = new pivot_cache_records_xform_js_1.PivotCacheRecordsXform();
|
|
402
|
-
const cacheRecords = await xform.parseStream(stream);
|
|
403
|
-
if (cacheRecords) {
|
|
404
|
-
model.pivotCacheRecords[name] = cacheRecords;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
105
|
+
// ===========================================================================
|
|
106
|
+
// Node.js specific: Stream operations
|
|
107
|
+
// ===========================================================================
|
|
407
108
|
async read(stream, options) {
|
|
408
|
-
//
|
|
409
|
-
const
|
|
109
|
+
// Collect all stream data into a single buffer
|
|
110
|
+
const chunks = [];
|
|
410
111
|
await new Promise((resolve, reject) => {
|
|
411
|
-
let filesProcessed = 0;
|
|
412
|
-
let zipEnded = false;
|
|
413
|
-
let filesStarted = 0;
|
|
414
|
-
const cleanup = () => {
|
|
415
|
-
stream.removeListener("data", onData);
|
|
416
|
-
stream.removeListener("end", onEnd);
|
|
417
|
-
stream.removeListener("error", onError);
|
|
418
|
-
};
|
|
419
|
-
const checkCompletion = () => {
|
|
420
|
-
if (zipEnded && filesProcessed === filesStarted) {
|
|
421
|
-
cleanup();
|
|
422
|
-
resolve();
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
const unzipper = new fflate_1.Unzip((file) => {
|
|
426
|
-
filesStarted++;
|
|
427
|
-
const fileChunks = [];
|
|
428
|
-
let totalLength = 0;
|
|
429
|
-
file.ondata = (err, data, final) => {
|
|
430
|
-
if (err) {
|
|
431
|
-
cleanup();
|
|
432
|
-
reject(err);
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
if (data) {
|
|
436
|
-
fileChunks.push(data);
|
|
437
|
-
totalLength += data.length;
|
|
438
|
-
}
|
|
439
|
-
if (final) {
|
|
440
|
-
// Optimize for single chunk case
|
|
441
|
-
if (fileChunks.length === 1) {
|
|
442
|
-
allFiles[file.name] = fileChunks[0];
|
|
443
|
-
}
|
|
444
|
-
else if (fileChunks.length > 1) {
|
|
445
|
-
const fullData = new Uint8Array(totalLength);
|
|
446
|
-
let offset = 0;
|
|
447
|
-
for (const chunk of fileChunks) {
|
|
448
|
-
fullData.set(chunk, offset);
|
|
449
|
-
offset += chunk.length;
|
|
450
|
-
}
|
|
451
|
-
allFiles[file.name] = fullData;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
allFiles[file.name] = new Uint8Array(0);
|
|
455
|
-
}
|
|
456
|
-
filesProcessed++;
|
|
457
|
-
fileChunks.length = 0;
|
|
458
|
-
checkCompletion();
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
file.start();
|
|
462
|
-
});
|
|
463
|
-
unzipper.register(fflate_1.UnzipInflate);
|
|
464
112
|
const onData = (chunk) => {
|
|
465
|
-
|
|
113
|
+
chunks.push(chunk);
|
|
466
114
|
};
|
|
467
115
|
const onEnd = () => {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
116
|
+
stream.removeListener("data", onData);
|
|
117
|
+
stream.removeListener("end", onEnd);
|
|
118
|
+
stream.removeListener("error", onError);
|
|
119
|
+
resolve();
|
|
471
120
|
};
|
|
472
121
|
const onError = (err) => {
|
|
473
|
-
|
|
122
|
+
stream.removeListener("data", onData);
|
|
123
|
+
stream.removeListener("end", onEnd);
|
|
124
|
+
stream.removeListener("error", onError);
|
|
474
125
|
reject(err);
|
|
475
126
|
};
|
|
476
127
|
stream.on("data", onData);
|
|
477
128
|
stream.on("end", onEnd);
|
|
478
129
|
stream.on("error", onError);
|
|
479
130
|
});
|
|
131
|
+
// Combine chunks into a single buffer
|
|
132
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
133
|
+
const buffer = new Uint8Array(totalLength);
|
|
134
|
+
let offset = 0;
|
|
135
|
+
for (const chunk of chunks) {
|
|
136
|
+
buffer.set(chunk, offset);
|
|
137
|
+
offset += chunk.length;
|
|
138
|
+
}
|
|
139
|
+
// Use native ZipParser for extraction
|
|
140
|
+
const parser = new zip_parser_1.ZipParser(buffer);
|
|
141
|
+
const filesMap = await parser.extractAll();
|
|
142
|
+
// Convert Map to Record for loadFromFiles
|
|
143
|
+
const allFiles = {};
|
|
144
|
+
for (const [path, content] of filesMap) {
|
|
145
|
+
allFiles[path] = content;
|
|
146
|
+
}
|
|
480
147
|
return this.loadFromFiles(allFiles, options);
|
|
481
148
|
}
|
|
149
|
+
async write(stream, options) {
|
|
150
|
+
options = options || {};
|
|
151
|
+
const { model } = this.workbook;
|
|
152
|
+
const zip = new zip_stream_1.ZipWriter(options.zip);
|
|
153
|
+
zip.pipe(stream);
|
|
154
|
+
this.prepareModel(model, options);
|
|
155
|
+
await this.addContentTypes(zip, model);
|
|
156
|
+
await this.addOfficeRels(zip, model);
|
|
157
|
+
await this.addWorkbookRels(zip, model);
|
|
158
|
+
await this.addWorksheets(zip, model);
|
|
159
|
+
await this.addSharedStrings(zip, model);
|
|
160
|
+
this.addDrawings(zip, model);
|
|
161
|
+
this.addTables(zip, model);
|
|
162
|
+
this.addPivotTables(zip, model);
|
|
163
|
+
await Promise.all([this.addThemes(zip, model), this.addStyles(zip, model)]);
|
|
164
|
+
await this.addMedia(zip, model);
|
|
165
|
+
await Promise.all([this.addApp(zip, model), this.addCore(zip, model)]);
|
|
166
|
+
await this.addWorkbook(zip, model);
|
|
167
|
+
return this._finalize(zip);
|
|
168
|
+
}
|
|
169
|
+
// ===========================================================================
|
|
170
|
+
// Node.js specific: Buffer operations
|
|
171
|
+
// ===========================================================================
|
|
482
172
|
async load(data, options) {
|
|
483
173
|
let buffer;
|
|
484
|
-
// Validate input type
|
|
485
174
|
if (!data ||
|
|
486
175
|
(typeof data === "object" &&
|
|
487
176
|
!Buffer.isBuffer(data) &&
|
|
@@ -495,299 +184,18 @@ class XLSX {
|
|
|
495
184
|
else {
|
|
496
185
|
buffer = data;
|
|
497
186
|
}
|
|
498
|
-
|
|
499
|
-
const PassThroughStream = stream_1.PassThrough;
|
|
500
|
-
const stream = new PassThroughStream();
|
|
187
|
+
const stream = new stream_1.PassThrough();
|
|
501
188
|
stream.end(buffer);
|
|
502
189
|
return this.read(stream, options);
|
|
503
190
|
}
|
|
504
|
-
async
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
worksheetRels: [],
|
|
509
|
-
themes: {},
|
|
510
|
-
media: [],
|
|
511
|
-
mediaIndex: {},
|
|
512
|
-
drawings: {},
|
|
513
|
-
drawingRels: {},
|
|
514
|
-
comments: {},
|
|
515
|
-
tables: {},
|
|
516
|
-
vmlDrawings: {},
|
|
517
|
-
// Pivot table storage for loaded files
|
|
518
|
-
pivotTables: {},
|
|
519
|
-
pivotTableRels: {},
|
|
520
|
-
pivotCacheDefinitions: {},
|
|
521
|
-
pivotCacheDefinitionRels: {},
|
|
522
|
-
pivotCacheRecords: {}
|
|
523
|
-
};
|
|
524
|
-
// Convert fflate format to JSZip-like structure for compatibility
|
|
525
|
-
const entries = Object.keys(zipData).map(name => ({
|
|
526
|
-
name,
|
|
527
|
-
dir: name.endsWith("/"),
|
|
528
|
-
data: zipData[name]
|
|
529
|
-
}));
|
|
530
|
-
for (const entry of entries) {
|
|
531
|
-
if (!entry.dir) {
|
|
532
|
-
let entryName = entry.name;
|
|
533
|
-
if (entryName[0] === "/") {
|
|
534
|
-
entryName = entryName.substr(1);
|
|
535
|
-
}
|
|
536
|
-
let stream;
|
|
537
|
-
if (entryName.match(/xl\/media\//) ||
|
|
538
|
-
// themes are not parsed as stream
|
|
539
|
-
entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)) {
|
|
540
|
-
stream = new stream_1.PassThrough();
|
|
541
|
-
stream.end(Buffer.from(entry.data));
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
// use object mode to avoid buffer-string convention
|
|
545
|
-
stream = new stream_1.PassThrough({
|
|
546
|
-
readableObjectMode: true,
|
|
547
|
-
writableObjectMode: true
|
|
548
|
-
});
|
|
549
|
-
const content = (0, utils_js_1.bufferToString)(Buffer.from(entry.data));
|
|
550
|
-
stream.end(content);
|
|
551
|
-
}
|
|
552
|
-
let match;
|
|
553
|
-
match = entryName.match(/xl\/worksheets\/sheet(\d+)[.]xml/);
|
|
554
|
-
if (match) {
|
|
555
|
-
const sheetNo = parseInt(match[1], 10);
|
|
556
|
-
await this._processWorksheetEntry(stream, model, sheetNo, options, entryName);
|
|
557
|
-
}
|
|
558
|
-
else {
|
|
559
|
-
switch (entryName) {
|
|
560
|
-
case "_rels/.rels":
|
|
561
|
-
model.globalRels = await this.parseRels(stream);
|
|
562
|
-
break;
|
|
563
|
-
case "xl/workbook.xml": {
|
|
564
|
-
const workbook = await this.parseWorkbook(stream);
|
|
565
|
-
model.sheets = workbook.sheets;
|
|
566
|
-
model.definedNames = workbook.definedNames;
|
|
567
|
-
model.views = workbook.views;
|
|
568
|
-
model.properties = workbook.properties;
|
|
569
|
-
model.calcProperties = workbook.calcProperties;
|
|
570
|
-
// pivotCaches contains the mapping from rId to cacheId
|
|
571
|
-
// needed for linking pivot tables to their cache data
|
|
572
|
-
model.pivotCaches = workbook.pivotCaches;
|
|
573
|
-
break;
|
|
574
|
-
}
|
|
575
|
-
case "xl/sharedStrings.xml":
|
|
576
|
-
model.sharedStrings = new shared_strings_xform_js_1.SharedStringsXform();
|
|
577
|
-
await model.sharedStrings.parseStream(stream);
|
|
578
|
-
break;
|
|
579
|
-
case "xl/_rels/workbook.xml.rels":
|
|
580
|
-
model.workbookRels = await this.parseRels(stream);
|
|
581
|
-
break;
|
|
582
|
-
case "docProps/app.xml": {
|
|
583
|
-
const appXform = new app_xform_js_1.AppXform();
|
|
584
|
-
const appProperties = await appXform.parseStream(stream);
|
|
585
|
-
model.company = appProperties.company;
|
|
586
|
-
model.manager = appProperties.manager;
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
case "docProps/core.xml": {
|
|
590
|
-
const coreXform = new core_xform_js_1.CoreXform();
|
|
591
|
-
const coreProperties = await coreXform.parseStream(stream);
|
|
592
|
-
Object.assign(model, coreProperties);
|
|
593
|
-
break;
|
|
594
|
-
}
|
|
595
|
-
case "xl/styles.xml":
|
|
596
|
-
model.styles = new styles_xform_js_1.StylesXform();
|
|
597
|
-
await model.styles.parseStream(stream);
|
|
598
|
-
break;
|
|
599
|
-
default: {
|
|
600
|
-
match = entryName.match(/xl\/worksheets\/_rels\/sheet(\d+)[.]xml[.]rels/);
|
|
601
|
-
if (match) {
|
|
602
|
-
const sheetNo = parseInt(match[1], 10);
|
|
603
|
-
await this._processWorksheetRelsEntry(stream, model, sheetNo);
|
|
604
|
-
break;
|
|
605
|
-
}
|
|
606
|
-
match = entryName.match(/xl\/media\/([a-zA-Z0-9]+[.][a-zA-Z0-9]{3,4})$/);
|
|
607
|
-
if (match) {
|
|
608
|
-
await this._processMediaEntry(stream, model, match[1]);
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
match = entryName.match(/xl\/drawings\/(drawing\d+)[.]xml/);
|
|
612
|
-
if (match) {
|
|
613
|
-
await this._processDrawingEntry(stream, model, match[1]);
|
|
614
|
-
break;
|
|
615
|
-
}
|
|
616
|
-
match = entryName.match(/xl\/drawings\/_rels\/(drawing\d+)[.]xml[.]rels/);
|
|
617
|
-
if (match) {
|
|
618
|
-
await this._processDrawingRelsEntry(stream, model, match[1]);
|
|
619
|
-
break;
|
|
620
|
-
}
|
|
621
|
-
match = entryName.match(/xl\/drawings\/(vmlDrawing\d+)[.]vml/);
|
|
622
|
-
if (match) {
|
|
623
|
-
await this._processVmlDrawingEntry(stream, model, match[1]);
|
|
624
|
-
break;
|
|
625
|
-
}
|
|
626
|
-
match = entryName.match(/xl\/comments(\d+)[.]xml/);
|
|
627
|
-
if (match) {
|
|
628
|
-
await this._processCommentEntry(stream, model, `comments${match[1]}`);
|
|
629
|
-
break;
|
|
630
|
-
}
|
|
631
|
-
match = entryName.match(/xl\/tables\/(table\d+)[.]xml/);
|
|
632
|
-
if (match) {
|
|
633
|
-
await this._processTableEntry(stream, model, match[1]);
|
|
634
|
-
break;
|
|
635
|
-
}
|
|
636
|
-
match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/);
|
|
637
|
-
if (match) {
|
|
638
|
-
await this._processThemeEntry(stream, model, match[1]);
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
641
|
-
// Pivot table files
|
|
642
|
-
match = entryName.match(/xl\/pivotTables\/(pivotTable\d+)[.]xml/);
|
|
643
|
-
if (match) {
|
|
644
|
-
await this._processPivotTableEntry(stream, model, match[1]);
|
|
645
|
-
break;
|
|
646
|
-
}
|
|
647
|
-
match = entryName.match(/xl\/pivotTables\/_rels\/(pivotTable\d+)[.]xml[.]rels/);
|
|
648
|
-
if (match) {
|
|
649
|
-
await this._processPivotTableRelsEntry(stream, model, match[1]);
|
|
650
|
-
break;
|
|
651
|
-
}
|
|
652
|
-
// Pivot cache files
|
|
653
|
-
match = entryName.match(/xl\/pivotCache\/(pivotCacheDefinition\d+)[.]xml/);
|
|
654
|
-
if (match) {
|
|
655
|
-
await this._processPivotCacheDefinitionEntry(stream, model, match[1]);
|
|
656
|
-
break;
|
|
657
|
-
}
|
|
658
|
-
match = entryName.match(/xl\/pivotCache\/_rels\/(pivotCacheDefinition\d+)[.]xml[.]rels/);
|
|
659
|
-
if (match) {
|
|
660
|
-
await this._processPivotCacheDefinitionRelsEntry(stream, model, match[1]);
|
|
661
|
-
break;
|
|
662
|
-
}
|
|
663
|
-
match = entryName.match(/xl\/pivotCache\/(pivotCacheRecords\d+)[.]xml/);
|
|
664
|
-
if (match) {
|
|
665
|
-
await this._processPivotCacheRecordsEntry(stream, model, match[1]);
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
this.reconcile(model, options);
|
|
674
|
-
// apply model
|
|
675
|
-
this.workbook.model = model;
|
|
676
|
-
return this.workbook;
|
|
677
|
-
}
|
|
678
|
-
// =========================================================================
|
|
679
|
-
// Write
|
|
680
|
-
async addContentTypes(zip, model) {
|
|
681
|
-
const xform = new content_types_xform_js_1.ContentTypesXform();
|
|
682
|
-
const xml = xform.toXml(model);
|
|
683
|
-
zip.append(xml, { name: "[Content_Types].xml" });
|
|
684
|
-
}
|
|
685
|
-
async addApp(zip, model) {
|
|
686
|
-
const xform = new app_xform_js_1.AppXform();
|
|
687
|
-
const xml = xform.toXml(model);
|
|
688
|
-
zip.append(xml, { name: "docProps/app.xml" });
|
|
689
|
-
}
|
|
690
|
-
async addCore(zip, model) {
|
|
691
|
-
const xform = new core_xform_js_1.CoreXform();
|
|
692
|
-
zip.append(xform.toXml(model), { name: "docProps/core.xml" });
|
|
693
|
-
}
|
|
694
|
-
async addThemes(zip, model) {
|
|
695
|
-
const themes = model.themes || { theme1: theme1_js_1.theme1Xml };
|
|
696
|
-
Object.keys(themes).forEach(name => {
|
|
697
|
-
const xml = themes[name];
|
|
698
|
-
const path = `xl/theme/${name}.xml`;
|
|
699
|
-
zip.append(xml, { name: path });
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
async addOfficeRels(zip, _model) {
|
|
703
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
704
|
-
const xml = xform.toXml([
|
|
705
|
-
{ Id: "rId1", Type: XLSX.RelType.OfficeDocument, Target: "xl/workbook.xml" },
|
|
706
|
-
{ Id: "rId2", Type: XLSX.RelType.CoreProperties, Target: "docProps/core.xml" },
|
|
707
|
-
{ Id: "rId3", Type: XLSX.RelType.ExtenderProperties, Target: "docProps/app.xml" }
|
|
708
|
-
]);
|
|
709
|
-
zip.append(xml, { name: "_rels/.rels" });
|
|
710
|
-
}
|
|
711
|
-
async addWorkbookRels(zip, model) {
|
|
712
|
-
let count = 1;
|
|
713
|
-
const relationships = [
|
|
714
|
-
{ Id: `rId${count++}`, Type: XLSX.RelType.Styles, Target: "styles.xml" },
|
|
715
|
-
{ Id: `rId${count++}`, Type: XLSX.RelType.Theme, Target: "theme/theme1.xml" }
|
|
716
|
-
];
|
|
717
|
-
if (model.sharedStrings.count) {
|
|
718
|
-
relationships.push({
|
|
719
|
-
Id: `rId${count++}`,
|
|
720
|
-
Type: XLSX.RelType.SharedStrings,
|
|
721
|
-
Target: "sharedStrings.xml"
|
|
722
|
-
});
|
|
723
|
-
}
|
|
724
|
-
// Add relationships for all pivot tables
|
|
725
|
-
(model.pivotTables || []).forEach((pivotTable) => {
|
|
726
|
-
pivotTable.rId = `rId${count++}`;
|
|
727
|
-
relationships.push({
|
|
728
|
-
Id: pivotTable.rId,
|
|
729
|
-
Type: XLSX.RelType.PivotCacheDefinition,
|
|
730
|
-
Target: `pivotCache/pivotCacheDefinition${pivotTable.tableNumber}.xml`
|
|
731
|
-
});
|
|
732
|
-
});
|
|
733
|
-
model.worksheets.forEach((worksheet, index) => {
|
|
734
|
-
// Use sequential index (1-based) for file naming, not worksheet.id (sheetId)
|
|
735
|
-
// sheetId can be non-sequential (e.g., 1, 3, 5) which would create gaps in filenames
|
|
736
|
-
worksheet.rId = `rId${count++}`;
|
|
737
|
-
worksheet.fileIndex = index + 1; // Store for use in addWorksheets and content types
|
|
738
|
-
relationships.push({
|
|
739
|
-
Id: worksheet.rId,
|
|
740
|
-
Type: XLSX.RelType.Worksheet,
|
|
741
|
-
Target: `worksheets/sheet${worksheet.fileIndex}.xml`
|
|
742
|
-
});
|
|
743
|
-
});
|
|
744
|
-
const xform = new relationships_xform_js_1.RelationshipsXform();
|
|
745
|
-
const xml = xform.toXml(relationships);
|
|
746
|
-
zip.append(xml, { name: "xl/_rels/workbook.xml.rels" });
|
|
747
|
-
}
|
|
748
|
-
async addSharedStrings(zip, model) {
|
|
749
|
-
if (model.sharedStrings && model.sharedStrings.count) {
|
|
750
|
-
zip.append(model.sharedStrings.xml, { name: "xl/sharedStrings.xml" });
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
async addStyles(zip, model) {
|
|
754
|
-
const { xml } = model.styles;
|
|
755
|
-
if (xml) {
|
|
756
|
-
zip.append(xml, { name: "xl/styles.xml" });
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
async addWorkbook(zip, model) {
|
|
760
|
-
const xform = new workbook_xform_js_1.WorkbookXform();
|
|
761
|
-
zip.append(xform.toXml(model), { name: "xl/workbook.xml" });
|
|
762
|
-
}
|
|
763
|
-
async addWorksheets(zip, model) {
|
|
764
|
-
// preparation phase
|
|
765
|
-
const worksheetXform = new worksheet_xform_js_1.WorkSheetXform();
|
|
766
|
-
const relationshipsXform = new relationships_xform_js_1.RelationshipsXform();
|
|
767
|
-
const commentsXform = new comments_xform_js_1.CommentsXform();
|
|
768
|
-
const vmlNotesXform = new vml_notes_xform_js_1.VmlNotesXform();
|
|
769
|
-
// write sheets
|
|
770
|
-
model.worksheets.forEach((worksheet, index) => {
|
|
771
|
-
// Use fileIndex if set by addWorkbookRels, otherwise use index + 1
|
|
772
|
-
const fileIndex = worksheet.fileIndex || index + 1;
|
|
773
|
-
let xmlStream = new xml_stream_js_1.XmlStream();
|
|
774
|
-
worksheetXform.render(xmlStream, worksheet);
|
|
775
|
-
zip.append(xmlStream.xml, { name: `xl/worksheets/sheet${fileIndex}.xml` });
|
|
776
|
-
if (worksheet.rels && worksheet.rels.length) {
|
|
777
|
-
xmlStream = new xml_stream_js_1.XmlStream();
|
|
778
|
-
relationshipsXform.render(xmlStream, worksheet.rels);
|
|
779
|
-
zip.append(xmlStream.xml, { name: `xl/worksheets/_rels/sheet${fileIndex}.xml.rels` });
|
|
780
|
-
}
|
|
781
|
-
if (worksheet.comments.length > 0) {
|
|
782
|
-
xmlStream = new xml_stream_js_1.XmlStream();
|
|
783
|
-
commentsXform.render(xmlStream, worksheet);
|
|
784
|
-
zip.append(xmlStream.xml, { name: `xl/comments${fileIndex}.xml` });
|
|
785
|
-
xmlStream = new xml_stream_js_1.XmlStream();
|
|
786
|
-
vmlNotesXform.render(xmlStream, worksheet);
|
|
787
|
-
zip.append(xmlStream.xml, { name: `xl/drawings/vmlDrawing${fileIndex}.vml` });
|
|
788
|
-
}
|
|
789
|
-
});
|
|
191
|
+
async writeBuffer(options) {
|
|
192
|
+
const stream = new stream_buf_1.StreamBuf();
|
|
193
|
+
await this.write(stream, options);
|
|
194
|
+
return stream.read();
|
|
790
195
|
}
|
|
196
|
+
// ===========================================================================
|
|
197
|
+
// Node.js specific: Media handling with file support
|
|
198
|
+
// ===========================================================================
|
|
791
199
|
async addMedia(zip, model) {
|
|
792
200
|
await Promise.all(model.media.map(async (medium) => {
|
|
793
201
|
if (medium.type === "image") {
|
|
@@ -808,187 +216,5 @@ class XLSX {
|
|
|
808
216
|
throw new Error("Unsupported media");
|
|
809
217
|
}));
|
|
810
218
|
}
|
|
811
|
-
addDrawings(zip, model) {
|
|
812
|
-
const drawingXform = new drawing_xform_js_1.DrawingXform();
|
|
813
|
-
const relsXform = new relationships_xform_js_1.RelationshipsXform();
|
|
814
|
-
model.worksheets.forEach((worksheet) => {
|
|
815
|
-
const { drawing } = worksheet;
|
|
816
|
-
if (drawing) {
|
|
817
|
-
drawingXform.prepare(drawing);
|
|
818
|
-
let xml = drawingXform.toXml(drawing);
|
|
819
|
-
zip.append(xml, { name: `xl/drawings/${drawing.name}.xml` });
|
|
820
|
-
xml = relsXform.toXml(drawing.rels);
|
|
821
|
-
zip.append(xml, { name: `xl/drawings/_rels/${drawing.name}.xml.rels` });
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
addTables(zip, model) {
|
|
826
|
-
const tableXform = new table_xform_js_1.TableXform();
|
|
827
|
-
model.worksheets.forEach((worksheet) => {
|
|
828
|
-
const { tables } = worksheet;
|
|
829
|
-
tables.forEach((table) => {
|
|
830
|
-
tableXform.prepare(table, {});
|
|
831
|
-
const tableXml = tableXform.toXml(table);
|
|
832
|
-
zip.append(tableXml, { name: `xl/tables/${table.target}` });
|
|
833
|
-
});
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
addPivotTables(zip, model) {
|
|
837
|
-
if (!model.pivotTables.length) {
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
const pivotCacheRecordsXform = new pivot_cache_records_xform_js_1.PivotCacheRecordsXform();
|
|
841
|
-
const pivotCacheDefinitionXform = new pivot_cache_definition_xform_js_1.PivotCacheDefinitionXform();
|
|
842
|
-
const pivotTableXform = new pivot_table_xform_js_1.PivotTableXform();
|
|
843
|
-
const relsXform = new relationships_xform_js_1.RelationshipsXform();
|
|
844
|
-
// Generate files for each pivot table
|
|
845
|
-
model.pivotTables.forEach((pivotTable) => {
|
|
846
|
-
const n = pivotTable.tableNumber;
|
|
847
|
-
// For loaded pivot tables, use the stored cache data
|
|
848
|
-
// For new pivot tables, use the source data
|
|
849
|
-
const isLoaded = pivotTable.isLoaded;
|
|
850
|
-
if (isLoaded) {
|
|
851
|
-
// Loaded pivot table - use stored cache definition and records
|
|
852
|
-
if (pivotTable.cacheDefinition) {
|
|
853
|
-
const xml = pivotCacheDefinitionXform.toXml(pivotTable.cacheDefinition);
|
|
854
|
-
zip.append(xml, { name: `xl/pivotCache/pivotCacheDefinition${n}.xml` });
|
|
855
|
-
}
|
|
856
|
-
if (pivotTable.cacheRecords) {
|
|
857
|
-
const xml = pivotCacheRecordsXform.toXml(pivotTable.cacheRecords);
|
|
858
|
-
zip.append(xml, { name: `xl/pivotCache/pivotCacheRecords${n}.xml` });
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
else {
|
|
862
|
-
// New pivot table - generate from source
|
|
863
|
-
let xml = pivotCacheRecordsXform.toXml(pivotTable);
|
|
864
|
-
zip.append(xml, { name: `xl/pivotCache/pivotCacheRecords${n}.xml` });
|
|
865
|
-
xml = pivotCacheDefinitionXform.toXml(pivotTable);
|
|
866
|
-
zip.append(xml, { name: `xl/pivotCache/pivotCacheDefinition${n}.xml` });
|
|
867
|
-
}
|
|
868
|
-
// pivot cache definition rels (same for both)
|
|
869
|
-
let xml = relsXform.toXml([
|
|
870
|
-
{
|
|
871
|
-
Id: "rId1",
|
|
872
|
-
Type: XLSX.RelType.PivotCacheRecords,
|
|
873
|
-
Target: `pivotCacheRecords${n}.xml`
|
|
874
|
-
}
|
|
875
|
-
]);
|
|
876
|
-
zip.append(xml, { name: `xl/pivotCache/_rels/pivotCacheDefinition${n}.xml.rels` });
|
|
877
|
-
// pivot table
|
|
878
|
-
xml = pivotTableXform.toXml(pivotTable);
|
|
879
|
-
zip.append(xml, { name: `xl/pivotTables/pivotTable${n}.xml` });
|
|
880
|
-
xml = relsXform.toXml([
|
|
881
|
-
{
|
|
882
|
-
Id: "rId1",
|
|
883
|
-
Type: XLSX.RelType.PivotCacheDefinition,
|
|
884
|
-
Target: `../pivotCache/pivotCacheDefinition${n}.xml`
|
|
885
|
-
}
|
|
886
|
-
]);
|
|
887
|
-
zip.append(xml, { name: `xl/pivotTables/_rels/pivotTable${n}.xml.rels` });
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
_finalize(zip) {
|
|
891
|
-
return new Promise((resolve, reject) => {
|
|
892
|
-
zip.on("finish", () => {
|
|
893
|
-
resolve(this);
|
|
894
|
-
});
|
|
895
|
-
zip.on("error", reject);
|
|
896
|
-
zip.finalize();
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
prepareModel(model, options) {
|
|
900
|
-
// ensure following properties have sane values
|
|
901
|
-
model.creator = model.creator || "ExcelTS";
|
|
902
|
-
model.lastModifiedBy = model.lastModifiedBy || "ExcelTS";
|
|
903
|
-
model.created = model.created || new Date();
|
|
904
|
-
model.modified = model.modified || new Date();
|
|
905
|
-
model.useSharedStrings =
|
|
906
|
-
options.useSharedStrings !== undefined ? options.useSharedStrings : true;
|
|
907
|
-
model.useStyles = options.useStyles !== undefined ? options.useStyles : true;
|
|
908
|
-
// Manage the shared strings
|
|
909
|
-
model.sharedStrings = new shared_strings_xform_js_1.SharedStringsXform();
|
|
910
|
-
// add a style manager to handle cell formats, fonts, etc.
|
|
911
|
-
model.styles = model.useStyles ? new styles_xform_js_1.StylesXform(true) : new styles_xform_js_1.StylesXform.Mock();
|
|
912
|
-
// prepare all of the things before the render
|
|
913
|
-
const workbookXform = new workbook_xform_js_1.WorkbookXform();
|
|
914
|
-
const worksheetXform = new worksheet_xform_js_1.WorkSheetXform();
|
|
915
|
-
workbookXform.prepare(model);
|
|
916
|
-
const worksheetOptions = {
|
|
917
|
-
sharedStrings: model.sharedStrings,
|
|
918
|
-
styles: model.styles,
|
|
919
|
-
date1904: model.properties.date1904,
|
|
920
|
-
drawingsCount: 0,
|
|
921
|
-
media: model.media
|
|
922
|
-
};
|
|
923
|
-
worksheetOptions.drawings = model.drawings = [];
|
|
924
|
-
worksheetOptions.commentRefs = model.commentRefs = [];
|
|
925
|
-
let tableCount = 0;
|
|
926
|
-
model.tables = [];
|
|
927
|
-
model.worksheets.forEach((worksheet) => {
|
|
928
|
-
// assign unique filenames to tables
|
|
929
|
-
worksheet.tables.forEach((table) => {
|
|
930
|
-
tableCount++;
|
|
931
|
-
table.target = `table${tableCount}.xml`;
|
|
932
|
-
table.id = tableCount;
|
|
933
|
-
model.tables.push(table);
|
|
934
|
-
});
|
|
935
|
-
worksheetXform.prepare(worksheet, worksheetOptions);
|
|
936
|
-
});
|
|
937
|
-
// TODO: workbook drawing list
|
|
938
|
-
}
|
|
939
|
-
async write(stream, options) {
|
|
940
|
-
options = options || {};
|
|
941
|
-
const { model } = this.workbook;
|
|
942
|
-
const zip = new zip_stream_js_1.ZipWriter(options.zip);
|
|
943
|
-
zip.pipe(stream);
|
|
944
|
-
this.prepareModel(model, options);
|
|
945
|
-
// render
|
|
946
|
-
await this.addContentTypes(zip, model);
|
|
947
|
-
await this.addOfficeRels(zip, model);
|
|
948
|
-
await this.addWorkbookRels(zip, model);
|
|
949
|
-
await this.addWorksheets(zip, model);
|
|
950
|
-
await this.addSharedStrings(zip, model); // always after worksheets
|
|
951
|
-
this.addDrawings(zip, model);
|
|
952
|
-
this.addTables(zip, model);
|
|
953
|
-
this.addPivotTables(zip, model);
|
|
954
|
-
await Promise.all([this.addThemes(zip, model), this.addStyles(zip, model)]);
|
|
955
|
-
await this.addMedia(zip, model);
|
|
956
|
-
await Promise.all([this.addApp(zip, model), this.addCore(zip, model)]);
|
|
957
|
-
await this.addWorkbook(zip, model);
|
|
958
|
-
return this._finalize(zip);
|
|
959
|
-
}
|
|
960
|
-
writeFile(filename, options) {
|
|
961
|
-
const stream = fs_1.default.createWriteStream(filename);
|
|
962
|
-
return new Promise((resolve, reject) => {
|
|
963
|
-
const cleanup = () => {
|
|
964
|
-
stream.removeListener("finish", onFinish);
|
|
965
|
-
stream.removeListener("error", onError);
|
|
966
|
-
};
|
|
967
|
-
const onFinish = () => {
|
|
968
|
-
cleanup();
|
|
969
|
-
resolve();
|
|
970
|
-
};
|
|
971
|
-
const onError = (error) => {
|
|
972
|
-
cleanup();
|
|
973
|
-
reject(error);
|
|
974
|
-
};
|
|
975
|
-
stream.once("finish", onFinish);
|
|
976
|
-
stream.on("error", onError);
|
|
977
|
-
this.write(stream, options)
|
|
978
|
-
.then(() => {
|
|
979
|
-
stream.end();
|
|
980
|
-
})
|
|
981
|
-
.catch(err => {
|
|
982
|
-
cleanup();
|
|
983
|
-
reject(err);
|
|
984
|
-
});
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
async writeBuffer(options) {
|
|
988
|
-
const stream = new stream_buf_js_1.StreamBuf();
|
|
989
|
-
await this.write(stream, options);
|
|
990
|
-
return stream.read();
|
|
991
|
-
}
|
|
992
219
|
}
|
|
993
220
|
exports.XLSX = XLSX;
|
|
994
|
-
XLSX.RelType = rel_type_js_1.RelType;
|