@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.
Files changed (75) hide show
  1. package/README.md +19 -516
  2. package/dist/excel-cell.d.ts +28 -28
  3. package/dist/excel-cell.d.ts.map +1 -1
  4. package/dist/excel-cell.js +24 -24
  5. package/dist/excel-cell.js.map +1 -1
  6. package/dist/excel-col.d.ts +4 -4
  7. package/dist/excel-col.d.ts.map +1 -1
  8. package/dist/excel-col.js +3 -3
  9. package/dist/excel-row.d.ts +3 -3
  10. package/dist/excel-row.d.ts.map +1 -1
  11. package/dist/excel-row.js +2 -2
  12. package/dist/excel-workbook.d.ts +23 -23
  13. package/dist/excel-workbook.d.ts.map +1 -1
  14. package/dist/excel-workbook.js +15 -15
  15. package/dist/excel-workbook.js.map +1 -1
  16. package/dist/excel-worksheet.d.ts +32 -32
  17. package/dist/excel-worksheet.d.ts.map +1 -1
  18. package/dist/excel-worksheet.js +32 -32
  19. package/dist/excel-worksheet.js.map +1 -1
  20. package/dist/excel-wrapper.d.ts +7 -7
  21. package/dist/excel-wrapper.js +7 -7
  22. package/dist/excel-wrapper.js.map +1 -1
  23. package/dist/types.d.ts +16 -16
  24. package/dist/types.d.ts.map +1 -1
  25. package/dist/utils/excel-utils.d.ts +23 -23
  26. package/dist/utils/excel-utils.d.ts.map +1 -1
  27. package/dist/utils/excel-utils.js +25 -25
  28. package/dist/utils/excel-utils.js.map +1 -1
  29. package/dist/utils/zip-cache.d.ts +6 -6
  30. package/dist/xml/excel-xml-content-type.d.ts +2 -2
  31. package/dist/xml/excel-xml-drawing.d.ts +2 -2
  32. package/dist/xml/excel-xml-relationship.d.ts +2 -2
  33. package/dist/xml/excel-xml-relationship.js +1 -1
  34. package/dist/xml/excel-xml-relationship.js.map +1 -1
  35. package/dist/xml/excel-xml-shared-string.d.ts +2 -2
  36. package/dist/xml/excel-xml-style.d.ts +2 -2
  37. package/dist/xml/excel-xml-style.js +6 -6
  38. package/dist/xml/excel-xml-style.js.map +1 -1
  39. package/dist/xml/excel-xml-unknown.d.ts +2 -2
  40. package/dist/xml/excel-xml-workbook.d.ts +2 -2
  41. package/dist/xml/excel-xml-workbook.js +1 -1
  42. package/dist/xml/excel-xml-workbook.js.map +1 -1
  43. package/dist/xml/excel-xml-worksheet.d.ts +6 -6
  44. package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
  45. package/dist/xml/excel-xml-worksheet.js +9 -8
  46. package/dist/xml/excel-xml-worksheet.js.map +1 -1
  47. package/package.json +6 -5
  48. package/src/excel-cell.ts +35 -35
  49. package/src/excel-col.ts +4 -4
  50. package/src/excel-row.ts +3 -3
  51. package/src/excel-workbook.ts +30 -30
  52. package/src/excel-worksheet.ts +47 -47
  53. package/src/excel-wrapper.ts +18 -18
  54. package/src/index.ts +3 -3
  55. package/src/types.ts +15 -17
  56. package/src/utils/excel-utils.ts +38 -38
  57. package/src/utils/zip-cache.ts +6 -6
  58. package/src/xml/excel-xml-content-type.ts +3 -3
  59. package/src/xml/excel-xml-drawing.ts +2 -2
  60. package/src/xml/excel-xml-relationship.ts +3 -3
  61. package/src/xml/excel-xml-shared-string.ts +2 -2
  62. package/src/xml/excel-xml-style.ts +11 -11
  63. package/src/xml/excel-xml-unknown.ts +2 -2
  64. package/src/xml/excel-xml-workbook.ts +5 -5
  65. package/src/xml/excel-xml-worksheet.ts +44 -43
  66. package/tests/excel-cell.spec.ts +448 -0
  67. package/tests/excel-col.spec.ts +112 -0
  68. package/tests/excel-row.spec.ts +71 -0
  69. package/tests/excel-workbook.spec.ts +219 -0
  70. package/tests/excel-worksheet.spec.ts +389 -0
  71. package/tests/excel-wrapper.spec.ts +296 -0
  72. package/tests/fixtures/logo.png +0 -0
  73. package/tests/fixtures//354/264/210/352/270/260/355/231/224.xlsx +0 -0
  74. package/tests/image-insert.spec.ts +190 -0
  75. 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 val = cellData?.v?.[0] ?? cellData?.is?.[0]?.t?.[0]?._;
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
- // 마지막 CELL이면 ROW 삭제
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
- `병합 셀이 기존 병합 범위(${mergeCell.$.ref}) 겹칩니다: ${ExcelUtils.stringifyRangeAddr(newRange)}`,
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
- * 외부에서는 ExcelCol.setWidth() 사용한다.
228
+ * Use ExcelCol.setWidth() externally.
228
229
  *
229
- * @param colIndex 인덱스 (1-based, 문자열)
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(`잘못된 인덱스: ${colIndex}`);
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
- // 기존 범위가 여러 열인 경우: 범위를 분할하여 대상 열만 width 적용
257
- // 예: 기존 [1~5, width=10], 대상=3, width=20
258
- // [1~2, width=10], [3, width=20], [4~5, width=10]
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
- // 앞쪽 범위 생성 (min ~ colIndex-1): 원본 속성 유지
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
- // 대상 생성 (colIndex): width 적용
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
- // 뒤쪽 범위 생성 (colIndex+1 ~ max): 원본 속성 유지
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
- // 출발지ROW 데이터 복제
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
- // CELL 주소 변경
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
- // 순서 정렬 ("sheetData"기준 앞뒤로, 나머지는 원래위치대로)
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
- // ROW 정렬
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
- // CELL 정렬
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
- // Dimension 적용
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
- // ROW가 하나도 없으면 XML row부분 자체를 삭제
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
  }