@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.
- package/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/BiffReaderWriter.d.ts +44 -0
- package/dist/BiffReaderWriter.d.ts.map +1 -0
- package/dist/BiffReaderWriter.js +282 -0
- package/dist/BiffReaderWriter.js.map +1 -0
- package/dist/BigBuffer.d.ts +24 -0
- package/dist/BigBuffer.d.ts.map +1 -0
- package/dist/BigBuffer.js +120 -0
- package/dist/BigBuffer.js.map +1 -0
- package/dist/ExcelReaderAbstract.d.ts +17 -0
- package/dist/ExcelReaderAbstract.d.ts.map +1 -0
- package/dist/ExcelReaderAbstract.js +25 -0
- package/dist/ExcelReaderAbstract.js.map +1 -0
- package/dist/ReaderFactory.d.ts +6 -0
- package/dist/ReaderFactory.d.ts.map +1 -0
- package/dist/ReaderFactory.js +56 -0
- package/dist/ReaderFactory.js.map +1 -0
- package/dist/XlsbReader.d.ts +24 -0
- package/dist/XlsbReader.d.ts.map +1 -0
- package/dist/XlsbReader.js +186 -0
- package/dist/XlsbReader.js.map +1 -0
- package/dist/XlsbWriter.d.ts +69 -0
- package/dist/XlsbWriter.d.ts.map +1 -0
- package/dist/XlsbWriter.js +802 -0
- package/dist/XlsbWriter.js.map +1 -0
- package/dist/XlsxReader.d.ts +30 -0
- package/dist/XlsxReader.d.ts.map +1 -0
- package/dist/XlsxReader.js +341 -0
- package/dist/XlsxReader.js.map +1 -0
- package/dist/XlsxWriter.d.ts +31 -0
- package/dist/XlsxWriter.d.ts.map +1 -0
- package/dist/XlsxWriter.js +415 -0
- package/dist/XlsxWriter.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/docs/API.md +271 -0
- package/docs/BENCHMARK.md +129 -0
- package/docs/PUBLISHING.md +89 -0
- package/examples/basic-read.ts +109 -0
- package/examples/basic-write.ts +84 -0
- package/examples/large-dataset.ts +216 -0
- package/examples/multiple-sheets.ts +126 -0
- package/examples/streaming-example.ts +181 -0
- 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();
|