@justybase/spreadsheet-tasks 1.3.3 → 2.1.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 (62) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +151 -54
  3. package/browser/browser-spreadsheet.js +3044 -0
  4. package/browser/justybase-spreadsheet.min.js +36 -0
  5. package/dist/cjs/index.d.ts +559 -0
  6. package/dist/cjs/index.js +4971 -0
  7. package/dist/cjs/index.js.map +1 -0
  8. package/dist/esm/index.js +4914 -0
  9. package/dist/esm/index.js.map +1 -0
  10. package/dist/esm/package.json +1 -0
  11. package/docs/API.md +166 -9
  12. package/docs/PACKAGING.md +32 -0
  13. package/docs/PUBLISHING.md +8 -1
  14. package/examples/basic-read.ts +2 -2
  15. package/examples/basic-write.ts +1 -1
  16. package/examples/datetime-widths.ts +1 -1
  17. package/examples/formats-verify.ts +1 -2
  18. package/examples/large-dataset.ts +2 -2
  19. package/examples/multiple-sheets.ts +1 -1
  20. package/examples/streaming-example.ts +3 -1
  21. package/examples/update-existing.ts +53 -0
  22. package/package.json +29 -14
  23. package/dist/BiffReaderWriter.d.ts +0 -44
  24. package/dist/BiffReaderWriter.d.ts.map +0 -1
  25. package/dist/BiffReaderWriter.js +0 -282
  26. package/dist/BiffReaderWriter.js.map +0 -1
  27. package/dist/BigBuffer.d.ts +0 -24
  28. package/dist/BigBuffer.d.ts.map +0 -1
  29. package/dist/BigBuffer.js +0 -120
  30. package/dist/BigBuffer.js.map +0 -1
  31. package/dist/ExcelReaderAbstract.d.ts +0 -17
  32. package/dist/ExcelReaderAbstract.d.ts.map +0 -1
  33. package/dist/ExcelReaderAbstract.js +0 -25
  34. package/dist/ExcelReaderAbstract.js.map +0 -1
  35. package/dist/Formats.d.ts +0 -34
  36. package/dist/Formats.d.ts.map +0 -1
  37. package/dist/Formats.js +0 -48
  38. package/dist/Formats.js.map +0 -1
  39. package/dist/ReaderFactory.d.ts +0 -6
  40. package/dist/ReaderFactory.d.ts.map +0 -1
  41. package/dist/ReaderFactory.js +0 -56
  42. package/dist/ReaderFactory.js.map +0 -1
  43. package/dist/XlsbReader.d.ts +0 -24
  44. package/dist/XlsbReader.d.ts.map +0 -1
  45. package/dist/XlsbReader.js +0 -186
  46. package/dist/XlsbReader.js.map +0 -1
  47. package/dist/XlsbWriter.d.ts +0 -80
  48. package/dist/XlsbWriter.d.ts.map +0 -1
  49. package/dist/XlsbWriter.js +0 -964
  50. package/dist/XlsbWriter.js.map +0 -1
  51. package/dist/XlsxReader.d.ts +0 -30
  52. package/dist/XlsxReader.d.ts.map +0 -1
  53. package/dist/XlsxReader.js +0 -341
  54. package/dist/XlsxReader.js.map +0 -1
  55. package/dist/XlsxWriter.d.ts +0 -51
  56. package/dist/XlsxWriter.d.ts.map +0 -1
  57. package/dist/XlsxWriter.js +0 -632
  58. package/dist/XlsxWriter.js.map +0 -1
  59. package/dist/index.d.ts +0 -10
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/index.js +0 -29
  62. package/dist/index.js.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [2.1.0] - 2026-08-07
