@simplysm/excel 13.0.69 → 13.0.71
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 +19 -516
- package/dist/excel-cell.d.ts +28 -28
- package/dist/excel-cell.d.ts.map +1 -1
- package/dist/excel-cell.js +24 -24
- package/dist/excel-cell.js.map +1 -1
- package/dist/excel-col.d.ts +4 -4
- package/dist/excel-col.d.ts.map +1 -1
- package/dist/excel-col.js +3 -3
- package/dist/excel-row.d.ts +3 -3
- package/dist/excel-row.d.ts.map +1 -1
- package/dist/excel-row.js +2 -2
- package/dist/excel-workbook.d.ts +23 -23
- package/dist/excel-workbook.d.ts.map +1 -1
- package/dist/excel-workbook.js +15 -15
- package/dist/excel-workbook.js.map +1 -1
- package/dist/excel-worksheet.d.ts +32 -32
- package/dist/excel-worksheet.d.ts.map +1 -1
- package/dist/excel-worksheet.js +32 -32
- package/dist/excel-worksheet.js.map +1 -1
- package/dist/excel-wrapper.d.ts +7 -7
- package/dist/excel-wrapper.js +7 -7
- package/dist/excel-wrapper.js.map +1 -1
- package/dist/types.d.ts +16 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/excel-utils.d.ts +23 -23
- package/dist/utils/excel-utils.d.ts.map +1 -1
- package/dist/utils/excel-utils.js +25 -25
- package/dist/utils/excel-utils.js.map +1 -1
- package/dist/utils/zip-cache.d.ts +6 -6
- package/dist/xml/excel-xml-content-type.d.ts +2 -2
- package/dist/xml/excel-xml-drawing.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.js +1 -1
- package/dist/xml/excel-xml-relationship.js.map +1 -1
- package/dist/xml/excel-xml-shared-string.d.ts +2 -2
- package/dist/xml/excel-xml-style.d.ts +2 -2
- package/dist/xml/excel-xml-style.js +6 -6
- package/dist/xml/excel-xml-style.js.map +1 -1
- package/dist/xml/excel-xml-unknown.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.js +1 -1
- package/dist/xml/excel-xml-workbook.js.map +1 -1
- package/dist/xml/excel-xml-worksheet.d.ts +6 -6
- package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
- package/dist/xml/excel-xml-worksheet.js +9 -8
- package/dist/xml/excel-xml-worksheet.js.map +1 -1
- package/package.json +6 -5
- package/src/excel-cell.ts +35 -35
- package/src/excel-col.ts +4 -4
- package/src/excel-row.ts +3 -3
- package/src/excel-workbook.ts +30 -30
- package/src/excel-worksheet.ts +47 -47
- package/src/excel-wrapper.ts +18 -18
- package/src/index.ts +3 -3
- package/src/types.ts +15 -17
- package/src/utils/excel-utils.ts +38 -38
- package/src/utils/zip-cache.ts +6 -6
- package/src/xml/excel-xml-content-type.ts +3 -3
- package/src/xml/excel-xml-drawing.ts +2 -2
- package/src/xml/excel-xml-relationship.ts +3 -3
- package/src/xml/excel-xml-shared-string.ts +2 -2
- package/src/xml/excel-xml-style.ts +11 -11
- package/src/xml/excel-xml-unknown.ts +2 -2
- package/src/xml/excel-xml-workbook.ts +5 -5
- package/src/xml/excel-xml-worksheet.ts +44 -43
- package/tests/excel-cell.spec.ts +448 -0
- package/tests/excel-col.spec.ts +112 -0
- package/tests/excel-row.spec.ts +71 -0
- package/tests/excel-workbook.spec.ts +219 -0
- package/tests/excel-worksheet.spec.ts +389 -0
- package/tests/excel-wrapper.spec.ts +296 -0
- package/tests/fixtures/logo.png +0 -0
- package/tests/fixtures//354/264/210/352/270/260/355/231/224.xlsx +0 -0
- package/tests/image-insert.spec.ts +190 -0
- package/tests/utils/excel-utils.spec.ts +242 -0
|
@@ -16,8 +16,8 @@ interface RowInfo {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* xl/worksheets/sheet*.xml
|
|
20
|
-
*
|
|
19
|
+
* Class managing xl/worksheets/sheet*.xml files.
|
|
20
|
+
* Handles cell data, merges, column widths, row heights, etc.
|
|
21
21
|
*/
|
|
22
22
|
export class ExcelXmlWorksheet implements ExcelXml {
|
|
23
23
|
data: ExcelXmlWorksheetData;
|
|
@@ -99,7 +99,8 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
99
99
|
|
|
100
100
|
getCellVal(addr: { r: number; c: number }): string | undefined {
|
|
101
101
|
const cellData = this._getCellData(addr);
|
|
102
|
-
const
|
|
102
|
+
const tVal = cellData?.is?.[0]?.t?.[0];
|
|
103
|
+
const val = cellData?.v?.[0] ?? (typeof tVal === "string" ? tVal : tVal?._);
|
|
103
104
|
return typeof val === "string" ? val : undefined;
|
|
104
105
|
}
|
|
105
106
|
|
|
@@ -130,21 +131,21 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
deleteCell(addr: { r: number; c: number }): void {
|
|
133
|
-
// ROW
|
|
134
|
+
// No-op if ROW does not exist
|
|
134
135
|
const rowInfo = this._dataMap.get(addr.r);
|
|
135
136
|
if (rowInfo == null) return;
|
|
136
137
|
|
|
137
|
-
// CELL
|
|
138
|
+
// No-op if CELL does not exist
|
|
138
139
|
const cellData = rowInfo.cellMap.get(addr.c);
|
|
139
140
|
if (cellData == null) return;
|
|
140
141
|
|
|
141
|
-
// CELL
|
|
142
|
+
// Delete CELL
|
|
142
143
|
const cellsData = rowInfo.data.c!;
|
|
143
144
|
const cellIndex = cellsData.indexOf(cellData);
|
|
144
145
|
if (cellIndex !== -1) cellsData.splice(cellIndex, 1);
|
|
145
146
|
rowInfo.cellMap.delete(addr.c);
|
|
146
147
|
|
|
147
|
-
//
|
|
148
|
+
// Delete ROW if it was the last CELL
|
|
148
149
|
if (rowInfo.cellMap.size === 0) {
|
|
149
150
|
this._deleteRow(addr.r);
|
|
150
151
|
}
|
|
@@ -160,7 +161,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
160
161
|
|
|
161
162
|
const newRange = { s: startAddr, e: endAddr };
|
|
162
163
|
|
|
163
|
-
//
|
|
164
|
+
// Check for merge overlap
|
|
164
165
|
const existingMergeCells = mergeCells[0].mergeCell;
|
|
165
166
|
for (const mergeCell of existingMergeCells) {
|
|
166
167
|
const existingRange = ExcelUtils.parseRangeAddrCode(mergeCell.$.ref);
|
|
@@ -172,7 +173,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
172
173
|
newRange.e.c >= existingRange.s.c
|
|
173
174
|
) {
|
|
174
175
|
throw new Error(
|
|
175
|
-
|
|
176
|
+
`Merged cell overlaps with existing merge range (${mergeCell.$.ref}): ${ExcelUtils.stringifyRangeAddr(newRange)}`,
|
|
176
177
|
);
|
|
177
178
|
}
|
|
178
179
|
}
|
|
@@ -180,7 +181,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
180
181
|
mergeCells[0].mergeCell.push({ $: { ref: ExcelUtils.stringifyRangeAddr(newRange) } });
|
|
181
182
|
mergeCells[0].$.count = mergeCells[0].mergeCell.length.toString();
|
|
182
183
|
|
|
183
|
-
//
|
|
184
|
+
// Delete all cells except the start cell
|
|
184
185
|
for (let r = startAddr.r; r <= endAddr.r; r++) {
|
|
185
186
|
for (let c = startAddr.c; c <= endAddr.c; c++) {
|
|
186
187
|
const currentAddr = { r, c };
|
|
@@ -221,23 +222,23 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
/**
|
|
224
|
-
*
|
|
225
|
+
* Set width of a specific column.
|
|
225
226
|
*
|
|
226
227
|
* @internal
|
|
227
|
-
*
|
|
228
|
+
* Use ExcelCol.setWidth() externally.
|
|
228
229
|
*
|
|
229
|
-
* @param colIndex
|
|
230
|
-
* @param width
|
|
230
|
+
* @param colIndex Column index (1-based, string)
|
|
231
|
+
* @param width Width to set
|
|
231
232
|
*/
|
|
232
233
|
setColWidth(colIndex: string, width: string): void {
|
|
233
234
|
const colIndexNumber = numParseInt(colIndex);
|
|
234
235
|
if (colIndexNumber == null) {
|
|
235
|
-
throw new Error(
|
|
236
|
+
throw new Error(`Invalid column index: ${colIndex}`);
|
|
236
237
|
}
|
|
237
238
|
|
|
238
239
|
const cols = this.data.worksheet.cols?.[0];
|
|
239
240
|
|
|
240
|
-
//
|
|
241
|
+
// Find existing range containing the target column
|
|
241
242
|
const col = cols
|
|
242
243
|
? cols.col.single(
|
|
243
244
|
(item) =>
|
|
@@ -248,20 +249,20 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
248
249
|
|
|
249
250
|
if (col != null && cols != null) {
|
|
250
251
|
if (col.$.min === col.$.max) {
|
|
251
|
-
//
|
|
252
|
+
// Single column range: update properties of that column only
|
|
252
253
|
col.$.bestFit = "1";
|
|
253
254
|
col.$.customWidth = "1";
|
|
254
255
|
col.$.width = width;
|
|
255
256
|
} else {
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
257
|
+
// Multi-column range: split the range and apply new width only to target column
|
|
258
|
+
// e.g.: existing [1~5, width=10], target=3, new width=20
|
|
259
|
+
// -> [1~2, width=10], [3, width=20], [4~5, width=10]
|
|
259
260
|
const minNumber = numParseInt(col.$.min) ?? 0;
|
|
260
261
|
const maxNumber = numParseInt(col.$.max) ?? 0;
|
|
261
262
|
|
|
262
263
|
let insertIndex = cols.col.indexOf(col);
|
|
263
264
|
|
|
264
|
-
//
|
|
265
|
+
// Create front range (min ~ colIndex-1): keep original properties
|
|
265
266
|
if (minNumber < colIndexNumber) {
|
|
266
267
|
cols.col.splice(insertIndex, 0, {
|
|
267
268
|
$: {
|
|
@@ -273,7 +274,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
273
274
|
insertIndex++;
|
|
274
275
|
}
|
|
275
276
|
|
|
276
|
-
//
|
|
277
|
+
// Create target column (colIndex): apply new width
|
|
277
278
|
cols.col.splice(insertIndex, 0, {
|
|
278
279
|
$: {
|
|
279
280
|
min: colIndex,
|
|
@@ -285,7 +286,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
285
286
|
});
|
|
286
287
|
insertIndex++;
|
|
287
288
|
|
|
288
|
-
//
|
|
289
|
+
// Create back range (colIndex+1 ~ max): keep original properties
|
|
289
290
|
if (maxNumber > colIndexNumber) {
|
|
290
291
|
cols.col.splice(insertIndex, 0, {
|
|
291
292
|
$: {
|
|
@@ -296,12 +297,12 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
296
297
|
});
|
|
297
298
|
}
|
|
298
299
|
|
|
299
|
-
//
|
|
300
|
+
// Delete original range
|
|
300
301
|
const colIndex2 = cols.col.indexOf(col);
|
|
301
302
|
if (colIndex2 !== -1) cols.col.splice(colIndex2, 1);
|
|
302
303
|
}
|
|
303
304
|
} else {
|
|
304
|
-
//
|
|
305
|
+
// No existing range: create new range
|
|
305
306
|
this.data.worksheet.cols = this.data.worksheet.cols ?? [{ col: [] }];
|
|
306
307
|
this.data.worksheet.cols[0].col.push({
|
|
307
308
|
$: {
|
|
@@ -353,17 +354,17 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
353
354
|
}
|
|
354
355
|
|
|
355
356
|
copyRow(sourceR: number, targetR: number): void {
|
|
356
|
-
//
|
|
357
|
+
// Clone source ROW data
|
|
357
358
|
const sourceRowInfo = this._dataMap.get(sourceR);
|
|
358
359
|
|
|
359
360
|
if (sourceRowInfo != null) {
|
|
360
|
-
// rowData
|
|
361
|
+
// Clone rowData
|
|
361
362
|
const newRowData: ExcelRowData = objClone(sourceRowInfo.data);
|
|
362
363
|
|
|
363
|
-
// ROW
|
|
364
|
+
// Update ROW address
|
|
364
365
|
newRowData.$.r = ExcelUtils.stringifyRowAddr(targetR);
|
|
365
366
|
|
|
366
|
-
//
|
|
367
|
+
// Update each CELL address
|
|
367
368
|
if (newRowData.c != null) {
|
|
368
369
|
for (const cellData of newRowData.c) {
|
|
369
370
|
const colAddr = ExcelUtils.parseColAddrCode(cellData.$.r);
|
|
@@ -376,19 +377,19 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
376
377
|
this._deleteRow(targetR);
|
|
377
378
|
}
|
|
378
379
|
|
|
379
|
-
//
|
|
380
|
+
// Copy and store source row merge cell info first
|
|
380
381
|
const sourceMergeCells = this.getMergeCells()
|
|
381
382
|
.filter((mc) => mc.s.r <= sourceR && mc.e.r >= sourceR)
|
|
382
383
|
.map((mc) => ({ s: { ...mc.s }, e: { ...mc.e } }));
|
|
383
384
|
|
|
384
|
-
//
|
|
385
|
+
// Remove existing merge cells in target row
|
|
385
386
|
for (const mergeCell of this.getMergeCells()) {
|
|
386
387
|
if (mergeCell.s.r <= targetR && mergeCell.e.r >= targetR) {
|
|
387
388
|
this.removeMergeCells(mergeCell.s, mergeCell.e);
|
|
388
389
|
}
|
|
389
390
|
}
|
|
390
391
|
|
|
391
|
-
//
|
|
392
|
+
// Copy stored source merge info to target
|
|
392
393
|
for (const mergeCell of sourceMergeCells) {
|
|
393
394
|
const rowDiff = targetR - sourceR;
|
|
394
395
|
const newStartAddr = { r: mergeCell.s.r + rowDiff, c: mergeCell.s.c };
|
|
@@ -412,7 +413,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
412
413
|
cleanup(): void {
|
|
413
414
|
const result = {} as ExcelXmlWorksheetData["worksheet"];
|
|
414
415
|
|
|
415
|
-
//
|
|
416
|
+
// Sort order (around "sheetData", keep others in original position)
|
|
416
417
|
|
|
417
418
|
for (const key of Object.keys(this.data.worksheet)) {
|
|
418
419
|
if (key === "mergeCells") continue;
|
|
@@ -442,11 +443,11 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
442
443
|
}
|
|
443
444
|
}
|
|
444
445
|
|
|
445
|
-
//
|
|
446
|
+
// Sort ROWs
|
|
446
447
|
const rowsData = (result.sheetData[0].row = result.sheetData[0].row ?? []);
|
|
447
448
|
rowsData.sort((a, b) => (numParseInt(a.$.r) ?? 0) - (numParseInt(b.$.r) ?? 0));
|
|
448
449
|
|
|
449
|
-
//
|
|
450
|
+
// Sort CELLs
|
|
450
451
|
for (const rowData of rowsData) {
|
|
451
452
|
const cellsData = rowData.c;
|
|
452
453
|
if (cellsData == null) continue;
|
|
@@ -455,7 +456,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
455
456
|
);
|
|
456
457
|
}
|
|
457
458
|
|
|
458
|
-
//
|
|
459
|
+
// Apply dimension value
|
|
459
460
|
if (result.dimension != null) {
|
|
460
461
|
result.dimension[0].$.ref = ExcelUtils.stringifyRangeAddr(this.range);
|
|
461
462
|
} else {
|
|
@@ -470,10 +471,10 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
470
471
|
}
|
|
471
472
|
|
|
472
473
|
private _getOrCreateCellData(addr: { r: number; c: number }): ExcelCellData {
|
|
473
|
-
// ROW
|
|
474
|
+
// Create ROW if it does not exist
|
|
474
475
|
const rowInfo = this._getOrCreateRowInfo(addr.r);
|
|
475
476
|
|
|
476
|
-
// CELL
|
|
477
|
+
// Create CELL if it does not exist
|
|
477
478
|
let cellData = rowInfo.cellMap.get(addr.c);
|
|
478
479
|
if (cellData === undefined) {
|
|
479
480
|
rowInfo.data.c = rowInfo.data.c ?? [];
|
|
@@ -497,11 +498,11 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
497
498
|
private _replaceRowData(r: number, rowData: ExcelRowData): RowInfo {
|
|
498
499
|
this._deleteRow(r);
|
|
499
500
|
|
|
500
|
-
// sheet
|
|
501
|
+
// Write to sheet
|
|
501
502
|
this.data.worksheet.sheetData[0].row = this.data.worksheet.sheetData[0].row ?? [];
|
|
502
503
|
this.data.worksheet.sheetData[0].row.push(rowData);
|
|
503
504
|
|
|
504
|
-
// cache
|
|
505
|
+
// Write to cache
|
|
505
506
|
const rowInfo = {
|
|
506
507
|
data: rowData,
|
|
507
508
|
cellMap: (rowData.c ?? []).toMap(
|
|
@@ -520,11 +521,11 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
520
521
|
// ROW
|
|
521
522
|
const targetRowInfo = this._getOrCreateRowInfo(addr.r);
|
|
522
523
|
|
|
523
|
-
// sheet
|
|
524
|
+
// Write to sheet
|
|
524
525
|
targetRowInfo.data.c = targetRowInfo.data.c ?? [];
|
|
525
526
|
targetRowInfo.data.c.push(cellData);
|
|
526
527
|
|
|
527
|
-
// cache
|
|
528
|
+
// Write to cache
|
|
528
529
|
targetRowInfo.cellMap.set(addr.c, cellData);
|
|
529
530
|
}
|
|
530
531
|
|
|
@@ -539,7 +540,7 @@ export class ExcelXmlWorksheet implements ExcelXml {
|
|
|
539
540
|
}
|
|
540
541
|
this._dataMap.delete(r);
|
|
541
542
|
|
|
542
|
-
//
|
|
543
|
+
// Delete the row section from XML if no ROWs remain
|
|
543
544
|
if (this.data.worksheet.sheetData[0].row?.length === 0) {
|
|
544
545
|
delete this.data.worksheet.sheetData[0].row;
|
|
545
546
|
}
|