@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
package/README.md CHANGED
@@ -1,532 +1,35 @@
1
1
  # @simplysm/excel
2
2
 
3
- A TypeScript library for reading and writing Excel files (.xlsx). It works in both Node.js and browser environments, and internally uses a ZIP-based Lazy Loading structure for memory-efficient operation even with large files.
3
+ Excel file processing library
4
4
 
5
5
  ## Installation
6
6
 
7
- ```bash
8
- npm install @simplysm/excel
9
- # or
10
- yarn add @simplysm/excel
11
- # or
12
7
  pnpm add @simplysm/excel
13
- ```
14
8
 
15
- ## Main Modules
9
+ ## Source Index
16
10
 
17
- ### Core Classes
11
+ ### Types and utilities
18
12
 
19
- | Class | Description |
20
- |--------|------|
21
- | `ExcelWorkbook` | Workbook creation, opening, exporting, resource management |
22
- | `ExcelWorksheet` | Worksheet access, data read/write, image insertion, view settings |
23
- | `ExcelRow` | Row-level cell access |
24
- | `ExcelCol` | Column-level cell access and width settings |
25
- | `ExcelCell` | Cell value, formula, style, merge handling |
13
+ | Source | Exports | Description | Test |
14
+ |--------|---------|-------------|------|
15
+ | `src/types.ts` | `ExcelXmlContentTypeData`, `ExcelXmlRelationshipData`, `ExcelRelationshipData`, `ExcelXmlWorkbookData`, `ExcelXmlWorksheetData`, `ExcelRowData`, `ExcelCellData`, `ExcelXmlDrawingData`, `ExcelXmlSharedStringData`, `ExcelXmlSharedStringDataSi`, `ExcelXmlSharedStringDataText`, `ExcelXmlStyleData`, `ExcelXmlStyleDataXf`, `ExcelXmlStyleDataFill`, `ExcelXmlStyleDataBorder`, `ExcelValueType`, `ExcelNumberFormat`, `ExcelCellType`, `ExcelAddressPoint`, `ExcelAddressRangePoint`, `ExcelXml`, `ExcelBorderPosition`, `ExcelHorizontalAlign`, `ExcelVerticalAlign`, `ExcelStyleOptions` | All shared XML data types, value types, address types, and style option interfaces | - |
16
+ | `src/utils/excel-utils.ts` | `ExcelUtils` | Utility functions for address conversion, date/number format mapping | `excel-utils.spec.ts` |
26
17
 
27
- ### Wrapper Classes
18
+ ### Core classes
28
19
 
29
- | Class | Description |
30
- |--------|------|
31
- | `ExcelWrapper` | Type-safe Excel data conversion based on Zod schemas |
20
+ | Source | Exports | Description | Test |
21
+ |--------|---------|-------------|------|
22
+ | `src/excel-cell.ts` | `ExcelCell` | Single cell with value, formula, style, and merge operations | `excel-cell.spec.ts` |
23
+ | `src/excel-row.ts` | `ExcelRow` | Row container providing cell access by column index | `excel-row.spec.ts` |
24
+ | `src/excel-col.ts` | `ExcelCol` | Column container providing cell access and column width setting | `excel-col.spec.ts` |
25
+ | `src/excel-worksheet.ts` | `ExcelWorksheet` | Worksheet with cell/row/col access, copy, data table, and image support | `excel-worksheet.spec.ts` |
26
+ | `src/excel-workbook.ts` | `ExcelWorkbook` | Workbook with lazy-loading ZIP, worksheet management, and export | `excel-workbook.spec.ts` |
32
27
 
33
- ### Utilities
28
+ ### Wrapper classes
34
29
 