9
+
10
+ ### Added
11
+
12
+ - `XlsxUpdater` and `XlsbUpdater` — replace the data of a worksheet inside an
13
+ existing `.xlsx` / `.xlsb` file without rebuilding the workbook. Pivot tables,
14
+ other sheets, styles and defined names are preserved; shared strings are
15
+ appended (never reordered), column styles are inherited, and pivot cache
16
+ ranges + `refreshOnLoad` are updated automatically.
17
+ - Shared helpers: `xmlUtils.ts` (XML escaping, column letters, shared strings
18
+ parsing) and `biff12Utils.ts` (BIFF12 record helpers for XLSB).
19
+ - `examples/update-existing.ts` — end-to-end example for refreshing a data
20
+ sheet in an existing XLSX / XLSB report.
21
+
22
+ ### Fixed
23
+
24
+ - `XlsbUpdater` pivot source range was one row too long when `headers` were not
25
+ provided, causing an empty trailing row (and a "(blank)" item in pivot
26
+ tables). The range now ends exactly at the last data row.
27
+ - Both updaters now trim trailing rows that contain only empty cells (padding
28
+ rows from SQL exports), so they don't appear as "(blank)" in pivot tables.
29
+ - `XlsbUpdater` no longer removes the worksheet's row-block terminator records
30
+ (0x92/0x217/0x1dd/0x1dc) and keeps the sheet dimension record (0x98) in sync
31
+ with the new row count — without these, Excel hid the last written row.
32
+
33
+ ## [2.0.0] - 2026-07-25
34
+
35
+ ### Breaking
36
+
37
+ - `XlsbReader.read()` is now `async` and returns `Promise<boolean>` (same as `XlsxReader`).
38
+ Update loops from `while (reader.read())` to `while (await reader.read())`.
39
+ - Package entry points moved under `dist/cjs` and `dist/esm` with an `exports` map.
40
+ Most consumers of `@justybase/spreadsheet-tasks` need no import path changes.
41
+
42
+ ### Added
43
+
44
+ - `CellValue` / `PrimitiveCellValue` types for writer and reader cell APIs
45
+ - Shared writer helpers: `sanitizeSheetName`, column-width helpers, `StreamingSheetState`
46
+ - Dual package build (CJS + ESM) via `tsup`
47
+ - Browser sources under `src/browser/` with `npm run build:browser`
48
+ - `docs/PACKAGING.md` (ZIP library rationale + dual package notes)
49
+ - Dist surface smoke test (`npm run test:dist`)
50
+
51
+ ### Changed
52
+
53
+ - `XlsbWriter` / `XlsxWriter` share sanitization, autofit, and streaming state helpers
54
+ - Tests import from `src/` (published surface still verified via `test:dist`)
55
+ - ZIP type definitions use `@types/*` only (hand-written ambient modules removed)
56
+
57
+ ### Browser
58
+
59
+ - Source of truth is TypeScript in `src/browser/`; `browser/*.js` writer sources are generated bundles
60
+
61
+ ## [1.3.2] - previous
62
+
63
+ See git history for 1.x changes.
package/README.md CHANGED
@@ -1,72 +1,112 @@
1
- # SpreadsheetTasks
1
+ # @justybase/spreadsheet-tasks
2
2
 
3
- A high-performance TypeScript library for reading and writing Excel files in XLSB and XLSX formats.
3
+ High-performance TypeScript library for reading and writing Excel files in XLSB and XLSX formats.
4
4
 
