@cj-tech-master/excelts 6.2.0 → 7.0.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 +45 -17
- package/README_zh.md +43 -15
- package/dist/browser/index.browser.d.ts +1 -1
- package/dist/browser/index.browser.js +1 -1
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +0 -2
- package/dist/browser/modules/excel/stream/workbook-writer.d.ts +2 -2
- package/dist/browser/modules/excel/types.d.ts +0 -2
- package/dist/browser/modules/pdf/excel-bridge.d.ts +29 -0
- package/dist/browser/modules/pdf/excel-bridge.js +423 -0
- package/dist/browser/modules/pdf/index.d.ts +22 -24
- package/dist/browser/modules/pdf/index.js +22 -25
- package/dist/browser/modules/pdf/pdf.d.ts +121 -0
- package/dist/browser/modules/pdf/pdf.js +255 -0
- package/dist/browser/modules/pdf/render/layout-engine.d.ts +10 -8
- package/dist/browser/modules/pdf/render/layout-engine.js +115 -209
- package/dist/browser/modules/pdf/render/pdf-exporter.d.ts +9 -62
- package/dist/browser/modules/pdf/render/pdf-exporter.js +38 -78
- package/dist/browser/modules/pdf/render/style-converter.d.ts +20 -18
- package/dist/browser/modules/pdf/render/style-converter.js +24 -23
- package/dist/browser/modules/pdf/types.d.ts +193 -11
- package/dist/browser/modules/pdf/types.js +22 -1
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/modules/pdf/excel-bridge.js +426 -0
- package/dist/cjs/modules/pdf/index.js +25 -28
- package/dist/cjs/modules/pdf/pdf.js +258 -0
- package/dist/cjs/modules/pdf/render/layout-engine.js +116 -210
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +37 -79
- package/dist/cjs/modules/pdf/render/style-converter.js +24 -23
- package/dist/cjs/modules/pdf/types.js +23 -2
- package/dist/esm/index.browser.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/modules/pdf/excel-bridge.js +423 -0
- package/dist/esm/modules/pdf/index.js +22 -25
- package/dist/esm/modules/pdf/pdf.js +255 -0
- package/dist/esm/modules/pdf/render/layout-engine.js +115 -209
- package/dist/esm/modules/pdf/render/pdf-exporter.js +38 -78
- package/dist/esm/modules/pdf/render/style-converter.js +24 -23
- package/dist/esm/modules/pdf/types.js +22 -1
- package/dist/iife/excelts.iife.js +728 -251
- 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 +2 -2
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +0 -2
- package/dist/types/modules/excel/stream/workbook-writer.d.ts +2 -2
- package/dist/types/modules/excel/types.d.ts +0 -2
- package/dist/types/modules/pdf/excel-bridge.d.ts +29 -0
- package/dist/types/modules/pdf/index.d.ts +22 -24
- package/dist/types/modules/pdf/pdf.d.ts +121 -0
- package/dist/types/modules/pdf/render/layout-engine.d.ts +10 -8
- package/dist/types/modules/pdf/render/pdf-exporter.d.ts +9 -62
- package/dist/types/modules/pdf/render/style-converter.d.ts +20 -18
- package/dist/types/modules/pdf/types.d.ts +193 -11
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @cj-tech-master/excelts
|
|
2
|
+
* @cj-tech-master/excelts v7.0.0
|
|
3
3
|
* TypeScript Excel Workbook Manager - Read and Write xlsx and csv Files.
|
|
4
4
|
* (c) 2026 cjnoname
|
|
5
5
|
* Released under the MIT License
|
|
@@ -4546,7 +4546,7 @@ var ExcelTS = (function(exports) {
|
|
|
4546
4546
|
* @param cell - A cell (or cell-like object) with `.value`, `.numFmt`, and `.text`
|
|
4547
4547
|
* @param dateFormat - Optional custom date format override
|
|
4548
4548
|
*/
|
|
4549
|
-
function getCellDisplayText(cell, dateFormat) {
|
|
4549
|
+
function getCellDisplayText$1(cell, dateFormat) {
|
|
4550
4550
|
const value = cell.value;
|
|
4551
4551
|
const numFmt = cell.numFmt;
|
|
4552
4552
|
const fmt = typeof numFmt === "string" ? numFmt : numFmt?.formatCode ?? "General";
|
|
@@ -9281,7 +9281,7 @@ var ExcelTS = (function(exports) {
|
|
|
9281
9281
|
const value = cell.value;
|
|
9282
9282
|
if (value && typeof value === "object" && "richText" in value) return measureRichTextWidthPx(value.richText, font);
|
|
9283
9283
|
}
|
|
9284
|
-
const displayText = getCellDisplayText(cell);
|
|
9284
|
+
const displayText = getCellDisplayText$1(cell);
|
|
9285
9285
|
if (!displayText) return 0;
|
|
9286
9286
|
return measureTextWidthPx(displayText, font);
|
|
9287
9287
|
}
|
|
@@ -9301,7 +9301,7 @@ var ExcelTS = (function(exports) {
|
|
|
9301
9301
|
const value = cell.value;
|
|
9302
9302
|
if (value && typeof value === "object" && "richText" in value) return calculateRichTextAutoFitHeight(value.richText, font, alignment, columnWidthPx);
|
|
9303
9303
|
}
|
|
9304
|
-
const displayText = getCellDisplayText(cell);
|
|
9304
|
+
const displayText = getCellDisplayText$1(cell);
|
|
9305
9305
|
if (!displayText) return 0;
|
|
9306
9306
|
return calculateAutoFitHeight(displayText, font, alignment, alignment?.wrapText ? columnWidthPx : void 0);
|
|
9307
9307
|
}
|
|
@@ -10367,7 +10367,7 @@ var ExcelTS = (function(exports) {
|
|
|
10367
10367
|
let isEmpty = true;
|
|
10368
10368
|
for (let col = startCol; col <= endCol; col++) {
|
|
10369
10369
|
const cell = this.getCell(row, col);
|
|
10370
|
-
const val = o.raw === false ? getCellDisplayText(cell, o.dateFormat).trim() : cell.value;
|
|
10370
|
+
const val = o.raw === false ? getCellDisplayText$1(cell, o.dateFormat).trim() : cell.value;
|
|
10371
10371
|
if (val != null && val !== "") {
|
|
10372
10372
|
rowData[col - startCol] = val;
|
|
10373
10373
|
isEmpty = false;
|
|
@@ -10386,7 +10386,7 @@ var ExcelTS = (function(exports) {
|
|
|
10386
10386
|
let isEmpty = true;
|
|
10387
10387
|
for (let col = startCol; col <= endCol; col++) {
|
|
10388
10388
|
const cell = this.getCell(row, col);
|
|
10389
|
-
const val = o.raw === false ? getCellDisplayText(cell, o.dateFormat).trim() : cell.value;
|
|
10389
|
+
const val = o.raw === false ? getCellDisplayText$1(cell, o.dateFormat).trim() : cell.value;
|
|
10390
10390
|
const key = encodeCol(col - 1);
|
|
10391
10391
|
if (val != null && val !== "") {
|
|
10392
10392
|
rowData[key] = val;
|
|
@@ -10407,7 +10407,7 @@ var ExcelTS = (function(exports) {
|
|
|
10407
10407
|
const colIdx = col - startCol;
|
|
10408
10408
|
const key = headerOpt[colIdx] ?? `__EMPTY_${colIdx}`;
|
|
10409
10409
|
const cell = this.getCell(row, col);
|
|
10410
|
-
const val = o.raw === false ? getCellDisplayText(cell, o.dateFormat).trim() : cell.value;
|
|
10410
|
+
const val = o.raw === false ? getCellDisplayText$1(cell, o.dateFormat).trim() : cell.value;
|
|
10411
10411
|
if (val != null && val !== "") {
|
|
10412
10412
|
rowData[key] = val;
|
|
10413
10413
|
isEmpty = false;
|
|
@@ -10436,7 +10436,7 @@ var ExcelTS = (function(exports) {
|
|
|
10436
10436
|
let isEmpty = true;
|
|
10437
10437
|
for (let col = startCol; col <= endCol; col++) {
|
|
10438
10438
|
const cell = this.getCell(row, col);
|
|
10439
|
-
const val = o.raw === false ? getCellDisplayText(cell, o.dateFormat).trim() : cell.value;
|
|
10439
|
+
const val = o.raw === false ? getCellDisplayText$1(cell, o.dateFormat).trim() : cell.value;
|
|
10440
10440
|
const key = headers[col - startCol];
|
|
10441
10441
|
if (val != null && val !== "") {
|
|
10442
10442
|
rowData[key] = val;
|
|
@@ -41222,7 +41222,7 @@ onmessage = async (ev) => {
|
|
|
41222
41222
|
* Normalize all input types to a unified format.
|
|
41223
41223
|
* Handles: objects, arrays, RowHashArray, and columns config.
|
|
41224
41224
|
*/
|
|
41225
|
-
function normalizeInput(data, options, cfg) {
|
|
41225
|
+
function normalizeInput$1(data, options, cfg) {
|
|
41226
41226
|
const { headers, columns } = options;
|
|
41227
41227
|
if (data.length === 0) {
|
|
41228
41228
|
if (columns && columns.length > 0) return {
|
|
@@ -41338,7 +41338,7 @@ onmessage = async (ev) => {
|
|
|
41338
41338
|
*/
|
|
41339
41339
|
function formatCsv(data, options = {}) {
|
|
41340
41340
|
const cfg = createFormatConfig(options);
|
|
41341
|
-
const { displayHeaders, rows } = normalizeInput(data, options, cfg);
|
|
41341
|
+
const { displayHeaders, rows } = normalizeInput$1(data, options, cfg);
|
|
41342
41342
|
const lines = [];
|
|
41343
41343
|
const effectiveHeaders = displayHeaders ? deduplicateHeaders(displayHeaders) : void 0;
|
|
41344
41344
|
if (effectiveHeaders && cfg.writeHeaders) lines.push(formatRowWithLookup(effectiveHeaders, cfg.regex, {
|
|
@@ -42137,6 +42137,59 @@ onmessage = async (ev) => {
|
|
|
42137
42137
|
return PaperSize;
|
|
42138
42138
|
}({});
|
|
42139
42139
|
//#endregion
|
|
42140
|
+
//#region src/modules/pdf/types.ts
|
|
42141
|
+
/**
|
|
42142
|
+
* Type definitions for the PDF module.
|
|
42143
|
+
* Covers input data models, export options, page layout, and internal rendering models.
|
|
42144
|
+
*
|
|
42145
|
+
* The input data models (PdfWorkbook, PdfSheetData, etc.) are fully independent of
|
|
42146
|
+
* the Excel module, allowing the PDF engine to be used standalone.
|
|
42147
|
+
*/
|
|
42148
|
+
/**
|
|
42149
|
+
* Cell value type discriminator for the PDF engine.
|
|
42150
|
+
*/
|
|
42151
|
+
const PdfCellType = {
|
|
42152
|
+
Empty: 0,
|
|
42153
|
+
String: 1,
|
|
42154
|
+
Number: 2,
|
|
42155
|
+
Boolean: 3,
|
|
42156
|
+
Date: 4,
|
|
42157
|
+
RichText: 5,
|
|
42158
|
+
Error: 6,
|
|
42159
|
+
Formula: 7,
|
|
42160
|
+
Hyperlink: 8,
|
|
42161
|
+
Merge: 9
|
|
42162
|
+
};
|
|
42163
|
+
/**
|
|
42164
|
+
* Predefined page sizes.
|
|
42165
|
+
*/
|
|
42166
|
+
const PageSizes = {
|
|
42167
|
+
A3: {
|
|
42168
|
+
width: 841.89,
|
|
42169
|
+
height: 1190.55
|
|
42170
|
+
},
|
|
42171
|
+
A4: {
|
|
42172
|
+
width: 595.28,
|
|
42173
|
+
height: 841.89
|
|
42174
|
+
},
|
|
42175
|
+
A5: {
|
|
42176
|
+
width: 419.53,
|
|
42177
|
+
height: 595.28
|
|
42178
|
+
},
|
|
42179
|
+
LETTER: {
|
|
42180
|
+
width: 612,
|
|
42181
|
+
height: 792
|
|
42182
|
+
},
|
|
42183
|
+
LEGAL: {
|
|
42184
|
+
width: 612,
|
|
42185
|
+
height: 1008
|
|
42186
|
+
},
|
|
42187
|
+
TABLOID: {
|
|
42188
|
+
width: 792,
|
|
42189
|
+
height: 1224
|
|
42190
|
+
}
|
|
42191
|
+
};
|
|
42192
|
+
//#endregion
|
|
42140
42193
|
//#region src/modules/pdf/core/pdf-object.ts
|
|
42141
42194
|
/**
|
|
42142
42195
|
* Low-level PDF object primitives.
|
|
@@ -44658,8 +44711,8 @@ onmessage = async (ev) => {
|
|
|
44658
44711
|
//#endregion
|
|
44659
44712
|
//#region src/modules/pdf/render/style-converter.ts
|
|
44660
44713
|
/**
|
|
44661
|
-
* Convert an
|
|
44662
|
-
*
|
|
44714
|
+
* Convert an ARGB color string to PDF RGB color.
|
|
44715
|
+
* Handles "AARRGGBB" (8-char) and "RRGGBB" (6-char) formats.
|
|
44663
44716
|
* PDF uses 0-1 floats for each component.
|
|
44664
44717
|
*/
|
|
44665
44718
|
function argbToPdfColor(argb) {
|
|
@@ -44689,7 +44742,7 @@ onmessage = async (ev) => {
|
|
|
44689
44742
|
};
|
|
44690
44743
|
}
|
|
44691
44744
|
/**
|
|
44692
|
-
* Convert
|
|
44745
|
+
* Convert a color data object to PDF color.
|
|
44693
44746
|
* Handles both ARGB and theme-based colors.
|
|
44694
44747
|
*/
|
|
44695
44748
|
function excelColorToPdf(color) {
|
|
@@ -44705,7 +44758,7 @@ onmessage = async (ev) => {
|
|
|
44705
44758
|
return null;
|
|
44706
44759
|
}
|
|
44707
44760
|
/**
|
|
44708
|
-
* Map
|
|
44761
|
+
* Map theme color indices to PDF colors.
|
|
44709
44762
|
* These are the default Office theme colors.
|
|
44710
44763
|
*/
|
|
44711
44764
|
function themeColorToPdf(themeIndex) {
|
|
@@ -44803,7 +44856,7 @@ onmessage = async (ev) => {
|
|
|
44803
44856
|
}
|
|
44804
44857
|
};
|
|
44805
44858
|
/**
|
|
44806
|
-
* Extract font properties
|
|
44859
|
+
* Extract font properties for PDF rendering.
|
|
44807
44860
|
*/
|
|
44808
44861
|
function extractFontProperties(font, defaultFamily, defaultSize) {
|
|
44809
44862
|
return {
|
|
@@ -44817,25 +44870,24 @@ onmessage = async (ev) => {
|
|
|
44817
44870
|
};
|
|
44818
44871
|
}
|
|
44819
44872
|
/**
|
|
44820
|
-
* Convert
|
|
44873
|
+
* Convert a fill to a PDF background color.
|
|
44821
44874
|
* Only pattern fills with "solid" pattern are supported as PDF backgrounds.
|
|
44822
44875
|
* Other patterns are approximated or ignored.
|
|
44823
44876
|
*/
|
|
44824
44877
|
function excelFillToPdfColor(fill) {
|
|
44825
44878
|
if (!fill) return null;
|
|
44826
44879
|
if (fill.type === "pattern") {
|
|
44827
|
-
|
|
44828
|
-
if (
|
|
44829
|
-
if (
|
|
44830
|
-
if (patternFill.fgColor) return excelColorToPdf(patternFill.fgColor);
|
|
44880
|
+
if (fill.pattern === "solid" && fill.fgColor) return excelColorToPdf(fill.fgColor);
|
|
44881
|
+
if (fill.pattern === "none") return null;
|
|
44882
|
+
if (fill.fgColor) return excelColorToPdf(fill.fgColor);
|
|
44831
44883
|
}
|
|
44832
44884
|
if (fill.type === "gradient") {
|
|
44833
|
-
if (
|
|
44885
|
+
if (fill.stops && fill.stops.length > 0) return excelColorToPdf(fill.stops[0].color);
|
|
44834
44886
|
}
|
|
44835
44887
|
return null;
|
|
44836
44888
|
}
|
|
44837
44889
|
/**
|
|
44838
|
-
* Map
|
|
44890
|
+
* Map border styles to PDF line widths.
|
|
44839
44891
|
*/
|
|
44840
44892
|
function borderStyleToLineWidth(style) {
|
|
44841
44893
|
switch (style) {
|
|
@@ -44856,7 +44908,7 @@ onmessage = async (ev) => {
|
|
|
44856
44908
|
}
|
|
44857
44909
|
}
|
|
44858
44910
|
/**
|
|
44859
|
-
* Map
|
|
44911
|
+
* Map border styles to PDF dash patterns.
|
|
44860
44912
|
* An empty array means a solid line.
|
|
44861
44913
|
*/
|
|
44862
44914
|
function borderStyleToDashPattern(style) {
|
|
@@ -44891,7 +44943,7 @@ onmessage = async (ev) => {
|
|
|
44891
44943
|
}
|
|
44892
44944
|
}
|
|
44893
44945
|
/**
|
|
44894
|
-
* Convert a single
|
|
44946
|
+
* Convert a single border side to a PDF LayoutBorder.
|
|
44895
44947
|
*/
|
|
44896
44948
|
function convertBorder(border) {
|
|
44897
44949
|
if (!border || !border.style) return null;
|
|
@@ -44902,7 +44954,7 @@ onmessage = async (ev) => {
|
|
|
44902
44954
|
};
|
|
44903
44955
|
}
|
|
44904
44956
|
/**
|
|
44905
|
-
* Convert
|
|
44957
|
+
* Convert border data to PDF LayoutBorders.
|
|
44906
44958
|
*/
|
|
44907
44959
|
function excelBordersToPdf(borders) {
|
|
44908
44960
|
if (!borders) return {
|
|
@@ -44919,7 +44971,7 @@ onmessage = async (ev) => {
|
|
|
44919
44971
|
};
|
|
44920
44972
|
}
|
|
44921
44973
|
/**
|
|
44922
|
-
* Convert
|
|
44974
|
+
* Convert horizontal alignment to PDF alignment.
|
|
44923
44975
|
*/
|
|
44924
44976
|
function excelHAlignToPdf(alignment) {
|
|
44925
44977
|
if (!alignment?.horizontal) return "left";
|
|
@@ -44931,7 +44983,7 @@ onmessage = async (ev) => {
|
|
|
44931
44983
|
}
|
|
44932
44984
|
}
|
|
44933
44985
|
/**
|
|
44934
|
-
* Convert
|
|
44986
|
+
* Convert vertical alignment to PDF alignment.
|
|
44935
44987
|
*/
|
|
44936
44988
|
function excelVAlignToPdf(alignment) {
|
|
44937
44989
|
if (!alignment?.vertical) return "bottom";
|
|
@@ -44948,9 +45000,9 @@ onmessage = async (ev) => {
|
|
|
44948
45000
|
const DEFAULT_ROW_HEIGHT = 15;
|
|
44949
45001
|
const MIN_COLUMN_WIDTH = 5;
|
|
44950
45002
|
/**
|
|
44951
|
-
* Compute the layout for a
|
|
45003
|
+
* Compute the layout for a sheet across one or more PDF pages.
|
|
44952
45004
|
*/
|
|
44953
|
-
function
|
|
45005
|
+
function layoutSheet(sheet, options, fontManager) {
|
|
44954
45006
|
const { margins } = options;
|
|
44955
45007
|
let pageWidth = options.pageSize.width;
|
|
44956
45008
|
let pageHeight = options.pageSize.height;
|
|
@@ -44960,28 +45012,20 @@ onmessage = async (ev) => {
|
|
|
44960
45012
|
const headerHeight = options.showSheetNames ? 20 : 0;
|
|
44961
45013
|
const footerHeight = options.showPageNumbers ? 20 : 0;
|
|
44962
45014
|
const availableHeight = contentHeight - headerHeight - footerHeight;
|
|
44963
|
-
const printRange = getPrintRange(
|
|
44964
|
-
const { columnWidths, visibleCols } = computeColumnWidths(
|
|
44965
|
-
if (visibleCols.length === 0) return [emptyPage(pageWidth, pageHeight,
|
|
44966
|
-
|
|
45015
|
+
const printRange = getPrintRange(sheet);
|
|
45016
|
+
const { columnWidths, visibleCols } = computeColumnWidths(sheet, printRange);
|
|
45017
|
+
if (visibleCols.length === 0) return [emptyPage(pageWidth, pageHeight, sheet.name, options)];
|
|
45018
|
+
const totalTableWidth = columnWidths.reduce((sum, w) => sum + w, 0);
|
|
44967
45019
|
let scaleFactor = options.scale;
|
|
44968
45020
|
if (options.fitToPage && totalTableWidth > 0) {
|
|
44969
45021
|
const fitScale = contentWidth / totalTableWidth;
|
|
44970
45022
|
if (fitScale < 1) scaleFactor *= fitScale;
|
|
44971
45023
|
}
|
|
44972
45024
|
const scaledColumnWidths = columnWidths.map((w) => w * scaleFactor);
|
|
44973
|
-
|
|
44974
|
-
const
|
|
44975
|
-
|
|
44976
|
-
|
|
44977
|
-
for (let i = 0; i < scaledColumnWidths.length; i++) {
|
|
44978
|
-
columnOffsets.push(xOffset);
|
|
44979
|
-
xOffset += scaledColumnWidths[i];
|
|
44980
|
-
}
|
|
44981
|
-
const { rowHeights, visibleRows } = computeRowHeights(worksheet, scaleFactor, printRange);
|
|
44982
|
-
const mergeMap = buildMergeMap(worksheet);
|
|
44983
|
-
const rowPages = paginateRows(rowHeights, availableHeight, typeof options.repeatRows === "number" ? options.repeatRows : 0, buildRowBreakSet(worksheet, visibleRows));
|
|
44984
|
-
const colGroups = paginateColumns(scaledColumnWidths, contentWidth, worksheet, visibleCols);
|
|
45025
|
+
const { rowHeights, visibleRows } = computeRowHeights(sheet, scaleFactor, printRange);
|
|
45026
|
+
const mergeMap = buildMergeMap(sheet);
|
|
45027
|
+
const rowPages = paginateRows(rowHeights, availableHeight, typeof options.repeatRows === "number" ? options.repeatRows : 0, buildRowBreakSet(sheet, visibleRows));
|
|
45028
|
+
const colGroups = paginateColumns(scaledColumnWidths, contentWidth, sheet, visibleCols);
|
|
44985
45029
|
const layoutPages = [];
|
|
44986
45030
|
for (const rowPage of rowPages) for (const colGroup of colGroups) {
|
|
44987
45031
|
const cells = [];
|
|
@@ -45007,13 +45051,11 @@ onmessage = async (ev) => {
|
|
|
45007
45051
|
const visibleRowIdx = rowPage[ri];
|
|
45008
45052
|
const wsRowNumber = visibleRows[visibleRowIdx];
|
|
45009
45053
|
for (let gci = 0; gci < colGroup.length; gci++) {
|
|
45010
|
-
const
|
|
45011
|
-
const wsColNumber = visibleCols[ci];
|
|
45054
|
+
const wsColNumber = visibleCols[colGroup[gci]];
|
|
45012
45055
|
const mergeKey = `${wsRowNumber}:${wsColNumber}`;
|
|
45013
45056
|
const mergeInfo = mergeMap.get(mergeKey);
|
|
45014
45057
|
if (mergeInfo && !mergeInfo.isMaster) continue;
|
|
45015
|
-
const
|
|
45016
|
-
const cell = row ? row.findCell(wsColNumber) : void 0;
|
|
45058
|
+
const cell = sheet.rows.get(wsRowNumber)?.cells.get(wsColNumber);
|
|
45017
45059
|
let colSpan = 1;
|
|
45018
45060
|
let rowSpan = 1;
|
|
45019
45061
|
if (mergeInfo && mergeInfo.isMaster) {
|
|
@@ -45035,7 +45077,7 @@ onmessage = async (ev) => {
|
|
|
45035
45077
|
let cellHeight = 0;
|
|
45036
45078
|
for (let s = 0; s < rowSpan && ri + s < pageRowHeights.length; s++) cellHeight += pageRowHeights[ri + s];
|
|
45037
45079
|
const rectY = cellY - cellHeight;
|
|
45038
|
-
cells.push(buildLayoutCell(cell,
|
|
45080
|
+
cells.push(buildLayoutCell(cell, cellX, rectY, cellWidth, cellHeight, colSpan, rowSpan, options, fontManager, scaleFactor));
|
|
45039
45081
|
}
|
|
45040
45082
|
}
|
|
45041
45083
|
layoutPages.push({
|
|
@@ -45044,17 +45086,17 @@ onmessage = async (ev) => {
|
|
|
45044
45086
|
cells,
|
|
45045
45087
|
width: pageWidth,
|
|
45046
45088
|
height: pageHeight,
|
|
45047
|
-
sheetName:
|
|
45048
|
-
|
|
45089
|
+
sheetName: sheet.name,
|
|
45090
|
+
sheetCols: colGroup.map((ci) => visibleCols[ci]),
|
|
45049
45091
|
columnOffsets: groupColOffsets,
|
|
45050
45092
|
columnWidths: groupColWidths,
|
|
45051
|
-
|
|
45093
|
+
sheetRows: rowPage.map((ri) => visibleRows[ri]),
|
|
45052
45094
|
rowYPositions,
|
|
45053
45095
|
rowHeights: pageRowHeights,
|
|
45054
45096
|
images: []
|
|
45055
45097
|
});
|
|
45056
45098
|
}
|
|
45057
|
-
if (layoutPages.length > 0) assignImagesToPages(
|
|
45099
|
+
if (layoutPages.length > 0 && sheet.images) assignImagesToPages(sheet.images, layoutPages);
|
|
45058
45100
|
return layoutPages;
|
|
45059
45101
|
}
|
|
45060
45102
|
function emptyPage(width, height, sheetName, options) {
|
|
@@ -45065,26 +45107,60 @@ onmessage = async (ev) => {
|
|
|
45065
45107
|
width,
|
|
45066
45108
|
height,
|
|
45067
45109
|
sheetName,
|
|
45068
|
-
|
|
45110
|
+
sheetCols: [],
|
|
45069
45111
|
columnOffsets: [],
|
|
45070
45112
|
columnWidths: [],
|
|
45071
|
-
|
|
45113
|
+
sheetRows: [],
|
|
45072
45114
|
rowYPositions: [],
|
|
45073
45115
|
rowHeights: [],
|
|
45074
45116
|
images: []
|
|
45075
45117
|
};
|
|
45076
45118
|
}
|
|
45077
45119
|
/**
|
|
45078
|
-
*
|
|
45120
|
+
* Parse a cell reference like "A1" into 0-indexed { c, r }.
|
|
45121
|
+
*/
|
|
45122
|
+
function parseCellRef(ref) {
|
|
45123
|
+
const upper = ref.replace(/\$/g, "").toUpperCase();
|
|
45124
|
+
let col = 0;
|
|
45125
|
+
let i = 0;
|
|
45126
|
+
while (i < upper.length && upper.charCodeAt(i) >= 65 && upper.charCodeAt(i) <= 90) {
|
|
45127
|
+
col = col * 26 + (upper.charCodeAt(i) - 64);
|
|
45128
|
+
i++;
|
|
45129
|
+
}
|
|
45130
|
+
const row = parseInt(upper.substring(i), 10);
|
|
45131
|
+
return {
|
|
45132
|
+
c: col - 1,
|
|
45133
|
+
r: row - 1
|
|
45134
|
+
};
|
|
45135
|
+
}
|
|
45136
|
+
/**
|
|
45137
|
+
* Parse a range string like "A1:B2" into 0-indexed start/end.
|
|
45138
|
+
*/
|
|
45139
|
+
function parseRangeRef(range) {
|
|
45140
|
+
const idx = range.indexOf(":");
|
|
45141
|
+
if (idx === -1) {
|
|
45142
|
+
const cell = parseCellRef(range);
|
|
45143
|
+
return {
|
|
45144
|
+
s: cell,
|
|
45145
|
+
e: { ...cell }
|
|
45146
|
+
};
|
|
45147
|
+
}
|
|
45148
|
+
return {
|
|
45149
|
+
s: parseCellRef(range.slice(0, idx)),
|
|
45150
|
+
e: parseCellRef(range.slice(idx + 1))
|
|
45151
|
+
};
|
|
45152
|
+
}
|
|
45153
|
+
/**
|
|
45154
|
+
* Get the print area range from the sheet's pageSetup.
|
|
45079
45155
|
* Returns null if no print area is set.
|
|
45080
45156
|
*/
|
|
45081
|
-
function getPrintRange(
|
|
45082
|
-
const printArea =
|
|
45157
|
+
function getPrintRange(sheet) {
|
|
45158
|
+
const printArea = sheet.pageSetup?.printArea;
|
|
45083
45159
|
if (!printArea || typeof printArea !== "string") return null;
|
|
45084
45160
|
const firstRange = printArea.split("&&")[0].trim();
|
|
45085
45161
|
if (!firstRange) return null;
|
|
45086
45162
|
try {
|
|
45087
|
-
const range =
|
|
45163
|
+
const range = parseRangeRef(firstRange);
|
|
45088
45164
|
return {
|
|
45089
45165
|
startRow: range.s.r + 1,
|
|
45090
45166
|
endRow: range.e.r + 1,
|
|
@@ -45095,20 +45171,20 @@ onmessage = async (ev) => {
|
|
|
45095
45171
|
return null;
|
|
45096
45172
|
}
|
|
45097
45173
|
}
|
|
45098
|
-
function computeColumnWidths(
|
|
45099
|
-
const
|
|
45100
|
-
if (!(
|
|
45174
|
+
function computeColumnWidths(sheet, printRange) {
|
|
45175
|
+
const bounds = sheet.bounds;
|
|
45176
|
+
if (!(bounds.top > 0 && bounds.left > 0)) return {
|
|
45101
45177
|
columnWidths: [],
|
|
45102
45178
|
visibleCols: []
|
|
45103
45179
|
};
|
|
45104
|
-
const startCol = printRange?.startCol ??
|
|
45105
|
-
const endCol = printRange?.endCol ??
|
|
45180
|
+
const startCol = printRange?.startCol ?? bounds.left;
|
|
45181
|
+
const endCol = printRange?.endCol ?? bounds.right;
|
|
45106
45182
|
const columnWidths = [];
|
|
45107
45183
|
const visibleCols = [];
|
|
45108
45184
|
for (let c = startCol; c <= endCol; c++) {
|
|
45109
|
-
const col =
|
|
45110
|
-
if (col
|
|
45111
|
-
const excelWidth = col
|
|
45185
|
+
const col = sheet.columns.get(c);
|
|
45186
|
+
if (col?.hidden) continue;
|
|
45187
|
+
const excelWidth = col?.width ?? DEFAULT_COLUMN_WIDTH;
|
|
45112
45188
|
const pointWidth = Math.max(excelWidth * EXCEL_CHAR_WIDTH_TO_POINTS, MIN_COLUMN_WIDTH);
|
|
45113
45189
|
columnWidths.push(pointWidth);
|
|
45114
45190
|
visibleCols.push(c);
|
|
@@ -45118,24 +45194,24 @@ onmessage = async (ev) => {
|
|
|
45118
45194
|
visibleCols
|
|
45119
45195
|
};
|
|
45120
45196
|
}
|
|
45121
|
-
function computeRowHeights(
|
|
45122
|
-
const
|
|
45123
|
-
if (
|
|
45197
|
+
function computeRowHeights(sheet, scaleFactor, printRange) {
|
|
45198
|
+
const bounds = sheet.bounds;
|
|
45199
|
+
if (bounds.top <= 0) return {
|
|
45124
45200
|
rowHeights: [],
|
|
45125
45201
|
visibleRows: []
|
|
45126
45202
|
};
|
|
45127
|
-
const startRow = printRange?.startRow ??
|
|
45128
|
-
const endRow = printRange?.endRow ??
|
|
45203
|
+
const startRow = printRange?.startRow ?? bounds.top;
|
|
45204
|
+
const endRow = printRange?.endRow ?? bounds.bottom;
|
|
45129
45205
|
const rowHeights = [];
|
|
45130
45206
|
const visibleRows = [];
|
|
45131
45207
|
for (let r = startRow; r <= endRow; r++) {
|
|
45132
|
-
const row =
|
|
45208
|
+
const row = sheet.rows.get(r);
|
|
45133
45209
|
if (row && row.hidden) continue;
|
|
45134
45210
|
let height;
|
|
45135
45211
|
if (row?.height) height = row.height;
|
|
45136
45212
|
else {
|
|
45137
45213
|
height = DEFAULT_ROW_HEIGHT;
|
|
45138
|
-
if (row)
|
|
45214
|
+
if (row) for (const cell of row.cells.values()) {
|
|
45139
45215
|
let fontSize = cell.style?.font?.size ?? 11;
|
|
45140
45216
|
const rtValue = cell.value;
|
|
45141
45217
|
if (rtValue?.richText) for (const run of rtValue.richText) {
|
|
@@ -45146,15 +45222,15 @@ onmessage = async (ev) => {
|
|
|
45146
45222
|
const text = cell.text ?? "";
|
|
45147
45223
|
const lineCount = Math.max(1, (text.match(/\n/g) ?? []).length + 1);
|
|
45148
45224
|
let wrapLineCount = lineCount;
|
|
45149
|
-
if (cell.alignment?.wrapText && lineCount === 1 && text.length > 0) {
|
|
45150
|
-
const colPts = (
|
|
45225
|
+
if (cell.style?.alignment?.wrapText && lineCount === 1 && text.length > 0) {
|
|
45226
|
+
const colPts = (sheet.columns.get(cell.col)?.width ?? DEFAULT_COLUMN_WIDTH) * EXCEL_CHAR_WIDTH_TO_POINTS * scaleFactor;
|
|
45151
45227
|
const avgCharWidth = fontSize * .55;
|
|
45152
45228
|
const charsPerLine = Math.max(1, Math.floor(colPts / avgCharWidth));
|
|
45153
45229
|
wrapLineCount = Math.ceil(text.length / charsPerLine);
|
|
45154
45230
|
}
|
|
45155
45231
|
const neededHeight = lineHeight * wrapLineCount;
|
|
45156
45232
|
if (neededHeight > height) height = neededHeight;
|
|
45157
|
-
}
|
|
45233
|
+
}
|
|
45158
45234
|
}
|
|
45159
45235
|
rowHeights.push(height * scaleFactor);
|
|
45160
45236
|
visibleRows.push(r);
|
|
@@ -45167,30 +45243,28 @@ onmessage = async (ev) => {
|
|
|
45167
45243
|
/**
|
|
45168
45244
|
* Build a set of visible-row indices where manual page breaks occur.
|
|
45169
45245
|
*/
|
|
45170
|
-
function buildRowBreakSet(
|
|
45246
|
+
function buildRowBreakSet(sheet, visibleRows) {
|
|
45171
45247
|
const breaks = /* @__PURE__ */ new Set();
|
|
45172
|
-
const rowBreaks =
|
|
45248
|
+
const rowBreaks = sheet.rowBreaks ?? [];
|
|
45173
45249
|
if (rowBreaks.length === 0) return breaks;
|
|
45174
45250
|
const rowToIndex = /* @__PURE__ */ new Map();
|
|
45175
45251
|
for (let i = 0; i < visibleRows.length; i++) rowToIndex.set(visibleRows[i], i);
|
|
45176
45252
|
for (const brk of rowBreaks) {
|
|
45177
|
-
const idx = rowToIndex.get(brk
|
|
45253
|
+
const idx = rowToIndex.get(brk);
|
|
45178
45254
|
if (idx !== void 0) breaks.add(idx + 1);
|
|
45179
45255
|
}
|
|
45180
45256
|
return breaks;
|
|
45181
45257
|
}
|
|
45182
45258
|
/**
|
|
45183
|
-
* Build a map of all merged cell regions
|
|
45184
|
-
* Uses the worksheet model's public mergeCells property.
|
|
45259
|
+
* Build a map of all merged cell regions.
|
|
45185
45260
|
* Key: "row:col" (1-based), Value: merge info
|
|
45186
45261
|
*/
|
|
45187
|
-
function buildMergeMap(
|
|
45262
|
+
function buildMergeMap(sheet) {
|
|
45188
45263
|
const map = /* @__PURE__ */ new Map();
|
|
45189
|
-
|
|
45190
|
-
|
|
45191
|
-
|
|
45192
|
-
|
|
45193
|
-
const range = decodeRange(rangeStr);
|
|
45264
|
+
const merges = sheet.merges;
|
|
45265
|
+
if (!merges || merges.length === 0) return map;
|
|
45266
|
+
for (const rangeStr of merges) {
|
|
45267
|
+
const range = parseRangeRef(rangeStr);
|
|
45194
45268
|
const top = range.s.r + 1;
|
|
45195
45269
|
const left = range.s.c + 1;
|
|
45196
45270
|
const bottom = range.e.r + 1;
|
|
@@ -45257,18 +45331,16 @@ onmessage = async (ev) => {
|
|
|
45257
45331
|
}
|
|
45258
45332
|
/**
|
|
45259
45333
|
* Split columns into groups for horizontal pagination.
|
|
45260
|
-
* Each group is an array of column indices (into the visibleCols/scaledColumnWidths arrays).
|
|
45261
|
-
* If the total width fits in contentWidth and there are no colBreaks, returns a single group.
|
|
45262
45334
|
*/
|
|
45263
|
-
function paginateColumns(columnWidths, contentWidth,
|
|
45335
|
+
function paginateColumns(columnWidths, contentWidth, sheet, visibleCols) {
|
|
45264
45336
|
if (columnWidths.length === 0) return [[]];
|
|
45265
45337
|
const colBreaks = /* @__PURE__ */ new Set();
|
|
45266
|
-
const wsColBreaks =
|
|
45338
|
+
const wsColBreaks = sheet.colBreaks ?? [];
|
|
45267
45339
|
if (wsColBreaks.length > 0) {
|
|
45268
45340
|
const colToIndex = /* @__PURE__ */ new Map();
|
|
45269
45341
|
for (let i = 0; i < visibleCols.length; i++) colToIndex.set(visibleCols[i], i);
|
|
45270
45342
|
for (const brk of wsColBreaks) {
|
|
45271
|
-
const idx = colToIndex.get(brk
|
|
45343
|
+
const idx = colToIndex.get(brk);
|
|
45272
45344
|
if (idx !== void 0) colBreaks.add(idx + 1);
|
|
45273
45345
|
}
|
|
45274
45346
|
}
|
|
@@ -45288,8 +45360,8 @@ onmessage = async (ev) => {
|
|
|
45288
45360
|
if (currentGroup.length > 0) groups.push(currentGroup);
|
|
45289
45361
|
return groups.length > 0 ? groups : [Array.from({ length: columnWidths.length }, (_, i) => i)];
|
|
45290
45362
|
}
|
|
45291
|
-
function buildLayoutCell(cell,
|
|
45292
|
-
const text =
|
|
45363
|
+
function buildLayoutCell(cell, x, y, width, height, colSpan, rowSpan, options, fontManager, scaleFactor) {
|
|
45364
|
+
const text = cell?.text ?? "";
|
|
45293
45365
|
const style = cell?.style ?? {};
|
|
45294
45366
|
const fontProps = extractFontProperties(style.font, options.defaultFontFamily, options.defaultFontSize);
|
|
45295
45367
|
const scaledFontSize = fontProps.fontSize * scaleFactor;
|
|
@@ -45328,32 +45400,17 @@ onmessage = async (ev) => {
|
|
|
45328
45400
|
};
|
|
45329
45401
|
}
|
|
45330
45402
|
/**
|
|
45331
|
-
*
|
|
45332
|
-
* their top-left anchor.
|
|
45403
|
+
* Assign pre-collected images to the pages that contain their top-left anchor.
|
|
45333
45404
|
*/
|
|
45334
|
-
function assignImagesToPages(
|
|
45335
|
-
const
|
|
45336
|
-
|
|
45337
|
-
const workbook = worksheet.workbook;
|
|
45338
|
-
if (!workbook) return;
|
|
45339
|
-
for (const wsImage of wsImages) {
|
|
45340
|
-
if (!wsImage.range?.tl) continue;
|
|
45341
|
-
const imageId = wsImage.imageId;
|
|
45342
|
-
const mediaItem = workbook.getImage?.(Number(imageId));
|
|
45343
|
-
if (!mediaItem) continue;
|
|
45344
|
-
let data;
|
|
45345
|
-
if (mediaItem.buffer instanceof Uint8Array) data = mediaItem.buffer;
|
|
45346
|
-
else if (mediaItem.base64) data = base64ToUint8Array(mediaItem.base64);
|
|
45347
|
-
if (!data || data.length === 0) continue;
|
|
45348
|
-
const format = mediaItem.extension;
|
|
45349
|
-
if (format !== "jpeg" && format !== "png") continue;
|
|
45350
|
-
const tl = wsImage.range.tl;
|
|
45405
|
+
function assignImagesToPages(images, layoutPages) {
|
|
45406
|
+
for (const img of images) {
|
|
45407
|
+
const tl = img.range.tl;
|
|
45351
45408
|
const tlCol = (tl.nativeCol ?? tl.col ?? 0) + 1;
|
|
45352
45409
|
const tlRow = (tl.nativeRow ?? tl.row ?? 0) + 1;
|
|
45353
|
-
const targetPage = layoutPages.find((page) => page.
|
|
45410
|
+
const targetPage = layoutPages.find((page) => page.sheetCols.includes(tlCol) && page.sheetRows.includes(tlRow));
|
|
45354
45411
|
if (!targetPage) continue;
|
|
45355
|
-
const pageColIndex = targetPage.
|
|
45356
|
-
const pageRowIndex = targetPage.
|
|
45412
|
+
const pageColIndex = targetPage.sheetCols.indexOf(tlCol);
|
|
45413
|
+
const pageRowIndex = targetPage.sheetRows.indexOf(tlRow);
|
|
45357
45414
|
const baseX = targetPage.columnOffsets[pageColIndex] ?? targetPage.options.margins.left;
|
|
45358
45415
|
const baseY = targetPage.rowYPositions[pageRowIndex] ?? targetPage.height - targetPage.options.margins.top - (targetPage.options.showSheetNames ? 20 : 0);
|
|
45359
45416
|
const tlColOff = (tl.nativeColOff ?? 0) / 12700 || 0;
|
|
@@ -45362,15 +45419,15 @@ onmessage = async (ev) => {
|
|
|
45362
45419
|
const imgY = baseY - tlRowOff;
|
|
45363
45420
|
let imgWidth = 100;
|
|
45364
45421
|
let imgHeight = 100;
|
|
45365
|
-
if (
|
|
45366
|
-
imgWidth = (
|
|
45367
|
-
imgHeight = (
|
|
45368
|
-
} else if (
|
|
45369
|
-
const br =
|
|
45422
|
+
if (img.range.ext) {
|
|
45423
|
+
imgWidth = (img.range.ext.width ?? 100) * .75;
|
|
45424
|
+
imgHeight = (img.range.ext.height ?? 100) * .75;
|
|
45425
|
+
} else if (img.range.br) {
|
|
45426
|
+
const br = img.range.br;
|
|
45370
45427
|
const brCol = (br.nativeCol ?? br.col ?? 0) + 1;
|
|
45371
45428
|
const brRow = (br.nativeRow ?? br.row ?? 0) + 1;
|
|
45372
|
-
const brPageColIndex = targetPage.
|
|
45373
|
-
const brPageRowIndex = targetPage.
|
|
45429
|
+
const brPageColIndex = targetPage.sheetCols.indexOf(brCol);
|
|
45430
|
+
const brPageRowIndex = targetPage.sheetRows.indexOf(brRow);
|
|
45374
45431
|
const brBaseX = brPageColIndex >= 0 ? targetPage.columnOffsets[brPageColIndex] : imgX + (targetPage.columnWidths[pageColIndex] ?? 100);
|
|
45375
45432
|
const brBaseY = brPageRowIndex >= 0 ? targetPage.rowYPositions[brPageRowIndex] : imgY - (targetPage.rowHeights[pageRowIndex] ?? 100);
|
|
45376
45433
|
const brColOff = (br.nativeColOff ?? 0) / 12700 || 0;
|
|
@@ -45381,8 +45438,8 @@ onmessage = async (ev) => {
|
|
|
45381
45438
|
imgHeight = imgY - brY;
|
|
45382
45439
|
}
|
|
45383
45440
|
targetPage.images.push({
|
|
45384
|
-
data,
|
|
45385
|
-
format,
|
|
45441
|
+
data: img.data,
|
|
45442
|
+
format: img.format,
|
|
45386
45443
|
rect: {
|
|
45387
45444
|
x: imgX,
|
|
45388
45445
|
y: imgY - imgHeight,
|
|
@@ -45393,49 +45450,11 @@ onmessage = async (ev) => {
|
|
|
45393
45450
|
}
|
|
45394
45451
|
}
|
|
45395
45452
|
/**
|
|
45396
|
-
* Extract display text from a cell, applying numFmt formatting.
|
|
45397
|
-
*/
|
|
45398
|
-
function getCellText(cell) {
|
|
45399
|
-
if (!cell) return "";
|
|
45400
|
-
switch (cell.type) {
|
|
45401
|
-
case ValueType.Null:
|
|
45402
|
-
case ValueType.Merge: return "";
|
|
45403
|
-
case ValueType.RichText: return cell.text;
|
|
45404
|
-
case ValueType.Hyperlink: return cell.text;
|
|
45405
|
-
case ValueType.Error: return cell.value?.error ?? cell.text;
|
|
45406
|
-
case ValueType.Formula: {
|
|
45407
|
-
const result = cell.result;
|
|
45408
|
-
if (result !== void 0 && result !== null) {
|
|
45409
|
-
if (typeof result === "object" && "error" in result) return result.error;
|
|
45410
|
-
return formatCellValueSafe(result, cell.style?.numFmt);
|
|
45411
|
-
}
|
|
45412
|
-
return cell.text;
|
|
45413
|
-
}
|
|
45414
|
-
default: {
|
|
45415
|
-
const value = cell.value;
|
|
45416
|
-
if (value === null || value === void 0) return "";
|
|
45417
|
-
return formatCellValueSafe(value, cell.style?.numFmt);
|
|
45418
|
-
}
|
|
45419
|
-
}
|
|
45420
|
-
}
|
|
45421
|
-
/**
|
|
45422
|
-
* Safely format a cell value using its numFmt.
|
|
45423
|
-
* Falls back to toString if formatting fails or no format is specified.
|
|
45424
|
-
*/
|
|
45425
|
-
function formatCellValueSafe(value, numFmt) {
|
|
45426
|
-
const fmt = typeof numFmt === "string" ? numFmt : numFmt?.formatCode;
|
|
45427
|
-
if (fmt && (typeof value === "number" || value instanceof Date || typeof value === "boolean")) try {
|
|
45428
|
-
return formatCellValue(value, fmt);
|
|
45429
|
-
} catch {}
|
|
45430
|
-
if (value instanceof Date) return value.toLocaleDateString();
|
|
45431
|
-
return String(value);
|
|
45432
|
-
}
|
|
45433
|
-
/**
|
|
45434
45453
|
* Build rich text runs from a RichText cell.
|
|
45435
45454
|
* Returns null for non-RichText cells.
|
|
45436
45455
|
*/
|
|
45437
45456
|
function buildRichTextRuns(cell, options, fontManager, scaleFactor) {
|
|
45438
|
-
if (!cell || cell.type !==
|
|
45457
|
+
if (!cell || cell.type !== PdfCellType.RichText) return null;
|
|
45439
45458
|
const rtValue = cell.value;
|
|
45440
45459
|
if (!rtValue?.richText || rtValue.richText.length === 0) return null;
|
|
45441
45460
|
return rtValue.richText.map((run) => {
|
|
@@ -46508,54 +46527,27 @@ onmessage = async (ev) => {
|
|
|
46508
46527
|
};
|
|
46509
46528
|
}
|
|
46510
46529
|
//#endregion
|
|
46511
|
-
//#region src/modules/pdf/
|
|
46530
|
+
//#region src/modules/pdf/render/pdf-exporter.ts
|
|
46512
46531
|
/**
|
|
46513
|
-
*
|
|
46532
|
+
* PDF Exporter - Main orchestrator for PDF document generation.
|
|
46533
|
+
*
|
|
46534
|
+
* Coordinates the layout engine, page renderer, font manager, and PDF writer
|
|
46535
|
+
* to produce a complete PDF document from a PdfWorkbook data structure.
|
|
46536
|
+
*
|
|
46537
|
+
* This module is fully independent of the Excel module.
|
|
46538
|
+
* It is used internally by the public `pdf()` and `excelToPdf()` APIs.
|
|
46514
46539
|
*/
|
|
46515
|
-
const PageSizes = {
|
|
46516
|
-
A3: {
|
|
46517
|
-
width: 841.89,
|
|
46518
|
-
height: 1190.55
|
|
46519
|
-
},
|
|
46520
|
-
A4: {
|
|
46521
|
-
width: 595.28,
|
|
46522
|
-
height: 841.89
|
|
46523
|
-
},
|
|
46524
|
-
A5: {
|
|
46525
|
-
width: 419.53,
|
|
46526
|
-
height: 595.28
|
|
46527
|
-
},
|
|
46528
|
-
LETTER: {
|
|
46529
|
-
width: 612,
|
|
46530
|
-
height: 792
|
|
46531
|
-
},
|
|
46532
|
-
LEGAL: {
|
|
46533
|
-
width: 612,
|
|
46534
|
-
height: 1008
|
|
46535
|
-
},
|
|
46536
|
-
TABLOID: {
|
|
46537
|
-
width: 792,
|
|
46538
|
-
height: 1224
|
|
46539
|
-
}
|
|
46540
|
-
};
|
|
46541
|
-
//#endregion
|
|
46542
|
-
//#region src/modules/pdf/render/pdf-exporter.ts
|
|
46543
46540
|
/**
|
|
46544
|
-
* Export a
|
|
46541
|
+
* Export a PdfWorkbook to PDF format.
|
|
46545
46542
|
*
|
|
46546
|
-
* @param workbook - The workbook to export
|
|
46543
|
+
* @param workbook - The workbook data to export
|
|
46547
46544
|
* @param options - Export options controlling layout, pagination, and appearance
|
|
46548
46545
|
* @returns PDF file as a Uint8Array
|
|
46549
|
-
* @throws {PdfError} If the workbook has no
|
|
46550
|
-
*
|
|
46551
|
-
* @example
|
|
46552
|
-
* ```typescript
|
|
46553
|
-
* const pdf = exportPdf(workbook, { fitToPage: true, showGridLines: true });
|
|
46554
|
-
* ```
|
|
46546
|
+
* @throws {PdfError} If the workbook has no sheets or export fails
|
|
46555
46547
|
*/
|
|
46556
46548
|
function exportPdf(workbook, options) {
|
|
46557
|
-
const
|
|
46558
|
-
if (
|
|
46549
|
+
const sheets = selectSheets(workbook, options?.sheets);
|
|
46550
|
+
if (sheets.length === 0) throw new PdfError("No sheets to export. The workbook is empty or no sheets matched.");
|
|
46559
46551
|
const fontManager = new FontManager();
|
|
46560
46552
|
const writer = new PdfWriter();
|
|
46561
46553
|
if (options?.font) try {
|
|
@@ -46565,24 +46557,24 @@ onmessage = async (ev) => {
|
|
|
46565
46557
|
throw new PdfRenderError("Failed to parse TrueType font", { cause: err });
|
|
46566
46558
|
}
|
|
46567
46559
|
const allPages = [];
|
|
46568
|
-
for (const
|
|
46569
|
-
const pages =
|
|
46560
|
+
for (const sheet of sheets) try {
|
|
46561
|
+
const pages = layoutSheet(sheet, resolveOptions(options, sheet), fontManager);
|
|
46570
46562
|
allPages.push(...pages);
|
|
46571
46563
|
} catch (err) {
|
|
46572
|
-
throw new PdfRenderError(`Failed to layout
|
|
46564
|
+
throw new PdfRenderError(`Failed to layout sheet "${sheet.name}"`, { cause: err });
|
|
46573
46565
|
}
|
|
46574
|
-
const documentOptions = resolveOptions(options,
|
|
46566
|
+
const documentOptions = resolveOptions(options, sheets[0]);
|
|
46575
46567
|
if (allPages.length === 0) allPages.push({
|
|
46576
46568
|
pageNumber: 1,
|
|
46577
46569
|
options: documentOptions,
|
|
46578
46570
|
cells: [],
|
|
46579
46571
|
width: documentOptions.pageSize.width,
|
|
46580
46572
|
height: documentOptions.pageSize.height,
|
|
46581
|
-
sheetName:
|
|
46582
|
-
|
|
46573
|
+
sheetName: sheets[0]?.name ?? "Sheet1",
|
|
46574
|
+
sheetCols: [],
|
|
46583
46575
|
columnOffsets: [],
|
|
46584
46576
|
columnWidths: [],
|
|
46585
|
-
|
|
46577
|
+
sheetRows: [],
|
|
46586
46578
|
rowYPositions: [],
|
|
46587
46579
|
rowHeights: [],
|
|
46588
46580
|
images: []
|
|
@@ -46674,34 +46666,10 @@ onmessage = async (ev) => {
|
|
|
46674
46666
|
return writer.build();
|
|
46675
46667
|
}
|
|
46676
46668
|
/**
|
|
46677
|
-
*
|
|
46678
|
-
*
|
|
46679
|
-
* @example
|
|
46680
|
-
* ```typescript
|
|
46681
|
-
* const exporter = new PdfExporter(workbook);
|
|
46682
|
-
* const pdfBuffer = exporter.export({ fitToPage: true });
|
|
46683
|
-
* ```
|
|
46669
|
+
* Select which sheets to export based on the options.
|
|
46684
46670
|
*/
|
|
46685
|
-
|
|
46686
|
-
|
|
46687
|
-
this.workbook = workbook;
|
|
46688
|
-
}
|
|
46689
|
-
/**
|
|
46690
|
-
* Export the workbook as a PDF document.
|
|
46691
|
-
*
|
|
46692
|
-
* @param options - Export options controlling layout, pagination, and appearance
|
|
46693
|
-
* @returns PDF file as a Uint8Array
|
|
46694
|
-
* @throws {PdfError} If the workbook has no worksheets or export fails
|
|
46695
|
-
*/
|
|
46696
|
-
export(options) {
|
|
46697
|
-
return exportPdf(this.workbook, options);
|
|
46698
|
-
}
|
|
46699
|
-
};
|
|
46700
|
-
/**
|
|
46701
|
-
* Select which worksheets to export based on the options.
|
|
46702
|
-
*/
|
|
46703
|
-
function selectWorksheets(workbook, sheets) {
|
|
46704
|
-
const allSheets = workbook.worksheets;
|
|
46671
|
+
function selectSheets(workbook, sheets) {
|
|
46672
|
+
const allSheets = workbook.sheets;
|
|
46705
46673
|
if (!sheets || sheets.length === 0) return allSheets.filter((ws) => ws.state !== "hidden" && ws.state !== "veryHidden");
|
|
46706
46674
|
const result = [];
|
|
46707
46675
|
for (const selector of sheets) if (typeof selector === "string") {
|
|
@@ -46716,8 +46684,8 @@ onmessage = async (ev) => {
|
|
|
46716
46684
|
/**
|
|
46717
46685
|
* Resolve user options with defaults.
|
|
46718
46686
|
*/
|
|
46719
|
-
function resolveOptions(options,
|
|
46720
|
-
const ps =
|
|
46687
|
+
function resolveOptions(options, sheet) {
|
|
46688
|
+
const ps = sheet?.pageSetup;
|
|
46721
46689
|
const pageSize = resolvePageSize(options?.pageSize, ps?.paperSize);
|
|
46722
46690
|
const orientation = options?.orientation ?? (ps?.orientation === "landscape" ? "landscape" : "portrait");
|
|
46723
46691
|
const margins = resolveMargins(options?.margins, ps?.margins);
|
|
@@ -46750,10 +46718,7 @@ onmessage = async (ev) => {
|
|
|
46750
46718
|
creator: options?.creator ?? "excelts"
|
|
46751
46719
|
};
|
|
46752
46720
|
}
|
|
46753
|
-
/**
|
|
46754
|
-
* Resolve the page size from options.
|
|
46755
|
-
*/
|
|
46756
|
-
/** Map Excel PaperSize enum values to PDF page sizes. */
|
|
46721
|
+
/** Map PaperSize enum values to PDF page sizes. */
|
|
46757
46722
|
const PAPER_SIZE_MAP = {
|
|
46758
46723
|
1: PageSizes.LETTER,
|
|
46759
46724
|
5: PageSizes.LEGAL,
|
|
@@ -46771,8 +46736,8 @@ onmessage = async (ev) => {
|
|
|
46771
46736
|
return PageSizes.A4;
|
|
46772
46737
|
}
|
|
46773
46738
|
/**
|
|
46774
|
-
* Resolve margins with defaults.
|
|
46775
|
-
* When partial PDF margins are specified, unset sides fall back to
|
|
46739
|
+
* Resolve margins with defaults. Sheet margins are in inches, convert to points (×72).
|
|
46740
|
+
* When partial PDF margins are specified, unset sides fall back to sheet margins,
|
|
46776
46741
|
* then to the default 72pt (1 inch).
|
|
46777
46742
|
*/
|
|
46778
46743
|
function resolveMargins(margins, wsMargins) {
|
|
@@ -46797,7 +46762,7 @@ onmessage = async (ev) => {
|
|
|
46797
46762
|
}
|
|
46798
46763
|
/**
|
|
46799
46764
|
* Build a PDF outlines tree for sheet-level navigation.
|
|
46800
|
-
* Creates one bookmark entry per
|
|
46765
|
+
* Creates one bookmark entry per sheet, pointing to the first page.
|
|
46801
46766
|
*/
|
|
46802
46767
|
function buildOutlines(writer, sheetFirstPage, pageObjNums) {
|
|
46803
46768
|
const outlinesObjNum = writer.allocObject();
|
|
@@ -46881,6 +46846,518 @@ onmessage = async (ev) => {
|
|
|
46881
46846
|
};
|
|
46882
46847
|
}
|
|
46883
46848
|
//#endregion
|
|
46849
|
+
//#region src/modules/pdf/pdf.ts
|
|
46850
|
+
/**
|
|
46851
|
+
* Simplified PDF generation API.
|
|
46852
|
+
*
|
|
46853
|
+
* Provides a concise way to create PDFs from plain data — no need to manually
|
|
46854
|
+
* construct Map objects, compute bounds, or specify cell types.
|
|
46855
|
+
*
|
|
46856
|
+
* @example Simplest — pass a 2D array:
|
|
46857
|
+
* ```typescript
|
|
46858
|
+
* import { pdf } from "@cj-tech-master/excelts/pdf";
|
|
46859
|
+
*
|
|
46860
|
+
* const bytes = pdf([
|
|
46861
|
+
* ["Product", "Revenue"],
|
|
46862
|
+
* ["Widget", 1000],
|
|
46863
|
+
* ["Gadget", 2500]
|
|
46864
|
+
* ]);
|
|
46865
|
+
* ```
|
|
46866
|
+
*
|
|
46867
|
+
* @example With options:
|
|
46868
|
+
* ```typescript
|
|
46869
|
+
* const bytes = pdf([
|
|
46870
|
+
* ["Name", "Score"],
|
|
46871
|
+
* ["Alice", 95],
|
|
46872
|
+
* ["Bob", 87]
|
|
46873
|
+
* ], { showGridLines: true, title: "Scores" });
|
|
46874
|
+
* ```
|
|
46875
|
+
*
|
|
46876
|
+
* @example Multiple sheets:
|
|
46877
|
+
* ```typescript
|
|
46878
|
+
* const bytes = pdf({
|
|
46879
|
+
* sheets: [
|
|
46880
|
+
* { name: "Sales", data: [["Product", "Revenue"], ["Widget", 1000]] },
|
|
46881
|
+
* { name: "Costs", data: [["Item", "Amount"], ["Rent", 500]] }
|
|
46882
|
+
* ]
|
|
46883
|
+
* });
|
|
46884
|
+
* ```
|
|
46885
|
+
*
|
|
46886
|
+
* @example With column widths and styles:
|
|
46887
|
+
* ```typescript
|
|
46888
|
+
* const bytes = pdf({
|
|
46889
|
+
* name: "Report",
|
|
46890
|
+
* columns: [{ width: 25 }, { width: 15 }],
|
|
46891
|
+
* data: [
|
|
46892
|
+
* ["Product", "Revenue"],
|
|
46893
|
+
* ["Widget", "$1,000"]
|
|
46894
|
+
* ]
|
|
46895
|
+
* });
|
|
46896
|
+
* ```
|
|
46897
|
+
*/
|
|
46898
|
+
/**
|
|
46899
|
+
* Generate a PDF.
|
|
46900
|
+
*
|
|
46901
|
+
* Accepts anything from a plain 2D array to a multi-sheet workbook.
|
|
46902
|
+
*
|
|
46903
|
+
* @param input - 2D array, sheet object, or workbook object
|
|
46904
|
+
* @param options - PDF export options (page size, margins, etc.)
|
|
46905
|
+
* @returns PDF file as Uint8Array
|
|
46906
|
+
*/
|
|
46907
|
+
function pdf(input, options) {
|
|
46908
|
+
return exportPdf(normalizeInput(input), options);
|
|
46909
|
+
}
|
|
46910
|
+
function normalizeInput(input) {
|
|
46911
|
+
if (Array.isArray(input)) return { sheets: [normalizeSheet({ data: input })] };
|
|
46912
|
+
if ("sheets" in input) return {
|
|
46913
|
+
title: input.title,
|
|
46914
|
+
creator: input.author,
|
|
46915
|
+
sheets: input.sheets.map((s, i) => normalizeSheet(s, i))
|
|
46916
|
+
};
|
|
46917
|
+
return { sheets: [normalizeSheet(input)] };
|
|
46918
|
+
}
|
|
46919
|
+
function normalizeSheet(sheet, index) {
|
|
46920
|
+
const data = sheet.data;
|
|
46921
|
+
const sheetName = sheet.name ?? `Sheet${(index ?? 0) + 1}`;
|
|
46922
|
+
const columnHeaders = sheet.columns?.map((c) => typeof c === "number" ? void 0 : c.header);
|
|
46923
|
+
const hasHeaders = columnHeaders?.some((h) => h !== void 0) ?? false;
|
|
46924
|
+
let maxCols = 0;
|
|
46925
|
+
for (const row of data) if (row.length > maxCols) maxCols = row.length;
|
|
46926
|
+
let colCount = Math.max(maxCols, sheet.columns?.length ?? 0);
|
|
46927
|
+
let totalRows = data.length + (hasHeaders ? 1 : 0);
|
|
46928
|
+
if (sheet.images) for (const img of sheet.images) {
|
|
46929
|
+
const imgCol = img.col + 1;
|
|
46930
|
+
const imgRow = img.row + 1;
|
|
46931
|
+
if (imgCol > colCount) colCount = imgCol;
|
|
46932
|
+
if (imgRow > totalRows) totalRows = imgRow;
|
|
46933
|
+
}
|
|
46934
|
+
if (colCount === 0) return {
|
|
46935
|
+
name: sheetName,
|
|
46936
|
+
bounds: {
|
|
46937
|
+
top: 0,
|
|
46938
|
+
left: 0,
|
|
46939
|
+
bottom: 0,
|
|
46940
|
+
right: 0
|
|
46941
|
+
},
|
|
46942
|
+
columns: /* @__PURE__ */ new Map(),
|
|
46943
|
+
rows: /* @__PURE__ */ new Map()
|
|
46944
|
+
};
|
|
46945
|
+
const columns = /* @__PURE__ */ new Map();
|
|
46946
|
+
if (sheet.columns) for (let i = 0; i < sheet.columns.length; i++) {
|
|
46947
|
+
const col = sheet.columns[i];
|
|
46948
|
+
const width = typeof col === "number" ? col : col.width;
|
|
46949
|
+
columns.set(i + 1, { width: width ?? 12 });
|
|
46950
|
+
}
|
|
46951
|
+
for (let c = 1; c <= colCount; c++) if (!columns.has(c)) columns.set(c, { width: 12 });
|
|
46952
|
+
const rows = /* @__PURE__ */ new Map();
|
|
46953
|
+
let rowOffset = 1;
|
|
46954
|
+
if (hasHeaders && columnHeaders) {
|
|
46955
|
+
const cells = /* @__PURE__ */ new Map();
|
|
46956
|
+
for (let c = 0; c < columnHeaders.length; c++) {
|
|
46957
|
+
const text = columnHeaders[c];
|
|
46958
|
+
if (text === void 0) continue;
|
|
46959
|
+
cells.set(c + 1, {
|
|
46960
|
+
type: PdfCellType.String,
|
|
46961
|
+
value: text,
|
|
46962
|
+
text,
|
|
46963
|
+
col: c + 1,
|
|
46964
|
+
style: { font: { bold: true } }
|
|
46965
|
+
});
|
|
46966
|
+
}
|
|
46967
|
+
rows.set(1, { cells });
|
|
46968
|
+
rowOffset = 2;
|
|
46969
|
+
}
|
|
46970
|
+
for (let r = 0; r < data.length; r++) {
|
|
46971
|
+
const rowNum = r + rowOffset;
|
|
46972
|
+
const row = data[r];
|
|
46973
|
+
const cells = /* @__PURE__ */ new Map();
|
|
46974
|
+
for (let c = 0; c < row.length; c++) {
|
|
46975
|
+
const cell = normalizeCell(row[c], c + 1);
|
|
46976
|
+
if (cell) cells.set(c + 1, cell);
|
|
46977
|
+
}
|
|
46978
|
+
rows.set(rowNum, { cells });
|
|
46979
|
+
}
|
|
46980
|
+
let images;
|
|
46981
|
+
if (sheet.images && sheet.images.length > 0) {
|
|
46982
|
+
images = sheet.images.map((img) => ({
|
|
46983
|
+
data: img.data,
|
|
46984
|
+
format: img.format,
|
|
46985
|
+
range: {
|
|
46986
|
+
tl: {
|
|
46987
|
+
col: img.col,
|
|
46988
|
+
row: img.row
|
|
46989
|
+
},
|
|
46990
|
+
ext: {
|
|
46991
|
+
width: img.width,
|
|
46992
|
+
height: img.height
|
|
46993
|
+
}
|
|
46994
|
+
}
|
|
46995
|
+
}));
|
|
46996
|
+
for (let c = 1; c <= colCount; c++) if (!columns.has(c)) columns.set(c, { width: 12 });
|
|
46997
|
+
for (let r = 1; r <= totalRows; r++) if (!rows.has(r)) rows.set(r, { cells: /* @__PURE__ */ new Map() });
|
|
46998
|
+
}
|
|
46999
|
+
return {
|
|
47000
|
+
name: sheetName,
|
|
47001
|
+
bounds: {
|
|
47002
|
+
top: 1,
|
|
47003
|
+
left: 1,
|
|
47004
|
+
bottom: totalRows,
|
|
47005
|
+
right: colCount
|
|
47006
|
+
},
|
|
47007
|
+
columns,
|
|
47008
|
+
rows,
|
|
47009
|
+
images
|
|
47010
|
+
};
|
|
47011
|
+
}
|
|
47012
|
+
function normalizeCell(value, col) {
|
|
47013
|
+
if (value === null || value === void 0) return null;
|
|
47014
|
+
if (typeof value === "object" && !(value instanceof Date) && "value" in value) {
|
|
47015
|
+
const cell = value;
|
|
47016
|
+
const inner = normalizeCell(cell.value, col);
|
|
47017
|
+
if (!inner) return null;
|
|
47018
|
+
const style = {};
|
|
47019
|
+
if (cell.bold || cell.italic || cell.fontSize || cell.fontColor) style.font = {
|
|
47020
|
+
bold: cell.bold,
|
|
47021
|
+
italic: cell.italic,
|
|
47022
|
+
size: cell.fontSize,
|
|
47023
|
+
color: cell.fontColor ? { argb: cell.fontColor } : void 0
|
|
47024
|
+
};
|
|
47025
|
+
if (cell.fillColor) style.fill = {
|
|
47026
|
+
type: "pattern",
|
|
47027
|
+
pattern: "solid",
|
|
47028
|
+
fgColor: { argb: cell.fillColor }
|
|
47029
|
+
};
|
|
47030
|
+
if (cell.align) style.alignment = { horizontal: cell.align };
|
|
47031
|
+
inner.style = style;
|
|
47032
|
+
return inner;
|
|
47033
|
+
}
|
|
47034
|
+
if (typeof value === "string") return {
|
|
47035
|
+
type: PdfCellType.String,
|
|
47036
|
+
value,
|
|
47037
|
+
text: value,
|
|
47038
|
+
col
|
|
47039
|
+
};
|
|
47040
|
+
if (typeof value === "number") return {
|
|
47041
|
+
type: PdfCellType.Number,
|
|
47042
|
+
value,
|
|
47043
|
+
text: String(value),
|
|
47044
|
+
col
|
|
47045
|
+
};
|
|
47046
|
+
if (typeof value === "boolean") return {
|
|
47047
|
+
type: PdfCellType.Boolean,
|
|
47048
|
+
value,
|
|
47049
|
+
text: value ? "TRUE" : "FALSE",
|
|
47050
|
+
col
|
|
47051
|
+
};
|
|
47052
|
+
if (value instanceof Date) return {
|
|
47053
|
+
type: PdfCellType.Date,
|
|
47054
|
+
value,
|
|
47055
|
+
text: value.toLocaleDateString(),
|
|
47056
|
+
col
|
|
47057
|
+
};
|
|
47058
|
+
return null;
|
|
47059
|
+
}
|
|
47060
|
+
//#endregion
|
|
47061
|
+
//#region src/modules/pdf/excel-bridge.ts
|
|
47062
|
+
/**
|
|
47063
|
+
* Export an Excel Workbook directly to PDF.
|
|
47064
|
+
*
|
|
47065
|
+
* This is a convenience function that converts the Workbook to the PDF module's
|
|
47066
|
+
* data model and then generates the PDF.
|
|
47067
|
+
*
|
|
47068
|
+
* @param workbook - An Excel Workbook instance
|
|
47069
|
+
* @param options - PDF export options
|
|
47070
|
+
* @returns PDF file as a Uint8Array
|
|
47071
|
+
*/
|
|
47072
|
+
function excelToPdf(workbook, options) {
|
|
47073
|
+
return exportPdf(excelWorkbookToPdf(workbook), options);
|
|
47074
|
+
}
|
|
47075
|
+
/**
|
|
47076
|
+
* Convert an Excel Workbook to the internal PdfWorkbook data structure.
|
|
47077
|
+
*/
|
|
47078
|
+
function excelWorkbookToPdf(workbook) {
|
|
47079
|
+
return {
|
|
47080
|
+
title: workbook.title || void 0,
|
|
47081
|
+
creator: workbook.creator || void 0,
|
|
47082
|
+
subject: workbook.subject || void 0,
|
|
47083
|
+
sheets: workbook.worksheets.map((ws) => convertSheet(ws, workbook))
|
|
47084
|
+
};
|
|
47085
|
+
}
|
|
47086
|
+
function convertSheet(ws, workbook) {
|
|
47087
|
+
const dimensions = ws.dimensions;
|
|
47088
|
+
const hasData = dimensions && dimensions.model.top > 0 && dimensions.model.left > 0;
|
|
47089
|
+
const bounds = hasData ? {
|
|
47090
|
+
top: dimensions.model.top,
|
|
47091
|
+
left: dimensions.model.left,
|
|
47092
|
+
bottom: dimensions.model.bottom,
|
|
47093
|
+
right: dimensions.model.right
|
|
47094
|
+
} : {
|
|
47095
|
+
top: 0,
|
|
47096
|
+
left: 0,
|
|
47097
|
+
bottom: 0,
|
|
47098
|
+
right: 0
|
|
47099
|
+
};
|
|
47100
|
+
const columns = /* @__PURE__ */ new Map();
|
|
47101
|
+
if (hasData) for (let c = bounds.left; c <= bounds.right; c++) {
|
|
47102
|
+
const col = ws.getColumn(c);
|
|
47103
|
+
columns.set(c, {
|
|
47104
|
+
hidden: col.hidden || void 0,
|
|
47105
|
+
width: col.width ?? void 0
|
|
47106
|
+
});
|
|
47107
|
+
}
|
|
47108
|
+
const rows = /* @__PURE__ */ new Map();
|
|
47109
|
+
if (hasData) for (let r = bounds.top; r <= bounds.bottom; r++) {
|
|
47110
|
+
const row = ws.findRow(r);
|
|
47111
|
+
if (!row) continue;
|
|
47112
|
+
const cells = /* @__PURE__ */ new Map();
|
|
47113
|
+
row.eachCell({ includeEmpty: false }, (cell) => {
|
|
47114
|
+
cells.set(cell.col, convertCell(cell));
|
|
47115
|
+
});
|
|
47116
|
+
rows.set(r, {
|
|
47117
|
+
hidden: row.hidden || void 0,
|
|
47118
|
+
height: row.height ?? void 0,
|
|
47119
|
+
cells
|
|
47120
|
+
});
|
|
47121
|
+
}
|
|
47122
|
+
const merges = ws.hasMerges && ws.model.mergeCells ? [...ws.model.mergeCells] : void 0;
|
|
47123
|
+
const ps = ws.pageSetup;
|
|
47124
|
+
const pageSetup = ps ? {
|
|
47125
|
+
orientation: ps.orientation,
|
|
47126
|
+
paperSize: ps.paperSize,
|
|
47127
|
+
margins: ps.margins ? {
|
|
47128
|
+
left: ps.margins.left,
|
|
47129
|
+
right: ps.margins.right,
|
|
47130
|
+
top: ps.margins.top,
|
|
47131
|
+
bottom: ps.margins.bottom
|
|
47132
|
+
} : void 0,
|
|
47133
|
+
scale: ps.scale,
|
|
47134
|
+
printTitlesRow: ps.printTitlesRow,
|
|
47135
|
+
showGridLines: ps.showGridLines,
|
|
47136
|
+
printArea: ps.printArea
|
|
47137
|
+
} : void 0;
|
|
47138
|
+
const rowBreaks = ws.rowBreaks?.map((b) => b.id);
|
|
47139
|
+
const colBreaks = ws.colBreaks?.map((b) => b.id);
|
|
47140
|
+
const images = collectImages(ws, workbook);
|
|
47141
|
+
if (images) {
|
|
47142
|
+
for (const img of images) {
|
|
47143
|
+
const tl = img.range.tl;
|
|
47144
|
+
const tlCol = (tl.nativeCol ?? tl.col ?? 0) + 1;
|
|
47145
|
+
const tlRow = (tl.nativeRow ?? tl.row ?? 0) + 1;
|
|
47146
|
+
if (bounds.top === 0 && bounds.left === 0) {
|
|
47147
|
+
bounds.top = 1;
|
|
47148
|
+
bounds.left = 1;
|
|
47149
|
+
}
|
|
47150
|
+
if (tlCol > bounds.right) bounds.right = tlCol;
|
|
47151
|
+
if (tlRow > bounds.bottom) bounds.bottom = tlRow;
|
|
47152
|
+
if (img.range.br) {
|
|
47153
|
+
const br = img.range.br;
|
|
47154
|
+
const brCol = (br.nativeCol ?? br.col ?? 0) + 1;
|
|
47155
|
+
const brRow = (br.nativeRow ?? br.row ?? 0) + 1;
|
|
47156
|
+
if (brCol > bounds.right) bounds.right = brCol;
|
|
47157
|
+
if (brRow > bounds.bottom) bounds.bottom = brRow;
|
|
47158
|
+
}
|
|
47159
|
+
}
|
|
47160
|
+
for (let c = bounds.left; c <= bounds.right; c++) if (!columns.has(c)) {
|
|
47161
|
+
const col = ws.getColumn(c);
|
|
47162
|
+
columns.set(c, {
|
|
47163
|
+
hidden: col.hidden || void 0,
|
|
47164
|
+
width: col.width ?? void 0
|
|
47165
|
+
});
|
|
47166
|
+
}
|
|
47167
|
+
for (let r = bounds.top; r <= bounds.bottom; r++) if (!rows.has(r)) rows.set(r, { cells: /* @__PURE__ */ new Map() });
|
|
47168
|
+
}
|
|
47169
|
+
return {
|
|
47170
|
+
name: ws.name,
|
|
47171
|
+
state: ws.state ?? "visible",
|
|
47172
|
+
bounds,
|
|
47173
|
+
columns,
|
|
47174
|
+
rows,
|
|
47175
|
+
merges,
|
|
47176
|
+
pageSetup,
|
|
47177
|
+
rowBreaks,
|
|
47178
|
+
colBreaks,
|
|
47179
|
+
images
|
|
47180
|
+
};
|
|
47181
|
+
}
|
|
47182
|
+
function convertCell(cell) {
|
|
47183
|
+
const type = mapValueType(cell.type);
|
|
47184
|
+
const text = getCellDisplayText(cell);
|
|
47185
|
+
const style = convertCellStyle(cell.style);
|
|
47186
|
+
return {
|
|
47187
|
+
type,
|
|
47188
|
+
value: convertCellValue(cell),
|
|
47189
|
+
text,
|
|
47190
|
+
style,
|
|
47191
|
+
hyperlink: cell.hyperlink || void 0,
|
|
47192
|
+
result: cell.result ?? void 0,
|
|
47193
|
+
col: cell.col
|
|
47194
|
+
};
|
|
47195
|
+
}
|
|
47196
|
+
function mapValueType(vt) {
|
|
47197
|
+
switch (vt) {
|
|
47198
|
+
case ValueType.Null: return PdfCellType.Empty;
|
|
47199
|
+
case ValueType.Merge: return PdfCellType.Merge;
|
|
47200
|
+
case ValueType.Number: return PdfCellType.Number;
|
|
47201
|
+
case ValueType.String:
|
|
47202
|
+
case ValueType.SharedString: return PdfCellType.String;
|
|
47203
|
+
case ValueType.Date: return PdfCellType.Date;
|
|
47204
|
+
case ValueType.Hyperlink: return PdfCellType.Hyperlink;
|
|
47205
|
+
case ValueType.Formula: return PdfCellType.Formula;
|
|
47206
|
+
case ValueType.RichText: return PdfCellType.RichText;
|
|
47207
|
+
case ValueType.Boolean: return PdfCellType.Boolean;
|
|
47208
|
+
case ValueType.Error: return PdfCellType.Error;
|
|
47209
|
+
default: return PdfCellType.String;
|
|
47210
|
+
}
|
|
47211
|
+
}
|
|
47212
|
+
/**
|
|
47213
|
+
* Get display text for a cell, applying numFmt formatting.
|
|
47214
|
+
*/
|
|
47215
|
+
function getCellDisplayText(cell) {
|
|
47216
|
+
if (!cell) return "";
|
|
47217
|
+
switch (cell.type) {
|
|
47218
|
+
case ValueType.Null:
|
|
47219
|
+
case ValueType.Merge: return "";
|
|
47220
|
+
case ValueType.RichText:
|
|
47221
|
+
case ValueType.Hyperlink: return cell.text ?? "";
|
|
47222
|
+
case ValueType.Error: return cell.value?.error ?? cell.text ?? "";
|
|
47223
|
+
case ValueType.Formula: {
|
|
47224
|
+
const result = cell.result;
|
|
47225
|
+
if (result !== void 0 && result !== null) {
|
|
47226
|
+
if (typeof result === "object" && "error" in result) return result.error;
|
|
47227
|
+
return formatCellValueSafe(result, cell.style?.numFmt);
|
|
47228
|
+
}
|
|
47229
|
+
return cell.text ?? "";
|
|
47230
|
+
}
|
|
47231
|
+
default: {
|
|
47232
|
+
const value = cell.value;
|
|
47233
|
+
if (value === null || value === void 0) return "";
|
|
47234
|
+
return formatCellValueSafe(value, cell.style?.numFmt);
|
|
47235
|
+
}
|
|
47236
|
+
}
|
|
47237
|
+
}
|
|
47238
|
+
function formatCellValueSafe(value, numFmt) {
|
|
47239
|
+
const fmt = typeof numFmt === "string" ? numFmt : numFmt?.formatCode;
|
|
47240
|
+
if (fmt && (typeof value === "number" || value instanceof Date || typeof value === "boolean")) try {
|
|
47241
|
+
return formatCellValue(value, fmt);
|
|
47242
|
+
} catch {}
|
|
47243
|
+
if (value instanceof Date) return value.toLocaleDateString();
|
|
47244
|
+
return String(value);
|
|
47245
|
+
}
|
|
47246
|
+
function convertCellValue(cell) {
|
|
47247
|
+
if (cell.type === ValueType.RichText) {
|
|
47248
|
+
const rtValue = cell.value;
|
|
47249
|
+
if (rtValue?.richText) return { richText: rtValue.richText.map((run) => ({
|
|
47250
|
+
text: run.text,
|
|
47251
|
+
font: run.font ? convertFontStyle(run.font) : void 0
|
|
47252
|
+
})) };
|
|
47253
|
+
}
|
|
47254
|
+
return cell.value;
|
|
47255
|
+
}
|
|
47256
|
+
function convertCellStyle(style) {
|
|
47257
|
+
if (!style) return;
|
|
47258
|
+
return {
|
|
47259
|
+
font: style.font ? convertFontStyle(style.font) : void 0,
|
|
47260
|
+
numFmt: style.numFmt,
|
|
47261
|
+
fill: style.fill ? convertFill(style.fill) : void 0,
|
|
47262
|
+
border: style.border ? convertBorders(style.border) : void 0,
|
|
47263
|
+
alignment: style.alignment ? convertAlignment(style.alignment) : void 0
|
|
47264
|
+
};
|
|
47265
|
+
}
|
|
47266
|
+
function convertFontStyle(font) {
|
|
47267
|
+
return {
|
|
47268
|
+
name: font.name,
|
|
47269
|
+
size: font.size,
|
|
47270
|
+
bold: font.bold,
|
|
47271
|
+
italic: font.italic,
|
|
47272
|
+
strike: font.strike,
|
|
47273
|
+
underline: font.underline,
|
|
47274
|
+
color: font.color ? convertColor(font.color) : void 0
|
|
47275
|
+
};
|
|
47276
|
+
}
|
|
47277
|
+
function convertColor(color) {
|
|
47278
|
+
return {
|
|
47279
|
+
argb: color.argb,
|
|
47280
|
+
theme: color.theme,
|
|
47281
|
+
tint: color.tint
|
|
47282
|
+
};
|
|
47283
|
+
}
|
|
47284
|
+
function convertFill(fill) {
|
|
47285
|
+
const result = {
|
|
47286
|
+
type: fill.type ?? "pattern",
|
|
47287
|
+
pattern: fill.pattern,
|
|
47288
|
+
fgColor: fill.fgColor ? convertColor(fill.fgColor) : void 0
|
|
47289
|
+
};
|
|
47290
|
+
if (fill.stops) result.stops = fill.stops.map((s) => ({ color: convertColor(s.color) }));
|
|
47291
|
+
return result;
|
|
47292
|
+
}
|
|
47293
|
+
function convertBorderSide(border) {
|
|
47294
|
+
return {
|
|
47295
|
+
style: border.style,
|
|
47296
|
+
color: border.color ? convertColor(border.color) : void 0
|
|
47297
|
+
};
|
|
47298
|
+
}
|
|
47299
|
+
function convertBorders(borders) {
|
|
47300
|
+
return {
|
|
47301
|
+
top: borders.top ? convertBorderSide(borders.top) : void 0,
|
|
47302
|
+
right: borders.right ? convertBorderSide(borders.right) : void 0,
|
|
47303
|
+
bottom: borders.bottom ? convertBorderSide(borders.bottom) : void 0,
|
|
47304
|
+
left: borders.left ? convertBorderSide(borders.left) : void 0
|
|
47305
|
+
};
|
|
47306
|
+
}
|
|
47307
|
+
function convertAlignment(alignment) {
|
|
47308
|
+
return {
|
|
47309
|
+
horizontal: alignment.horizontal,
|
|
47310
|
+
vertical: alignment.vertical,
|
|
47311
|
+
wrapText: alignment.wrapText,
|
|
47312
|
+
indent: alignment.indent,
|
|
47313
|
+
textRotation: alignment.textRotation
|
|
47314
|
+
};
|
|
47315
|
+
}
|
|
47316
|
+
function collectImages(ws, workbook) {
|
|
47317
|
+
const wsImages = ws.getImages?.();
|
|
47318
|
+
if (!wsImages || !Array.isArray(wsImages) || wsImages.length === 0) return;
|
|
47319
|
+
const images = [];
|
|
47320
|
+
for (const wsImage of wsImages) {
|
|
47321
|
+
if (!wsImage.range?.tl) continue;
|
|
47322
|
+
const imageId = wsImage.imageId;
|
|
47323
|
+
const mediaItem = workbook.getImage?.(Number(imageId));
|
|
47324
|
+
if (!mediaItem) continue;
|
|
47325
|
+
let data;
|
|
47326
|
+
if (mediaItem.buffer instanceof Uint8Array) data = mediaItem.buffer;
|
|
47327
|
+
else if (mediaItem.base64) data = base64ToUint8Array(mediaItem.base64);
|
|
47328
|
+
if (!data || data.length === 0) continue;
|
|
47329
|
+
const format = mediaItem.extension;
|
|
47330
|
+
if (format !== "jpeg" && format !== "png") continue;
|
|
47331
|
+
images.push({
|
|
47332
|
+
data,
|
|
47333
|
+
format,
|
|
47334
|
+
range: {
|
|
47335
|
+
tl: {
|
|
47336
|
+
col: wsImage.range.tl.col ?? 0,
|
|
47337
|
+
row: wsImage.range.tl.row ?? 0,
|
|
47338
|
+
nativeCol: wsImage.range.tl.nativeCol,
|
|
47339
|
+
nativeRow: wsImage.range.tl.nativeRow,
|
|
47340
|
+
nativeColOff: wsImage.range.tl.nativeColOff,
|
|
47341
|
+
nativeRowOff: wsImage.range.tl.nativeRowOff
|
|
47342
|
+
},
|
|
47343
|
+
br: wsImage.range.br ? {
|
|
47344
|
+
col: wsImage.range.br.col ?? 0,
|
|
47345
|
+
row: wsImage.range.br.row ?? 0,
|
|
47346
|
+
nativeCol: wsImage.range.br.nativeCol,
|
|
47347
|
+
nativeRow: wsImage.range.br.nativeRow,
|
|
47348
|
+
nativeColOff: wsImage.range.br.nativeColOff,
|
|
47349
|
+
nativeRowOff: wsImage.range.br.nativeRowOff
|
|
47350
|
+
} : void 0,
|
|
47351
|
+
ext: wsImage.range.ext ? {
|
|
47352
|
+
width: wsImage.range.ext.width,
|
|
47353
|
+
height: wsImage.range.ext.height
|
|
47354
|
+
} : void 0
|
|
47355
|
+
}
|
|
47356
|
+
});
|
|
47357
|
+
}
|
|
47358
|
+
return images.length > 0 ? images : void 0;
|
|
47359
|
+
}
|
|
47360
|
+
//#endregion
|
|
46884
47361
|
exports.Anchor = Anchor;
|
|
46885
47362
|
exports.BaseError = BaseError;
|
|
46886
47363
|
exports.Cell = Cell;
|
|
@@ -46911,7 +47388,6 @@ onmessage = async (ev) => {
|
|
|
46911
47388
|
exports.PageSizes = PageSizes;
|
|
46912
47389
|
exports.PaperSize = PaperSize;
|
|
46913
47390
|
exports.PdfError = PdfError;
|
|
46914
|
-
exports.PdfExporter = PdfExporter;
|
|
46915
47391
|
exports.PdfFontError = PdfFontError;
|
|
46916
47392
|
exports.PdfRenderError = PdfRenderError;
|
|
46917
47393
|
exports.PdfStructureError = PdfStructureError;
|
|
@@ -46947,12 +47423,13 @@ onmessage = async (ev) => {
|
|
|
46947
47423
|
exports.encodeRow = encodeRow;
|
|
46948
47424
|
exports.errorToJSON = errorToJSON;
|
|
46949
47425
|
exports.excelToDate = excelToDate;
|
|
46950
|
-
exports.
|
|
47426
|
+
exports.excelToPdf = excelToPdf;
|
|
46951
47427
|
exports.getErrorChain = getErrorChain;
|
|
46952
47428
|
exports.getRootCause = getRootCause;
|
|
46953
47429
|
exports.getSupportedFormats = getSupportedFormats;
|
|
46954
47430
|
exports.isExcelError = isExcelError;
|
|
46955
47431
|
exports.isPdfError = isPdfError;
|
|
47432
|
+
exports.pdf = pdf;
|
|
46956
47433
|
exports.stringToUint8Array = stringToUint8Array;
|
|
46957
47434
|
exports.toError = toError;
|
|
46958
47435
|
exports.toUint8Array = toUint8Array;
|