@simplysm/excel 13.0.76 → 13.0.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +539 -17
- package/dist/excel-cell.d.ts +4 -4
- package/dist/excel-cell.d.ts.map +1 -1
- package/dist/excel-cell.js +9 -10
- package/dist/excel-cell.js.map +1 -1
- package/dist/excel-workbook.d.ts +3 -3
- package/dist/excel-workbook.d.ts.map +1 -1
- package/dist/excel-workbook.js +3 -3
- package/dist/excel-workbook.js.map +1 -1
- package/dist/excel-worksheet.d.ts +1 -1
- package/dist/excel-worksheet.d.ts.map +1 -1
- package/dist/excel-worksheet.js +13 -17
- package/dist/excel-worksheet.js.map +1 -1
- package/dist/excel-wrapper.d.ts +1 -1
- package/dist/excel-wrapper.js +7 -7
- package/dist/excel-wrapper.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/excel-utils.d.ts +5 -5
- package/dist/utils/excel-utils.d.ts.map +1 -1
- package/dist/utils/excel-utils.js +15 -15
- package/dist/utils/excel-utils.js.map +1 -1
- package/dist/utils/zip-cache.js +3 -3
- package/dist/utils/zip-cache.js.map +1 -1
- package/dist/xml/excel-xml-relationship.js +2 -2
- package/dist/xml/excel-xml-relationship.js.map +1 -1
- package/dist/xml/excel-xml-style.js +16 -16
- package/dist/xml/excel-xml-style.js.map +1 -1
- package/dist/xml/excel-xml-workbook.js +6 -6
- package/dist/xml/excel-xml-workbook.js.map +1 -1
- package/dist/xml/excel-xml-worksheet.d.ts +5 -2
- package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
- package/dist/xml/excel-xml-worksheet.js +38 -20
- package/dist/xml/excel-xml-worksheet.js.map +1 -1
- package/package.json +2 -2
- package/src/excel-cell.ts +10 -11
- package/src/excel-workbook.ts +3 -3
- package/src/excel-worksheet.ts +17 -18
- package/src/excel-wrapper.ts +7 -7
- package/src/types.ts +1 -1
- package/src/utils/excel-utils.ts +15 -15
- package/src/utils/zip-cache.ts +3 -3
- package/src/xml/excel-xml-relationship.ts +2 -2
- package/src/xml/excel-xml-style.ts +16 -16
- package/src/xml/excel-xml-workbook.ts +6 -6
- package/src/xml/excel-xml-worksheet.ts +47 -22
- package/tests/excel-cell.spec.ts +85 -69
- package/tests/excel-col.spec.ts +17 -17
- package/tests/excel-row.spec.ts +13 -13
- package/tests/excel-workbook.spec.ts +26 -26
- package/tests/excel-worksheet.spec.ts +217 -101
- package/tests/excel-wrapper.spec.ts +24 -24
- package/tests/image-insert.spec.ts +5 -5
- package/tests/utils/excel-utils.spec.ts +14 -14
|
@@ -5,7 +5,7 @@ describe("ExcelWorksheet", () => {
|
|
|
5
5
|
describe("Sheet name", () => {
|
|
6
6
|
it("should change sheet name", async () => {
|
|
7
7
|
const wb = new ExcelWorkbook();
|
|
8
|
-
const ws = await wb.
|
|
8
|
+
const ws = await wb.addWorksheet("OldName");
|
|
9
9
|
|
|
10
10
|
await ws.setName("NewName");
|
|
11
11
|
const name = await ws.getName();
|
|
@@ -14,10 +14,10 @@ describe("ExcelWorksheet", () => {
|
|
|
14
14
|
|
|
15
15
|
it("should preserve changed sheet name after roundtrip", async () => {
|
|
16
16
|
const wb = new ExcelWorkbook();
|
|
17
|
-
const ws = await wb.
|
|
17
|
+
const ws = await wb.addWorksheet("OldName");
|
|
18
18
|
await ws.setName("NewName");
|
|
19
19
|
|
|
20
|
-
const bytes = await wb.
|
|
20
|
+
const bytes = await wb.toBytes();
|
|
21
21
|
|
|
22
22
|
const wb2 = new ExcelWorkbook(bytes);
|
|
23
23
|
const names = await wb2.getWorksheetNames();
|
|
@@ -33,47 +33,47 @@ describe("ExcelWorksheet", () => {
|
|
|
33
33
|
describe("Row/Column copy", () => {
|
|
34
34
|
it("should copy row", async () => {
|
|
35
35
|
const wb = new ExcelWorkbook();
|
|
36
|
-
const ws = await wb.
|
|
36
|
+
const ws = await wb.addWorksheet("Test");
|
|
37
37
|
|
|
38
38
|
// Set source row
|
|
39
|
-
await ws.cell(0, 0).
|
|
40
|
-
await ws.cell(0, 1).
|
|
41
|
-
await ws.cell(0, 2).
|
|
39
|
+
await ws.cell(0, 0).setValue("A");
|
|
40
|
+
await ws.cell(0, 1).setValue("B");
|
|
41
|
+
await ws.cell(0, 2).setValue("C");
|
|
42
42
|
|
|
43
43
|
// Copy row
|
|
44
44
|
await ws.copyRow(0, 2);
|
|
45
45
|
|
|
46
|
-
expect(await ws.cell(2, 0).
|
|
47
|
-
expect(await ws.cell(2, 1).
|
|
48
|
-
expect(await ws.cell(2, 2).
|
|
46
|
+
expect(await ws.cell(2, 0).getValue()).toBe("A");
|
|
47
|
+
expect(await ws.cell(2, 1).getValue()).toBe("B");
|
|
48
|
+
expect(await ws.cell(2, 2).getValue()).toBe("C");
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
it("should copy cell", async () => {
|
|
52
52
|
const wb = new ExcelWorkbook();
|
|
53
|
-
const ws = await wb.
|
|
53
|
+
const ws = await wb.addWorksheet("Test");
|
|
54
54
|
|
|
55
|
-
await ws.cell(0, 0).
|
|
55
|
+
await ws.cell(0, 0).setValue("Original");
|
|
56
56
|
await ws.copyCell({ r: 0, c: 0 }, { r: 1, c: 1 });
|
|
57
57
|
|
|
58
|
-
expect(await ws.cell(1, 1).
|
|
58
|
+
expect(await ws.cell(1, 1).getValue()).toBe("Original");
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
it("should copy only row style", async () => {
|
|
62
62
|
const wb = new ExcelWorkbook();
|
|
63
|
-
const ws = await wb.
|
|
63
|
+
const ws = await wb.addWorksheet("Test");
|
|
64
64
|
|
|
65
65
|
// Set styles
|
|
66
|
-
await ws.cell(0, 0).
|
|
66
|
+
await ws.cell(0, 0).setValue("Styled");
|
|
67
67
|
await ws.cell(0, 0).setStyle({ background: "00FF0000" });
|
|
68
|
-
await ws.cell(0, 1).
|
|
68
|
+
await ws.cell(0, 1).setValue("Also Styled");
|
|
69
69
|
await ws.cell(0, 1).setStyle({ background: "0000FF00" });
|
|
70
70
|
|
|
71
71
|
// Copy only styles
|
|
72
72
|
await ws.copyRowStyle(0, 2);
|
|
73
73
|
|
|
74
74
|
// Values should not be copied
|
|
75
|
-
expect(await ws.cell(2, 0).
|
|
76
|
-
expect(await ws.cell(2, 1).
|
|
75
|
+
expect(await ws.cell(2, 0).getValue()).toBeUndefined();
|
|
76
|
+
expect(await ws.cell(2, 1).getValue()).toBeUndefined();
|
|
77
77
|
|
|
78
78
|
// Styles should be copied
|
|
79
79
|
const styleId0 = await ws.cell(0, 0).getStyleId();
|
|
@@ -83,65 +83,85 @@ describe("ExcelWorksheet", () => {
|
|
|
83
83
|
|
|
84
84
|
it("should insert copy row when srcR < targetR", async () => {
|
|
85
85
|
const wb = new ExcelWorkbook();
|
|
86
|
-
const ws = await wb.
|
|
86
|
+
const ws = await wb.addWorksheet("Test");
|
|
87
87
|
|
|
88
|
-
await ws.cell(0, 0).
|
|
89
|
-
await ws.cell(1, 0).
|
|
90
|
-
await ws.cell(2, 0).
|
|
88
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
89
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
90
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
91
91
|
|
|
92
92
|
// Insert copy row 0 at position 1 (existing rows are shifted)
|
|
93
93
|
await ws.insertCopyRow(0, 1);
|
|
94
94
|
|
|
95
|
-
expect(await ws.cell(0, 0).
|
|
96
|
-
expect(await ws.cell(1, 0).
|
|
97
|
-
expect(await ws.cell(2, 0).
|
|
98
|
-
expect(await ws.cell(3, 0).
|
|
95
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Row0");
|
|
96
|
+
expect(await ws.cell(1, 0).getValue()).toBe("Row0"); // copied
|
|
97
|
+
expect(await ws.cell(2, 0).getValue()).toBe("Row1"); // shifted
|
|
98
|
+
expect(await ws.cell(3, 0).getValue()).toBe("Row2"); // shifted
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
it("should insert copy row when srcR > targetR", async () => {
|
|
102
102
|
const wb = new ExcelWorkbook();
|
|
103
|
-
const ws = await wb.
|
|
103
|
+
const ws = await wb.addWorksheet("Test");
|
|
104
104
|
|
|
105
|
-
await ws.cell(0, 0).
|
|
106
|
-
await ws.cell(1, 0).
|
|
107
|
-
await ws.cell(2, 0).
|
|
108
|
-
await ws.cell(3, 0).
|
|
105
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
106
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
107
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
108
|
+
await ws.cell(3, 0).setValue("Row3");
|
|
109
109
|
|
|
110
110
|
// Insert copy row 2 at position 1 (existing rows are shifted)
|
|
111
111
|
await ws.insertCopyRow(2, 1);
|
|
112
112
|
|
|
113
|
-
expect(await ws.cell(0, 0).
|
|
114
|
-
expect(await ws.cell(1, 0).
|
|
115
|
-
expect(await ws.cell(2, 0).
|
|
116
|
-
expect(await ws.cell(3, 0).
|
|
117
|
-
expect(await ws.cell(4, 0).
|
|
113
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Row0");
|
|
114
|
+
expect(await ws.cell(1, 0).getValue()).toBe("Row2"); // copied
|
|
115
|
+
expect(await ws.cell(2, 0).getValue()).toBe("Row1"); // shifted
|
|
116
|
+
expect(await ws.cell(3, 0).getValue()).toBe("Row2"); // shifted (original Row2)
|
|
117
|
+
expect(await ws.cell(4, 0).getValue()).toBe("Row3"); // shifted
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
it("should insert copy row when srcR == targetR", async () => {
|
|
121
121
|
const wb = new ExcelWorkbook();
|
|
122
|
-
const ws = await wb.
|
|
122
|
+
const ws = await wb.addWorksheet("Test");
|
|
123
123
|
|
|
124
|
-
await ws.cell(0, 0).
|
|
125
|
-
await ws.cell(1, 0).
|
|
126
|
-
await ws.cell(2, 0).
|
|
124
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
125
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
126
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
127
127
|
|
|
128
128
|
// Insert copy row 1 at position 1 (copy itself)
|
|
129
129
|
await ws.insertCopyRow(1, 1);
|
|
130
130
|
|
|
131
|
-
expect(await ws.cell(0, 0).
|
|
132
|
-
expect(await ws.cell(1, 0).
|
|
133
|
-
expect(await ws.cell(2, 0).
|
|
134
|
-
expect(await ws.cell(3, 0).
|
|
131
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Row0");
|
|
132
|
+
expect(await ws.cell(1, 0).getValue()).toBe("Row1"); // copied
|
|
133
|
+
expect(await ws.cell(2, 0).getValue()).toBe("Row1"); // shifted (original Row1)
|
|
134
|
+
expect(await ws.cell(3, 0).getValue()).toBe("Row2"); // shifted
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should skip merge handling when skipMerge is true", async () => {
|
|
138
|
+
const wb = new ExcelWorkbook();
|
|
139
|
+
const ws = await wb.addWorksheet("Test");
|
|
140
|
+
|
|
141
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
142
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
143
|
+
await ws.cell(0, 0).merge(0, 1); // Merge A1:B1
|
|
144
|
+
|
|
145
|
+
const wsData = await ws["_getWsData"]();
|
|
146
|
+
|
|
147
|
+
// Copy row 0 to row 1, but skip merge handling
|
|
148
|
+
wsData.copyRow(0, 1, { skipMerge: true });
|
|
149
|
+
|
|
150
|
+
// Row 1 should have the data but merge should not be copied
|
|
151
|
+
const merges = wsData.getMergeCells();
|
|
152
|
+
expect(merges).toEqual([
|
|
153
|
+
{ s: { r: 0, c: 0 }, e: { r: 0, c: 1 } }, // original merge, unchanged
|
|
154
|
+
]);
|
|
135
155
|
});
|
|
136
156
|
});
|
|
137
157
|
|
|
138
158
|
describe("Range and cell access", () => {
|
|
139
159
|
it("should get data range", async () => {
|
|
140
160
|
const wb = new ExcelWorkbook();
|
|
141
|
-
const ws = await wb.
|
|
161
|
+
const ws = await wb.addWorksheet("Test");
|
|
142
162
|
|
|
143
|
-
await ws.cell(0, 0).
|
|
144
|
-
await ws.cell(2, 3).
|
|
163
|
+
await ws.cell(0, 0).setValue("A");
|
|
164
|
+
await ws.cell(2, 3).setValue("D");
|
|
145
165
|
|
|
146
166
|
const range = await ws.getRange();
|
|
147
167
|
expect(range.s.r).toBe(0);
|
|
@@ -152,12 +172,12 @@ describe("ExcelWorksheet", () => {
|
|
|
152
172
|
|
|
153
173
|
it("should get all cells", async () => {
|
|
154
174
|
const wb = new ExcelWorkbook();
|
|
155
|
-
const ws = await wb.
|
|
175
|
+
const ws = await wb.addWorksheet("Test");
|
|
156
176
|
|
|
157
|
-
await ws.cell(0, 0).
|
|
158
|
-
await ws.cell(0, 1).
|
|
159
|
-
await ws.cell(1, 0).
|
|
160
|
-
await ws.cell(1, 1).
|
|
177
|
+
await ws.cell(0, 0).setValue("A");
|
|
178
|
+
await ws.cell(0, 1).setValue("B");
|
|
179
|
+
await ws.cell(1, 0).setValue("C");
|
|
180
|
+
await ws.cell(1, 1).setValue("D");
|
|
161
181
|
|
|
162
182
|
const cells = await ws.getCells();
|
|
163
183
|
expect(cells.length).toBe(2);
|
|
@@ -168,16 +188,16 @@ describe("ExcelWorksheet", () => {
|
|
|
168
188
|
describe("Data table", () => {
|
|
169
189
|
it("should get data table", async () => {
|
|
170
190
|
const wb = new ExcelWorkbook();
|
|
171
|
-
const ws = await wb.
|
|
191
|
+
const ws = await wb.addWorksheet("Test");
|
|
172
192
|
|
|
173
193
|
// Headers
|
|
174
|
-
await ws.cell(0, 0).
|
|
175
|
-
await ws.cell(0, 1).
|
|
194
|
+
await ws.cell(0, 0).setValue("Name");
|
|
195
|
+
await ws.cell(0, 1).setValue("Age");
|
|
176
196
|
// Data
|
|
177
|
-
await ws.cell(1, 0).
|
|
178
|
-
await ws.cell(1, 1).
|
|
179
|
-
await ws.cell(2, 0).
|
|
180
|
-
await ws.cell(2, 1).
|
|
197
|
+
await ws.cell(1, 0).setValue("Alice");
|
|
198
|
+
await ws.cell(1, 1).setValue(30);
|
|
199
|
+
await ws.cell(2, 0).setValue("Bob");
|
|
200
|
+
await ws.cell(2, 1).setValue(25);
|
|
181
201
|
|
|
182
202
|
const data = await ws.getDataTable();
|
|
183
203
|
expect(data.length).toBe(2);
|
|
@@ -189,14 +209,14 @@ describe("ExcelWorksheet", () => {
|
|
|
189
209
|
|
|
190
210
|
it("should filter specific headers only", async () => {
|
|
191
211
|
const wb = new ExcelWorkbook();
|
|
192
|
-
const ws = await wb.
|
|
212
|
+
const ws = await wb.addWorksheet("Test");
|
|
193
213
|
|
|
194
|
-
await ws.cell(0, 0).
|
|
195
|
-
await ws.cell(0, 1).
|
|
196
|
-
await ws.cell(0, 2).
|
|
197
|
-
await ws.cell(1, 0).
|
|
198
|
-
await ws.cell(1, 1).
|
|
199
|
-
await ws.cell(1, 2).
|
|
214
|
+
await ws.cell(0, 0).setValue("Name");
|
|
215
|
+
await ws.cell(0, 1).setValue("Age");
|
|
216
|
+
await ws.cell(0, 2).setValue("Ignore");
|
|
217
|
+
await ws.cell(1, 0).setValue("Alice");
|
|
218
|
+
await ws.cell(1, 1).setValue(30);
|
|
219
|
+
await ws.cell(1, 2).setValue("X");
|
|
200
220
|
|
|
201
221
|
const data = await ws.getDataTable({
|
|
202
222
|
usableHeaderNameFn: (name) => name !== "Ignore",
|
|
@@ -209,7 +229,7 @@ describe("ExcelWorksheet", () => {
|
|
|
209
229
|
|
|
210
230
|
it("should set data matrix", async () => {
|
|
211
231
|
const wb = new ExcelWorkbook();
|
|
212
|
-
const ws = await wb.
|
|
232
|
+
const ws = await wb.addWorksheet("Test");
|
|
213
233
|
|
|
214
234
|
const matrix = [
|
|
215
235
|
["A", "B", "C"],
|
|
@@ -219,14 +239,14 @@ describe("ExcelWorksheet", () => {
|
|
|
219
239
|
|
|
220
240
|
await ws.setDataMatrix(matrix);
|
|
221
241
|
|
|
222
|
-
expect(await ws.cell(0, 0).
|
|
223
|
-
expect(await ws.cell(0, 2).
|
|
224
|
-
expect(await ws.cell(2, 2).
|
|
242
|
+
expect(await ws.cell(0, 0).getValue()).toBe("A");
|
|
243
|
+
expect(await ws.cell(0, 2).getValue()).toBe("C");
|
|
244
|
+
expect(await ws.cell(2, 2).getValue()).toBe(6);
|
|
225
245
|
});
|
|
226
246
|
|
|
227
247
|
it("should set records array", async () => {
|
|
228
248
|
const wb = new ExcelWorkbook();
|
|
229
|
-
const ws = await wb.
|
|
249
|
+
const ws = await wb.addWorksheet("Test");
|
|
230
250
|
|
|
231
251
|
const records = [
|
|
232
252
|
{ Name: "Alice", Age: 30 },
|
|
@@ -236,7 +256,7 @@ describe("ExcelWorksheet", () => {
|
|
|
236
256
|
await ws.setRecords(records);
|
|
237
257
|
|
|
238
258
|
// Check headers
|
|
239
|
-
const headers = [await ws.cell(0, 0).
|
|
259
|
+
const headers = [await ws.cell(0, 0).getValue(), await ws.cell(0, 1).getValue()];
|
|
240
260
|
expect(headers).toContain("Name");
|
|
241
261
|
expect(headers).toContain("Age");
|
|
242
262
|
|
|
@@ -249,13 +269,13 @@ describe("ExcelWorksheet", () => {
|
|
|
249
269
|
describe("Column width", () => {
|
|
250
270
|
it("should preserve column width after roundtrip", async () => {
|
|
251
271
|
const wb = new ExcelWorkbook();
|
|
252
|
-
const ws = await wb.
|
|
272
|
+
const ws = await wb.addWorksheet("Test");
|
|
253
273
|
|
|
254
|
-
await ws.cell(0, 0).
|
|
274
|
+
await ws.cell(0, 0).setValue("A1");
|
|
255
275
|
await ws.col(0).setWidth(25);
|
|
256
276
|
await ws.col(2).setWidth(30);
|
|
257
277
|
|
|
258
|
-
const bytes = await wb.
|
|
278
|
+
const bytes = await wb.toBytes();
|
|
259
279
|
|
|
260
280
|
const wb2 = new ExcelWorkbook(bytes);
|
|
261
281
|
await wb2.getWorksheet("Test");
|
|
@@ -279,33 +299,33 @@ describe("ExcelWorksheet", () => {
|
|
|
279
299
|
describe("Column access", () => {
|
|
280
300
|
it("should get all cells in column", async () => {
|
|
281
301
|
const wb = new ExcelWorkbook();
|
|
282
|
-
const ws = await wb.
|
|
302
|
+
const ws = await wb.addWorksheet("Test");
|
|
283
303
|
|
|
284
|
-
await ws.cell(0, 0).
|
|
285
|
-
await ws.cell(1, 0).
|
|
286
|
-
await ws.cell(2, 0).
|
|
304
|
+
await ws.cell(0, 0).setValue("A1");
|
|
305
|
+
await ws.cell(1, 0).setValue("A2");
|
|
306
|
+
await ws.cell(2, 0).setValue("A3");
|
|
287
307
|
|
|
288
308
|
const cells = await ws.col(0).getCells();
|
|
289
309
|
expect(cells.length).toBe(3);
|
|
290
|
-
expect(await cells[0].
|
|
291
|
-
expect(await cells[1].
|
|
292
|
-
expect(await cells[2].
|
|
310
|
+
expect(await cells[0].getValue()).toBe("A1");
|
|
311
|
+
expect(await cells[1].getValue()).toBe("A2");
|
|
312
|
+
expect(await cells[2].getValue()).toBe("A3");
|
|
293
313
|
});
|
|
294
314
|
});
|
|
295
315
|
|
|
296
316
|
describe("Data table edge cases", () => {
|
|
297
317
|
it("should return empty array when calling getDataTable on empty sheet", async () => {
|
|
298
318
|
const wb = new ExcelWorkbook();
|
|
299
|
-
const ws = await wb.
|
|
319
|
+
const ws = await wb.addWorksheet("Empty");
|
|
300
320
|
const data = await ws.getDataTable();
|
|
301
321
|
expect(data).toEqual([]);
|
|
302
322
|
});
|
|
303
323
|
|
|
304
324
|
it("should return empty array when only headers exist without data", async () => {
|
|
305
325
|
const wb = new ExcelWorkbook();
|
|
306
|
-
const ws = await wb.
|
|
307
|
-
await ws.cell(0, 0).
|
|
308
|
-
await ws.cell(0, 1).
|
|
326
|
+
const ws = await wb.addWorksheet("Test");
|
|
327
|
+
await ws.cell(0, 0).setValue("Header1");
|
|
328
|
+
await ws.cell(0, 1).setValue("Header2");
|
|
309
329
|
const data = await ws.getDataTable();
|
|
310
330
|
expect(data).toEqual([]);
|
|
311
331
|
});
|
|
@@ -314,16 +334,16 @@ describe("ExcelWorksheet", () => {
|
|
|
314
334
|
describe("Data table options", () => {
|
|
315
335
|
it("should specify header row with headerRowIndex", async () => {
|
|
316
336
|
const wb = new ExcelWorkbook();
|
|
317
|
-
const ws = await wb.
|
|
337
|
+
const ws = await wb.addWorksheet("Test");
|
|
318
338
|
|
|
319
339
|
// Row 0 is title
|
|
320
|
-
await ws.cell(0, 0).
|
|
340
|
+
await ws.cell(0, 0).setValue("Title");
|
|
321
341
|
// Row 1 is header
|
|
322
|
-
await ws.cell(1, 0).
|
|
323
|
-
await ws.cell(1, 1).
|
|
342
|
+
await ws.cell(1, 0).setValue("Name");
|
|
343
|
+
await ws.cell(1, 1).setValue("Age");
|
|
324
344
|
// Data starts from row 2
|
|
325
|
-
await ws.cell(2, 0).
|
|
326
|
-
await ws.cell(2, 1).
|
|
345
|
+
await ws.cell(2, 0).setValue("Alice");
|
|
346
|
+
await ws.cell(2, 1).setValue(30);
|
|
327
347
|
|
|
328
348
|
const data = await ws.getDataTable({ headerRowIndex: 1 });
|
|
329
349
|
expect(data.length).toBe(1);
|
|
@@ -333,16 +353,16 @@ describe("ExcelWorksheet", () => {
|
|
|
333
353
|
|
|
334
354
|
it("should detect data end with checkEndColIndex", async () => {
|
|
335
355
|
const wb = new ExcelWorkbook();
|
|
336
|
-
const ws = await wb.
|
|
337
|
-
|
|
338
|
-
await ws.cell(0, 0).
|
|
339
|
-
await ws.cell(0, 1).
|
|
340
|
-
await ws.cell(1, 0).
|
|
341
|
-
await ws.cell(1, 1).
|
|
342
|
-
await ws.cell(2, 0).
|
|
343
|
-
await ws.cell(2, 1).
|
|
356
|
+
const ws = await wb.addWorksheet("Test");
|
|
357
|
+
|
|
358
|
+
await ws.cell(0, 0).setValue("Name");
|
|
359
|
+
await ws.cell(0, 1).setValue("Age");
|
|
360
|
+
await ws.cell(1, 0).setValue("Alice");
|
|
361
|
+
await ws.cell(1, 1).setValue(30);
|
|
362
|
+
await ws.cell(2, 0).setValue("Bob");
|
|
363
|
+
await ws.cell(2, 1).setValue(25);
|
|
344
364
|
// Row 3 has empty Name column -> data end
|
|
345
|
-
await ws.cell(3, 1).
|
|
365
|
+
await ws.cell(3, 1).setValue(999);
|
|
346
366
|
|
|
347
367
|
const data = await ws.getDataTable({ checkEndColIndex: 0 });
|
|
348
368
|
expect(data.length).toBe(2);
|
|
@@ -350,4 +370,100 @@ describe("ExcelWorksheet", () => {
|
|
|
350
370
|
expect(data[1]["Name"]).toBe("Bob");
|
|
351
371
|
});
|
|
352
372
|
});
|
|
373
|
+
|
|
374
|
+
describe("Merge cells", () => {
|
|
375
|
+
it("should shift merge cells when inserting row", async () => {
|
|
376
|
+
const wb = new ExcelWorkbook();
|
|
377
|
+
const ws = await wb.addWorksheet("Test");
|
|
378
|
+
|
|
379
|
+
// Create merged cells: A1:B2 and C3:D4
|
|
380
|
+
await ws.cell(0, 0).merge(1, 1); // A1:B2
|
|
381
|
+
await ws.cell(2, 2).merge(3, 3); // C3:D4
|
|
382
|
+
|
|
383
|
+
const wsData = await ws["_getWsData"](); // Access private method for testing
|
|
384
|
+
wsData.shiftMergeCells(2, 1); // Shift rows >= 2 by +1
|
|
385
|
+
|
|
386
|
+
const merges = wsData.getMergeCells();
|
|
387
|
+
expect(merges).toEqual([
|
|
388
|
+
{ s: { r: 0, c: 0 }, e: { r: 1, c: 1 } }, // unchanged
|
|
389
|
+
{ s: { r: 3, c: 2 }, e: { r: 4, c: 3 } }, // shifted down by 1
|
|
390
|
+
]);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it("should shift merge cells when inserting row with merges", async () => {
|
|
394
|
+
const wb = new ExcelWorkbook();
|
|
395
|
+
const ws = await wb.addWorksheet("Test");
|
|
396
|
+
|
|
397
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
398
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
399
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
400
|
+
|
|
401
|
+
// Create merge A3:B4 (rows 2-3, well below insertion point)
|
|
402
|
+
await ws.cell(2, 0).merge(3, 1);
|
|
403
|
+
|
|
404
|
+
// Insert copy of row 0 at position 1
|
|
405
|
+
await ws.insertCopyRow(0, 1);
|
|
406
|
+
|
|
407
|
+
// Check that merge was shifted correctly
|
|
408
|
+
const wsData = await ws["_getWsData"]();
|
|
409
|
+
const merges = wsData.getMergeCells();
|
|
410
|
+
|
|
411
|
+
// Merge at rows 2-3 should shift to rows 3-4
|
|
412
|
+
expect(merges).toEqual([
|
|
413
|
+
{ s: { r: 3, c: 0 }, e: { r: 4, c: 1 } },
|
|
414
|
+
]);
|
|
415
|
+
|
|
416
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Row0");
|
|
417
|
+
expect(await ws.cell(1, 0).getValue()).toBe("Row0"); // copied
|
|
418
|
+
expect(await ws.cell(2, 0).getValue()).toBe("Row1"); // shifted
|
|
419
|
+
expect(await ws.cell(3, 0).getValue()).toBe("Row2"); // shifted
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it("should handle multi-row merge when inserting row", async () => {
|
|
423
|
+
const wb = new ExcelWorkbook();
|
|
424
|
+
const ws = await wb.addWorksheet("Test");
|
|
425
|
+
|
|
426
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
427
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
428
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
429
|
+
await ws.cell(3, 0).setValue("Row3");
|
|
430
|
+
|
|
431
|
+
// Create merge A3:B4 (rows 2-3, below insertion point)
|
|
432
|
+
await ws.cell(2, 0).merge(3, 1);
|
|
433
|
+
|
|
434
|
+
// Insert copy of row 0 at position 1
|
|
435
|
+
await ws.insertCopyRow(0, 1);
|
|
436
|
+
|
|
437
|
+
const wsData = await ws["_getWsData"]();
|
|
438
|
+
const merges = wsData.getMergeCells();
|
|
439
|
+
|
|
440
|
+
// Merge at rows 2-3 should shift to rows 3-4 (rows >= 1 shift by 1)
|
|
441
|
+
expect(merges).toHaveLength(1);
|
|
442
|
+
expect(merges[0].s).toEqual({ r: 3, c: 0 });
|
|
443
|
+
expect(merges[0].e).toEqual({ r: 4, c: 1 }); // shifted from 2-3 to 3-4
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it("should not shift merge above insertion point", async () => {
|
|
447
|
+
const wb = new ExcelWorkbook();
|
|
448
|
+
const ws = await wb.addWorksheet("Test");
|
|
449
|
+
|
|
450
|
+
await ws.cell(0, 0).setValue("Row0");
|
|
451
|
+
await ws.cell(1, 0).setValue("Row1");
|
|
452
|
+
await ws.cell(2, 0).setValue("Row2");
|
|
453
|
+
|
|
454
|
+
// Create merge A1:B1 (row 0)
|
|
455
|
+
await ws.cell(0, 0).merge(0, 1);
|
|
456
|
+
|
|
457
|
+
// Insert copy of row 1 at position 2
|
|
458
|
+
await ws.insertCopyRow(1, 2);
|
|
459
|
+
|
|
460
|
+
const wsData = await ws["_getWsData"]();
|
|
461
|
+
const merges = wsData.getMergeCells();
|
|
462
|
+
|
|
463
|
+
// Merge should remain unchanged at A1:B1
|
|
464
|
+
expect(merges).toEqual([
|
|
465
|
+
{ s: { r: 0, c: 0 }, e: { r: 0, c: 1 } },
|
|
466
|
+
]);
|
|
467
|
+
});
|
|
468
|
+
});
|
|
353
469
|
});
|
|
@@ -24,16 +24,16 @@ describe("ExcelWrapper", () => {
|
|
|
24
24
|
const ws = await wb.getWorksheet("Users");
|
|
25
25
|
|
|
26
26
|
// Check headers
|
|
27
|
-
expect(await ws.cell(0, 0).
|
|
28
|
-
expect(await ws.cell(0, 1).
|
|
29
|
-
expect(await ws.cell(0, 2).
|
|
30
|
-
expect(await ws.cell(0, 3).
|
|
27
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Name");
|
|
28
|
+
expect(await ws.cell(0, 1).getValue()).toBe("Age");
|
|
29
|
+
expect(await ws.cell(0, 2).getValue()).toBe("Email");
|
|
30
|
+
expect(await ws.cell(0, 3).getValue()).toBe("Active");
|
|
31
31
|
|
|
32
32
|
// Check data
|
|
33
|
-
expect(await ws.cell(1, 0).
|
|
34
|
-
expect(await ws.cell(1, 1).
|
|
35
|
-
expect(await ws.cell(2, 0).
|
|
36
|
-
expect(await ws.cell(2, 1).
|
|
33
|
+
expect(await ws.cell(1, 0).getValue()).toBe("John Doe");
|
|
34
|
+
expect(await ws.cell(1, 1).getValue()).toBe(30);
|
|
35
|
+
expect(await ws.cell(2, 0).getValue()).toBe("Jane Smith");
|
|
36
|
+
expect(await ws.cell(2, 1).getValue()).toBe(25);
|
|
37
37
|
|
|
38
38
|
await wb.close();
|
|
39
39
|
});
|
|
@@ -65,7 +65,7 @@ describe("ExcelWrapper", () => {
|
|
|
65
65
|
];
|
|
66
66
|
|
|
67
67
|
const wb = await wrapper.write("Users", records);
|
|
68
|
-
const buffer = await wb.
|
|
68
|
+
const buffer = await wb.toBytes();
|
|
69
69
|
await wb.close();
|
|
70
70
|
|
|
71
71
|
// Read from Excel
|
|
@@ -85,7 +85,7 @@ describe("ExcelWrapper", () => {
|
|
|
85
85
|
|
|
86
86
|
const records = [{ name: "Test", age: 20 }];
|
|
87
87
|
const wb = await wrapper.write("Sheet1", records);
|
|
88
|
-
const buffer = await wb.
|
|
88
|
+
const buffer = await wb.toBytes();
|
|
89
89
|
await wb.close();
|
|
90
90
|
|
|
91
91
|
const readRecords = await wrapper.read(buffer, 0);
|
|
@@ -100,7 +100,7 @@ describe("ExcelWrapper", () => {
|
|
|
100
100
|
|
|
101
101
|
// Save without active field
|
|
102
102
|
const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
|
|
103
|
-
const buffer = await wb.
|
|
103
|
+
const buffer = await wb.toBytes();
|
|
104
104
|
await wb.close();
|
|
105
105
|
|
|
106
106
|
const records = await wrapper.read(buffer);
|
|
@@ -120,7 +120,7 @@ describe("ExcelWrapper", () => {
|
|
|
120
120
|
const records = [{ title: "Event 1", date: new DateOnly(2024, 6, 15) }, { title: "Event 2" }];
|
|
121
121
|
|
|
122
122
|
const wb = await wrapper.write("Events", records);
|
|
123
|
-
const buffer = await wb.
|
|
123
|
+
const buffer = await wb.toBytes();
|
|
124
124
|
await wb.close();
|
|
125
125
|
|
|
126
126
|
const readRecords = await wrapper.read(buffer, "Events");
|
|
@@ -144,7 +144,7 @@ describe("ExcelWrapper", () => {
|
|
|
144
144
|
const records = [{ title: "Meeting", datetime: new DateTime(2024, 6, 15, 14, 30, 0) }];
|
|
145
145
|
|
|
146
146
|
const wb = await wrapper.write("Events", records);
|
|
147
|
-
const buffer = await wb.
|
|
147
|
+
const buffer = await wb.toBytes();
|
|
148
148
|
await wb.close();
|
|
149
149
|
|
|
150
150
|
const readRecords = await wrapper.read(buffer, "Events");
|
|
@@ -168,7 +168,7 @@ describe("ExcelWrapper", () => {
|
|
|
168
168
|
const records = [{ title: "Alarm", time: new Time(9, 30, 0) }];
|
|
169
169
|
|
|
170
170
|
const wb = await wrapper.write("Events", records);
|
|
171
|
-
const buffer = await wb.
|
|
171
|
+
const buffer = await wb.toBytes();
|
|
172
172
|
await wb.close();
|
|
173
173
|
|
|
174
174
|
const readRecords = await wrapper.read(buffer, "Events");
|
|
@@ -185,7 +185,7 @@ describe("ExcelWrapper", () => {
|
|
|
185
185
|
|
|
186
186
|
// Create empty Excel with only headers
|
|
187
187
|
const wb = await wrapper.write("Empty", []);
|
|
188
|
-
const buffer = await wb.
|
|
188
|
+
const buffer = await wb.toBytes();
|
|
189
189
|
await wb.close();
|
|
190
190
|
|
|
191
191
|
await expect(wrapper.read(buffer, "Empty")).rejects.toThrow(
|
|
@@ -197,7 +197,7 @@ describe("ExcelWrapper", () => {
|
|
|
197
197
|
const wrapper = new ExcelWrapper(testSchema);
|
|
198
198
|
|
|
199
199
|
const wb = await wrapper.write("Test", [{ name: "Test", age: 20 }]);
|
|
200
|
-
const buffer = await wb.
|
|
200
|
+
const buffer = await wb.toBytes();
|
|
201
201
|
await wb.close();
|
|
202
202
|
|
|
203
203
|
await expect(wrapper.read(buffer, "NotExist")).rejects.toThrow();
|
|
@@ -215,9 +215,9 @@ describe("ExcelWrapper", () => {
|
|
|
215
215
|
|
|
216
216
|
// Modify data directly to trigger validation failure
|
|
217
217
|
const ws = await wb.getWorksheet("Validation");
|
|
218
|
-
await ws.cell(1, 0).
|
|
218
|
+
await ws.cell(1, 0).setValue("AB"); // Change to less than 5 characters
|
|
219
219
|
|
|
220
|
-
const buffer = await wb.
|
|
220
|
+
const buffer = await wb.toBytes();
|
|
221
221
|
await wb.close();
|
|
222
222
|
|
|
223
223
|
// Should throw validation error
|
|
@@ -241,13 +241,13 @@ describe("ExcelWrapper", () => {
|
|
|
241
241
|
const ws = await wb.getWorksheet("Test");
|
|
242
242
|
|
|
243
243
|
// Headers: only name and age exist
|
|
244
|
-
expect(await ws.cell(0, 0).
|
|
245
|
-
expect(await ws.cell(0, 1).
|
|
246
|
-
expect(await ws.cell(0, 2).
|
|
244
|
+
expect(await ws.cell(0, 0).getValue()).toBe("Name");
|
|
245
|
+
expect(await ws.cell(0, 1).getValue()).toBe("Age");
|
|
246
|
+
expect(await ws.cell(0, 2).getValue()).toBeUndefined();
|
|
247
247
|
|
|
248
248
|
// Check data
|
|
249
|
-
expect(await ws.cell(1, 0).
|
|
250
|
-
expect(await ws.cell(1, 1).
|
|
249
|
+
expect(await ws.cell(1, 0).getValue()).toBe("John Doe");
|
|
250
|
+
expect(await ws.cell(1, 1).getValue()).toBe(30);
|
|
251
251
|
|
|
252
252
|
await wb.close();
|
|
253
253
|
});
|
|
@@ -258,7 +258,7 @@ describe("ExcelWrapper", () => {
|
|
|
258
258
|
// Create Excel with all fields
|
|
259
259
|
const records = [{ name: "John Doe", age: 30, email: "john@test.com", phone: "010-1234-5678" }];
|
|
260
260
|
const wb = await wrapper.write("Test", records);
|
|
261
|
-
const buffer = await wb.
|
|
261
|
+
const buffer = await wb.toBytes();
|
|
262
262
|
await wb.close();
|
|
263
263
|
|
|
264
264
|
// Read with excludes
|