5
- [![npm version](https://badge.fury.io/js/@justybase%2Fspreadsheet-tasks.svg)](https://www.npmjs.com/package/@justybase/spreadsheet-tasks)
5
+ [![npm version](https://img.shields.io/npm/v/@justybase/spreadsheet-tasks.svg)](https://www.npmjs.com/package/@justybase/spreadsheet-tasks)
6
+ [![CI](https://github.com/justybase/justybase_spreadsheet_tasks/actions/workflows/ci.yml/badge.svg)](https://github.com/justybase/justybase_spreadsheet_tasks/actions/workflows/ci.yml)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
 
8
- ## 🚀 Features
9
-
10
- - **High Performance** - XLSB format is 3.3x faster to write and 2.1x faster to read than XLSX
11
- - **Small File Size** - XLSB files are ~47% smaller than equivalent XLSX files
12
- - **TypeScript First** - Full TypeScript support with type definitions
13
- - **Dual Format Support** - Read and write both XLSB and XLSX formats
14
- - **Zero External Dependencies** - Uses only Node.js built-in modules and minimal zip libraries
15
- - **Streaming Support** - Efficient memory usage for large files
16
- - **Multiple Sheets** - Support for multiple worksheets per workbook
17
- - **Auto-filter** - Automatic filter headers support
18
-
19
- ## 📊 Benchmark Results
9
+ ## Table of Contents
10
+
11
+ - [Features](#features)
12
+ - [Benchmark Results](#benchmark-results)
13
+ - [Requirements](#requirements)
14
+ - [Installation](#installation)
15
+ - [Browser Support](#browser-support)
16
+ - [Quick Start](#quick-start)
17
+ - [API Documentation](#api-documentation)
18
+ - [Examples](#examples)
19
+ - [When to Use XLSB vs XLSX](#when-to-use-xlsb-vs-xlsx)
20
+ - [Contributing](#contributing)
21
+ - [License](#license)
22
+ - [Acknowledgments](#acknowledgments)
23
+
24
+ ## Features
25
+
26
+ - **High Performance** — XLSB is about 3.3× faster to write and 2.3× faster to read than XLSX (see [benchmarks](#benchmark-results))
27
+ - **Small File Size** — XLSB files are ~47% smaller than equivalent XLSX files
28
+ - **TypeScript First** — Full TypeScript support with type definitions
29
+ - **Dual Format Support** — Read and write both XLSB and XLSX formats
30
+ - **Lightweight Node Dependencies** — Small ZIP-focused runtime deps (`adm-zip`, `archiver`, `yauzl`); no heavy Excel framework
31
+ - **Streaming Support** — Efficient memory usage for large files
32
+ - **Multiple Sheets** — Support for multiple worksheets per workbook
33
+ - **Auto-filter** — Automatic filter headers support
34
+ - **In-place Updates** — Replace the data of a worksheet inside an existing XLSX or XLSB (e.g. `report.xlsx` / `report.xlsb`) while keeping pivot tables, other sheets and formatting untouched
35
+
36
+ ## Benchmark Results
37
+
38
+ Measured with `npm run benchmark` (50K rows). Your results may vary by hardware and dataset.
20
39
 
21
40
  | Operation | XLSB | XLSX | Performance Gain |
22
41
  |-----------|------|------|------------------|
23
- | Write (50K rows) | 140 ms | 467 ms | **3.3x faster** |
24
- | Read (50K rows) | 118 ms | 276 ms | **2.3x faster** |
42
+ | Write (50K rows) | 140 ms | 467 ms | **3.3× faster** |
43
+ | Read (50K rows) | 118 ms | 276 ms | **2.3× faster** |
25
44
  | File Size | 1.49 MB | 2.83 MB | **47% smaller** |
26
45
 
27
- ## 📦 Installation
46
+ ## Requirements
47
+
48
+ - **Node.js** 16 or newer ([`engines`](./package.json) in `package.json`)
49
+
50
+ ## Installation
28
51
 
29
52
  ```bash
30
53
  npm install @justybase/spreadsheet-tasks
31
54
  ```
32
55
 
33
- ## 🌐 Browser Support & CDN (Zero Dependencies)
56
+ CommonJS:
57
+
58
+ ```js
59
+ const { XlsbWriter } = require('@justybase/spreadsheet-tasks');
60
+ ```
61
+
62
+ ES modules:
63
+
64
+ ```js
65
+ import { XlsbWriter } from '@justybase/spreadsheet-tasks';
66
+ ```
34
67
 
35
- This library includes browser-compatible modules to generate XLSB and XLSX files directly on the client side without relying on Node.js APIs or external dependencies.
68
+ ## Browser Support
36
69
 
37
- To bundle the browser version into a single minified file (e.g. for deployment to a CDN), run the following command in the project root:
70
+ Browser writers live in TypeScript under `src/browser/` and are bundled with:
38
71
 
39
72
  ```bash
40
- npx esbuild browser/browser-spreadsheet.js --bundle --minify --format=esm --outfile=browser/justybase-spreadsheet.min.js
73
+ npm run build:browser
41
74
  ```
42
75
 
43
- You can then import this single file via a script tag in any web application:
76
+ This produces:
77
+
78
+ - `browser/justybase-spreadsheet.min.js` — IIFE (`JustybaseSpreadsheet` global)
79
+ - `browser/browser-spreadsheet.js` — ESM for local demos (`demo.html`, `test.html`)
80
+
81
+ The browser bundle has **no runtime npm dependencies** (ZIP logic is inlined).
44
82
 
45
83
  ```html
46
84
  <script type="module">
47
- import { downloadXlsb, downloadXlsx } from 'https://your-cdn.com/justybase-spreadsheet.min.js';
48
-
49
- const headers = ["ID", "Name", "Score"];
85
+ import { downloadXlsb, downloadXlsx, F } from './browser-spreadsheet.js';
86
+
87
+ const headers = ['ID', 'Name', 'Score'];
50
88
  const rows = [
51
- [1, "Alice", 99.5],
52
- [2, "Bob", 88.0]
89
+ [1, 'Alice', 99.5],
90
+ [2, 'Bob', 88.0],
53
91
  ];
54
-
55
- // Generates the file and triggers the browser download automatically
92
+
56
93
  document.getElementById('downloadBtn').addEventListener('click', () => {
57
- downloadXlsb('report.xlsb', rows, headers, { headerStyle: 'bold+fill' });
94
+ downloadXlsb('report.xlsb', rows, headers);
58
95
  });
59
96
  </script>
60
97
  ```
61
98
 
62
99
  **Features included in the browser build:**
63
- - Built-in Zip archiving (no external libraries needed)
100
+
101
+ - Built-in ZIP archiving (no external libraries in the bundle)
64
102
  - Memory-efficient `Uint8Array` buffer handling
65
103
  - Auto-fitted column widths
66
104
  - Frozen and styled headers (styles: `bold`, `fill`, `bold+fill`)
67
105
  - Auto-filters enabled by default
68
106
 
69
- ## 🔧 Quick Start
107
+ See [CHANGELOG.md](./CHANGELOG.md) for v2 breaking changes (`await reader.read()`).
108
+
109
+ ## Quick Start
70
110
 
71
111
  ### Writing Excel Files
72
112
 
@@ -131,13 +171,13 @@ await writer.finalize();
131
171
  ```
132
172
 
133
173
  **Benefits of Streaming API:**
134
- - ✅ Constant memory usage regardless of dataset size
135
- - ✅ Write millions of rows without loading all data into RAM
136
- - ✅ Generate data on-the-fly from databases, APIs, or other sources
137
- - ✅ Same performance as batch mode
138
174
 
139
- ### Reading Excel Files
175
+ - Constant memory usage regardless of dataset size
176
+ - Write millions of rows without loading all data into RAM
177
+ - Generate data on-the-fly from databases, APIs, or other sources
178
+ - Same performance as batch mode
140
179
 
180
+ ### Reading Excel Files
141
181
 
142
182
  ```typescript
143
183
  import { XlsbReader, XlsxReader, ReaderFactory } from '@justybase/spreadsheet-tasks';
@@ -148,7 +188,7 @@ await reader.open('data.xlsb');
148
188
 
149
189
  console.log('Sheet names:', reader.getSheetNames());
150
190
 
151
- while (reader.read()) {
191
+ while (await reader.read()) {
152
192
  const row = [];
153
193
  for (let i = 0; i < reader.fieldCount; i++) {
154
194
  row.push(reader.getValue(i));
@@ -162,28 +202,69 @@ await xlsbReader.open('data.xlsb');
162
202
  // ... same API as above
163
203
  ```
164
204
 
165
- ## 📖 API Documentation
205
+ ### Updating Data in an Existing Workbook
206
+
207
+ `XlsxUpdater` and `XlsbUpdater` replace the cell data of a worksheet inside an
208
+ existing workbook without rebuilding it. Everything else — pivot tables, charts,
209
+ other sheets, styles, defined names — is preserved, so you can keep an advanced
210
+ Excel file (like a report with pivot tables wired to a data sheet) and only
211
+ refresh its data:
212
+
213
+ ```typescript
214
+ import { XlsxUpdater, XlsbUpdater } from '@justybase/spreadsheet-tasks';
215
+
216
+ // XLSX
217
+ const xlsx = new XlsxUpdater('report.xlsx');
218
+ xlsx.replaceSheetData('data1', rows, { headers: ['ID', 'NAME', 'AMOUNT'] });
219
+ xlsx.save(); // overwrite in place, or xlsx.save('report_new.xlsx')
220
+
221
+ // XLSB — the same API
222
+ const xlsb = new XlsbUpdater('report.xlsb');
223
+ xlsb.replaceSheetData('data1', rows, { headers: ['ID', 'NAME', 'AMOUNT'] });
224
+ xlsb.save('report_new.xlsb');
225
+ ```
226
+
227
+ **What happens under the hood:**
228
+
229
+ - The target sheet's cell data is cleared and replaced with the new rows.
230
+ - New strings are appended to the shared strings table (existing entries and
231
+ their indices are never moved, so other sheets stay valid).
232
+ - New cells reuse the dominant style of their column from the original data
233
+ (dates stay dates, numbers stay numbers). Pass `styleFallback: 'general'`
234
+ to write everything as General.
235
+ - Pivot tables whose cache source is the updated sheet get their source range
236
+ and record count adjusted, and `refreshOnLoad` is enabled so Excel refreshes
237
+ them automatically on open.
238
+
239
+ > **Tip:** always pass the `headers` matching the original columns. When
240
+ > `headers` are omitted, the first data row lands in row 1 and becomes the
241
+ > pivot's field names (Excel reads the first row of the source range as
242
+ > headers), so the pivot's columns would be replaced by the first record's
243
+ > values.
244
+
245
+ ## API Documentation
166
246
 
167
247
  See [API Documentation](./docs/API.md) for detailed API reference.
168
248
 
169
- ## 💡 Examples
249
+ ## Examples
170
250
 
171
251
  Check out the [examples](./examples) folder for more usage examples:
172
252
 
173
- - [Basic Write](./examples/basic-write.ts) - Writing data to Excel files
174
- - [Basic Read](./examples/basic-read.ts) - Reading data from Excel files
175
- - [Multiple Sheets](./examples/multiple-sheets.ts) - Working with multiple worksheets
176
- - [Large Dataset](./examples/large-dataset.ts) - Handling large datasets efficiently
177
- - [Streaming Example](./examples/streaming-example.ts) - Write millions of rows without loading all data in memory
253
+ - [Basic Write](./examples/basic-write.ts) — Writing data to Excel files
254
+ - [Basic Read](./examples/basic-read.ts) — Reading data from Excel files
255
+ - [Multiple Sheets](./examples/multiple-sheets.ts) — Working with multiple worksheets
256
+ - [Update Existing Workbook](./examples/update-existing.ts) — Replacing the data of a sheet in an existing XLSX/XLSB with pivot tables
257
+ - [Large Dataset](./examples/large-dataset.ts) — Handling large datasets efficiently
258
+ - [Streaming Example](./examples/streaming-example.ts) — Write millions of rows without loading all data in memory
178
259
 
179
260
  Run examples with:
261
+
180
262
  ```bash
181
263
  npm run build
182
264
  npx ts-node examples/basic-write.ts
183
265
  ```
184
266
 
185
-
186
- ## 🔍 When to Use XLSB vs XLSX
267
+ ## When to Use XLSB vs XLSX
187
268
 
188
269
  | Use XLSB When | Use XLSX When |
189
270
  |---------------|---------------|
@@ -192,14 +273,30 @@ npx ts-node examples/basic-write.ts
192
273
  | Internal/backend processing | Human-readable XML is needed |
193
274
  | Storage space is limited | Third-party integrations require it |
194
275
 
195
- ## 🤝 Contributing
276
+ ## Contributing
277
+
278
+ Contributions are welcome. To work on the project locally:
279
+
280
+ ```bash
281
+ git clone https://github.com/justybase/justybase_spreadsheet_tasks.git
282
+ cd justybase_spreadsheet_tasks
283
+ npm install
284
+ npm run build
285
+ npm test
286
+ ```
287
+
288
+ Before opening a pull request:
289
+
290
+ 1. Run `npm run lint` and `npm test`.
291
+ 2. Add or update tests if you change behavior.
292
+ 3. Update [CHANGELOG.md](./CHANGELOG.md) for user-visible changes.
196
293
 
197
- Contributions are welcome! Please feel free to submit a Pull Request.
294
+ Please open an issue or pull request on [GitHub](https://github.com/justybase/justybase_spreadsheet_tasks).
198
295
 
199
- ## 📄 License
296
+ ## License
200
297
 
201
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
298
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
202
299
 
203
- ## 🙏 Acknowledgments
300
+ ## Acknowledgments
204
301
 
205
- - Inspired by and reimplemented from [SpreadSheetTasks](https://github.com/KrzysztofDusko/SpreadSheetTasks)
302
+ - Inspired by and reimplemented from [SpreadSheetTasks](https://github.com/justybae/SpreadSheetTasks)