@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.
- package/README.md +19 -516
- package/dist/excel-cell.d.ts +28 -28
- package/dist/excel-cell.d.ts.map +1 -1
- package/dist/excel-cell.js +24 -24
- package/dist/excel-cell.js.map +1 -1
- package/dist/excel-col.d.ts +4 -4
- package/dist/excel-col.d.ts.map +1 -1
- package/dist/excel-col.js +3 -3
- package/dist/excel-row.d.ts +3 -3
- package/dist/excel-row.d.ts.map +1 -1
- package/dist/excel-row.js +2 -2
- package/dist/excel-workbook.d.ts +23 -23
- package/dist/excel-workbook.d.ts.map +1 -1
- package/dist/excel-workbook.js +15 -15
- package/dist/excel-workbook.js.map +1 -1
- package/dist/excel-worksheet.d.ts +32 -32
- package/dist/excel-worksheet.d.ts.map +1 -1
- package/dist/excel-worksheet.js +32 -32
- package/dist/excel-worksheet.js.map +1 -1
- package/dist/excel-wrapper.d.ts +7 -7
- package/dist/excel-wrapper.js +7 -7
- package/dist/excel-wrapper.js.map +1 -1
- package/dist/types.d.ts +16 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/excel-utils.d.ts +23 -23
- package/dist/utils/excel-utils.d.ts.map +1 -1
- package/dist/utils/excel-utils.js +25 -25
- package/dist/utils/excel-utils.js.map +1 -1
- package/dist/utils/zip-cache.d.ts +6 -6
- package/dist/xml/excel-xml-content-type.d.ts +2 -2
- package/dist/xml/excel-xml-drawing.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.js +1 -1
- package/dist/xml/excel-xml-relationship.js.map +1 -1
- package/dist/xml/excel-xml-shared-string.d.ts +2 -2
- package/dist/xml/excel-xml-style.d.ts +2 -2
- package/dist/xml/excel-xml-style.js +6 -6
- package/dist/xml/excel-xml-style.js.map +1 -1
- package/dist/xml/excel-xml-unknown.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.js +1 -1
- package/dist/xml/excel-xml-workbook.js.map +1 -1
- package/dist/xml/excel-xml-worksheet.d.ts +6 -6
- package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
- package/dist/xml/excel-xml-worksheet.js +9 -8
- package/dist/xml/excel-xml-worksheet.js.map +1 -1
- package/package.json +6 -5
- package/src/excel-cell.ts +35 -35
- package/src/excel-col.ts +4 -4
- package/src/excel-row.ts +3 -3
- package/src/excel-workbook.ts +30 -30
- package/src/excel-worksheet.ts +47 -47
- package/src/excel-wrapper.ts +18 -18
- package/src/index.ts +3 -3
- package/src/types.ts +15 -17
- package/src/utils/excel-utils.ts +38 -38
- package/src/utils/zip-cache.ts +6 -6
- package/src/xml/excel-xml-content-type.ts +3 -3
- package/src/xml/excel-xml-drawing.ts +2 -2
- package/src/xml/excel-xml-relationship.ts +3 -3
- package/src/xml/excel-xml-shared-string.ts +2 -2
- package/src/xml/excel-xml-style.ts +11 -11
- package/src/xml/excel-xml-unknown.ts +2 -2
- package/src/xml/excel-xml-workbook.ts +5 -5
- package/src/xml/excel-xml-worksheet.ts +44 -43
- package/tests/excel-cell.spec.ts +448 -0
- package/tests/excel-col.spec.ts +112 -0
- package/tests/excel-row.spec.ts +71 -0
- package/tests/excel-workbook.spec.ts +219 -0
- package/tests/excel-worksheet.spec.ts +389 -0
- package/tests/excel-wrapper.spec.ts +296 -0
- package/tests/fixtures/logo.png +0 -0
- package/tests/fixtures//354/264/210/352/270/260/355/231/224.xlsx +0 -0
- package/tests/image-insert.spec.ts +190 -0
- package/tests/utils/excel-utils.spec.ts +242 -0
package/README.md
CHANGED
|
@@ -1,532 +1,35 @@
|
|
|
1
1
|
# @simplysm/excel
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
##
|
|
9
|
+
## Source Index
|
|
16
10
|
|
|
17
|
-
###
|
|
11
|
+
### Types and utilities
|
|
18
12
|
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
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
|
-
###
|
|
18
|
+
### Core classes
|
|
28
19
|
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
| `
|
|
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
|
-
###
|
|
28
|
+
### Wrapper classes
|
|
34
29
|
|
|
35
|
-
|
|
|
36
|
-
|
|
37
|
-
| `
|
|
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
|
|
package/dist/excel-cell.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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()`
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
38
|
-
* @param c
|
|
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
|
|
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
|
-
/**
|
|
44
|
+
/** Return cell style ID */
|
|
45
45
|
getStyleId(): Promise<string | undefined>;
|
|
46
|
-
/**
|
|
46
|
+
/** Set cell style ID */
|
|
47
47
|
setStyleId(styleId: string | undefined): Promise<void>;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @param opts
|
|
51
|
-
* @param opts.background
|
|
52
|
-
* @param opts.border
|
|
53
|
-
* @param opts.horizontalAlign
|
|
54
|
-
* @param opts.verticalAlign
|
|
55
|
-
* @param opts.numberFormat
|
|
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;
|
package/dist/excel-cell.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|