35
- | Class | Description |
36
- |--------|------|
37
- | `ExcelUtils` | Cell address conversion, date/number conversion, number format handling |
38
-
39
- ### Types
40
-
41
- | Type | Description |
42
- |------|------|
43
- | `ExcelValueType` | Cell value type (`number \| string \| DateOnly \| DateTime \| Time \| boolean \| undefined`) |
44
- | `ExcelNumberFormat` | Number format (`"number" \| "string" \| "DateOnly" \| "DateTime" \| "Time"`) |
45
- | `ExcelCellType` | Cell internal type (`"s" \| "b" \| "str" \| "n" \| "inlineStr" \| "e"`) |
46
- | `ExcelStyleOptions` | Cell style options (background color, border, alignment, number format) |
47
- | `ExcelBorderPosition` | Border position (`"left" \| "right" \| "top" \| "bottom"`) |
48
- | `ExcelHorizontalAlign` | Horizontal alignment (`"center" \| "left" \| "right"`) |
49
- | `ExcelVerticalAlign` | Vertical alignment (`"center" \| "top" \| "bottom"`) |
50
- | `ExcelAddressPoint` | Cell coordinates (`{ r: number; c: number }`) |
51
- | `ExcelAddressRangePoint` | Range coordinates (`{ s: ExcelAddressPoint; e: ExcelAddressPoint }`) |
52
- | `ExcelXml` | Interface for internal XML data objects (`{ readonly data: unknown; cleanup(): void }`) |
53
-
54
- ## Usage
55
-
56
- ### Creating a New Workbook and Writing Cell Values
57
-
58
- ```typescript
59
- import { ExcelWorkbook } from "@simplysm/excel";
60
-
61
- const wb = new ExcelWorkbook();
62
- const ws = await wb.createWorksheet("Sheet1");
63
-
64
- // Set cell values (both row and column are 0-based indices)
65
- await ws.cell(0, 0).setVal("Name");
66
- await ws.cell(0, 1).setVal("Age");
67
- await ws.cell(1, 0).setVal("John Doe");
68
- await ws.cell(1, 1).setVal(30);
69
-
70
- // Export as Uint8Array
71
- const bytes = await wb.getBytes();
72
-
73
- // Or export as Blob (useful for browser downloads)
74
- const blob = await wb.getBlob();
75
-
76
- // Release resources (required)
77
- await wb.close();
78
- ```
79
-
80
- ### Reading an Existing File
81
-
82
- ```typescript
83
- import { ExcelWorkbook } from "@simplysm/excel";
84
-
85
- // Open workbook from Uint8Array or Blob
86
- const wb = new ExcelWorkbook(bytes);
87
-
88
- // Access worksheet by index (0-based)
89
- const ws = await wb.getWorksheet(0);
90
-
91
- // Or access worksheet by name
92
- const wsByName = await wb.getWorksheet("Sheet1");
93
-
94
- // Read cell values
95
- const name = await ws.cell(0, 0).getVal(); // string | number | boolean | DateOnly | DateTime | Time | undefined
96
- const age = await ws.cell(0, 1).getVal();
97
-
98
- // Get list of worksheet names
99
- const sheetNames = await wb.getWorksheetNames();
100
-
101
- await wb.close();
102
- ```
103
-
104
- ### Resource Management (await using)
105
-
106
- `ExcelWorkbook` implements `Symbol.asyncDispose` for automatic resource cleanup with the `await using` syntax.
107
-
108
- ```typescript
109
- import { ExcelWorkbook } from "@simplysm/excel";
110
-
111
- // close() is automatically called when the scope ends
112
- await using wb = new ExcelWorkbook(bytes);
113
- const ws = await wb.getWorksheet(0);
114
- const value = await ws.cell(0, 0).getVal();
115
- ```
116
-
117
- If you don't use `await using`, you must release resources with `try-finally`.
118
-
119
- ```typescript
120
- const wb = new ExcelWorkbook(bytes);
121
- try {
122
- const ws = await wb.getWorksheet(0);
123
- // ... perform operations
124
- } finally {
125
- await wb.close();
126
- }
127
- ```
128
-
129
- ### Setting Cell Styles
130
-
131
- ```typescript
132
- const cell = ws.cell(0, 0);
133
-
134
- // Background color (ARGB 8-digit hexadecimal: AA=alpha, RR=red, GG=green, BB=blue)
135
- await cell.setStyle({ background: "FFFF0000" }); // Red (opaque)
136
- await cell.setStyle({ background: "00FFFF00" }); // Yellow
137
-
138
- // Border
139
- await cell.setStyle({ border: ["left", "right", "top", "bottom"] });
140
-
141
- // Alignment
142
- await cell.setStyle({
143
- horizontalAlign: "center",
144
- verticalAlign: "center",
145
- });
146
-
147
- // Number format
148
- await cell.setStyle({ numberFormat: "number" });
149
- await cell.setStyle({ numberFormat: "DateOnly" });
150
- await cell.setStyle({ numberFormat: "DateTime" });
151
- await cell.setStyle({ numberFormat: "Time" });
152
- await cell.setStyle({ numberFormat: "string" });
153
-
154
- // Apply multiple styles at once
155
- await cell.setStyle({
156
- background: "FFFF0000",
157
- border: ["left", "right", "top", "bottom"],
158
- horizontalAlign: "center",
159
- verticalAlign: "center",
160
- numberFormat: "number",
161
- });
162
- ```
163
-
164
- ### Formulas
165
-
166
- ```typescript
167
- await ws.cell(0, 0).setVal(10);
168
- await ws.cell(0, 1).setVal(20);
169
- await ws.cell(0, 2).setFormula("A1+B1"); // Result: 30
170
-
171
- // Read formula
172
- const formula = await ws.cell(0, 2).getFormula(); // "A1+B1"
173
-
174
- // Delete formula
175
- await ws.cell(0, 2).setFormula(undefined);
176
- ```
177
-
178
- ### Cell Merging
179
-
180
- ```typescript
181
- await ws.cell(0, 0).setVal("Merged Cell");
182
-
183
- // Merge from current cell (0,0) to (2,3) (3 rows x 4 columns area, i.e. A1:D3)
184
- await ws.cell(0, 0).merge(2, 3);
185
- ```
186
-
187
- The arguments of the `merge(r, c)` method are the 0-based row/column indices of the merge endpoint.
188
-
189
- ### Setting Column Width
190
-
191
- ```typescript
192
- // Set width of column 0 (column A) to 20
193
- await ws.col(0).setWidth(20);
194
- ```
195
-
196
- ### Copying Rows/Cells
197
-
198
- ```typescript
199
- // Copy only the style of row 0 to row 2
200
- await ws.copyRowStyle(0, 2);
201
-
202
- // Copy entire row 0 to row 2 (values + styles)
203
- await ws.copyRow(0, 2);
204
-
205
- // Copy individual cell
206
- await ws.copyCell({ r: 0, c: 0 }, { r: 1, c: 1 });
207
-
208
- // Insert copy of source row at target position (existing rows shift down)
209
- await ws.insertCopyRow(0, 3);
210
- ```
211
-
212
- ### Reading Data Table (getDataTable)
213
-
214
- Converts worksheet data into a header-based record array. Uses the first row as headers and returns in `Record<string, ExcelValueType>[]` format.
215
-
216
- ```typescript
217
- // Basic usage: first row is header
218
- const data = await ws.getDataTable();
219
- // [{ "Name": "John Doe", "Age": 30 }, { "Name": "Jane Smith", "Age": 25 }]
220
-
221
- // Specify header row index
222
- const data2 = await ws.getDataTable({ headerRowIndex: 2 });
223
-
224
- // Determine end of data when specific column is empty
225
- const data3 = await ws.getDataTable({ checkEndColIndex: 0 });
226
-
227
- // Filter to only use certain headers
228
- const data4 = await ws.getDataTable({
229
- usableHeaderNameFn: (name) => ["Name", "Age"].includes(name),
230
- });
231
- ```
232
-
233
- ### Writing Data (setDataMatrix / setRecords)
234
-
235
- ```typescript
236
- // Write as 2D array
237
- await ws.setDataMatrix([
238
- ["Name", "Age"],
239
- ["John Doe", 30],
240
- ["Jane Smith", 25],
241
- ]);
242
-
243
- // Write as record array (automatic header generation)
244
- await ws.setRecords([
245
- { "Name": "John Doe", "Age": 30 },
246
- { "Name": "Jane Smith", "Age": 25 },
247
- ]);
248
- ```
249
-
250
- ### Inserting Images
251
-
252
- ```typescript
253
- await ws.addImage({
254
- bytes: imageBytes, // Uint8Array
255
- ext: "png", // Extension (png, jpg, etc.)
256
- from: { r: 0, c: 0 }, // Start position (0-based)
257
- to: { r: 5, c: 3 }, // End position (0-based)
258
- });
259
-
260
- // Specify offset in EMU (English Metric Units)
261
- await ws.addImage({
262
- bytes: imageBytes,
263
- ext: "jpg",
264
- from: { r: 0, c: 0, rOff: 0, cOff: 0 },
265
- to: { r: 5, c: 3, rOff: 100000, cOff: 100000 },
266
- });
267
-
268
- // If 'to' is omitted, inserts at 'from' position with 1 cell size
269
- await ws.addImage({
270
- bytes: imageBytes,
271
- ext: "png",
272
- from: { r: 0, c: 0 },
273
- });
274
- ```
275
-
276
- ### View Settings
277
-
278
- ```typescript
279
- // Set zoom level (percentage)
280
- await ws.setZoom(85);
281
-
282
- // Freeze rows/columns
283
- await ws.setFix({ r: 0 }); // Freeze first row
284
- await ws.setFix({ c: 0 }); // Freeze first column
285
- await ws.setFix({ r: 0, c: 0 }); // Freeze first row + column
286
- ```
287
-
288
- ### Worksheet Name Management
289
-
290
- ```typescript
291
- const name = await ws.getName();
292
- await ws.setName("New Sheet Name");
293
- ```
294
-
295
- ### ExcelWrapper (Zod Schema-based Wrapper)
296
-
297
- `ExcelWrapper` is a wrapper class that allows type-safe reading and writing of Excel data based on Zod schemas.
298
-
299
- ```typescript
300
- import { z } from "zod";
301
- import { ExcelWrapper } from "@simplysm/excel";
302
-
303
- // Define schema (use .describe() for Excel header names; defaults to field key if omitted)
304
- const schema = z.object({
305
- name: z.string().describe("Name"),
306
- age: z.number().describe("Age"),
307
- email: z.string().optional().describe("Email"),
308
- active: z.boolean().describe("Active Status"),
309
- });
310
-
311
- const wrapper = new ExcelWrapper(schema);
312
- ```
313
-
314
- #### Writing to Excel
315
-
316
- ```typescript
317
- const records = [
318
- { name: "John Doe", age: 30, email: "john@test.com", active: true },
319
- { name: "Jane Smith", age: 25, active: false },
320
- ];
321
-
322
- // write() accepts Partial records and returns ExcelWorkbook, so resource management is required
323
- await using wb = await wrapper.write("Users", records);
324
- const bytes = await wb.getBytes();
325
-
326
- // Exclude specific fields from the output
327
- await using wb2 = await wrapper.write("Users", records, { excludes: ["email"] });
328
- ```
329
-
330
- The `write()` method automatically applies the following formatting:
331
- - Borders on all cells
332
- - Yellow background on required field headers (fields without optional/nullable/default)
333
- - 85% zoom, freeze first row
334
-
335
- #### Reading from Excel
336
-
337
- ```typescript
338
- // Read records from file (Uint8Array or Blob)
339
- const records = await wrapper.read(bytes);
340
- // records: { name: string; age: number; email?: string; active: boolean }[]
341
-
342
- // Specify worksheet name or index
343
- const records2 = await wrapper.read(bytes, "Users");
344
- const records3 = await wrapper.read(bytes, 0);
345
-
346
- // Exclude specific fields when reading
347
- const records4 = await wrapper.read(bytes, 0, { excludes: ["email"] });
348
- ```
349
-
350
- Behavior of the `read()` method:
351
- - Only reads headers defined in the schema (via `.describe()` or field key names)
352
- - Skips rows where all values are empty
353
- - Validates each row with the Zod schema, throws error on validation failure
354
- - Throws error if there is no data
355
- - Automatic type conversion: string -> number, string -> boolean ("1"/"true" -> true), etc.
356
-
357
- ## ExcelUtils API
358
-
359
- | Method | Input | Output | Description |
360
- |--------|------|------|------|
361
- | `stringifyAddr(point)` | `{ r: 0, c: 0 }` | `"A1"` | Convert coordinates to cell address string |
362
- | `stringifyRowAddr(r)` | `0` | `"1"` | Convert row index to row address |
363
- | `stringifyColAddr(c)` | `0` | `"A"` | Convert column index to column address (0~16383) |
364
- | `parseCellAddrCode(addr)` | `"B3"` | `{ r: 2, c: 1 }` | Convert cell address to coordinates |
365
- | `parseRowAddrCode(addr)` | `"A3"` | `2` | Extract row index from cell address |
366
- | `parseColAddrCode(addr)` | `"B3"` | `1` | Extract column index from cell address |
367
- | `parseRangeAddrCode(range)` | `"A1:C3"` | `{ s: {r:0,c:0}, e: {r:2,c:2} }` | Convert range address to coordinates |
368
- | `stringifyRangeAddr(point)` | `{ s: {r:0,c:0}, e: {r:2,c:2} }` | `"A1:C3"` | Convert range coordinates to address string |
369
- | `convertTimeTickToNumber(tick)` | JS timestamp (ms) | Excel date number | Convert JS date to Excel number |
370
- | `convertNumberToTimeTick(num)` | Excel date number | JS timestamp (ms) | Convert Excel number to JS date |
371
- | `convertNumFmtIdToName(id)` | Format ID | `ExcelNumberFormat` | Convert built-in format ID to name |
372
- | `convertNumFmtCodeToName(code)` | Format code | `ExcelNumberFormat` | Convert format code to name |
373
- | `convertNumFmtNameToId(name)` | `ExcelNumberFormat` | Format ID | Convert format name to ID |
374
-
375
- ## ExcelRow API
376
-
377
- | Method | Return Type | Description |
378
- |--------|-----------|------|
379
- | `cell(c)` | `ExcelCell` | Get cell at column index (0-based) |
380
- | `getCells()` | `Promise<ExcelCell[]>` | Get all cells in the row |
381
-
382
- ## ExcelCol API
383
-
384
- | Method | Return Type | Description |
385
- |--------|-----------|------|
386
- | `cell(r)` | `ExcelCell` | Get cell at row index (0-based) |
387
- | `getCells()` | `Promise<ExcelCell[]>` | Get all cells in the column |
388
- | `setWidth(size)` | `Promise<void>` | Set column width |
389
-
390
- ## ExcelCell API
391
-
392
- | Member | Type / Return Type | Description |
393
- |--------|-----------|------|
394
- | `addr` | `ExcelAddressPoint` (readonly) | Cell address as 0-based row/column indices |
395
- | `getVal()` | `Promise<ExcelValueType>` | Get cell value |
396
- | `setVal(val)` | `Promise<void>` | Set cell value (deletes cell if undefined) |
397
- | `getFormula()` | `Promise<string \| undefined>` | Get formula |
398
- | `setFormula(val)` | `Promise<void>` | Set formula (deletes formula if undefined) |
399
- | `setStyle(opts)` | `Promise<void>` | Set style |
400
- | `merge(r, c)` | `Promise<void>` | Merge from current cell to (r, c) |
401
- | `getStyleId()` | `Promise<string \| undefined>` | Get style ID |
402
- | `setStyleId(id)` | `Promise<void>` | Directly set style ID |
403
-
404
- ## ExcelWorksheet API
405
-
406
- | Method | Return Type | Description |
407
- |--------|-----------|------|
408
- | `cell(r, c)` | `ExcelCell` | Get cell object (0-based) |
409
- | `row(r)` | `ExcelRow` | Get row object (0-based) |
410
- | `col(c)` | `ExcelCol` | Get column object (0-based) |
411
- | `getName()` | `Promise<string>` | Get worksheet name |
412
- | `setName(name)` | `Promise<void>` | Change worksheet name |
413
- | `getRange()` | `Promise<ExcelAddressRangePoint>` | Get data range |
414
- | `getCells()` | `Promise<ExcelCell[][]>` | Get all cells as 2D array |
415
- | `getDataTable(opt?)` | `Promise<Record<string, ExcelValueType>[]>` | Convert to header-based record array |
416
- | `setDataMatrix(matrix)` | `Promise<void>` | Write 2D array data |
417
- | `setRecords(records)` | `Promise<void>` | Write record array (automatic header generation) |
418
- | `copyRow(src, target)` | `Promise<void>` | Copy row |
419
- | `copyRowStyle(src, target)` | `Promise<void>` | Copy only row style |
420
- | `copyCell(src, target)` | `Promise<void>` | Copy cell |
421
- | `copyCellStyle(src, target)` | `Promise<void>` | Copy only cell style |
422
- | `insertCopyRow(src, target)` | `Promise<void>` | Insert copy of row (existing rows shift) |
423
- | `addImage(opts)` | `Promise<void>` | Insert image |
424
- | `setZoom(percent)` | `Promise<void>` | Set zoom level |
425
- | `setFix(point)` | `Promise<void>` | Set freeze panes |
426
-
427
- ## ExcelWorkbook API
428
-
429
- | Member | Type / Return Type | Description |
430
- |--------|-----------|------|
431
- | `constructor(arg?)` | — | Create a new workbook (no arg), or open an existing file from `Uint8Array` or `Blob` |
432
- | `getWorksheet(nameOrIndex)` | `Promise<ExcelWorksheet>` | Get worksheet (name or 0-based index) |
433
- | `createWorksheet(name)` | `Promise<ExcelWorksheet>` | Create new worksheet |
434
- | `getWorksheetNames()` | `Promise<string[]>` | Get all worksheet names |
435
- | `getBytes()` | `Promise<Uint8Array>` | Export as Uint8Array |
436
- | `getBlob()` | `Promise<Blob>` | Export as Blob |
437
- | `close()` | `Promise<void>` | Release resources |
438
-
439
- ## ExcelWrapper API
440
-
441
- | Member | Type / Return Type | Description |
442
- |--------|-----------|------|
443
- | `constructor(schema)` | — | Create wrapper with a Zod schema (use `.describe()` on fields for Excel header names; defaults to field key) |
444
- | `read(file, wsNameOrIndex?, options?)` | `Promise<z.infer<TSchema>[]>` | Read records from Excel file (`Uint8Array` or `Blob`); defaults to first worksheet. `options.excludes` omits specific fields. |
445
- | `write(wsName, records, options?)` | `Promise<ExcelWorkbook>` | Write partial records to a new workbook; caller must manage the returned workbook's lifecycle. `options.excludes` omits specific fields. |
446
-
447
- ## XML Data Types
448
-
449
- These types represent the raw OOXML structure used internally by the library. They are exported for advanced use cases such as direct XML manipulation.
450
-
451
- | Type | Description |
452
- |------|-------------|
453
- | `ExcelXmlContentTypeData` | Structure of `[Content_Types].xml` |
454
- | `ExcelXmlRelationshipData` | Structure of `.rels` relationship XML files |
455
- | `ExcelRelationshipData` | Single relationship entry within `ExcelXmlRelationshipData` |
456
- | `ExcelXmlWorkbookData` | Structure of `xl/workbook.xml` |
457
- | `ExcelXmlWorksheetData` | Structure of `xl/worksheets/sheet*.xml` |
458
- | `ExcelRowData` | Single row entry within `ExcelXmlWorksheetData` |
459
- | `ExcelCellData` | Single cell entry within a row |
460
- | `ExcelXmlDrawingData` | Structure of `xl/drawings/drawing*.xml` |
461
- | `ExcelXmlSharedStringData` | Structure of `xl/sharedStrings.xml` |
462
- | `ExcelXmlSharedStringDataSi` | Single shared string item (plain text or rich text) |
463
- | `ExcelXmlSharedStringDataText` | Text element inside a shared string item |
464
- | `ExcelXmlStyleData` | Structure of `xl/styles.xml` |
465
- | `ExcelXmlStyleDataXf` | Cell format (`xf`) entry within `cellXfs` |
466
- | `ExcelXmlStyleDataFill` | Fill entry within `fills` |
467
- | `ExcelXmlStyleDataBorder` | Border entry within `borders` |
468
-
469
- ```typescript
470
- import type { ExcelXmlWorksheetData, ExcelCellData } from "@simplysm/excel";
471
- ```
472
-
473
- ## Caveats
474
-
475
- ### All Cell Methods are Asynchronous
476
-
477
- All cell-related methods in this library are designed as `async`. This is due to the Lazy Loading structure for memory efficiency with large files. Only the necessary XML is loaded selectively depending on the cell type:
478
-
479
- - Reading string cells: Loads SharedStrings.xml
480
- - Reading number cells: Does not load SharedStrings
481
- - Cells with styles: Loads Styles.xml
482
-
483
- ```typescript
484
- // Correct usage
485
- const value = await cell.getVal();
486
- await cell.setVal("Hello");
487
-
488
- // Incorrect usage - returns Promise object
489
- const value = cell.getVal();
490
- cell.setVal("Hello");
491
- ```
492
-
493
- ### Resource Cleanup is Required
494
-
495
- `ExcelWorkbook` manages ZIP resources internally, so you must call `close()` after use or use `await using`. After calling `close()`, the workbook instance cannot be used.
496
-
497
- ### Resource Management of ExcelWrapper.write()
498
-
499
- `ExcelWrapper.write()` returns `ExcelWorkbook`, so the caller must manage the resource.
500
-
501
- ```typescript
502
- // Correct usage
503
- await using wb = await wrapper.write("Sheet1", records);
504
- const bytes = await wb.getBytes();
505
-
506
- // Or
507
- const wb = await wrapper.write("Sheet1", records);
508
- try {
509
- const bytes = await wb.getBytes();
510
- } finally {
511
- await wb.close();
512
- }
513
- ```
514
-
515
- ### Background Color Format
516
-
517
- Background colors use the ARGB 8-digit hexadecimal format. It must satisfy the `/^[0-9A-F]{8}$/i` pattern, otherwise an error will occur.
518
-
519
- ```
520
- Format: AARRGGBB
521
- AA = alpha (00=transparent, FF=opaque, but reversed in Excel: 00=opaque)
522
- RR = red
523
- GG = green
524
- BB = blue
525
- ```
526
-
527
- ### 0-based Indexing
528
-
529
- All row/column indices are 0-based. Cell A1 in Excel corresponds to `cell(0, 0)`, cell B3 corresponds to `cell(2, 1)`.
30
+ | Source | Exports | Description | Test |
31
+ |--------|---------|-------------|------|
32
+ | `src/excel-wrapper.ts` | `ExcelWrapper` | Zod schema-based type-safe Excel read/write wrapper | `excel-wrapper.spec.ts` |
530
33
 
