@simplysm/excel 13.0.0-beta.5 → 13.0.0-beta.50

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,188 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { ExcelWorkbook } from "../src/excel-workbook";
3
-
4
- // globalThis.window가 없으면 Node.js 환경
5
- declare const window: unknown;
6
- // Node.js 전용 타입 (browser 환경에서도 타입체크가 통과되도록)
7
- declare const require: (id: string) => unknown;
8
-
9
- /**
10
- * PNG 파일 로드 (Node/브라우저 환경 분기)
11
- */
12
- async function loadPngFile(): Promise<Uint8Array> {
13
- const url = new URL("./fixtures/logo.png", import.meta.url);
14
-
15
- // Node 환경: fs 사용
16
- if (typeof window === "undefined") {
17
- const fs = require("fs") as { readFileSync: (path: string) => Uint8Array };
18
- const { fileURLToPath } = require("url") as { fileURLToPath: (url: URL) => string };
19
- const filePath = fileURLToPath(url);
20
- return new Uint8Array(fs.readFileSync(filePath));
21
- }
22
-
23
- // 브라우저 환경: fetch 사용
24
- const response = await fetch(url);
25
- const arrayBuffer = await response.arrayBuffer();
26
- return new Uint8Array(arrayBuffer);
27
- }
28
-
29
- /**
30
- * 통합 테스트: ExcelWorksheet.addImage 동작 검증
31
- */
32
-
33
- describe("ExcelWorksheet.addImage integration", () => {
34
- it("should write media, drawing, drawing rels, worksheet rel and content types", async () => {
35
- const wb = new ExcelWorkbook();
36
- const ws = await wb.createWorksheet("Sheet1");
37
-
38
- const bytes = await loadPngFile();
39
-
40
- // call addImage (the single entry API)
41
- await ws.addImage({
42
- bytes,
43
- ext: "png",
44
- from: { r: 0, c: 0 },
45
- to: { r: 2, c: 2 },
46
- });
47
-
48
- // --- 1) media 존재 및 내용 검사
49
- const mediaPath = `xl/media/image1.png`;
50
- const mediaObj = await (ws as any)._zipCache.get(mediaPath);
51
- expect(mediaObj).toBeDefined();
52
- expect(mediaObj instanceof Uint8Array).toBe(true);
53
- expect(mediaObj).toEqual(bytes);
54
-
55
- // --- 2) Content Types 에 media / drawing override 존재
56
- const types = await (ws as any)._zipCache.get("[Content_Types].xml");
57
- expect(types).toBeDefined();
58
- // types는 ExcelXmlContentType 인스턴스일 가능성이 높음
59
- const overrides = types.data?.Types?.Override ?? [];
60
- expect(overrides.some((o: any) => o.$.PartName === "/xl/media/image1.png")).toBeTruthy();
61
- expect(overrides.some((o: any) => o.$.PartName === "/xl/drawings/drawing1.xml")).toBeTruthy();
62
-
63
- // --- 3) drawing xml(객체) 존재 및 a:blip r:embed가 rId로 설정되어 있는지 확인
64
- const drawingPath = "xl/drawings/drawing1.xml";
65
- const drawingObj = await (ws as any)._zipCache.get(drawingPath);
66
- expect(drawingObj).toBeDefined();
67
-
68
- // drawingObj는 객체(ExcelXmlDrawing)일 가능성이 높음 — 내부 구조 확인
69
- const wsDr = drawingObj?.data?.wsDr;
70
- expect(wsDr).toBeDefined();
71
- const anchors = wsDr.twoCellAnchor ?? [];
72
- expect(anchors.length).toBeGreaterThan(0);
73
- const pic = anchors[0].pic?.[0];
74
- expect(pic).toBeDefined();
75
- const aBlip = pic?.blipFill?.[0]?.["a:blip"]?.[0];
76
- expect(aBlip).toBeDefined();
77
- const embedVal = aBlip?.$?.["r:embed"];
78
- expect(typeof embedVal === "string" && /^rId\d+$/.test(embedVal)).toBeTruthy();
79
-
80
- // --- 4) drawing rels 존재 및 media target 참조
81
- const drawingRels = await (ws as any)._zipCache.get("xl/drawings/_rels/drawing1.xml.rels");
82
- expect(drawingRels).toBeDefined();
83
- const relsArr = drawingRels?.data?.Relationships?.Relationship ?? [];
84
- expect(relsArr.some((r: any) => r.$.Target === "../media/image1.png")).toBeTruthy();
85
-
86
- // --- 5) worksheet rels에 drawing rel 추가 및 worksheet xml에 <drawing r:id="..."/> 존재
87
- const sheetFileName = (ws as any)._targetFileName; // e.g., "sheet1.xml"
88
- const sheetRelsPath = `xl/worksheets/_rels/${sheetFileName}.rels`;
89
- const sheetRels = await (ws as any)._zipCache.get(sheetRelsPath);
90
- expect(sheetRels).toBeDefined();
91
- const sheetRelsArr = sheetRels?.data?.Relationships?.Relationship ?? [];
92
- expect(
93
- sheetRelsArr.some((r: any) => r.$.Target != null && r.$.Target.indexOf("/drawings/drawing") !== -1),
94
- ).toBeTruthy();
95
-
96
- const wsXml = await (ws as any)._zipCache.get(`xl/worksheets/${sheetFileName}`);
97
- expect(wsXml).toBeDefined();
98
- expect(Array.isArray(wsXml.data?.worksheet?.drawing)).toBeTruthy();
99
- const drawingElems = wsXml.data.worksheet.drawing;
100
- expect(drawingElems.some((d: any) => d.$ != null && d.$["r:id"] != null)).toBeTruthy();
101
-
102
- // Buffer 생성 검증
103
- const resultBuffer = await wb.getBytes();
104
- expect(resultBuffer).toBeDefined();
105
- expect(resultBuffer.length).toBeGreaterThan(0);
106
- });
107
-
108
- it("같은 워크시트에 여러 이미지를 삽입할 수 있다", async () => {
109
- const wb = new ExcelWorkbook();
110
- const ws = await wb.createWorksheet("Sheet1");
111
-
112
- const bytes = await loadPngFile();
113
-
114
- // 첫 번째 이미지 삽입
115
- await ws.addImage({
116
- bytes,
117
- ext: "png",
118
- from: { r: 0, c: 0 },
119
- to: { r: 2, c: 2 },
120
- });
121
-
122
- // 두 번째 이미지 삽입 (다른 위치)
123
- await ws.addImage({
124
- bytes,
125
- ext: "png",
126
- from: { r: 3, c: 0 },
127
- to: { r: 5, c: 2 },
128
- });
129
-
130
- // --- 1) 두 개의 media 파일이 각각 생성되었는지 확인
131
- const media1 = await (ws as any)._zipCache.get("xl/media/image1.png");
132
- const media2 = await (ws as any)._zipCache.get("xl/media/image2.png");
133
- expect(media1).toBeDefined();
134
- expect(media2).toBeDefined();
135
- expect(media1 instanceof Uint8Array).toBe(true);
136
- expect(media2 instanceof Uint8Array).toBe(true);
137
-
138
- // --- 2) Content Types에 두 이미지가 모두 등록되었는지 확인
139
- const types = await (ws as any)._zipCache.get("[Content_Types].xml");
140
- const overrides = types.data?.Types?.Override ?? [];
141
- expect(overrides.some((o: any) => o.$.PartName === "/xl/media/image1.png")).toBeTruthy();
142
- expect(overrides.some((o: any) => o.$.PartName === "/xl/media/image2.png")).toBeTruthy();
143
-
144
- // --- 3) drawing xml에 두 개의 anchor가 있는지 확인
145
- const drawingObj = await (ws as any)._zipCache.get("xl/drawings/drawing1.xml");
146
- const anchors = drawingObj?.data?.wsDr?.twoCellAnchor ?? [];
147
- expect(anchors.length).toBe(2);
148
-
149
- // 첫 번째 이미지 anchor
150
- const pic1 = anchors[0].pic?.[0];
151
- expect(pic1).toBeDefined();
152
- const embed1 = pic1?.blipFill?.[0]?.["a:blip"]?.[0]?.$?.["r:embed"];
153
- expect(embed1).toBeDefined();
154
-
155
- // 두 번째 이미지 anchor
156
- const pic2 = anchors[1].pic?.[0];
157
- expect(pic2).toBeDefined();
158
- const embed2 = pic2?.blipFill?.[0]?.["a:blip"]?.[0]?.$?.["r:embed"];
159
- expect(embed2).toBeDefined();
160
-
161
- // 서로 다른 rId인지 확인
162
- expect(embed1).not.toBe(embed2);
163
-
164
- // --- 4) drawing rels에 두 이미지에 대한 관계가 있는지 확인
165
- const drawingRels = await (ws as any)._zipCache.get("xl/drawings/_rels/drawing1.xml.rels");
166
- const relsArr = drawingRels?.data?.Relationships?.Relationship ?? [];
167
- expect(relsArr.some((r: any) => r.$.Target === "../media/image1.png")).toBeTruthy();
168
- expect(relsArr.some((r: any) => r.$.Target === "../media/image2.png")).toBeTruthy();
169
-
170
- // Buffer 생성 검증
171
- const resultBuffer = await wb.getBytes();
172
- expect(resultBuffer).toBeDefined();
173
- expect(resultBuffer.length).toBeGreaterThan(0);
174
- });
175
-
176
- it("지원되지 않는 확장자는 에러 발생", async () => {
177
- const wb = new ExcelWorkbook();
178
- const ws = await wb.createWorksheet("Sheet1");
179
-
180
- await expect(
181
- ws.addImage({
182
- bytes: new Uint8Array([0, 1, 2, 3]),
183
- ext: "xyz123",
184
- from: { r: 0, c: 0 },
185
- }),
186
- ).rejects.toThrow("MIME 타입을 확인할 수 없습니다");
187
- });
188
- });
@@ -1,240 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { ExcelUtils } from "../../src/utils/excel-utils";
3
-
4
- describe("ExcelUtils", () => {
5
- describe("stringifyColAddr / parseColAddrCode", () => {
6
- it("0-25를 A-Z로 변환한다", () => {
7
- expect(ExcelUtils.stringifyColAddr(0)).toBe("A");
8
- expect(ExcelUtils.stringifyColAddr(1)).toBe("B");
9
- expect(ExcelUtils.stringifyColAddr(25)).toBe("Z");
10
- });
11
-
12
- it("26 이상을 AA, AB 등으로 변환한다", () => {
13
- expect(ExcelUtils.stringifyColAddr(26)).toBe("AA");
14
- expect(ExcelUtils.stringifyColAddr(27)).toBe("AB");
15
- expect(ExcelUtils.stringifyColAddr(51)).toBe("AZ");
16
- expect(ExcelUtils.stringifyColAddr(52)).toBe("BA");
17
- });
18
-
19
- it("큰 열 인덱스도 처리한다", () => {
20
- // 702 = AAA (26^2 + 26 = 702)
21
- expect(ExcelUtils.stringifyColAddr(702)).toBe("AAA");
22
- });
23
-
24
- it("Excel 최대 열 인덱스(XFD, 16383)를 처리한다", () => {
25
- // Excel 최대 열은 XFD (16383번 인덱스, 0-based)
26
- expect(ExcelUtils.stringifyColAddr(16383)).toBe("XFD");
27
- expect(ExcelUtils.parseColAddrCode("XFD")).toBe(16383);
28
- });
29
-
30
- it("A-Z를 0-25로 파싱한다", () => {
31
- expect(ExcelUtils.parseColAddrCode("A")).toBe(0);
32
- expect(ExcelUtils.parseColAddrCode("B")).toBe(1);
33
- expect(ExcelUtils.parseColAddrCode("Z")).toBe(25);
34
- });
35
-
36
- it("AA, AB 등을 26 이상으로 파싱한다", () => {
37
- expect(ExcelUtils.parseColAddrCode("AA")).toBe(26);
38
- expect(ExcelUtils.parseColAddrCode("AB")).toBe(27);
39
- expect(ExcelUtils.parseColAddrCode("AZ")).toBe(51);
40
- expect(ExcelUtils.parseColAddrCode("BA")).toBe(52);
41
- });
42
-
43
- it("셀 주소에서 열 인덱스를 파싱한다", () => {
44
- expect(ExcelUtils.parseColAddrCode("A1")).toBe(0);
45
- expect(ExcelUtils.parseColAddrCode("B10")).toBe(1);
46
- expect(ExcelUtils.parseColAddrCode("AA100")).toBe(26);
47
- });
48
-
49
- it("라운드트립: stringify → parse가 원래 값을 반환한다", () => {
50
- for (let i = 0; i < 100; i++) {
51
- const stringified = ExcelUtils.stringifyColAddr(i);
52
- const parsed = ExcelUtils.parseColAddrCode(stringified);
53
- expect(parsed).toBe(i);
54
- }
55
- });
56
-
57
- it("음수 열 인덱스 입력 시 에러", () => {
58
- expect(() => ExcelUtils.stringifyColAddr(-1)).toThrow();
59
- expect(() => ExcelUtils.stringifyColAddr(-100)).toThrow();
60
- });
61
- });
62
-
63
- describe("stringifyRowAddr / parseRowAddrCode", () => {
64
- it("0-based 인덱스를 1-based 문자열로 변환한다", () => {
65
- expect(ExcelUtils.stringifyRowAddr(0)).toBe("1");
66
- expect(ExcelUtils.stringifyRowAddr(9)).toBe("10");
67
- expect(ExcelUtils.stringifyRowAddr(99)).toBe("100");
68
- });
69
-
70
- it("1-based 문자열을 0-based 인덱스로 파싱한다", () => {
71
- expect(ExcelUtils.parseRowAddrCode("A1")).toBe(0);
72
- expect(ExcelUtils.parseRowAddrCode("B10")).toBe(9);
73
- expect(ExcelUtils.parseRowAddrCode("AA100")).toBe(99);
74
- });
75
- });
76
-
77
- describe("stringifyAddr / parseCellAddrCode", () => {
78
- it("셀 주소를 올바르게 변환한다", () => {
79
- expect(ExcelUtils.stringifyAddr({ r: 0, c: 0 })).toBe("A1");
80
- expect(ExcelUtils.stringifyAddr({ r: 9, c: 1 })).toBe("B10");
81
- expect(ExcelUtils.stringifyAddr({ r: 99, c: 26 })).toBe("AA100");
82
- });
83
-
84
- it("셀 주소를 올바르게 파싱한다", () => {
85
- expect(ExcelUtils.parseCellAddrCode("A1")).toEqual({ r: 0, c: 0 });
86
- expect(ExcelUtils.parseCellAddrCode("B10")).toEqual({ r: 9, c: 1 });
87
- expect(ExcelUtils.parseCellAddrCode("AA100")).toEqual({ r: 99, c: 26 });
88
- });
89
- });
90
-
91
- describe("parseRangeAddrCode / stringifyRangeAddr", () => {
92
- it("단일 셀 범위를 파싱한다", () => {
93
- const range = ExcelUtils.parseRangeAddrCode("A1");
94
- expect(range.s).toEqual({ r: 0, c: 0 });
95
- expect(range.e).toEqual({ r: 0, c: 0 });
96
- });
97
-
98
- it("다중 셀 범위를 파싱한다", () => {
99
- const range = ExcelUtils.parseRangeAddrCode("A1:C3");
100
- expect(range.s).toEqual({ r: 0, c: 0 });
101
- expect(range.e).toEqual({ r: 2, c: 2 });
102
- });
103
-
104
- it("단일 셀 범위를 문자열로 변환한다", () => {
105
- const addr = ExcelUtils.stringifyRangeAddr({
106
- s: { r: 0, c: 0 },
107
- e: { r: 0, c: 0 },
108
- });
109
- expect(addr).toBe("A1");
110
- });
111
-
112
- it("다중 셀 범위를 문자열로 변환한다", () => {
113
- const addr = ExcelUtils.stringifyRangeAddr({
114
- s: { r: 0, c: 0 },
115
- e: { r: 2, c: 2 },
116
- });
117
- expect(addr).toBe("A1:C3");
118
- });
119
- });
120
-
121
- describe("convertTimeTickToNumber / convertNumberToTimeTick", () => {
122
- it("1970-01-01을 올바르게 변환한다", () => {
123
- const date = new Date(Date.UTC(1970, 0, 1, 0, 0, 0));
124
- const tick = date.getTime();
125
- const excelNum = ExcelUtils.convertTimeTickToNumber(tick);
126
- // 1970-01-01은 Excel 기준 25569일째
127
- expect(excelNum).toBeCloseTo(25569, 0);
128
- });
129
-
130
- it("2024-06-15를 올바르게 변환한다", () => {
131
- const date = new Date(Date.UTC(2024, 5, 15, 0, 0, 0));
132
- const tick = date.getTime();
133
- const excelNum = ExcelUtils.convertTimeTickToNumber(tick);
134
- // 대략적인 값 확인
135
- expect(excelNum).toBeGreaterThan(45000);
136
- });
137
-
138
- it("시간 포함 날짜를 올바르게 변환한다", () => {
139
- const date = new Date(Date.UTC(2024, 5, 15, 12, 0, 0));
140
- const tick = date.getTime();
141
- const excelNum = ExcelUtils.convertTimeTickToNumber(tick);
142
- // 12시 = 0.5일 추가
143
- const baseNum = ExcelUtils.convertTimeTickToNumber(new Date(Date.UTC(2024, 5, 15, 0, 0, 0)).getTime());
144
- expect(excelNum - baseNum).toBeCloseTo(0.5, 1);
145
- });
146
-
147
- it("라운드트립: tick → number → tick이 원래 값을 반환한다", () => {
148
- const originalDate = new Date(Date.UTC(2024, 5, 15, 14, 30, 45));
149
- const tick = originalDate.getTime();
150
- const excelNum = ExcelUtils.convertTimeTickToNumber(tick);
151
- const recoveredTick = ExcelUtils.convertNumberToTimeTick(excelNum);
152
- // 밀리초 단위까지 정확히 일치하지 않을 수 있으므로 초 단위로 비교
153
- expect(Math.floor(recoveredTick / 1000)).toBe(Math.floor(tick / 1000));
154
- });
155
- });
156
-
157
- describe("convertNumFmtCodeToName", () => {
158
- it("General을 number로 인식한다", () => {
159
- expect(ExcelUtils.convertNumFmtCodeToName("General")).toBe("number");
160
- });
161
-
162
- it("날짜 패턴을 DateOnly로 인식한다", () => {
163
- expect(ExcelUtils.convertNumFmtCodeToName("yyyy-mm-dd")).toBe("DateOnly");
164
- expect(ExcelUtils.convertNumFmtCodeToName("yy/mm/dd")).toBe("DateOnly");
165
- expect(ExcelUtils.convertNumFmtCodeToName("dd-mmm-yyyy")).toBe("DateOnly");
166
- });
167
-
168
- // NOTE: 현재 구현에서 'mm'은 날짜(month)와 시간(minute) 둘 다에서 사용됨
169
- // 정규식: hasDate = /yy|dd|mm/i, hasTime = /hh|ss/i
170
- // 따라서 "hh:mm:ss"는 hasDate(mm)=true, hasTime(hh,ss)=true → DateTime
171
- // "h:mm"은 hasDate(mm)=true, hasTime=false (h는 hh가 아님) → DateOnly
172
- it("시간 패턴을 처리한다 (mm 모호성 주의)", () => {
173
- // "hh:mm:ss": hasDate(mm)=true, hasTime(hh,ss)=true → DateTime
174
- expect(ExcelUtils.convertNumFmtCodeToName("hh:mm:ss")).toBe("DateTime");
175
- // "h:mm": hasDate(mm)=true, hasTime=false (h≠hh) → DateOnly
176
- expect(ExcelUtils.convertNumFmtCodeToName("h:mm")).toBe("DateOnly");
177
- // 순수 시간 포맷 (ss만 있고 mm 없는 경우)
178
- expect(ExcelUtils.convertNumFmtCodeToName("[h]:ss")).toBe("Time");
179
- });
180
-
181
- it("날짜+시간 패턴을 DateTime으로 인식한다", () => {
182
- expect(ExcelUtils.convertNumFmtCodeToName("yyyy-mm-dd hh:mm:ss")).toBe("DateTime");
183
- // "yy/mm/dd h:mm"는 날짜만 감지됨 (h:mm에서 hh가 아니고 ss도 없으므로)
184
- expect(ExcelUtils.convertNumFmtCodeToName("yy/mm/dd h:mm")).toBe("DateOnly");
185
- // 명확한 DateTime 패턴
186
- expect(ExcelUtils.convertNumFmtCodeToName("yyyy/mm/dd hh:mm:ss")).toBe("DateTime");
187
- });
188
-
189
- it("숫자 패턴을 number로 인식한다", () => {
190
- expect(ExcelUtils.convertNumFmtCodeToName("#,##0")).toBe("number");
191
- expect(ExcelUtils.convertNumFmtCodeToName("0.00")).toBe("number");
192
- expect(ExcelUtils.convertNumFmtCodeToName("#,0")).toBe("number");
193
- });
194
-
195
- it("알 수 없는 포맷 코드 입력 시 에러", () => {
196
- expect(() => ExcelUtils.convertNumFmtCodeToName("unknown-format-xyz")).toThrow();
197
- });
198
- });
199
-
200
- describe("convertNumFmtIdToName", () => {
201
- it("일반적인 숫자 포맷을 인식한다", () => {
202
- expect(ExcelUtils.convertNumFmtIdToName(0)).toBe("number");
203
- expect(ExcelUtils.convertNumFmtIdToName(1)).toBe("number");
204
- expect(ExcelUtils.convertNumFmtIdToName(2)).toBe("number");
205
- });
206
-
207
- it("날짜 포맷을 인식한다", () => {
208
- expect(ExcelUtils.convertNumFmtIdToName(14)).toBe("DateOnly");
209
- expect(ExcelUtils.convertNumFmtIdToName(15)).toBe("DateOnly");
210
- });
211
-
212
- it("날짜+시간 포맷을 인식한다", () => {
213
- expect(ExcelUtils.convertNumFmtIdToName(22)).toBe("DateTime");
214
- });
215
-
216
- it("시간 포맷을 인식한다", () => {
217
- expect(ExcelUtils.convertNumFmtIdToName(18)).toBe("Time");
218
- expect(ExcelUtils.convertNumFmtIdToName(19)).toBe("Time");
219
- });
220
-
221
- it("텍스트 포맷을 인식한다", () => {
222
- expect(ExcelUtils.convertNumFmtIdToName(49)).toBe("string");
223
- });
224
-
225
- it("알 수 없는 numFmtId 입력 시 에러", () => {
226
- expect(() => ExcelUtils.convertNumFmtIdToName(23)).toThrow();
227
- expect(() => ExcelUtils.convertNumFmtIdToName(100)).toThrow();
228
- });
229
- });
230
-
231
- describe("convertNumFmtNameToId", () => {
232
- it("포맷 이름을 ID로 변환한다", () => {
233
- expect(ExcelUtils.convertNumFmtNameToId("number")).toBe(0);
234
- expect(ExcelUtils.convertNumFmtNameToId("DateOnly")).toBe(14);
235
- expect(ExcelUtils.convertNumFmtNameToId("DateTime")).toBe(22);
236
- expect(ExcelUtils.convertNumFmtNameToId("Time")).toBe(18);
237
- expect(ExcelUtils.convertNumFmtNameToId("string")).toBe(49);
238
- });
239
- });
240
- });
File without changes
File without changes
File without changes