tinyweb-office-cells 1.0.0
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/LICENSE +21 -0
- package/README.md +615 -0
- package/dist/index.d.mts +2084 -0
- package/dist/index.d.ts +2084 -0
- package/dist/index.js +8874 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8868 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 aspose-cells-node contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
# tinyweb-cells
|
|
2
|
+
|
|
3
|
+
> Open-source Node.js/TypeScript library for reading, writing, and manipulating Excel XLSX files with full formatting, formula evaluation, and Aspose Cells-compatible API.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/tinyweb-cells)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ✅ **Read/Write XLSX files** — full round-trip fidelity (preserves unmodified XML)
|
|
11
|
+
- ✅ **Cell formatting** — fonts, colors, borders, fills, number formats, alignment
|
|
12
|
+
- ✅ **Merge cells** — column widths, row heights
|
|
13
|
+
- ✅ **Formula evaluation** — 43 built-in Excel functions
|
|
14
|
+
- ✅ **Data validation** — dropdown lists, numeric ranges, date ranges, custom formulas
|
|
15
|
+
- ✅ **Conditional formatting** — cell value rules, color scales, data bars, formulas
|
|
16
|
+
- ✅ **Named ranges** — workbook and sheet-scoped defined names
|
|
17
|
+
- ✅ **Hyperlinks** — external URLs, internal sheet references, email links
|
|
18
|
+
- ✅ **Comments** — cell comments with author and size support
|
|
19
|
+
- ✅ **AutoFilter** — column filters with custom, color, dynamic, and top-10 filters
|
|
20
|
+
- ✅ **Page breaks** — horizontal and vertical page break management
|
|
21
|
+
- ✅ **Sheet/workbook protection** — password-based protection with granular permissions
|
|
22
|
+
- ✅ **Document properties** — title, author, subject, keywords, and custom properties
|
|
23
|
+
- ✅ **Page setup** — orientation, paper size, margins, print area, headers/footers
|
|
24
|
+
- ✅ **Freeze panes** — freeze rows and columns
|
|
25
|
+
- ✅ **Dual API naming** — both `camelCase` and `snake_case` method names
|
|
26
|
+
- ✅ **TypeScript-first** — full type declarations included
|
|
27
|
+
- ✅ **Zero native dependencies** — pure JavaScript, works everywhere Node.js runs
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install tinyweb-cells
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Create a Workbook and Save
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { Workbook, SaveFormat } from 'tinyweb-cells';
|
|
41
|
+
|
|
42
|
+
// Create a new workbook
|
|
43
|
+
const workbook = new Workbook();
|
|
44
|
+
const sheet = workbook.worksheets.get(0);
|
|
45
|
+
|
|
46
|
+
// Set cell values
|
|
47
|
+
sheet.cells.get('A1').putValue('Name');
|
|
48
|
+
sheet.cells.get('B1').putValue('Score');
|
|
49
|
+
sheet.cells.get('A2').putValue('Alice');
|
|
50
|
+
sheet.cells.get('B2').putValue(95);
|
|
51
|
+
sheet.cells.get('A3').putValue('Bob');
|
|
52
|
+
sheet.cells.get('B3').putValue(87);
|
|
53
|
+
|
|
54
|
+
// Add a formula
|
|
55
|
+
sheet.cells.get('B4').setFormula('=SUM(B2:B3)');
|
|
56
|
+
|
|
57
|
+
// Save to file
|
|
58
|
+
await workbook.save('output.xlsx');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Read an Existing File
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { Workbook } from 'tinyweb-cells';
|
|
65
|
+
|
|
66
|
+
const workbook = new Workbook();
|
|
67
|
+
await workbook.loadFile('input.xlsx');
|
|
68
|
+
|
|
69
|
+
const sheet = workbook.worksheets.get(0);
|
|
70
|
+
console.log(sheet.cells.get('A1').value); // Read cell value
|
|
71
|
+
console.log(sheet.name); // Sheet name
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Apply Formatting
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Workbook } from 'tinyweb-cells';
|
|
78
|
+
|
|
79
|
+
const workbook = new Workbook();
|
|
80
|
+
const sheet = workbook.worksheets.get(0);
|
|
81
|
+
const cell = sheet.cells.get('A1');
|
|
82
|
+
cell.putValue('Hello, Excel!');
|
|
83
|
+
|
|
84
|
+
// Get cell style and modify
|
|
85
|
+
const style = cell.getStyle();
|
|
86
|
+
style.font.name = 'Arial';
|
|
87
|
+
style.font.size = 14;
|
|
88
|
+
style.font.bold = true;
|
|
89
|
+
style.font.color = '#FF0000';
|
|
90
|
+
style.fill.patternType = 'solid';
|
|
91
|
+
style.fill.fgColor = '#FFFF00';
|
|
92
|
+
style.borders.top.lineStyle = 'thin';
|
|
93
|
+
style.borders.top.color = '#000000';
|
|
94
|
+
style.alignment.horizontal = 'center';
|
|
95
|
+
cell.setStyle(style);
|
|
96
|
+
|
|
97
|
+
await workbook.save('formatted.xlsx');
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API Reference
|
|
101
|
+
|
|
102
|
+
### Workbook
|
|
103
|
+
|
|
104
|
+
The main entry point for creating and manipulating Excel files.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const workbook = new Workbook();
|
|
108
|
+
|
|
109
|
+
// Load from file
|
|
110
|
+
await workbook.loadFile('path/to/file.xlsx');
|
|
111
|
+
|
|
112
|
+
// Load from buffer
|
|
113
|
+
await workbook.loadBuffer(buffer);
|
|
114
|
+
|
|
115
|
+
// Save to file
|
|
116
|
+
await workbook.save('output.xlsx');
|
|
117
|
+
await workbook.save('output.xlsx', SaveFormat.XLSX);
|
|
118
|
+
|
|
119
|
+
// Save to buffer
|
|
120
|
+
const buffer = await workbook.saveToBuffer(SaveFormat.XLSX);
|
|
121
|
+
|
|
122
|
+
// Access worksheets
|
|
123
|
+
workbook.worksheets; // WorksheetCollection
|
|
124
|
+
workbook.worksheets.get(0); // By index
|
|
125
|
+
workbook.worksheets.get('Sheet1'); // By name
|
|
126
|
+
workbook.worksheets.add('NewSheet');
|
|
127
|
+
|
|
128
|
+
// Workbook protection
|
|
129
|
+
workbook.properties.protection.lockStructure = true;
|
|
130
|
+
workbook.properties.protection.password = 'secret';
|
|
131
|
+
|
|
132
|
+
// Document properties
|
|
133
|
+
workbook.documentProperties.title = 'My Report';
|
|
134
|
+
workbook.documentProperties.author = 'John Doe';
|
|
135
|
+
workbook.documentProperties.subject = 'Q4 Sales';
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Worksheet
|
|
139
|
+
|
|
140
|
+
Represents a single sheet in the workbook.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const sheet = workbook.worksheets.get(0);
|
|
144
|
+
|
|
145
|
+
// Properties
|
|
146
|
+
sheet.name = 'DataSheet';
|
|
147
|
+
sheet.isVisible = true;
|
|
148
|
+
sheet.tabColor = '#FF0000';
|
|
149
|
+
|
|
150
|
+
// Cells
|
|
151
|
+
sheet.cells.get('A1').putValue('Hello');
|
|
152
|
+
|
|
153
|
+
// Merge cells
|
|
154
|
+
sheet.cells.merge(0, 0, 2, 3); // startRow, startCol, rowCount, colCount
|
|
155
|
+
|
|
156
|
+
// Column width and row height
|
|
157
|
+
sheet.cells.setColumnWidth(0, 20); // Column A = 20
|
|
158
|
+
sheet.cells.setRowHeight(0, 30); // Row 1 = 30
|
|
159
|
+
|
|
160
|
+
// Freeze panes
|
|
161
|
+
sheet.freezePanes(1, 0); // Freeze first row
|
|
162
|
+
|
|
163
|
+
// Page setup
|
|
164
|
+
sheet.pageSetup.orientation = 'landscape';
|
|
165
|
+
sheet.pageSetup.paperSize = 'A4';
|
|
166
|
+
|
|
167
|
+
// Sheet protection
|
|
168
|
+
sheet.protect('password');
|
|
169
|
+
sheet.protection.sheet = true;
|
|
170
|
+
sheet.protection.formatCells = false;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Cell / Cells
|
|
174
|
+
|
|
175
|
+
Access and manipulate individual cells.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const cells = sheet.cells;
|
|
179
|
+
|
|
180
|
+
// Get a cell (creates if not exists)
|
|
181
|
+
const cell = cells.get('A1');
|
|
182
|
+
// Also supports: cells.get(0, 0)
|
|
183
|
+
|
|
184
|
+
// Set values
|
|
185
|
+
cell.putValue('text'); // String
|
|
186
|
+
cell.putValue(42); // Number
|
|
187
|
+
cell.putValue(true); // Boolean
|
|
188
|
+
cell.putValue(new Date()); // Date
|
|
189
|
+
|
|
190
|
+
// Read values
|
|
191
|
+
cell.value; // Raw value
|
|
192
|
+
cell.stringValue; // String representation
|
|
193
|
+
cell.type; // CellDataType
|
|
194
|
+
|
|
195
|
+
// Formulas
|
|
196
|
+
cell.setFormula('=SUM(A1:A10)');
|
|
197
|
+
cell.formula; // Get formula string
|
|
198
|
+
cell.hasFormula(); // Check if cell has formula
|
|
199
|
+
|
|
200
|
+
// Styling
|
|
201
|
+
const style = cell.getStyle();
|
|
202
|
+
style.font.bold = true;
|
|
203
|
+
cell.setStyle(style);
|
|
204
|
+
|
|
205
|
+
// Comments
|
|
206
|
+
cell.comment = { text: 'Note', author: 'Admin' };
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Style (Font, Fill, Borders, Alignment, NumberFormat)
|
|
210
|
+
|
|
211
|
+
Full cell formatting support.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const style = cell.getStyle();
|
|
215
|
+
|
|
216
|
+
// Font
|
|
217
|
+
style.font.name = 'Calibri';
|
|
218
|
+
style.font.size = 12;
|
|
219
|
+
style.font.bold = true;
|
|
220
|
+
style.font.italic = true;
|
|
221
|
+
style.font.underline = 'single';
|
|
222
|
+
style.font.strikethrough = true;
|
|
223
|
+
style.font.color = '#0000FF';
|
|
224
|
+
|
|
225
|
+
// Fill
|
|
226
|
+
style.fill.patternType = 'solid';
|
|
227
|
+
style.fill.fgColor = '#FFFF00';
|
|
228
|
+
style.fill.bgColor = '#FFFFFF';
|
|
229
|
+
|
|
230
|
+
// Borders
|
|
231
|
+
style.borders.top.lineStyle = 'thin'; // thin, medium, thick, dashed, dotted, double
|
|
232
|
+
style.borders.top.color = '#000000';
|
|
233
|
+
style.borders.bottom.lineStyle = 'double';
|
|
234
|
+
style.borders.left.lineStyle = 'medium';
|
|
235
|
+
style.borders.right.lineStyle = 'thin';
|
|
236
|
+
style.borders.diagonal.lineStyle = 'thin';
|
|
237
|
+
|
|
238
|
+
// Alignment
|
|
239
|
+
style.alignment.horizontal = 'center'; // left, center, right, fill, justify
|
|
240
|
+
style.alignment.vertical = 'center'; // top, center, bottom
|
|
241
|
+
style.alignment.wrapText = true;
|
|
242
|
+
style.alignment.textRotation = 45;
|
|
243
|
+
style.alignment.indent = 2;
|
|
244
|
+
style.alignment.shrinkToFit = true;
|
|
245
|
+
|
|
246
|
+
// Number format
|
|
247
|
+
style.numberFormat.formatCode = '#,##0.00';
|
|
248
|
+
style.numberFormat.formatCode = '0.00%';
|
|
249
|
+
style.numberFormat.formatCode = 'yyyy-mm-dd';
|
|
250
|
+
style.numberFormat.formatCode = '$#,##0.00';
|
|
251
|
+
|
|
252
|
+
// Protection
|
|
253
|
+
style.protection.locked = true;
|
|
254
|
+
style.protection.hidden = true;
|
|
255
|
+
|
|
256
|
+
cell.setStyle(style);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### FormulaEvaluator
|
|
260
|
+
|
|
261
|
+
Evaluate formulas in cells.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { FormulaEvaluator } from 'tinyweb-cells';
|
|
265
|
+
|
|
266
|
+
// Set up formulas
|
|
267
|
+
sheet.cells.get('A1').putValue(10);
|
|
268
|
+
sheet.cells.get('A2').putValue(20);
|
|
269
|
+
sheet.cells.get('A3').setFormula('=SUM(A1:A2)');
|
|
270
|
+
|
|
271
|
+
// Evaluate all formulas
|
|
272
|
+
const evaluator = new FormulaEvaluator(workbook);
|
|
273
|
+
evaluator.evaluateAll();
|
|
274
|
+
|
|
275
|
+
console.log(sheet.cells.get('A3').value); // 30
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Data Validation
|
|
279
|
+
|
|
280
|
+
Add data validation rules to cells.
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { DataValidation, DataValidationType, DataValidationOperator } from 'tinyweb-cells';
|
|
284
|
+
|
|
285
|
+
const validations = sheet.dataValidations;
|
|
286
|
+
|
|
287
|
+
// Dropdown list
|
|
288
|
+
const dv = validations.add();
|
|
289
|
+
dv.sqref = 'A1:A10';
|
|
290
|
+
dv.type = DataValidationType.LIST;
|
|
291
|
+
dv.formula1 = '"Apple,Banana,Cherry"';
|
|
292
|
+
|
|
293
|
+
// Numeric range
|
|
294
|
+
const numDv = validations.add();
|
|
295
|
+
numDv.sqref = 'B1:B10';
|
|
296
|
+
numDv.type = DataValidationType.WHOLE;
|
|
297
|
+
numDv.operator = DataValidationOperator.BETWEEN;
|
|
298
|
+
numDv.formula1 = '1';
|
|
299
|
+
numDv.formula2 = '100';
|
|
300
|
+
numDv.showErrorMessage = true;
|
|
301
|
+
numDv.errorTitle = 'Invalid Input';
|
|
302
|
+
numDv.error = 'Please enter a number between 1 and 100';
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Conditional Formatting
|
|
306
|
+
|
|
307
|
+
Apply conditional formatting rules.
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
const cfCollection = sheet.conditionalFormattings;
|
|
311
|
+
|
|
312
|
+
// Cell value rule
|
|
313
|
+
const cf = cfCollection.add();
|
|
314
|
+
cf.sqref = 'A1:A20';
|
|
315
|
+
cf.type = 'cellIs';
|
|
316
|
+
cf.operator = 'greaterThan';
|
|
317
|
+
cf.formula1 = '90';
|
|
318
|
+
cf.priority = 1;
|
|
319
|
+
cf.dxf = {
|
|
320
|
+
font: { color: '#006100' },
|
|
321
|
+
fill: { bgColor: '#C6EFCE' },
|
|
322
|
+
};
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Hyperlinks
|
|
326
|
+
|
|
327
|
+
Add hyperlinks to cells.
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
const hyperlinks = sheet.hyperlinks;
|
|
331
|
+
|
|
332
|
+
// External URL
|
|
333
|
+
hyperlinks.add('A1', 1, 1, 'https://example.com');
|
|
334
|
+
const link = hyperlinks.get(0);
|
|
335
|
+
link.textToDisplay = 'Visit Example';
|
|
336
|
+
link.screenTip = 'Click to open';
|
|
337
|
+
|
|
338
|
+
// Internal reference
|
|
339
|
+
hyperlinks.add('A2', 1, 1, '#Sheet2!A1');
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Named Ranges
|
|
343
|
+
|
|
344
|
+
Define and use named ranges.
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
// Add a defined name
|
|
348
|
+
workbook.definedNames.add('SalesData', 'Sheet1!$A$1:$D$100');
|
|
349
|
+
workbook.definedNames.add('TaxRate', '0.08');
|
|
350
|
+
|
|
351
|
+
// Use in formulas
|
|
352
|
+
sheet.cells.get('E1').setFormula('=SUM(SalesData)');
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### AutoFilter
|
|
356
|
+
|
|
357
|
+
Apply auto-filtering to data ranges.
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const autoFilter = sheet.autoFilter;
|
|
361
|
+
autoFilter.range = 'A1:D100';
|
|
362
|
+
|
|
363
|
+
// Add a filter column
|
|
364
|
+
const fc = autoFilter.addFilterColumn(0);
|
|
365
|
+
fc.setValues(['Active', 'Pending']);
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Comments
|
|
369
|
+
|
|
370
|
+
Add comments to cells.
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
const cell = sheet.cells.get('A1');
|
|
374
|
+
cell.comment = {
|
|
375
|
+
text: 'This is a comment',
|
|
376
|
+
author: 'Admin',
|
|
377
|
+
width: 200,
|
|
378
|
+
height: 100,
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Page Setup
|
|
383
|
+
|
|
384
|
+
Configure print settings.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
sheet.pageSetup.orientation = 'landscape';
|
|
388
|
+
sheet.pageSetup.paperSize = 'A4';
|
|
389
|
+
sheet.pageSetup.printArea = 'A1:H50';
|
|
390
|
+
sheet.pageSetup.fitToPagesTall = 1;
|
|
391
|
+
sheet.pageSetup.fitToPagesWide = 1;
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Formula Support
|
|
395
|
+
|
|
396
|
+
The built-in formula evaluator supports **43 Excel functions** across 7 categories:
|
|
397
|
+
|
|
398
|
+
### Math & Statistics (16 functions)
|
|
399
|
+
`SUM` · `AVERAGE` · `MIN` · `MAX` · `COUNT` · `COUNTA` · `ABS` · `ROUND` · `ROUNDUP` · `ROUNDDOWN` · `INT` · `MOD` · `POWER` · `SQRT` · `CEILING` · `FLOOR`
|
|
400
|
+
|
|
401
|
+
### String Functions (11 functions)
|
|
402
|
+
`CONCATENATE` · `CONCAT` · `TEXT` · `LEN` · `TRIM` · `UPPER` · `LOWER` · `LEFT` · `RIGHT` · `MID` · `SUBSTITUTE` · `REPT`
|
|
403
|
+
|
|
404
|
+
### Logic Functions (4 functions)
|
|
405
|
+
`IF` · `AND` · `OR` · `NOT`
|
|
406
|
+
|
|
407
|
+
### Lookup & Reference (4 functions)
|
|
408
|
+
`VLOOKUP` · `HLOOKUP` · `INDEX` · `MATCH`
|
|
409
|
+
|
|
410
|
+
### Date & Time (6 functions)
|
|
411
|
+
`TODAY` · `NOW` · `DATE` · `YEAR` · `MONTH` · `DAY`
|
|
412
|
+
|
|
413
|
+
### Information Functions (5 functions)
|
|
414
|
+
`ISNUMBER` · `ISTEXT` · `ISBLANK` · `ISERROR` · `ISNA`
|
|
415
|
+
|
|
416
|
+
### Other Functions (2 functions)
|
|
417
|
+
`VALUE` · `CHOOSE`
|
|
418
|
+
|
|
419
|
+
### Also Supports
|
|
420
|
+
- Arithmetic operators: `+` `-` `*` `/` `^`
|
|
421
|
+
- Comparison operators: `=` `<>` `<` `>` `<=` `>=`
|
|
422
|
+
- String concatenation: `&`
|
|
423
|
+
- Cell references: `A1`, `$A$1`, `Sheet1!A1`
|
|
424
|
+
- Range references: `A1:B5`
|
|
425
|
+
- Defined names / named ranges
|
|
426
|
+
- Nested formulas with recursive evaluation
|
|
427
|
+
- Error values: `#VALUE!`, `#REF!`, `#NAME?`, `#DIV/0!`, `#N/A`
|
|
428
|
+
|
|
429
|
+
## Examples
|
|
430
|
+
|
|
431
|
+
### Create and Save a Workbook
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import { Workbook } from 'tinyweb-cells';
|
|
435
|
+
|
|
436
|
+
const wb = new Workbook();
|
|
437
|
+
const ws = wb.worksheets.get(0);
|
|
438
|
+
ws.name = 'Sales Report';
|
|
439
|
+
|
|
440
|
+
// Headers
|
|
441
|
+
['Product', 'Q1', 'Q2', 'Q3', 'Q4', 'Total'].forEach((h, i) => {
|
|
442
|
+
const cell = ws.cells.get(0, i);
|
|
443
|
+
cell.putValue(h);
|
|
444
|
+
const style = cell.getStyle();
|
|
445
|
+
style.font.bold = true;
|
|
446
|
+
style.fill.patternType = 'solid';
|
|
447
|
+
style.fill.fgColor = '#4472C4';
|
|
448
|
+
style.font.color = '#FFFFFF';
|
|
449
|
+
cell.setStyle(style);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// Data
|
|
453
|
+
const data = [
|
|
454
|
+
['Widget A', 1200, 1350, 1100, 1500],
|
|
455
|
+
['Widget B', 800, 920, 870, 1050],
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
data.forEach((row, r) => {
|
|
459
|
+
row.forEach((val, c) => {
|
|
460
|
+
ws.cells.get(r + 1, c).putValue(val);
|
|
461
|
+
});
|
|
462
|
+
// Total formula
|
|
463
|
+
ws.cells.get(r + 1, 5).setFormula(`=SUM(B${r + 2}:E${r + 2})`);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
await wb.save('sales-report.xlsx');
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Read and Modify an Existing File
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { Workbook } from 'tinyweb-cells';
|
|
473
|
+
|
|
474
|
+
const wb = new Workbook();
|
|
475
|
+
await wb.loadFile('existing.xlsx');
|
|
476
|
+
|
|
477
|
+
const ws = wb.worksheets.get(0);
|
|
478
|
+
|
|
479
|
+
// Read all data
|
|
480
|
+
for (let r = 0; r < 100; r++) {
|
|
481
|
+
for (let c = 0; c < 10; c++) {
|
|
482
|
+
const cell = ws.cells.get(r, c);
|
|
483
|
+
if (cell.value !== null) {
|
|
484
|
+
console.log(`${cell.name}: ${cell.value}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Modify a cell
|
|
490
|
+
ws.cells.get('A1').putValue('Updated!');
|
|
491
|
+
await wb.save('modified.xlsx');
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Data Validation with Dropdown
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
import { Workbook, DataValidationType } from 'tinyweb-cells';
|
|
498
|
+
|
|
499
|
+
const wb = new Workbook();
|
|
500
|
+
const ws = wb.worksheets.get(0);
|
|
501
|
+
|
|
502
|
+
ws.cells.get('A1').putValue('Select a fruit:');
|
|
503
|
+
|
|
504
|
+
const dv = ws.dataValidations.add();
|
|
505
|
+
dv.sqref = 'B1';
|
|
506
|
+
dv.type = DataValidationType.LIST;
|
|
507
|
+
dv.formula1 = '"Apple,Banana,Cherry,Date,Elderberry"';
|
|
508
|
+
dv.showDropDown = true;
|
|
509
|
+
dv.showInputMessage = true;
|
|
510
|
+
dv.inputTitle = 'Fruit Selection';
|
|
511
|
+
dv.inputMessage = 'Choose a fruit from the list';
|
|
512
|
+
|
|
513
|
+
await wb.save('dropdown.xlsx');
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Conditional Formatting
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
import { Workbook } from 'tinyweb-cells';
|
|
520
|
+
|
|
521
|
+
const wb = new Workbook();
|
|
522
|
+
const ws = wb.worksheets.get(0);
|
|
523
|
+
|
|
524
|
+
// Add some scores
|
|
525
|
+
for (let i = 0; i < 20; i++) {
|
|
526
|
+
ws.cells.get(i, 0).putValue(Math.floor(Math.random() * 100));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Highlight scores above 80 in green
|
|
530
|
+
const cf = ws.conditionalFormattings.add();
|
|
531
|
+
cf.sqref = 'A1:A20';
|
|
532
|
+
cf.type = 'cellIs';
|
|
533
|
+
cf.operator = 'greaterThanOrEqual';
|
|
534
|
+
cf.formula1 = '80';
|
|
535
|
+
cf.dxf = {
|
|
536
|
+
fill: { bgColor: '#C6EFCE' },
|
|
537
|
+
font: { color: '#006100' },
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
await wb.save('conditional.xlsx');
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
## API Compatibility
|
|
544
|
+
|
|
545
|
+
This library provides **dual naming conventions** for maximum compatibility:
|
|
546
|
+
|
|
547
|
+
| camelCase (TypeScript) | snake_case (Python-compat) |
|
|
548
|
+
|---|---|
|
|
549
|
+
| `cell.putValue(v)` | `cell.put_value(v)` |
|
|
550
|
+
| `cell.getStyle()` | `cell.get_style()` |
|
|
551
|
+
| `cell.setStyle(s)` | `cell.set_style(s)` |
|
|
552
|
+
| `cell.hasFormula()` | `cell.has_formula()` |
|
|
553
|
+
| `cell.setFormula(f)` | `cell.set_formula(f)` |
|
|
554
|
+
| `cell.stringValue` | `cell.string_value` |
|
|
555
|
+
| `cells.setColumnWidth()` | `cells.set_column_width()` |
|
|
556
|
+
| `cells.setRowHeight()` | `cells.set_row_height()` |
|
|
557
|
+
| `workbook.loadFile()` | `workbook.load_file()` |
|
|
558
|
+
| `workbook.saveToBuffer()` | `workbook.save_to_buffer()` |
|
|
559
|
+
|
|
560
|
+
Both naming styles work identically — use whichever fits your codebase.
|
|
561
|
+
|
|
562
|
+
## TypeScript
|
|
563
|
+
|
|
564
|
+
Full TypeScript declarations are included. All classes, interfaces, enums, and types are exported:
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
import {
|
|
568
|
+
Workbook,
|
|
569
|
+
Worksheet,
|
|
570
|
+
Cell,
|
|
571
|
+
Cells,
|
|
572
|
+
Style,
|
|
573
|
+
Font,
|
|
574
|
+
Fill,
|
|
575
|
+
Border,
|
|
576
|
+
Borders,
|
|
577
|
+
Alignment,
|
|
578
|
+
NumberFormat,
|
|
579
|
+
Protection,
|
|
580
|
+
SaveFormat,
|
|
581
|
+
FormulaEvaluator,
|
|
582
|
+
DataValidation,
|
|
583
|
+
DataValidationCollection,
|
|
584
|
+
DataValidationType,
|
|
585
|
+
DataValidationOperator,
|
|
586
|
+
ConditionalFormat,
|
|
587
|
+
ConditionalFormatCollection,
|
|
588
|
+
Hyperlink,
|
|
589
|
+
HyperlinkCollection,
|
|
590
|
+
AutoFilter,
|
|
591
|
+
FilterColumn,
|
|
592
|
+
DefinedName,
|
|
593
|
+
DefinedNameCollection,
|
|
594
|
+
HorizontalPageBreakCollection,
|
|
595
|
+
VerticalPageBreakCollection,
|
|
596
|
+
SheetProtection,
|
|
597
|
+
PageSetup,
|
|
598
|
+
FreezePane,
|
|
599
|
+
WorkbookProtection,
|
|
600
|
+
DocumentProperties,
|
|
601
|
+
} from 'tinyweb-cells';
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
## Dependencies
|
|
605
|
+
|
|
606
|
+
| Package | Purpose |
|
|
607
|
+
|---|---|
|
|
608
|
+
| [jszip](https://www.npmjs.com/package/jszip) | XLSX ZIP container read/write |
|
|
609
|
+
| [fast-xml-parser](https://www.npmjs.com/package/fast-xml-parser) | XML parsing and generation |
|
|
610
|
+
|
|
611
|
+
No native/binary dependencies — works on any platform where Node.js runs.
|
|
612
|
+
|
|
613
|
+
## License
|
|
614
|
+
|
|
615
|
+
[MIT](./LICENSE)
|