531
34
  ## License
532
35
 
@@ -1,58 +1,58 @@
1
1
  import type { ZipCache } from "./utils/zip-cache";
2
2
  import type { ExcelAddressPoint, ExcelStyleOptions, ExcelValueType } from "./types";
3
3
  /**
4
- * Excel 셀을 나타내는 클래스.
5
- * 읽기/쓰기, 수식 설정, 스타일 설정, 병합 등의 기능을 제공한다.
4
+ * Class representing an Excel cell.
5
+ * Provides value read/write, formula, style, and cell merge functionality.
6
6
  *
7
7
  * @remarks
8
- * ## 비동기 메서드 설계
8
+ * ## Async Method Design
9
9
  *
10
- * `getVal()`, `setVal()` 모든 셀 메서드가 `async`인 이유:
11
- * - 타입에 따라 필요한 XML만 선택적으로 로드한다
12
- * - 문자열 셀: SharedStrings.xml 로드
13
- * - 숫자 셀: SharedStrings 로드 안함
14
- * - 스타일이 있는 셀: Styles.xml 로드
10
+ * Why all cell methods like `getVal()`, `setVal()` are `async`:
11
+ * - Only the XML needed for the cell type is selectively loaded
12
+ * - String cell: loads SharedStrings.xml
13
+ * - Number cell: does not load SharedStrings
14
+ * - Styled cell: loads Styles.xml
15
15
  *
16
- * 어떤 셀을 읽을지 미리 없기 때문에 동기 구조로는 구현할 없다.
17
- * 동기 구조로 만들려면 모든 XML을 미리 로드해야 하므로 대용량 파일에서 메모리 문제가 발생한다.
16
+ * Since the cell to be read cannot be known in advance, a synchronous design is not feasible.
17
+ * A synchronous design would require preloading all XML, causing memory issues with large files.
18
18
  */
