@simplysm/excel 13.0.0-beta.6 → 13.0.1

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 (163) hide show
  1. package/README.md +15 -0
  2. package/dist/excel-cell.d.ts.map +1 -0
  3. package/dist/excel-cell.js +3 -3
  4. package/dist/excel-cell.js.map +0 -1
  5. package/dist/excel-col.d.ts.map +1 -0
  6. package/dist/excel-col.js +1 -1
  7. package/dist/excel-col.js.map +0 -1
  8. package/dist/excel-row.d.ts.map +1 -0
  9. package/dist/excel-row.js +1 -1
  10. package/dist/excel-row.js.map +0 -1
  11. package/dist/excel-workbook.d.ts.map +1 -0
  12. package/dist/excel-workbook.js +7 -7
  13. package/dist/excel-workbook.js.map +1 -2
  14. package/dist/excel-worksheet.d.ts.map +1 -0
  15. package/dist/excel-worksheet.js +4 -4
  16. package/dist/excel-worksheet.js.map +0 -1
  17. package/dist/excel-wrapper.d.ts.map +1 -0
  18. package/dist/excel-wrapper.js +1 -1
  19. package/dist/excel-wrapper.js.map +0 -1
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +8 -8
  22. package/dist/index.js.map +0 -1
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js.map +0 -1
  25. package/dist/utils/excel-utils.d.ts.map +1 -0
  26. package/dist/utils/excel-utils.js.map +0 -1
  27. package/dist/utils/zip-cache.d.ts.map +1 -0
  28. package/dist/utils/zip-cache.js +8 -8
  29. package/dist/utils/zip-cache.js.map +0 -1
  30. package/dist/xml/excel-xml-content-type.d.ts.map +1 -0
  31. package/dist/xml/excel-xml-content-type.js.map +0 -1
  32. package/dist/xml/excel-xml-drawing.d.ts.map +1 -0
  33. package/dist/xml/excel-xml-drawing.js.map +0 -1
  34. package/dist/xml/excel-xml-relationship.d.ts.map +1 -0
  35. package/dist/xml/excel-xml-relationship.js.map +0 -1
  36. package/dist/xml/excel-xml-shared-string.d.ts.map +1 -0
  37. package/dist/xml/excel-xml-shared-string.js.map +0 -1
  38. package/dist/xml/excel-xml-style.d.ts.map +1 -0
  39. package/dist/xml/excel-xml-style.js.map +0 -1
  40. package/dist/xml/excel-xml-unknown.d.ts.map +1 -0
  41. package/dist/xml/excel-xml-unknown.js.map +0 -1
  42. package/dist/xml/excel-xml-workbook.d.ts.map +1 -0
  43. package/dist/xml/excel-xml-workbook.js.map +0 -1
  44. package/dist/xml/excel-xml-worksheet.d.ts.map +1 -0
  45. package/dist/xml/excel-xml-worksheet.js +1 -1
  46. package/dist/xml/excel-xml-worksheet.js.map +0 -1
  47. package/package.json +8 -4
  48. package/src/excel-workbook.ts +1 -1
  49. package/.cache/typecheck-browser.tsbuildinfo +0 -1
  50. package/.cache/typecheck-node.tsbuildinfo +0 -1
  51. package/.cache/typecheck-tests-browser.tsbuildinfo +0 -1
  52. package/.cache/typecheck-tests-node.tsbuildinfo +0 -1
  53. package/dist/core-common/src/common.types.d.ts +0 -74
  54. package/dist/core-common/src/common.types.d.ts.map +0 -1
  55. package/dist/core-common/src/env.d.ts +0 -6
  56. package/dist/core-common/src/env.d.ts.map +0 -1
  57. package/dist/core-common/src/errors/argument-error.d.ts +0 -25
  58. package/dist/core-common/src/errors/argument-error.d.ts.map +0 -1
  59. package/dist/core-common/src/errors/not-implemented-error.d.ts +0 -29
  60. package/dist/core-common/src/errors/not-implemented-error.d.ts.map +0 -1
  61. package/dist/core-common/src/errors/sd-error.d.ts +0 -27
  62. package/dist/core-common/src/errors/sd-error.d.ts.map +0 -1
  63. package/dist/core-common/src/errors/timeout-error.d.ts +0 -31
  64. package/dist/core-common/src/errors/timeout-error.d.ts.map +0 -1
  65. package/dist/core-common/src/extensions/arr-ext.d.ts +0 -15
  66. package/dist/core-common/src/extensions/arr-ext.d.ts.map +0 -1
  67. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +0 -19
  68. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +0 -1
  69. package/dist/core-common/src/extensions/arr-ext.types.d.ts +0 -215
  70. package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +0 -1
  71. package/dist/core-common/src/extensions/map-ext.d.ts +0 -57
  72. package/dist/core-common/src/extensions/map-ext.d.ts.map +0 -1
  73. package/dist/core-common/src/extensions/set-ext.d.ts +0 -36
  74. package/dist/core-common/src/extensions/set-ext.d.ts.map +0 -1
  75. package/dist/core-common/src/features/debounce-queue.d.ts +0 -53
  76. package/dist/core-common/src/features/debounce-queue.d.ts.map +0 -1
  77. package/dist/core-common/src/features/event-emitter.d.ts +0 -66
  78. package/dist/core-common/src/features/event-emitter.d.ts.map +0 -1
  79. package/dist/core-common/src/features/serial-queue.d.ts +0 -47
  80. package/dist/core-common/src/features/serial-queue.d.ts.map +0 -1
  81. package/dist/core-common/src/index.d.ts +0 -32
  82. package/dist/core-common/src/index.d.ts.map +0 -1
  83. package/dist/core-common/src/types/date-only.d.ts +0 -152
  84. package/dist/core-common/src/types/date-only.d.ts.map +0 -1
  85. package/dist/core-common/src/types/date-time.d.ts +0 -96
  86. package/dist/core-common/src/types/date-time.d.ts.map +0 -1
  87. package/dist/core-common/src/types/lazy-gc-map.d.ts +0 -80
  88. package/dist/core-common/src/types/lazy-gc-map.d.ts.map +0 -1
  89. package/dist/core-common/src/types/time.d.ts +0 -68
  90. package/dist/core-common/src/types/time.d.ts.map +0 -1
  91. package/dist/core-common/src/types/uuid.d.ts +0 -35
  92. package/dist/core-common/src/types/uuid.d.ts.map +0 -1
  93. package/dist/core-common/src/utils/bytes.d.ts +0 -51
  94. package/dist/core-common/src/utils/bytes.d.ts.map +0 -1
  95. package/dist/core-common/src/utils/date-format.d.ts +0 -90
  96. package/dist/core-common/src/utils/date-format.d.ts.map +0 -1
  97. package/dist/core-common/src/utils/json.d.ts +0 -34
  98. package/dist/core-common/src/utils/json.d.ts.map +0 -1
  99. package/dist/core-common/src/utils/num.d.ts +0 -60
  100. package/dist/core-common/src/utils/num.d.ts.map +0 -1
  101. package/dist/core-common/src/utils/obj.d.ts +0 -258
  102. package/dist/core-common/src/utils/obj.d.ts.map +0 -1
  103. package/dist/core-common/src/utils/path.d.ts +0 -23
  104. package/dist/core-common/src/utils/path.d.ts.map +0 -1
  105. package/dist/core-common/src/utils/primitive.d.ts +0 -18
  106. package/dist/core-common/src/utils/primitive.d.ts.map +0 -1
  107. package/dist/core-common/src/utils/str.d.ts +0 -103
  108. package/dist/core-common/src/utils/str.d.ts.map +0 -1
  109. package/dist/core-common/src/utils/template-strings.d.ts +0 -84
  110. package/dist/core-common/src/utils/template-strings.d.ts.map +0 -1
  111. package/dist/core-common/src/utils/transferable.d.ts +0 -47
  112. package/dist/core-common/src/utils/transferable.d.ts.map +0 -1
  113. package/dist/core-common/src/utils/wait.d.ts +0 -19
  114. package/dist/core-common/src/utils/wait.d.ts.map +0 -1
  115. package/dist/core-common/src/utils/xml.d.ts +0 -36
  116. package/dist/core-common/src/utils/xml.d.ts.map +0 -1
  117. package/dist/core-common/src/zip/sd-zip.d.ts +0 -80
  118. package/dist/core-common/src/zip/sd-zip.d.ts.map +0 -1
  119. package/dist/excel/src/excel-cell.d.ts.map +0 -1
  120. package/dist/excel/src/excel-col.d.ts.map +0 -1
  121. package/dist/excel/src/excel-row.d.ts.map +0 -1
  122. package/dist/excel/src/excel-workbook.d.ts.map +0 -1
  123. package/dist/excel/src/excel-worksheet.d.ts.map +0 -1
  124. package/dist/excel/src/excel-wrapper.d.ts.map +0 -1
  125. package/dist/excel/src/index.d.ts.map +0 -1
  126. package/dist/excel/src/types.d.ts.map +0 -1
  127. package/dist/excel/src/utils/excel-utils.d.ts.map +0 -1
  128. package/dist/excel/src/utils/zip-cache.d.ts.map +0 -1
  129. package/dist/excel/src/xml/excel-xml-content-type.d.ts.map +0 -1
  130. package/dist/excel/src/xml/excel-xml-drawing.d.ts.map +0 -1
  131. package/dist/excel/src/xml/excel-xml-relationship.d.ts.map +0 -1
  132. package/dist/excel/src/xml/excel-xml-shared-string.d.ts.map +0 -1
  133. package/dist/excel/src/xml/excel-xml-style.d.ts.map +0 -1
  134. package/dist/excel/src/xml/excel-xml-unknown.d.ts.map +0 -1
  135. package/dist/excel/src/xml/excel-xml-workbook.d.ts.map +0 -1
  136. package/dist/excel/src/xml/excel-xml-worksheet.d.ts.map +0 -1
  137. package/tests/excel-cell.spec.ts +0 -407
  138. package/tests/excel-col.spec.ts +0 -112
  139. package/tests/excel-row.spec.ts +0 -71
  140. package/tests/excel-workbook.spec.ts +0 -166
  141. package/tests/excel-worksheet.spec.ts +0 -389
  142. package/tests/excel-wrapper.spec.ts +0 -275
  143. package/tests/fixtures/logo.png +0 -0
  144. package/tests/image-insert.spec.ts +0 -188
  145. package/tests/utils/excel-utils.spec.ts +0 -240
  146. /package/dist/{excel/src/excel-cell.d.ts → excel-cell.d.ts} +0 -0
  147. /package/dist/{excel/src/excel-col.d.ts → excel-col.d.ts} +0 -0
  148. /package/dist/{excel/src/excel-row.d.ts → excel-row.d.ts} +0 -0
  149. /package/dist/{excel/src/excel-workbook.d.ts → excel-workbook.d.ts} +0 -0
  150. /package/dist/{excel/src/excel-worksheet.d.ts → excel-worksheet.d.ts} +0 -0
  151. /package/dist/{excel/src/excel-wrapper.d.ts → excel-wrapper.d.ts} +0 -0
  152. /package/dist/{excel/src/index.d.ts → index.d.ts} +0 -0
  153. /package/dist/{excel/src/types.d.ts → types.d.ts} +0 -0
  154. /package/dist/{excel/src/utils → utils}/excel-utils.d.ts +0 -0
  155. /package/dist/{excel/src/utils → utils}/zip-cache.d.ts +0 -0
  156. /package/dist/{excel/src/xml → xml}/excel-xml-content-type.d.ts +0 -0
  157. /package/dist/{excel/src/xml → xml}/excel-xml-drawing.d.ts +0 -0
  158. /package/dist/{excel/src/xml → xml}/excel-xml-relationship.d.ts +0 -0
  159. /package/dist/{excel/src/xml → xml}/excel-xml-shared-string.d.ts +0 -0
  160. /package/dist/{excel/src/xml → xml}/excel-xml-style.d.ts +0 -0
  161. /package/dist/{excel/src/xml → xml}/excel-xml-unknown.d.ts +0 -0
  162. /package/dist/{excel/src/xml → xml}/excel-xml-workbook.d.ts +0 -0
  163. /package/dist/{excel/src/xml → xml}/excel-xml-worksheet.d.ts +0 -0
