@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
@@ -2,26 +2,26 @@ import { numParseInt } from "@simplysm/core-common";
2
2
  import type { ExcelAddressPoint, ExcelAddressRangePoint, ExcelNumberFormat } from "../types";
3
3
 
4
4
  /**
5
- * Excel 관련 유틸리티 함수 모음.
6
- * 주소 변환, 날짜/숫자 변환, 숫자 형식 처리 등의 기능을 제공한다.
5
+ * Collection of Excel utility functions.
6
+ * Provides cell address conversion, date/number conversion, and number format processing.
7
7
  */
8
8
  export class ExcelUtils {
9
- /** 좌표를 "A1" 형식 문자열로 변환 */
9
+ /** Convert cell coordinates to "A1" format string */
10
10
  static stringifyAddr(point: ExcelAddressPoint): string {
11
11
  const rowStr = this.stringifyRowAddr(point.r);
12
12
  const colStr = this.stringifyColAddr(point.c);
13
13
  return `${colStr}${rowStr}`;
14
14
  }
15
15
 
16
- /** 인덱스(0-based) 주소 문자열로 변환 (예: 0 -> "1") */
16
+ /** Convert row index (0-based) to row address string (e.g. 0 -> "1") */
17
17
  static stringifyRowAddr(r: number): string {
18
18
  return (r + 1).toString();
19
19
  }
20
20
 
21
- /** 인덱스(0-based) 주소 문자열로 변환 (예: 0 -> "A", 26 -> "AA") */
21
+ /** Convert column index (0-based) to column address string (e.g. 0 -> "A", 26 -> "AA") */
22
22
  static stringifyColAddr(c: number): string {
23
23
  if (c < 0 || c > 16383) {
24
- throw new Error(`열 인덱스는 0~16383 범위여야 합니다: ${c}`);
24
+ throw new Error(`Column index must be in range 0~16383: ${c}`);
25
25
  }
26
26
 
27
27
  let remained = c;
@@ -34,17 +34,17 @@ export class ExcelUtils {
34
34
  return result;
35
35
  }
36
36
 
37
- /** 주소에서 인덱스 추출 (예: "A3" -> 2) */
37
+ /** Extract row index from cell address (e.g. "A3" -> 2) */
38
38
  static parseRowAddrCode(addrCode: string): number {
39
39
  const rowAddrCode = /\d*$/.exec(addrCode)?.[0] ?? "";
40
40
  const parsed = numParseInt(rowAddrCode);
41
41
  if (parsed == null) {
42
- throw new Error(`잘못된 주소 코드: ${addrCode}`);
42
+ throw new Error(`Invalid row address code: ${addrCode}`);
43
43
  }
44
44
  return parsed - 1;
45
45
  }
46
46
 
47
- /** 주소에서 인덱스 추출 (예: "B3" -> 1) */
47
+ /** Extract column index from cell address (e.g. "B3" -> 1) */
48
48
  static parseColAddrCode(addrCode: string): number {
49
49
  const colAddrCode = /^[a-zA-Z]*/.exec(addrCode)?.[0] ?? "";
50
50
 
@@ -57,7 +57,7 @@ export class ExcelUtils {
57
57
  return result;
58
58
  }
59
59
 
60
- /** 주소를 좌표로 변환 (예: "B3" -> {r: 2, c: 1}) */
60
+ /** Convert cell address to coordinates (e.g. "B3" -> {r: 2, c: 1}) */
61
61
  static parseCellAddrCode(addr: string): ExcelAddressPoint {
62
62
  return {
63
63
  r: ExcelUtils.parseRowAddrCode(addr),
@@ -65,7 +65,7 @@ export class ExcelUtils {
65
65
  };
66
66
  }
67
67
 
68
- /** 범위 주소를 좌표로 변환 (예: "A1:C3" -> {s: {r:0,c:0}, e: {r:2,c:2}}) */
68
+ /** Convert range address to coordinates (e.g. "A1:C3" -> {s: {r:0,c:0}, e: {r:2,c:2}}) */
69
69
  static parseRangeAddrCode(rangeAddr: string): ExcelAddressRangePoint {
70
70
  const parts = rangeAddr.split(":");
71
71
  return {
@@ -74,7 +74,7 @@ export class ExcelUtils {
74
74
  };
75
75
  }
76
76
 
77
- /** 범위 좌표를 주소 문자열로 변환 */
77
+ /** Convert range coordinates to address string */
78
78
  static stringifyRangeAddr(point: ExcelAddressRangePoint): string {
79
79
  const sAddr = this.stringifyAddr(point.s);
80
80
  const eAddr = this.stringifyAddr(point.e);
@@ -87,8 +87,8 @@ export class ExcelUtils {
87
87
  }
88
88
 
89
89
  /**
90
- * JavaScript 타임스탬프(ms) Excel 날짜 숫자로 변환.
91
- * Excel 1900-01-01 1 계산한다 (1899-12-30 날짜 0).
90
+ * Convert JavaScript timestamp (ms) to Excel date number.
91
+ * Excel counts 1900-01-01 as 1 (1899-12-30 is date 0).
92
92
  */
93
93
  static convertTimeTickToNumber(tick: number): number {
94
94
  const currDate = new Date(tick);
@@ -99,8 +99,8 @@ export class ExcelUtils {
99
99
  }
100
100
 
101
101
  /**
102
- * Excel 날짜 숫자를 JavaScript 타임스탬프(ms)로 변환.
103
- * Excel 1900-01-01 1 계산한다 (1899-12-30 날짜 0).
102
+ * Convert Excel date number to JavaScript timestamp (ms).
103
+ * Excel counts 1900-01-01 as 1 (1899-12-30 is date 0).
104
104
  */
105
105
  static convertNumberToTimeTick(num: number): number {
106
106
  const excelBaseDateNumberUtc = Date.UTC(1899, 11, 31);
@@ -111,7 +111,7 @@ export class ExcelUtils {
111
111
  return date.getTime();
112
112
  }
113
113
 
114
- /** 숫자 형식 코드를 형식 이름으로 변환 */
114
+ /** Convert number format code to format name */
115
115
  static convertNumFmtCodeToName(numFmtCode: string): ExcelNumberFormat {
116
116
  if (numFmtCode === "General") {
117
117
  return "number";
@@ -121,40 +121,40 @@ export class ExcelUtils {
121
121
  const hasTime = /hh/i.test(numFmtCode) || /ss/i.test(numFmtCode);
122
122
 
123
123
  if (hasDate && hasTime) {
124
- return "DateTime"; // 날짜+시간 = DateTime
124
+ return "DateTime"; // date+time = DateTime
125
125
  } else if (hasDate) {
126
- return "DateOnly"; // 날짜만 = DateOnly
126
+ return "DateOnly"; // date only = DateOnly
127
127
  } else if (hasTime) {
128
- return "Time"; // 시간만 = Time
128
+ return "Time"; // time only = Time
129
129
  }
130
- // 숫자 형식 패턴: 0, #, 소수점, 천단위 구분자, 음수 구분자, 괄호, 통화, 공백, 지수, 백분율
131
- // "[조건부 서식]실제형식" 구조에서 실제형식 부분만 검사 (split("]").at(-1))
130
+ // Number format pattern: 0, #, decimal, thousands separator, negative separator, parentheses, currency, space, exponent, percent, etc.
131
+ // In "[conditional format]actual format" structure, only check the actual format part (split("]").at(-1))
132
132
  else if (/^[0.#,_;()\-\\$ @*?"E%+]*$/.test(numFmtCode.split("]").at(-1) ?? "")) {
133
133
  return "number";
134
134
  } else if ((numFmtCode.split("]").at(-1) ?? "").includes("#,0")) {
135
135
  return "number";
136
136
  } else {
137
- throw new Error(`[numFmtCode: ${numFmtCode}]에 대한 형식을 알 수 없습니다.`);
137
+ throw new Error(`Unknown format for [numFmtCode: ${numFmtCode}].`);
138
138
  }
139
139
  }
140
140
 
141
141
  /**
142
- * 숫자 형식 ID 형식 이름으로 변환
142
+ * Convert number format ID to format name
143
143
  *
144
144
  * @remarks
145
- * Excel 내장 형식 ID 범위:
146
- * - 0~13, 37~40, 48: 숫자/일반/통화/백분율 형식
147
- * - 14~17, 27~31, 34~36, 50~58: 날짜 형식 (지역화 포함)
148
- * - 22: 날짜+시간 형식
149
- * - 18~21, 32~33, 45~47: 시간 형식
150
- * - 49: 텍스트 형식
145
+ * Excel built-in format ID ranges:
146
+ * - 0~13, 37~40, 48: number/general/currency/percent formats
147
+ * - 14~17, 27~31, 34~36, 50~58: date formats (including localized)
148
+ * - 22: date+time format
149
+ * - 18~21, 32~33, 45~47: time formats
150
+ * - 49: text format
151
151
  */
152
152
  static convertNumFmtIdToName(numFmtId: number): ExcelNumberFormat {
153
- // 숫자/일반/통화/백분율 형식
153
+ // Number/general/currency/percent formats
154
154
  if (numFmtId <= 13 || (numFmtId >= 37 && numFmtId <= 40) || numFmtId === 48) {
155
155
  return "number";
156
156
  }
157
- // 날짜 형식 (지역화 포함)
157
+ // Date formats (including localized)
158
158
  else if (
159
159
  (numFmtId >= 14 && numFmtId <= 17) ||
160
160
  (numFmtId >= 27 && numFmtId <= 31) ||
@@ -163,11 +163,11 @@ export class ExcelUtils {
163
163
  ) {
164
164
  return "DateOnly";
165
165
  }
166
- // 날짜+시간 형식
166
+ // Date+time format
167
167
  else if (numFmtId === 22) {
168
168
  return "DateTime";
169
169
  }
170
- // 시간 형식
170
+ // Time formats
171
171
  else if (
172
172
  (numFmtId >= 18 && numFmtId <= 21) ||
173
173
  (numFmtId >= 32 && numFmtId <= 33) ||
@@ -175,15 +175,15 @@ export class ExcelUtils {
175
175
  ) {
176
176
  return "Time";
177
177
  }
178
- // 텍스트 형식
178
+ // Text format
179
179
  else if (numFmtId === 49) {
180
180
  return "string";
181
181
  } else {
182
- throw new Error(`[numFmtId: ${numFmtId}]에 대한 형식을 알 수 없습니다.`);
182
+ throw new Error(`Unknown format for [numFmtId: ${numFmtId}].`);
183
183
  }
184
184
  }
185
185
 
186
- /** 숫자 형식 이름을 형식 ID 변환 */
186
+ /** Convert number format name to format ID */
187
187
  static convertNumFmtNameToId(numFmtName: ExcelNumberFormat): number {
188
188
  if (numFmtName === "number") {
189
189
  return 0;
@@ -194,7 +194,7 @@ export class ExcelUtils {
194
194
  } else if (numFmtName === "Time") {
195
195
  return 18;
196
196
  } else {
197
- // 마지막 케이스: "string" (TypeScript 타입 좁히기를 통해 자동으로 확인)
197
+ // Last case: "string" (TypeScript verifies automatically through type narrowing)
198
198
  return 49;
199
199
  }
200
200
  }
@@ -20,15 +20,15 @@ import { ExcelXmlWorkbook } from "../xml/excel-xml-workbook";
20
20
  import { ExcelXmlWorksheet } from "../xml/excel-xml-worksheet";
21
21
 
22
22
  /**
23
- * Excel ZIP 아카이브의 파일 캐시를 관리하는 클래스.
24
- * XML 파일은 파싱하여 ExcelXml 객체로, 파일은 바이트 배열로 캐싱한다.
23
+ * Class managing file cache for Excel ZIP archives.
24
+ * XML files are parsed into ExcelXml objects; other files are cached as byte arrays.
25
25
  *
26
26
  * @remarks
27
- * ## Lazy Loading 캐시 전략
27
+ * ## Lazy Loading Cache Strategy
28
28
  *
29
- * - 파일은 접근 시에만 ZIP에서 읽고 파싱한다
30
- * - 이후 접근은 캐시된 객체를 반환한다
31
- * - 대용량 Excel 파일에서 필요한 부분만 로드하여 메모리 효율성을 높인다
29
+ * - Files are read and parsed from the ZIP only on first access
30
+ * - Subsequent accesses return the cached object
31
+ * - Loads only the needed parts from large Excel files for memory efficiency
32
32
  */
33
33
  export class ZipCache {
34
34
  private readonly _cache = new Map<string, ExcelXml | Bytes | undefined>();
@@ -1,8 +1,8 @@
1
1
  import type { ExcelXml, ExcelXmlContentTypeData } from "../types";
2
2
 
3
3
  /**
4
- * [Content_Types].xml 파일을 관리하는 클래스.
5
- * 파일별 MIME 타입 정보를 관리한다.
4
+ * Class managing [Content_Types].xml.
5
+ * Manages MIME type information per file.
6
6
  */
7
7
  export class ExcelXmlContentType implements ExcelXml {
8
8
  data: ExcelXmlContentTypeData;
@@ -45,7 +45,7 @@ export class ExcelXmlContentType implements ExcelXml {
45
45
  }
46
46
 
47
47
  add(partName: string, contentType: string): this {
48
- // 중복 체크
48
+ // Duplicate check
49
49
  const exists = this.data.Types.Override.some((item) => item.$.PartName === partName);
50
50
  if (exists) {
51
51
  return this;
@@ -1,8 +1,8 @@
1
1
  import type { ExcelXml, ExcelXmlDrawingData } from "../types";
2
2
 
3
3
  /**
4
- * xl/drawings/drawing*.xml 파일을 관리하는 클래스.
5
- * 이미지 삽입 위치 참조 정보를 처리한다.
4
+ * Class managing xl/drawings/drawing*.xml files.
5
+ * Handles position and reference information for image insertion.
6
6
  */
7
7
  export class ExcelXmlDrawing implements ExcelXml {
8
8
  data: ExcelXmlDrawingData;
@@ -3,8 +3,8 @@ import { numParseInt } from "@simplysm/core-common";
3
3
  import type { ExcelRelationshipData, ExcelXml, ExcelXmlRelationshipData } from "../types";
4
4
 
5
5
  /**
6
- * *.rels 파일을 관리하는 클래스.
7
- * 파일 간의 참조 관계를 처리한다.
6
+ * Class managing *.rels files.
7
+ * Handles reference relationships between files.
8
8
  */
9
9
  export class ExcelXmlRelationship implements ExcelXml {
10
10
  data: ExcelXmlRelationshipData;
@@ -82,7 +82,7 @@ export class ExcelXmlRelationship implements ExcelXml {
82
82
  private _getRelId(rel: ExcelRelationshipData): number {
83
83
  const match = /[0-9]+$/.exec(rel.$.Id);
84
84
  if (match == null) {
85
- throw new Error(`잘못된 관계 ID 형식입니다: ${rel.$.Id}`);
85
+ throw new Error(`Invalid relationship ID format: ${rel.$.Id}`);
86
86
  }
87
87
  return numParseInt(match[0])!;
88
88
  }
@@ -7,8 +7,8 @@ import type {
7
7
  import "@simplysm/core-common";
8
8
 
9
9
  /**
10
- * xl/sharedStrings.xml 파일을 관리하는 클래스.
11
- * 문자열 중복을 방지하여 파일 크기를 최적화한다.
10
+ * Class managing xl/sharedStrings.xml.
11
+ * Optimizes file size by preventing string duplication.
12
12
  */
13
13
  export class ExcelXmlSharedString implements ExcelXml {
14
14
  data: ExcelXmlSharedStringData;
@@ -21,8 +21,8 @@ export interface ExcelStyle {
21
21
  }
22
22
 
23
23
  /**
24
- * xl/styles.xml 파일을 관리하는 클래스.
25
- * 숫자 형식, 배경색, 테두리, 정렬 등의 스타일을 처리한다.
24
+ * Class managing xl/styles.xml.
25
+ * Handles styles such as number formats, background colors, borders, and alignment.
26
26
  */
27
27
  export class ExcelXmlStyle implements ExcelXml {
28
28
  data: ExcelXmlStyleData;
@@ -108,11 +108,11 @@ export class ExcelXmlStyle implements ExcelXml {
108
108
  addWithClone(id: string, style: ExcelStyle): string {
109
109
  const idNum = numParseInt(id);
110
110
  if (idNum == null) {
111
- throw new Error(`잘못된 스타일 ID: ${id}`);
111
+ throw new Error(`Invalid style ID: ${id}`);
112
112
  }
113
113
  const xfArray = this.data.styleSheet.cellXfs[0].xf;
114
114
  if (idNum < 0 || idNum >= xfArray.length) {
115
- throw new Error(`존재하지 않는 스타일 ID: ${id} (범위: 0-${xfArray.length - 1})`);
115
+ throw new Error(`Non-existent style ID: ${id} (Range: 0-${xfArray.length - 1})`);
116
116
  }
117
117
  const prevXf = xfArray[idNum];
118
118
  const cloneXf = objClone(prevXf);
@@ -187,7 +187,7 @@ export class ExcelXmlStyle implements ExcelXml {
187
187
  get(id: string): ExcelStyle {
188
188
  const idNum = numParseInt(id);
189
189
  if (idNum == null) {
190
- throw new Error(`잘못된 스타일 ID: ${id}`);
190
+ throw new Error(`Invalid style ID: ${id}`);
191
191
  }
192
192
  const xf = this.data.styleSheet.cellXfs[0].xf[idNum] as ExcelXmlStyleDataXf | undefined;
193
193
 
@@ -204,7 +204,7 @@ export class ExcelXmlStyle implements ExcelXml {
204
204
  | undefined;
205
205
  if (fill == null) {
206
206
  throw new Error(
207
- `존재하지 않는 fill ID: ${xf.$.fillId} (범위: 0-${this.data.styleSheet.fills[0].fill.length - 1})`,
207
+ `Non-existent fill ID: ${xf.$.fillId} (Range: 0-${this.data.styleSheet.fills[0].fill.length - 1})`,
208
208
  );
209
209
  }
210
210
  result.background = fill.patternFill[0].fgColor?.[0].$.rgb;
@@ -214,14 +214,14 @@ export class ExcelXmlStyle implements ExcelXml {
214
214
  if (xf.$.borderId !== undefined) {
215
215
  const borderIdNum = numParseInt(xf.$.borderId);
216
216
  if (borderIdNum == null) {
217
- throw new Error(`잘못된 border ID: ${xf.$.borderId}`);
217
+ throw new Error(`Invalid border ID: ${xf.$.borderId}`);
218
218
  }
219
219
  const border = this.data.styleSheet.borders[0].border[borderIdNum] as
220
220
  | ExcelXmlStyleDataBorder
221
221
  | undefined;
222
222
  if (border == null) {
223
223
  throw new Error(
224
- `존재하지 않는 border ID: ${xf.$.borderId} (범위: 0-${this.data.styleSheet.borders[0].border.length - 1})`,
224
+ `Non-existent border ID: ${xf.$.borderId} (Range: 0-${this.data.styleSheet.borders[0].border.length - 1})`,
225
225
  );
226
226
  }
227
227
  if (
@@ -262,7 +262,7 @@ export class ExcelXmlStyle implements ExcelXml {
262
262
  cleanup(): void {
263
263
  const result = {} as ExcelXmlStyleData["styleSheet"];
264
264
 
265
- // 순서 정렬 (numFmts 맨위로)
265
+ // Sort order (numFmts first)
266
266
 
267
267
  if (this.data.styleSheet.numFmts != null) {
268
268
  result.numFmts = this.data.styleSheet.numFmts;
@@ -282,7 +282,7 @@ export class ExcelXmlStyle implements ExcelXml {
282
282
  //#region Private Methods
283
283
 
284
284
  private _setNumFmtCode(numFmtCode: string): string {
285
- // 이미 해당 code 있으면 넘기기
285
+ // Skip if the code already exists
286
286
  const existsNumFmtId = (this.data.styleSheet.numFmts?.[0].numFmt ?? []).single(
287
287
  (item) => item.$.formatCode === numFmtCode,
288
288
  )?.$.numFmtId;
@@ -299,7 +299,7 @@ export class ExcelXmlStyle implements ExcelXml {
299
299
 
300
300
  this.data.styleSheet.numFmts[0].numFmt = this.data.styleSheet.numFmts[0].numFmt ?? [];
301
301
 
302
- // Excel 사용자 정의 숫자 형식은 ID 180 이상부터 시작한다 (0-163: 내장 형식, 164-179: 예약됨)
302
+ // Excel custom number formats start from ID 180+ (0-163: built-in, 164-179: reserved)
303
303
  const numFmts = this.data.styleSheet.numFmts[0].numFmt;
304
304
  const maxItem =
305
305
  numFmts.length > 0
@@ -1,8 +1,8 @@
1
1
  import type { ExcelXml } from "../types";
2
2
 
3
3
  /**
4
- * 없는 형식의 Excel XML 데이터를 보존하는 클래스.
5
- * 원본 데이터를 손실 없이 유지한다.
4
+ * Class preserving Excel XML data of unknown format.
5
+ * Maintains original data without loss.
6
6
  */
7
7
  export class ExcelXmlUnknown implements ExcelXml {
8
8
  constructor(public readonly data: Record<string, unknown>) {}
@@ -3,8 +3,8 @@ import { numParseInt } from "@simplysm/core-common";
3
3
  import type { ExcelXml, ExcelXmlWorkbookData } from "../types";
4
4
 
5
5
  /**
6
- * xl/workbook.xml 파일을 관리하는 클래스.
7
- * 워크시트 목록과 관계 ID를 처리한다.
6
+ * Class managing xl/workbook.xml.
7
+ * Handles the worksheet list and relationship IDs.
8
8
  */
9
9
  export class ExcelXmlWorkbook implements ExcelXml {
10
10
  data: ExcelXmlWorkbookData;
@@ -55,7 +55,7 @@ export class ExcelXmlWorkbook implements ExcelXml {
55
55
  cleanup(): void {
56
56
  const result = {} as ExcelXmlWorkbookData["workbook"];
57
57
 
58
- // 순서 정렬 ("sheets"기준 앞뒤로, 나머지는 원래위치대로)
58
+ // Sort order (around "sheets", keep others in original position)
59
59
 
60
60
  const workbookRec = this.data.workbook as Record<string, unknown>;
61
61
  const resultRec = result as Record<string, unknown>;
@@ -99,7 +99,7 @@ export class ExcelXmlWorkbook implements ExcelXml {
99
99
  setWorksheetNameById(id: number, newName: string): void {
100
100
  const sheetData = this._getSheetDataById(id);
101
101
  if (sheetData == null) {
102
- throw new Error(`워크시트 ID ${id}를 찾을 수 없습니다`);
102
+ throw new Error(`Cannot find worksheet ID ${id}`);
103
103
  }
104
104
  const replacedName = this._getReplacedName(newName);
105
105
  sheetData.$.name = replacedName;
@@ -112,7 +112,7 @@ export class ExcelXmlWorkbook implements ExcelXml {
112
112
  }
113
113
 
114
114
  private _getReplacedName(name: string): string {
115
- //-- 시트명칭 사용불가 텍스트를 "_"로 변환
115
+ //-- Replace invalid sheet name characters with "_"
116
116
  return name.replace(/[:\\/?*\[\]']/g, "_");
117
117
  }
118
118
  }