19
19
  export declare class ExcelCell {
20
20
  private readonly _zipCache;
21
21
  private readonly _targetFileName;
22
22
  private readonly _r;
23
23
  private readonly _c;
24
- /** 주소 (0-based 행/열 인덱스) */
24
+ /** Cell address (0-based row/column index) */
25
25
  readonly addr: ExcelAddressPoint;
26
26
  constructor(_zipCache: ZipCache, _targetFileName: string, _r: number, _c: number);
27
- /** 셀에 수식 설정 (undefined: 수식 삭제) */
27
+ /** Set formula on cell (undefined: remove formula) */
28
28
  setFormula(val: string | undefined): Promise<void>;
29
- /** 셀의 수식 반환 */
29
+ /** Return cell formula */
30
30
  getFormula(): Promise<string | undefined>;
31
- /** 설정 (undefined: 삭제) */
31
+ /** Set cell value (undefined: delete cell) */
32
32
  setVal(val: ExcelValueType): Promise<void>;
33
- /** 반환 */
33
+ /** Return cell value */
34
34
  getVal(): Promise<ExcelValueType>;
35
35
  /**
36
- * 현재 셀부터 지정된 좌표까지 병합
37
- * @param r 병합 인덱스 (0-based)
38
- * @param c 병합 인덱스 (0-based)
36
+ * Merge cells from current cell to the specified end coordinates
37
+ * @param r End row index of merge (0-based)
38
+ * @param c End column index of merge (0-based)
39
39
  * @example
40
- * // A1 셀에서 호출하면 A1:C3 범위 (3 x 3)를 병합
40
+ * // Called from cell A1, merges range A1:C3 (3 rows x 3 columns)
41
41
  * await ws.cell(0, 0).merge(2, 2);
42
42
  */
43
43
  merge(r: number, c: number): Promise<void>;
44
- /** 셀의 스타일 ID 반환 */
44
+ /** Return cell style ID */
45
45
  getStyleId(): Promise<string | undefined>;
46
- /** 셀의 스타일 ID 설정 */
46
+ /** Set cell style ID */
47
47
  setStyleId(styleId: string | undefined): Promise<void>;
48
48
  /**
49
- * 스타일 설정
50
- * @param opts 스타일 옵션
51
- * @param opts.background 배경색 (ARGB 형식, 8자리 16진수. 예: "FFFF0000")
52
- * @param opts.border 테두리 위치 배열 (예: ["left", "right", "top", "bottom"])
53
- * @param opts.horizontalAlign 가로 정렬 ("left", "center", "right")
54
- * @param opts.verticalAlign 세로 정렬 ("top", "center", "bottom")
55
- * @param opts.numberFormat 숫자 형식 ("number", "DateOnly", "DateTime", "Time", "string")
49
+ * Set cell style
50
+ * @param opts Style options
51
+ * @param opts.background Background color (ARGB format, 8-digit hex. e.g. "FFFF0000")
52
+ * @param opts.border Border position array (e.g. ["left", "right", "top", "bottom"])
53
+ * @param opts.horizontalAlign Horizontal alignment ("left", "center", "right")
54
+ * @param opts.verticalAlign Vertical alignment ("top", "center", "bottom")
55
+ * @param opts.numberFormat Number format ("number", "DateOnly", "DateTime", "Time", "string")
56
56
  */
57
57
  setStyle(opts: ExcelStyleOptions): Promise<void>;
58
58
  private _deleteCell;
@@ -1 +1 @@
1
- {"version":3,"file":"excel-cell.d.ts","sourceRoot":"","sources":["..\\src\\excel-cell.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAapF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPrB,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;gBAGd,SAAS,EAAE,QAAQ,EACnB,eAAe,EAAE,MAAM,EACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM;IAO7B,kCAAkC;IAC5B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,eAAe;IACT,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,+BAA+B;IACzB,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAwChD,aAAa;IACP,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAwFvC;;;;;;;OAOG;IACG,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,mBAAmB;IACb,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,mBAAmB;IACb,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;;;;;;OAQG;IACG,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;YAiCxC,WAAW;YAKX,UAAU;YAIV,iBAAiB;YAYjB,YAAY;YAIZ,UAAU;YAIV,aAAa;YAIb,aAAa;YAIb,kBAAkB;YAqBlB,qBAAqB;CAsBpC"}
1
+ {"version":3,"file":"excel-cell.d.ts","sourceRoot":"","sources":["..\\src\\excel-cell.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAapF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,SAAS;IAKlB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAPrB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;gBAGd,SAAS,EAAE,QAAQ,EACnB,eAAe,EAAE,MAAM,EACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM;IAO7B,sDAAsD;IAChD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,0BAA0B;IACpB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,8CAA8C;IACxC,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAwChD,wBAAwB;IAClB,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAwFvC;;;;;;;OAOG;IACG,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,2BAA2B;IACrB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK/C,wBAAwB;IAClB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;;;;;;OAQG;IACG,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;YAiCxC,WAAW;YAKX,UAAU;YAIV,iBAAiB;YAYjB,YAAY;YAIZ,UAAU;YAIV,aAAa;YAIb,aAAa;YAIb,kBAAkB;YAqBlB,qBAAqB;CAsBpC"}