@justybase/spreadsheet-tasks 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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/dist/BiffReaderWriter.d.ts +44 -0
  4. package/dist/BiffReaderWriter.d.ts.map +1 -0
  5. package/dist/BiffReaderWriter.js +282 -0
  6. package/dist/BiffReaderWriter.js.map +1 -0
  7. package/dist/BigBuffer.d.ts +24 -0
  8. package/dist/BigBuffer.d.ts.map +1 -0
  9. package/dist/BigBuffer.js +120 -0
  10. package/dist/BigBuffer.js.map +1 -0
  11. package/dist/ExcelReaderAbstract.d.ts +17 -0
  12. package/dist/ExcelReaderAbstract.d.ts.map +1 -0
  13. package/dist/ExcelReaderAbstract.js +25 -0
  14. package/dist/ExcelReaderAbstract.js.map +1 -0
  15. package/dist/ReaderFactory.d.ts +6 -0
  16. package/dist/ReaderFactory.d.ts.map +1 -0
  17. package/dist/ReaderFactory.js +56 -0
  18. package/dist/ReaderFactory.js.map +1 -0
  19. package/dist/XlsbReader.d.ts +24 -0
  20. package/dist/XlsbReader.d.ts.map +1 -0
  21. package/dist/XlsbReader.js +186 -0
  22. package/dist/XlsbReader.js.map +1 -0
  23. package/dist/XlsbWriter.d.ts +69 -0
  24. package/dist/XlsbWriter.d.ts.map +1 -0
  25. package/dist/XlsbWriter.js +802 -0
  26. package/dist/XlsbWriter.js.map +1 -0
  27. package/dist/XlsxReader.d.ts +30 -0
  28. package/dist/XlsxReader.d.ts.map +1 -0
  29. package/dist/XlsxReader.js +341 -0
  30. package/dist/XlsxReader.js.map +1 -0
  31. package/dist/XlsxWriter.d.ts +31 -0
  32. package/dist/XlsxWriter.d.ts.map +1 -0
  33. package/dist/XlsxWriter.js +415 -0
  34. package/dist/XlsxWriter.js.map +1 -0
  35. package/dist/index.d.ts +9 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +23 -0
  38. package/dist/index.js.map +1 -0
  39. package/docs/API.md +271 -0
  40. package/docs/BENCHMARK.md +129 -0
  41. package/docs/PUBLISHING.md +89 -0
  42. package/examples/basic-read.ts +109 -0
  43. package/examples/basic-write.ts +84 -0
  44. package/examples/large-dataset.ts +216 -0
  45. package/examples/multiple-sheets.ts +126 -0
  46. package/examples/streaming-example.ts +181 -0
  47. package/package.json +70 -0