@@ -1,389 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { ExcelWorkbook } from "../src/excel-workbook";
3
-
4
- describe("ExcelWorksheet", () => {
5
- describe("시트 이름", () => {
6
- it("시트 이름을 가져올 수 있다", async () => {
7
- const wb = new ExcelWorkbook();
8
- const ws = await wb.createWorksheet("MySheet");
9
-
10
- const name = await ws.getName();
11
- expect(name).toBe("MySheet");
12
- });
13
-
14
- it("시트 이름을 변경할 수 있다", async () => {
15
- const wb = new ExcelWorkbook();
16
- const ws = await wb.createWorksheet("OldName");
17
-
18
- await ws.setName("NewName");
19
- const name = await ws.getName();
20
- expect(name).toBe("NewName");
21
- });
22
-
23
- it("변경한 시트 이름이 라운드트립 후에도 유지된다", async () => {
24
- const wb = new ExcelWorkbook();
25
- const ws = await wb.createWorksheet("OldName");
26
- await ws.setName("NewName");
27
-
28
- const bytes = await wb.getBytes();
29
-
30
- const wb2 = new ExcelWorkbook(bytes);
31
- const names = await wb2.getWorksheetNames();
32
- expect(names).toContain("NewName");
33
- expect(names).not.toContain("OldName");
34
-
35
- const ws2 = await wb2.getWorksheet("NewName");
36
- const name = await ws2.getName();
37
- expect(name).toBe("NewName");
38
- });
39
- });
40
-
41
- describe("행/열 복사", () => {
42
- it("행을 복사할 수 있다", async () => {
43
- const wb = new ExcelWorkbook();
44
- const ws = await wb.createWorksheet("Test");
45
-
46
- // 원본 행 설정
47
- await ws.cell(0, 0).setVal("A");
48
- await ws.cell(0, 1).setVal("B");
49
- await ws.cell(0, 2).setVal("C");
50
-
51
- // 행 복사
52
- await ws.copyRow(0, 2);
53
-
54
- expect(await ws.cell(2, 0).getVal()).toBe("A");
55
- expect(await ws.cell(2, 1).getVal()).toBe("B");
56
- expect(await ws.cell(2, 2).getVal()).toBe("C");
57
- });
58
-
59
- it("셀을 복사할 수 있다", async () => {
60
- const wb = new ExcelWorkbook();
61
- const ws = await wb.createWorksheet("Test");
62
-
63
- await ws.cell(0, 0).setVal("Original");
64
- await ws.copyCell({ r: 0, c: 0 }, { r: 1, c: 1 });
65
-
66
- expect(await ws.cell(1, 1).getVal()).toBe("Original");
67
- });
68
-
69
- it("행 스타일만 복사할 수 있다", async () => {
70
- const wb = new ExcelWorkbook();
71
- const ws = await wb.createWorksheet("Test");
72
-
73
- // 스타일 설정
74
- await ws.cell(0, 0).setVal("Styled");
75
- await ws.cell(0, 0).setStyle({ background: "00FF0000" });
76
- await ws.cell(0, 1).setVal("Also Styled");
77
- await ws.cell(0, 1).setStyle({ background: "0000FF00" });
78
-
79
- // 스타일만 복사
80
- await ws.copyRowStyle(0, 2);
81
-
82
- // 값은 복사되지 않음
83
- expect(await ws.cell(2, 0).getVal()).toBeUndefined();
84
- expect(await ws.cell(2, 1).getVal()).toBeUndefined();
85
-
86
- // 스타일은 복사됨
87
- const styleId0 = await ws.cell(0, 0).getStyleId();
88
- const styleId2 = await ws.cell(2, 0).getStyleId();
89
- expect(styleId2).toBe(styleId0);
90
- });
91
-
92
- it("행 삽입 복사를 할 수 있다 (srcR < targetR)", async () => {
93
- const wb = new ExcelWorkbook();
94
- const ws = await wb.createWorksheet("Test");
95
-
96
- await ws.cell(0, 0).setVal("Row0");
97
- await ws.cell(1, 0).setVal("Row1");
98
- await ws.cell(2, 0).setVal("Row2");
99
-
100
- // 0행을 1행 위치에 삽입 복사 (기존 행들이 밀림)
101
- await ws.insertCopyRow(0, 1);
102
-
103
- expect(await ws.cell(0, 0).getVal()).toBe("Row0");
104
- expect(await ws.cell(1, 0).getVal()).toBe("Row0"); // 복사됨
105
- expect(await ws.cell(2, 0).getVal()).toBe("Row1"); // 밀림
106
- expect(await ws.cell(3, 0).getVal()).toBe("Row2"); // 밀림
107
- });
108
-
109
- it("행 삽입 복사를 할 수 있다 (srcR > targetR)", async () => {
110
- const wb = new ExcelWorkbook();
111
- const ws = await wb.createWorksheet("Test");
112
-
113
- await ws.cell(0, 0).setVal("Row0");
114
- await ws.cell(1, 0).setVal("Row1");
115
- await ws.cell(2, 0).setVal("Row2");
116
- await ws.cell(3, 0).setVal("Row3");
117
-
118
- // 2행을 1행 위치에 삽입 복사 (기존 행들이 밀림)
119
- await ws.insertCopyRow(2, 1);
120
-
121
- expect(await ws.cell(0, 0).getVal()).toBe("Row0");
122
- expect(await ws.cell(1, 0).getVal()).toBe("Row2"); // 원래 Row2 복사됨
123
- expect(await ws.cell(2, 0).getVal()).toBe("Row1"); // 밀림
124
- expect(await ws.cell(3, 0).getVal()).toBe("Row2"); // 밀림 (원래 Row2)
125
- expect(await ws.cell(4, 0).getVal()).toBe("Row3"); // 밀림
126
- });
127
-
128
- it("행 삽입 복사를 할 수 있다 (srcR == targetR)", async () => {
129
- const wb = new ExcelWorkbook();
130
- const ws = await wb.createWorksheet("Test");
131
-
132
- await ws.cell(0, 0).setVal("Row0");
133
- await ws.cell(1, 0).setVal("Row1");
134
- await ws.cell(2, 0).setVal("Row2");
135
-
136
- // 1행을 1행 위치에 삽입 복사 (자기 자신을 복사)
137
- await ws.insertCopyRow(1, 1);
138
-
139
- expect(await ws.cell(0, 0).getVal()).toBe("Row0");
140
- expect(await ws.cell(1, 0).getVal()).toBe("Row1"); // 원래 Row1 복사됨
141
- expect(await ws.cell(2, 0).getVal()).toBe("Row1"); // 밀림 (원래 Row1)
142
- expect(await ws.cell(3, 0).getVal()).toBe("Row2"); // 밀림
143
- });
144
- });
145
-
146
- describe("범위 및 셀 접근", () => {
147
- it("데이터 범위를 가져올 수 있다", async () => {
148
- const wb = new ExcelWorkbook();
149
- const ws = await wb.createWorksheet("Test");
150
-
151
- await ws.cell(0, 0).setVal("A");
152
- await ws.cell(2, 3).setVal("D");
153
-
154
- const range = await ws.getRange();
155
- expect(range.s.r).toBe(0);
156
- expect(range.s.c).toBe(0);
157
- expect(range.e.r).toBe(2);
158
- expect(range.e.c).toBe(3);
159
- });
160
-
161
- it("모든 셀을 가져올 수 있다", async () => {
162
- const wb = new ExcelWorkbook();
163
- const ws = await wb.createWorksheet("Test");
164
-
165
- await ws.cell(0, 0).setVal("A");
166
- await ws.cell(0, 1).setVal("B");
167
- await ws.cell(1, 0).setVal("C");
168
- await ws.cell(1, 1).setVal("D");
169
-
170
- const cells = await ws.getCells();
171
- expect(cells.length).toBe(2);
172
- expect(cells[0].length).toBeGreaterThanOrEqual(2);
173
- });
174
- });
175
-
176
- describe("데이터 테이블", () => {
177
- it("데이터 테이블을 가져올 수 있다", async () => {
178
- const wb = new ExcelWorkbook();
179
- const ws = await wb.createWorksheet("Test");
180
-
181
- // 헤더
182
- await ws.cell(0, 0).setVal("Name");
183
- await ws.cell(0, 1).setVal("Age");
184
- // 데이터
185
- await ws.cell(1, 0).setVal("Alice");
186
- await ws.cell(1, 1).setVal(30);
187
- await ws.cell(2, 0).setVal("Bob");
188
- await ws.cell(2, 1).setVal(25);
189
-
190
- const data = await ws.getDataTable();
191
- expect(data.length).toBe(2);
192
- expect(data[0]["Name"]).toBe("Alice");
193
- expect(data[0]["Age"]).toBe(30);
194
- expect(data[1]["Name"]).toBe("Bob");
195
- expect(data[1]["Age"]).toBe(25);
196
- });
197
-
198
- it("특정 헤더만 필터링하여 가져올 수 있다", async () => {
199
- const wb = new ExcelWorkbook();
200
- const ws = await wb.createWorksheet("Test");
201
-
202
- await ws.cell(0, 0).setVal("Name");
203
- await ws.cell(0, 1).setVal("Age");
204
- await ws.cell(0, 2).setVal("Ignore");
205
- await ws.cell(1, 0).setVal("Alice");
206
- await ws.cell(1, 1).setVal(30);
207
- await ws.cell(1, 2).setVal("X");
208
-
209
- const data = await ws.getDataTable({
210
- usableHeaderNameFn: (name) => name !== "Ignore",
211
- });
212
-
213
- expect(data[0]["Name"]).toBe("Alice");
214
- expect(data[0]["Age"]).toBe(30);
215
- expect(data[0]["Ignore"]).toBeUndefined();
216
- });
217
-
218
- it("데이터 매트릭스를 설정할 수 있다", async () => {
219
- const wb = new ExcelWorkbook();
220
- const ws = await wb.createWorksheet("Test");
221
-
222
- const matrix = [
223
- ["A", "B", "C"],
224
- [1, 2, 3],
225
- [4, 5, 6],
226
- ];
227
-
228
- await ws.setDataMatrix(matrix);
229
-
230
- expect(await ws.cell(0, 0).getVal()).toBe("A");
231
- expect(await ws.cell(0, 2).getVal()).toBe("C");
232
- expect(await ws.cell(2, 2).getVal()).toBe(6);
233
- });
234
-
235
- it("레코드 배열을 설정할 수 있다", async () => {
236
- const wb = new ExcelWorkbook();
237
- const ws = await wb.createWorksheet("Test");
238
-
239
- const records = [
240
- { Name: "Alice", Age: 30 },
241
- { Name: "Bob", Age: 25 },
242
- ];
243
-
244
- await ws.setRecords(records);
245
-
246
- // 헤더 확인
247
- const headers = [await ws.cell(0, 0).getVal(), await ws.cell(0, 1).getVal()];
248
- expect(headers).toContain("Name");
249
- expect(headers).toContain("Age");
250
-
251
- // 데이터 확인 (순서는 다를 수 있음)
252
- const data = await ws.getDataTable();
253
- expect(data.length).toBe(2);
254
- });
255
- });
256
-
257
- describe("뷰 설정", () => {
258
- it("줌 레벨을 설정할 수 있다", async () => {
259
- const wb = new ExcelWorkbook();
260
- const ws = await wb.createWorksheet("Test");
261
-
262
- await ws.setZoom(85);
263
- // 에러 없이 설정되면 성공
264
- });
265
-
266
- it("틀 고정을 설정할 수 있다", async () => {
267
- const wb = new ExcelWorkbook();
268
- const ws = await wb.createWorksheet("Test");
269
-
270
- await ws.setFix({ r: 1 }); // 1행 고정
271
- await ws.setFix({ c: 2 }); // 2열 고정
272
- await ws.setFix({ r: 1, c: 1 }); // 1행 1열 고정
273
- // 에러 없이 설정되면 성공
274
- });
275
- });
276
-
277
- describe("열 너비", () => {
278
- it("열 너비를 설정할 수 있다", async () => {
279
- const wb = new ExcelWorkbook();
280
- const ws = await wb.createWorksheet("Test");
281
-
282
- await ws.col(0).setWidth(20);
283
- // 에러 없이 설정되면 성공
284
- });
285
-
286
- it("설정한 열 너비가 라운드트립 후에도 유지된다", async () => {
287
- const wb = new ExcelWorkbook();
288
- const ws = await wb.createWorksheet("Test");
289
-
290
- await ws.cell(0, 0).setVal("A1");
291
- await ws.col(0).setWidth(25);
292
- await ws.col(2).setWidth(30);
293
-
294
- const bytes = await wb.getBytes();
295
-
296
- const wb2 = new ExcelWorkbook(bytes);
297
- await wb2.getWorksheet("Test");
298
-
299
- // XML 구조에서 cols 데이터 확인
300
- const wsData = await (wb2 as any).zipCache.get("xl/worksheets/sheet1.xml");
301
- const cols = wsData.data.worksheet.cols?.[0]?.col ?? [];
302
-
303
- // 열 A (인덱스 0, 1-based=1)의 너비 확인
304
- const colA = cols.find((c: any) => c.$.min === "1" && c.$.max === "1");
305
- expect(colA).toBeDefined();
306
- expect(colA.$.width).toBe("25");
307
-
308
- // 열 C (인덱스 2, 1-based=3)의 너비 확인
309
- const colC = cols.find((c: any) => c.$.min === "3" && c.$.max === "3");
310
- expect(colC).toBeDefined();
311
- expect(colC.$.width).toBe("30");
312
- });
313
- });
314
-
315
- describe("열 접근", () => {
316
- it("열의 모든 셀을 가져올 수 있다", async () => {
317
- const wb = new ExcelWorkbook();
318
- const ws = await wb.createWorksheet("Test");
319
-
320
- await ws.cell(0, 0).setVal("A1");
321
- await ws.cell(1, 0).setVal("A2");
322
- await ws.cell(2, 0).setVal("A3");
323
-
324
- const cells = await ws.col(0).getCells();
325
- expect(cells.length).toBe(3);
326
- expect(await cells[0].getVal()).toBe("A1");
327
- expect(await cells[1].getVal()).toBe("A2");
328
- expect(await cells[2].getVal()).toBe("A3");
329
- });
330
- });
331
-
332
- describe("데이터 테이블 엣지 케이스", () => {
333
- it("빈 시트에서 getDataTable 호출 시 빈 배열 반환", async () => {
334
- const wb = new ExcelWorkbook();
335
- const ws = await wb.createWorksheet("Empty");
336
- const data = await ws.getDataTable();
337
- expect(data).toEqual([]);
338
- });
339
-
340
- it("헤더만 있고 데이터가 없는 경우 빈 배열 반환", async () => {
341
- const wb = new ExcelWorkbook();
342
- const ws = await wb.createWorksheet("Test");
343
- await ws.cell(0, 0).setVal("Header1");
344
- await ws.cell(0, 1).setVal("Header2");
345
- const data = await ws.getDataTable();
346
- expect(data).toEqual([]);
347
- });
348
- });
349
-
350
- describe("데이터 테이블 옵션", () => {
351
- it("headerRowIndex로 헤더 행을 지정할 수 있다", async () => {
352
- const wb = new ExcelWorkbook();
353
- const ws = await wb.createWorksheet("Test");
354
-
355
- // 0행은 제목
356
- await ws.cell(0, 0).setVal("Title");
357
- // 1행이 헤더
358
- await ws.cell(1, 0).setVal("Name");
359
- await ws.cell(1, 1).setVal("Age");
360
- // 2행부터 데이터
361
- await ws.cell(2, 0).setVal("Alice");
362
- await ws.cell(2, 1).setVal(30);
363
-
364
- const data = await ws.getDataTable({ headerRowIndex: 1 });
365
- expect(data.length).toBe(1);
366
- expect(data[0]["Name"]).toBe("Alice");
367
- expect(data[0]["Age"]).toBe(30);
368
- });
369
-
370
- it("checkEndColIndex로 데이터 끝을 감지할 수 있다", async () => {
371
- const wb = new ExcelWorkbook();
372
- const ws = await wb.createWorksheet("Test");
373
-
374
- await ws.cell(0, 0).setVal("Name");
375
- await ws.cell(0, 1).setVal("Age");
376
- await ws.cell(1, 0).setVal("Alice");
377
- await ws.cell(1, 1).setVal(30);
378
- await ws.cell(2, 0).setVal("Bob");
379
- await ws.cell(2, 1).setVal(25);
380
- // 3행은 Name 열이 비어있음 → 데이터 끝
381
- await ws.cell(3, 1).setVal(999);
382
-
383
- const data = await ws.getDataTable({ checkEndColIndex: 0 });
384
- expect(data.length).toBe(2);
385
- expect(data[0]["Name"]).toBe("Alice");
386
- expect(data[1]["Name"]).toBe("Bob");
387
- });
388
- });
389
- });
@@ -1,275 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { z } from "zod";
3
- import { ExcelWrapper } from "../src/excel-wrapper";
4
- import { DateOnly, DateTime, Time } from "@simplysm/core-common";
5
-
6
- describe("ExcelWrapper", () => {
7
- const testSchema = z.object({
8
- name: z.string(),
9
- age: z.number(),
10
- email: z.string().optional(),
11
- active: z.boolean().default(false),
12
- });
13
-
14
- const displayNameMap = {
15
- name: "이름",
16
- age: "나이",
17
- email: "이메일",
18
- active: "활성화",
19
- };
20
-
21
- describe("write", () => {
22
- it("레코드를 Excel로 변환할 수 있다", async () => {
23
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
24
-
25
- const records = [
26
- { name: "홍길동", age: 30, email: "hong@test.com", active: true },
27
- { name: "김철수", age: 25 },
28
- ];
29
-
30
- const wb = await wrapper.write("Users", records);
31
- const ws = await wb.getWorksheet("Users");
32
-
33
- // 헤더 확인
34
- expect(await ws.cell(0, 0).getVal()).toBe("이름");
35
- expect(await ws.cell(0, 1).getVal()).toBe("나이");
36
- expect(await ws.cell(0, 2).getVal()).toBe("이메일");
37
- expect(await ws.cell(0, 3).getVal()).toBe("활성화");
38
-
39
- // 데이터 확인
40
- expect(await ws.cell(1, 0).getVal()).toBe("홍길동");
41
- expect(await ws.cell(1, 1).getVal()).toBe(30);
42
- expect(await ws.cell(2, 0).getVal()).toBe("김철수");
43
- expect(await ws.cell(2, 1).getVal()).toBe(25);
44
-
45
- await wb.close();
46
- });
47
-
48
- it("필수 필드에 노란색 배경이 적용된다", async () => {
49
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
50
- const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
51
- const ws = await wb.getWorksheet("Test");
52
-
53
- // 필수 필드 (name, age)는 스타일이 적용됨
54
- const nameStyleId = await ws.cell(0, 0).getStyleId();
55
- const ageStyleId = await ws.cell(0, 1).getStyleId();
56
-
57
- expect(nameStyleId).toBeDefined();
58
- expect(ageStyleId).toBeDefined();
59
-
60
- await wb.close();
61
- });
62
- });
63
-
64
- describe("read", () => {
65
- it("Excel에서 레코드를 읽을 수 있다", async () => {
66
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
67
-
68
- // 먼저 Excel 생성
69
- const records = [
70
- { name: "홍길동", age: 30, email: "hong@test.com", active: true },
71
- { name: "김철수", age: 25, active: false },
72
- ];
73
-
74
- const wb = await wrapper.write("Users", records);
75
- const buffer = await wb.getBytes();
76
- await wb.close();
77
-
78
- // Excel에서 읽기
79
- const readRecords = await wrapper.read(buffer, "Users");
80
-
81
- expect(readRecords.length).toBe(2);
82
- expect(readRecords[0].name).toBe("홍길동");
83
- expect(readRecords[0].age).toBe(30);
84
- expect(readRecords[0].email).toBe("hong@test.com");
85
- expect(readRecords[0].active).toBe(true);
86
- expect(readRecords[1].name).toBe("김철수");
87
- expect(readRecords[1].age).toBe(25);
88
- });
89
-
90
- it("인덱스로 워크시트를 지정할 수 있다", async () => {
91
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
92
-
93
- const records = [{ name: "Test", age: 20 }];
94
- const wb = await wrapper.write("Sheet1", records);
95
- const buffer = await wb.getBytes();
96
- await wb.close();
97
-
98
- const readRecords = await wrapper.read(buffer, 0);
99
- expect(readRecords.length).toBe(1);
100
- expect(readRecords[0].name).toBe("Test");
101
- });
102
- });
103
-
104
- describe("타입 변환", () => {
105
- it("문자열을 숫자로 변환할 수 있다", async () => {
106
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
107
-
108
- // 수동으로 문자열로 저장된 Excel 시뮬레이션
109
- const wb = await wrapper.write("Test", [{ name: "Test", age: 25 }]);
110
- const buffer = await wb.getBytes();
111
- await wb.close();
112
-
113
- const records = await wrapper.read(buffer);
114
- expect(typeof records[0].age).toBe("number");
115
- expect(records[0].age).toBe(25);
116
- });
117
-
118
- it("기본값이 적용된다", async () => {
119
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
120
-
121
- // active 필드 없이 저장
122
- const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
123
- const buffer = await wb.getBytes();
124
- await wb.close();
125
-
126
- const records = await wrapper.read(buffer);
127
- expect(records[0].active).toBe(false); // 기본값
128
- });
129
- });
130
-
131
- describe("날짜 타입 지원", () => {
132
- const dateSchema = z.object({
133
- title: z.string(),
134
- date: z.instanceof(DateOnly).optional(),
135
- });
136
-
137
- const dateDisplayMap = {
138
- title: "제목",
139
- date: "날짜",
140
- };
141
-
142
- it("DateOnly 타입을 읽고 쓸 수 있다", async () => {
143
- const wrapper = new ExcelWrapper(dateSchema, dateDisplayMap);
144
-
145
- const records = [{ title: "Event 1", date: new DateOnly(2024, 6, 15) }, { title: "Event 2" }];
146
-
147
- const wb = await wrapper.write("Events", records);
148
- const buffer = await wb.getBytes();
149
- await wb.close();
150
-
151
- const readRecords = await wrapper.read(buffer, "Events");
152
-
153
- expect(readRecords[0].title).toBe("Event 1");
154
- expect(readRecords[0].date).toBeInstanceOf(DateOnly);
155
- expect(readRecords[0].date!.year).toBe(2024);
156
- expect(readRecords[0].date!.month).toBe(6);
157
- expect(readRecords[0].date!.day).toBe(15);
158
- expect(readRecords[1].date).toBeUndefined();
159
- });
160
-
161
- it("DateTime 타입을 읽고 쓸 수 있다", async () => {
162
- const dateTimeSchema = z.object({
163
- title: z.string(),
164
- datetime: z.instanceof(DateTime).optional(),
165
- });
166
-
167
- const dateTimeDisplayMap = {
168
- title: "제목",
169
- datetime: "일시",
170
- };
171
-
172
- const wrapper = new ExcelWrapper(dateTimeSchema, dateTimeDisplayMap);
173
-
174
- const records = [{ title: "Meeting", datetime: new DateTime(2024, 6, 15, 14, 30, 0) }];
175
-
176
- const wb = await wrapper.write("Events", records);
177
- const buffer = await wb.getBytes();
178
- await wb.close();
179
-
180
- const readRecords = await wrapper.read(buffer, "Events");
181
-
182
- expect(readRecords[0].datetime).toBeInstanceOf(DateTime);
183
- expect(readRecords[0].datetime!.year).toBe(2024);
184
- expect(readRecords[0].datetime!.month).toBe(6);
185
- expect(readRecords[0].datetime!.day).toBe(15);
186
- expect(readRecords[0].datetime!.hour).toBe(14);
187
- expect(readRecords[0].datetime!.minute).toBe(30);
188
- });
189
-
190
- it("Time 타입을 읽고 쓸 수 있다", async () => {
191
- const timeSchema = z.object({
192
- title: z.string(),
193
- time: z.instanceof(Time).optional(),
194
- });
195
-
196
- const timeDisplayMap = {
197
- title: "제목",
198
- time: "시간",
199
- };
200
-
201
- const wrapper = new ExcelWrapper(timeSchema, timeDisplayMap);
202
-
203
- const records = [{ title: "Alarm", time: new Time(9, 30, 0) }];
204
-
205
- const wb = await wrapper.write("Events", records);
206
- const buffer = await wb.getBytes();
207
- await wb.close();
208
-
209
- const readRecords = await wrapper.read(buffer, "Events");
210
-
211
- expect(readRecords[0].time).toBeInstanceOf(Time);
212
- expect(readRecords[0].time!.hour).toBe(9);
213
- expect(readRecords[0].time!.minute).toBe(30);
214
- });
215
- });
216
-
217
- describe("에러 처리", () => {
218
- it("빈 데이터에서 읽으면 에러 발생", async () => {
219
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
220
-
221
- // 헤더만 있는 빈 Excel 생성
222
- const wb = await wrapper.write("Empty", []);
223
- const buffer = await wb.getBytes();
224
- await wb.close();
225
-
226
- await expect(wrapper.read(buffer, "Empty")).rejects.toThrow("엑셀파일에서 데이터를 찾을 수 없습니다");
227
- });
228
-
229
- it("존재하지 않는 워크시트 이름으로 읽으면 에러 발생", async () => {
230
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
231
-
232
- const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
233
- const buffer = await wb.getBytes();
234
- await wb.close();
235
-
236
- await expect(wrapper.read(buffer, "NotExist")).rejects.toThrow();
237
- });
238
-
239
- it("존재하지 않는 워크시트 인덱스로 읽으면 에러 발생", async () => {
240
- const wrapper = new ExcelWrapper(testSchema, displayNameMap);
241
-
242
- const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
243
- const buffer = await wb.getBytes();
244
- await wb.close();
245
-
246
- await expect(wrapper.read(buffer, 99)).rejects.toThrow();
247
- });
248
-
249
- it("스키마 검증 실패 시 워크시트 이름과 상세 오류가 포함된 에러 발생", async () => {
250
- const strictSchema = z.object({
251
- name: z.string().min(5), // 최소 5자 이상
252
- age: z.number().min(0).max(150), // 0~150 사이
253
- });
254
-
255
- const strictDisplayMap = {
256
- name: "이름",
257
- age: "나이",
258
- };
259
-
260
- // 유효한 데이터로 Excel 생성
261
- const wrapper = new ExcelWrapper(strictSchema, strictDisplayMap);
262
- const wb = await wrapper.write("Validation", [{ name: "홍길동홍길동", age: 30 }]);
263
-
264
- // 데이터를 직접 수정하여 검증 실패 유도
265
- const ws = await wb.getWorksheet("Validation");
266
- await ws.cell(1, 0).setVal("AB"); // 최소 5자 미만으로 변경
267
-
268
- const buffer = await wb.getBytes();
269
- await wb.close();
270
-
271
- // 검증 실패 에러가 발생해야 함
272
- await expect(wrapper.read(buffer, "Validation")).rejects.toThrow();
273
- });
274
- });
275
- });
Binary file