package/docs/API.md ADDED
@@ -0,0 +1,271 @@
1
+ # API Documentation
2
+
3
+ ## Table of Contents
4
+
5
+ - [XlsbWriter](#xlsbwriter)
6
+ - [XlsxWriter](#xlsxwriter)
7
+ - [XlsbReader](#xlsbreader)
8
+ - [XlsxReader](#xlsxreader)
9
+ - [ReaderFactory](#readerfactory)
10
+ - [Types](#types)
11
+
12
+ ---
13
+
14
+ ## XlsbWriter
15
+
16
+ High-performance writer for Excel Binary Workbook (.xlsb) format.
17
+
18
+ ### Constructor
19
+
20
+ ```typescript
21
+ new XlsbWriter(filePath: string)
22
+ ```
23
+
24
+ **Parameters:**
25
+ - `filePath` - Path where the XLSB file will be created
26
+
27
+ **Example:**
28
+ ```typescript
29
+ const writer = new XlsbWriter('output.xlsb');
30
+ ```
31
+
32
+ ### Methods
33
+
34
+ #### `addSheet(sheetName: string, hidden?: boolean): void`
35
+
36
+ Adds a new worksheet to the workbook.
37
+
38
+ **Parameters:**
39
+ - `sheetName` - Name of the worksheet (max 31 characters, invalid characters will be sanitized)
40
+ - `hidden` - Optional. If `true`, the sheet will be hidden (default: `false`)
41
+
42
+ **Example:**
43
+ ```typescript
44
+ writer.addSheet('Sales Data');
45
+ writer.addSheet('Hidden Sheet', true);
46
+ ```
47
+
48
+ #### `writeSheet(rows: any[][], headers?: string[] | null, doAutofilter?: boolean): void`
49
+
50
+ Writes data to the current sheet.
51
+
52
+ **Parameters:**
53
+ - `rows` - 2D array of data to write
54
+ - `headers` - Optional. Array of header strings (if not provided, first row is used as headers)
55
+ - `doAutofilter` - Optional. If `true`, adds autofilter to headers (default: `true`)
56
+
57
+ **Supported Data Types:**
58
+ - `string` - Written as shared string
59
+ - `number` - Written as number (integer or double)
60
+ - `boolean` - Written as boolean
61
+ - `Date` - Written as Excel date serial number
62
+ - `null` / `undefined` - Written as empty cell
63
+
64
+ **Example:**
65
+ ```typescript
66
+ writer.writeSheet([
67
+ ['Product', 'Price', 'Quantity'],
68
+ ['Widget A', 19.99, 100],
69
+ ['Widget B', 29.99, 50]
70
+ ]);
71
+
72
+ // With separate headers
73
+ writer.writeSheet(
74
+ [['Widget A', 19.99, 100], ['Widget B', 29.99, 50]],
75
+ ['Product', 'Price', 'Quantity']
76
+ );
77
+ ```
78
+
79
+ #### `finalize(): Promise<void>`
80
+
81
+ Finalizes and closes the workbook. Must be called after all data is written.
82
+
83
+ **Example:**
84
+ ```typescript
85
+ await writer.finalize();
86
+ ```
87
+
88
+ ---
89
+
90
+ ## XlsxWriter
91
+
92
+ Writer for Excel Open XML Workbook (.xlsx) format. Has the same API as XlsbWriter.
93
+
94
+ ### Constructor
95
+
96
+ ```typescript
97
+ new XlsxWriter(filePath: string)
98
+ ```
99
+
100
+ ### Methods
101
+
102
+ All methods are identical to [XlsbWriter](#xlsbwriter):
103
+ - `addSheet(sheetName: string, hidden?: boolean): void`
104
+ - `writeSheet(rows: any[][], headers?: string[] | null, doAutofilter?: boolean): void`
105
+ - `finalize(): Promise<void>`
106
+
107
+ ---
108
+
109
+ ## XlsbReader
110
+
111
+ High-performance reader for Excel Binary Workbook (.xlsb) format.
112
+
113
+ ### Constructor
114
+
115
+ ```typescript
116
+ new XlsbReader()
117
+ ```
118
+
119
+ ### Properties
120
+
121
+ #### `fieldCount: number`
122
+
123
+ Number of columns in the current row.
124
+
125
+ #### `resultsCount: number`
126
+
127
+ Number of sheets in the workbook.
128
+
129
+ ### Methods
130
+
131
+ #### `open(path: string, readSharedStrings?: boolean): Promise<void>`
132
+
133
+ Opens an XLSB file for reading.
134
+
135
+ **Parameters:**
136
+ - `path` - Path to the XLSB file
137
+ - `readSharedStrings` - Optional. If `true`, reads shared strings table (default: `true`)
138
+
139
+ **Example:**
140
+ ```typescript
141
+ const reader = new XlsbReader();
142
+ await reader.open('data.xlsb');
143
+ ```
144
+
145
+ #### `getSheetNames(): string[]`
146
+
147
+ Returns array of worksheet names.
148
+
149
+ **Example:**
150
+ ```typescript
151
+ const sheets = reader.getSheetNames();
152
+ console.log(sheets); // ['Sheet1', 'Sheet2']
153
+ ```
154
+
155
+ #### `read(): boolean`
156
+
157
+ Reads the next row. Returns `true` if a row was read, `false` if end of sheet reached.
158
+
159
+ **Example:**
160
+ ```typescript
161
+ while (reader.read()) {
162
+ // Process row
163
+ }
164
+ ```
165
+
166
+ #### `getValue(columnIndex: number): any`
167
+
168
+ Gets value at the specified column index in the current row.
169
+
170
+ **Parameters:**
171
+ - `columnIndex` - Zero-based column index
172
+
173
+ **Returns:** Value at the column (string, number, boolean, Date, or null)
174
+
175
+ **Example:**
176
+ ```typescript
177
+ while (reader.read()) {
178
+ const name = reader.getValue(0);
179
+ const age = reader.getValue(1);
180
+ console.log(`${name}: ${age}`);
181
+ }
182
+ ```
183
+
184
+ ---
185
+
186
+ ## XlsxReader
187
+
188
+ Reader for Excel Open XML Workbook (.xlsx) format.
189
+
190
+ ### Constructor
191
+
192
+ ```typescript
193
+ new XlsxReader()
194
+ ```
195
+
196
+ ### Properties
197
+
198
+ Same as [XlsbReader](#xlsbreader):
199
+ - `fieldCount: number`
200
+ - `resultsCount: number`
201
+
202
+ ### Methods
203
+
204
+ #### `open(path: string, readSharedStrings?: boolean): Promise<void>`
205
+
206
+ Opens an XLSX file for reading.
207
+
208
+ #### `close(): Promise<void>`
209
+
210
+ Closes the reader and releases resources.
211
+
212
+ #### `getSheetNames(): string[]`
213
+
214
+ Returns array of worksheet names.
215
+
216
+ #### `read(): Promise<boolean>`
217
+
218
+ Reads the next row. Returns `true` if a row was read.
219
+
220
+ > **Note:** Unlike XlsbReader, this method is async due to the XML parsing nature.
221
+
222
+ #### `getValue(columnIndex: number): any`
223
+
224
+ Gets value at the specified column index.
225
+
226
+ ---
227
+
228
+ ## ReaderFactory
229
+
230
+ Factory class for creating appropriate reader based on file extension.
231
+
232
+ ### Methods
233
+
234
+ #### `static create(filePath: string): XlsbReader | XlsxReader`
235
+
236
+ Creates a reader instance based on file extension.
237
+
238
+ **Parameters:**
239
+ - `filePath` - Path to the Excel file
240
+
241
+ **Returns:** `XlsbReader` for .xlsb files, `XlsxReader` for .xlsx files
242
+
243
+ **Example:**
244
+ ```typescript
245
+ const reader = ReaderFactory.create('data.xlsb');
246
+ await reader.open('data.xlsb');
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Types
252
+
253
+ ### Supported Cell Types
254
+
255
+ | TypeScript Type | Excel Cell Type |
256
+ |-----------------|-----------------|
257
+ | `string` | Shared String |
258
+ | `number` (integer) | RK Number |
259
+ | `number` (float) | Double |
260
+ | `boolean` | Boolean |
261
+ | `Date` | Date Serial Number |
262
+ | `null` / `undefined` | Empty Cell |
263
+
264
+ ### Sheet Name Restrictions
265
+
266
+ Sheet names have the following restrictions:
267
+ - Maximum 31 characters
268
+ - Cannot contain: `\ / * ? [ ] :`
269
+ - Cannot be empty
270
+
271
+ Invalid characters are automatically removed when adding sheets.
@@ -0,0 +1,129 @@
1
+ # Benchmark Results
2
+
3
+ ## Overview
4
+
5
+ This document presents comprehensive benchmark results comparing XlsbWriterNode's XLSB format performance against XLSX format.
6
+
7
+ ## Test Environment
8
+
9
+ - **Platform:** Windows
10
+ - **Node.js:** v20+
11
+ - **Dataset:** 50,000 rows × 5 columns
12
+ - **Iterations:** 20 (for statistical accuracy)
13
+ - **Data Types:** Mixed (strings, numbers, dates)
14
+
15
+ ## Results Summary
16
+
17
+ | Operation | XLSB | XLSX | XLSB Advantage |
18
+ |-----------|------|------|----------------|
19
+ | **Write** | 140.09 ms | 467.14 ms | **3.33x faster** |
20
+ | **Read** | 118.24 ms | 276.23 ms | **2.34x faster** |
21
+ | **File Size** | 1.49 MB | 2.83 MB | **47% smaller** |
22
+
23
+ ## Detailed Results
24
+
25
+ ### Write Performance
26
+
27
+ ```
28
+ XlsbWriter:
29
+ Times: [259.8, 160.6, 134.6, 134.0, 146.1, 136.3, 133.0, 131.7, 146.1, 142.4,
30
+ 135.8, 132.2, 150.2, 140.7, 130.5, 129.3, 142.7, 139.1, 136.2, 195.9] ms
31
+ Average: 140.09 ms (±7.53 ms)
32
+ Size: 1.49 MB
33
+
34
+ XlsxWriter:
35
+ Times: [483.3, 444.1, 471.2, 456.7, 496.0, 529.8, 488.2, 450.9, 458.7, 443.2,
36
+ 495.4, 454.9, 469.6, 493.0, 499.6, 452.0, 463.7, 439.5, 441.1, 453.3] ms
37
+ Average: 467.14 ms (±17.96 ms)
38
+ Size: 2.83 MB
39
+ ```
40
+
41
+ ### Read Performance
42
+
43
+ ```
44
+ XlsbReader:
45
+ Times: [117.8, 136.3, 120.4, 132.1, 119.5, 118.7, 124.1, 113.7, 122.8, 113.8,
46
+ 121.7, 116.3, 121.7, 112.9, 117.0, 110.8, 117.8, 112.2, 121.3, 112.3] ms
47
+ Average: 118.24 ms (±3.56 ms)
48
+
49
+ XlsxReader:
50
+ Times: [290.1, 269.8, 284.1, 268.0, 291.6, 281.8, 266.7, 284.3, 281.1, 257.2,
51
+ 271.6, 260.2, 272.7, 264.5, 290.2, 264.7, 303.2, 265.9, 272.7, 300.1] ms
52
+ Average: 276.23 ms (±9.44 ms)
53
+ ```
54
+
55
+ ## Visual Comparison
56
+
57
+ ### Write Speed (lower is better)
58
+
59
+ ```
60
+ XLSB ██████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 140 ms
61
+ XLSX ████████████████████████████████████████████████ 467 ms
62
+ ```
63
+
64
+ ### Read Speed (lower is better)
65
+
66
+ ```
67
+ XLSB ████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 118 ms
68
+ XLSX ████████████████████████████████████████████████ 276 ms
69
+ ```
70
+
71
+ ### File Size (lower is better)
72
+
73
+ ```
74
+ XLSB ██████████████████████████░░░░░░░░░░░░░░░░░░░░░░ 1.49 MB
75
+ XLSX ████████████████████████████████████████████████ 2.83 MB
76
+ ```
77
+
78
+ ## Why XLSB is Faster
79
+
80
+ ### 1. Binary Format vs XML
81
+
82
+ - **XLSB** stores data in a compact binary format
83
+ - **XLSX** uses XML, which requires parsing/generating text
84
+
85
+ ### 2. Compression Efficiency
86
+
87
+ - XLSB's binary format compresses more efficiently
88
+ - Smaller files = faster I/O operations
89
+
90
+ ### 3. No XML Overhead
91
+
92
+ - No XML tags, attributes, or namespace declarations
93
+ - Direct data encoding reduces processing time
94
+
95
+ ## Running Your Own Benchmarks
96
+
97
+ To run benchmarks on your system:
98
+
99
+ ```bash
100
+ npm run benchmark
101
+ ```
102
+
103
+ Or use the TypeScript file directly:
104
+
105
+ ```bash
106
+ npx ts-node benchmark-our.ts
107
+ ```
108
+
109
+ ## Recommendations
110
+
111
+ | Scenario | Recommended Format |
112
+ |----------|-------------------|
113
+ | **Data processing pipelines** | XLSB |
114
+ | **Backend Excel generation** | XLSB |
115
+ | **Large datasets (>10K rows)** | XLSB |
116
+ | **Storage-constrained environments** | XLSB |
117
+ | **External sharing** | XLSX |
118
+ | **Legacy system compatibility** | XLSX |
119
+ | **Human-readable inspection needed** | XLSX |
120
+
121
+ ## Comparison with Other Libraries
122
+
123
+ While this benchmark focuses on internal format comparison, note that XlsbWriterNode is designed for:
124
+
125
+ - **Minimal dependencies** - Only uses essential zip libraries
126
+ - **Memory efficiency** - Streaming architecture for large files
127
+ - **Type safety** - Full TypeScript support
128
+
129
+ For comparison with external libraries (like ExcelJS, xlsx-populate, etc.), results may vary based on specific use cases and dataset characteristics.
@@ -0,0 +1,89 @@
1
+ # Publishing to npm
2
+
3
+ This document describes how to publish the `@justybase/spreadsheet-tasks` package to npm.
4
+
5
+ ## Automated Publishing (Recommended)
6
+
7
+ The package is automatically published to npm when a new release is created on GitHub.
8
+
9
+ ### Prerequisites
10
+
11
+ 1. Ensure the `NPM_TOKEN` secret is set in the GitHub repository settings
12
+ 2. The token must have publishing permissions for the `@justybase` scope
13
+
14
+ ### Steps
15
+
16
+ 1. Create a new tag: `git tag v1.0.0`
17
+ 2. Push the tag: `git push origin v1.0.0`
18
+ 3. Create a new release on GitHub using the tag
19
+ 4. The publish workflow will automatically run and publish to npm
20
+
21
+ You can also manually trigger the publish workflow from the Actions tab in GitHub.
22
+
23
+ ## Manual Publishing (Fallback)
24
+
25
+ If the automated workflow fails or you need to publish manually:
26
+
27
+ ### Prerequisites
28
+
29
+ 1. You must be logged in to npm: `npm login`
30
+ 2. Your npm account must have access to publish under the `@justybase` scope
31
+ 3. For first-time publishing, you may need to create the scope on npm first
32
+
33
+ ### Steps
34
+
35
+ 1. Build the project:
36
+ ```bash
37
+ npm run build
38
+ ```
39
+
40
+ 2. Run tests to ensure everything works:
41
+ ```bash
42
+ npm test
43
+ ```
44
+
45
+ 3. Publish to npm:
46
+ ```bash
47
+ npm publish --access public
48
+ ```
49
+
50
+ ## First Time Publishing
51
+
52
+ For the first time publishing a scoped package (`@justybase/spreadsheet-tasks`):
53
+
54
+ 1. **Option A**: Create the `@justybase` organization on npm
55
+ - Go to https://www.npmjs.com/
56
+ - Create a new organization named `justybase`
57
+ - Add your npm account as an owner
58
+
59
+ 2. **Option B**: Publish as an unscoped package
60
+ - Update `package.json` to change the name from `@justybase/spreadsheet-tasks` to `justybase-spreadsheet-tasks`
61
+ - This doesn't require an organization
62
+
63
+ 3. **Option C**: Use your personal npm scope
64
+ - Update `package.json` to use your npm username as the scope
65
+ - For example: `@yourusername/spreadsheet-tasks`
66
+
67
+ ## Troubleshooting
68
+
69
+ ### 404 Not Found Error
70
+
71
+ This typically means one of the following:
72
+
73
+ 1. **First time publishing**: The scoped package doesn't exist yet and you need to create the scope/organization on npm
74
+ 2. **Invalid token**: The `NPM_TOKEN` is expired or doesn't have the right permissions
75
+ 3. **Scope access**: You don't have permission to publish under the `@justybase` scope
76
+
77
+ ### Token Expired or Revoked
78
+
79
+ 1. Create a new npm access token at https://www.npmjs.com/settings/[username]/tokens
80
+ 2. Select "Automation" token type
81
+ 3. Copy the token
82
+ 4. Update the `NPM_TOKEN` secret in GitHub repository settings
83
+
84
+ ### Permission Denied
85
+
86
+ Ensure your npm account:
87
+ 1. Has 2FA enabled (required for publishing)
88
+ 2. Is a member of the `@justybase` organization (if using scoped packages)
89
+ 3. Has publishing permissions in the organization settings
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Basic Read Example
3
+ *
4
+ * This example demonstrates how to read data from XLSB and XLSX files
5
+ * using spreadsheet-tasks.
6
+ *
7
+ * Run with: npx ts-node examples/basic-read.ts
8
+ */
9
+
10
+ import { XlsbReader, XlsxReader, ReaderFactory } from '../dist';
11
+ import * as path from 'path';
12
+
13
+ async function readXlsbExample() {
14
+ console.log('=== Reading XLSB file ===\n');
15
+
16
+ const filePath = path.join(__dirname, 'output', 'basic.xlsb');
17
+
18
+ const reader = new XlsbReader();
19
+ await reader.open(filePath);
20
+
21
+ // Get sheet names
22
+ const sheetNames = reader.getSheetNames();
23
+ console.log('Sheet names:', sheetNames);
24
+ console.log('Number of sheets:', reader.resultsCount);
25
+ console.log('');
26
+
27
+ // Read all rows
28
+ let rowCount = 0;
29
+ while (reader.read()) {
30
+ const row: any[] = [];
31
+ for (let i = 0; i < reader.fieldCount; i++) {
32
+ row.push(reader.getValue(i));
33
+ }
34
+
35
+ if (rowCount === 0) {
36
+ console.log('Headers:', row);
37
+ } else {
38
+ console.log(`Row ${rowCount}:`, row);
39
+ }
40
+ rowCount++;
41
+ }
42
+
43
+ console.log(`\nTotal rows read: ${rowCount}\n`);
44
+ }
45
+
46
+ async function readXlsxExample() {
47
+ console.log('=== Reading XLSX file ===\n');
48
+
49
+ const filePath = path.join(__dirname, 'output', 'basic.xlsx');
50
+
51
+ const reader = new XlsxReader();
52
+ await reader.open(filePath);
53
+
54
+ // Get sheet names
55
+ const sheetNames = reader.getSheetNames();
56
+ console.log('Sheet names:', sheetNames);
57
+ console.log('');
58
+
59
+ // Read all rows
60
+ let rowCount = 0;
61
+ while (await reader.read()) {
62
+ const row: any[] = [];
63
+ for (let i = 0; i < reader.fieldCount; i++) {
64
+ row.push(reader.getValue(i));
65
+ }
66
+
67
+ if (rowCount === 0) {
68
+ console.log('Headers:', row);
69
+ } else {
70
+ console.log(`Row ${rowCount}:`, row);
71
+ }
72
+ rowCount++;
73
+ }
74
+
75
+ await reader.close();
76
+ console.log(`\nTotal rows read: ${rowCount}\n`);
77
+ }
78
+
79
+ async function useReaderFactory() {
80
+ console.log('=== Using ReaderFactory ===\n');
81
+
82
+ // ReaderFactory automatically selects the right reader based on file extension
83
+ const xlsbPath = path.join(__dirname, 'output', 'basic.xlsb');
84
+ const xlsxPath = path.join(__dirname, 'output', 'basic.xlsx');
85
+
86
+ // Read XLSB using factory
87
+ const xlsbReader = ReaderFactory.create(xlsbPath);
88
+ console.log('Reader for .xlsb:', xlsbReader.constructor.name);
89
+
90
+ // Read XLSX using factory
91
+ const xlsxReader = ReaderFactory.create(xlsxPath);
92
+ console.log('Reader for .xlsx:', xlsxReader.constructor.name);
93
+ }
94
+
95
+ async function main() {
96
+ try {
97
+ // Make sure to run basic-write.ts first to create the files
98
+ await readXlsbExample();
99
+ await readXlsxExample();
100
+ useReaderFactory();
101
+
102
+ console.log('\nAll files read successfully!');
103
+ } catch (error) {
104
+ console.error('Error:', error);
105
+ console.log('\nNote: Make sure to run basic-write.ts first to create the sample files.');
106
+ }
107
+ }
108
+
109
+ main();
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Basic Write Example
3
+ *
4
+ * This example demonstrates how to write data to XLSB and XLSX files
5
+ * using spreadsheet-tasks.
6
+ *
7
+ * Run with: npx ts-node examples/basic-write.ts
8
+ */
9
+
10
+ import { XlsbWriter, XlsxWriter } from '../dist';
11
+ import * as path from 'path';
12
+ import * as fs from 'fs';
13
+
14
+ // Ensure output directory exists
15
+ const outputDir = path.join(__dirname, 'output');
16
+ if (!fs.existsSync(outputDir)) {
17
+ fs.mkdirSync(outputDir, { recursive: true });
18
+ }
19
+
20
+ async function writeXlsbExample() {
21
+ console.log('Writing XLSB file...');
22
+
23
+ const filePath = path.join(outputDir, 'basic.xlsb');
24
+ const writer = new XlsbWriter(filePath);
25
+
26
+ // Add a sheet
27
+ writer.addSheet('Employees');
28
+
29
+ // Write data with headers
30
+ const data = [
31
+ ['Name', 'Department', 'Salary', 'Start Date', 'Active'],
32
+ ['Alice Johnson', 'Engineering', 85000, new Date('2020-03-15'), true],
33
+ ['Bob Smith', 'Marketing', 65000, new Date('2019-07-01'), true],
34
+ ['Charlie Brown', 'Sales', 72000, new Date('2021-01-10'), false],
35
+ ['Diana Ross', 'Engineering', 95000, new Date('2018-11-20'), true],
36
+ ['Eve Williams', 'HR', 55000, new Date('2022-05-05'), true],
37
+ ];
38
+
39
+ writer.writeSheet(data);
40
+
41
+ // Finalize the file
42
+ await writer.finalize();
43
+
44
+ console.log(`XLSB file created: ${filePath}`);
45
+ }
46
+
47
+ async function writeXlsxExample() {
48
+ console.log('Writing XLSX file...');
49
+
50
+ const filePath = path.join(outputDir, 'basic.xlsx');
51
+ const writer = new XlsxWriter(filePath);
52
+
53
+ // Add a sheet
54
+ writer.addSheet('Products');
55
+
56
+ // Write data - using separate headers parameter
57
+ const headers = ['Product ID', 'Name', 'Price', 'Quantity', 'In Stock'];
58
+ const data = [
59
+ ['P001', 'Widget A', 19.99, 150, true],
60
+ ['P002', 'Widget B', 29.99, 75, true],
61
+ ['P003', 'Gadget X', 49.99, 0, false],
62
+ ['P004', 'Gadget Y', 39.99, 200, true],
63
+ ['P005', 'Tool Z', 9.99, 500, true],
64
+ ];
65
+
66
+ writer.writeSheet(data, headers);
67
+
68
+ // Finalize the file
69
+ await writer.finalize();
70
+
71
+ console.log(`XLSX file created: ${filePath}`);
72
+ }
73
+
74
+ async function main() {
75
+ try {
76
+ await writeXlsbExample();
77
+ await writeXlsxExample();
78
+ console.log('\nAll files created successfully!');
79
+ } catch (error) {
80
+ console.error('Error:', error);
81
+ }
82
+ }
83
+
84
+ main();