@cj-tech-master/excelts 1.4.5 → 1.5.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 (49) hide show
  1. package/dist/browser/excelts.iife.js +454 -159
  2. package/dist/browser/excelts.iife.js.map +1 -1
  3. package/dist/browser/excelts.iife.min.js +28 -28
  4. package/dist/cjs/doc/anchor.js +25 -11
  5. package/dist/cjs/doc/cell.js +75 -43
  6. package/dist/cjs/doc/column.js +74 -22
  7. package/dist/cjs/doc/defined-names.js +53 -7
  8. package/dist/cjs/doc/image.js +11 -8
  9. package/dist/cjs/doc/range.js +64 -28
  10. package/dist/cjs/doc/row.js +72 -31
  11. package/dist/cjs/doc/table.js +3 -5
  12. package/dist/cjs/doc/workbook.js +30 -6
  13. package/dist/cjs/doc/worksheet.js +165 -41
  14. package/dist/cjs/utils/sheet-utils.js +3 -1
  15. package/dist/cjs/utils/unzip/extract.js +30 -82
  16. package/dist/cjs/utils/unzip/index.js +18 -2
  17. package/dist/cjs/utils/unzip/zip-parser.js +458 -0
  18. package/dist/esm/doc/anchor.js +25 -11
  19. package/dist/esm/doc/cell.js +75 -43
  20. package/dist/esm/doc/column.js +74 -22
  21. package/dist/esm/doc/defined-names.js +53 -7
  22. package/dist/esm/doc/image.js +11 -8
  23. package/dist/esm/doc/range.js +64 -28
  24. package/dist/esm/doc/row.js +72 -31
  25. package/dist/esm/doc/table.js +3 -5
  26. package/dist/esm/doc/workbook.js +30 -6
  27. package/dist/esm/doc/worksheet.js +165 -41
  28. package/dist/esm/utils/sheet-utils.js +3 -1
  29. package/dist/esm/utils/unzip/extract.js +28 -82
  30. package/dist/esm/utils/unzip/index.js +17 -2
  31. package/dist/esm/utils/unzip/zip-parser.js +451 -0
  32. package/dist/types/doc/anchor.d.ts +14 -7
  33. package/dist/types/doc/cell.d.ts +78 -37
  34. package/dist/types/doc/column.d.ts +72 -36
  35. package/dist/types/doc/defined-names.d.ts +11 -8
  36. package/dist/types/doc/image.d.ts +29 -12
  37. package/dist/types/doc/pivot-table.d.ts +1 -1
  38. package/dist/types/doc/range.d.ts +15 -4
  39. package/dist/types/doc/row.d.ts +78 -40
  40. package/dist/types/doc/table.d.ts +21 -36
  41. package/dist/types/doc/workbook.d.ts +54 -34
  42. package/dist/types/doc/worksheet.d.ts +255 -83
  43. package/dist/types/stream/xlsx/worksheet-reader.d.ts +3 -5
  44. package/dist/types/types.d.ts +86 -26
  45. package/dist/types/utils/col-cache.d.ts +11 -8
  46. package/dist/types/utils/unzip/extract.d.ts +16 -14
  47. package/dist/types/utils/unzip/index.d.ts +15 -1
  48. package/dist/types/utils/unzip/zip-parser.d.ts +92 -0
  49. package/package.json +1 -1
@@ -2,11 +2,17 @@ import { colCache } from "../utils/col-cache.js";
2
2
  // used by worksheet to calculate sheet dimensions
3
3
  class Range {
4
4
  constructor(...args) {
5
+ this.model = {
6
+ top: 0,
7
+ left: 0,
8
+ bottom: 0,
9
+ right: 0
10
+ };
5
11
  this.decode(args);
6
12
  }
7
13
  setTLBR(t, l, b, r, s) {
8
- if (arguments.length < 4) {
9
- // setTLBR(tl, br, s)
14
+ if (typeof t === "string" && typeof l === "string") {
15
+ // setTLBR(tl, br, s) - t and l are address strings
10
16
  const tl = colCache.decodeAddress(t);
11
17
  const br = colCache.decodeAddress(l);
12
18
  this.model = {
@@ -14,12 +20,14 @@ class Range {
14
20
  left: Math.min(tl.col, br.col),
15
21
  bottom: Math.max(tl.row, br.row),
16
22
  right: Math.max(tl.col, br.col),
17
- sheetName: b
23
+ sheetName: typeof b === "string" ? b : undefined
18
24
  };
19
- this.setTLBR(tl.row, tl.col, br.row, br.col, s);
20
25
  }
21
- else {
22
- // setTLBR(t, l, b, r, s)
26
+ else if (typeof t === "number" &&
27
+ typeof l === "number" &&
28
+ typeof b === "number" &&
29
+ typeof r === "number") {
30
+ // setTLBR(t, l, b, r, s) - all numbers
23
31
  this.model = {
24
32
  top: Math.min(t, b),
25
33
  left: Math.min(l, r),
@@ -32,16 +40,33 @@ class Range {
32
40
  decode(argv) {
33
41
  switch (argv.length) {
34
42
  case 5: // [t,l,b,r,s]
35
- this.setTLBR(argv[0], argv[1], argv[2], argv[3], argv[4]);
43
+ if (typeof argv[0] === "number" &&
44
+ typeof argv[1] === "number" &&
45
+ typeof argv[2] === "number" &&
46
+ typeof argv[3] === "number" &&
47
+ typeof argv[4] === "string") {
48
+ this.setTLBR(argv[0], argv[1], argv[2], argv[3], argv[4]);
49
+ }
36
50
  break;
37
51
  case 4: // [t,l,b,r]
38
- this.setTLBR(argv[0], argv[1], argv[2], argv[3]);
52
+ if (typeof argv[0] === "number" &&
53
+ typeof argv[1] === "number" &&
54
+ typeof argv[2] === "number" &&
55
+ typeof argv[3] === "number") {
56
+ this.setTLBR(argv[0], argv[1], argv[2], argv[3]);
57
+ }
39
58
  break;
40
59
  case 3: // [tl,br,s]
41
- this.setTLBR(argv[0], argv[1], argv[2]);
60
+ if (typeof argv[0] === "string" &&
61
+ typeof argv[1] === "string" &&
62
+ typeof argv[2] === "string") {
63
+ this.setTLBR(argv[0], argv[1], argv[2]);
64
+ }
42
65
  break;
43
66
  case 2: // [tl,br]
44
- this.setTLBR(argv[0], argv[1]);
67
+ if (typeof argv[0] === "string" && typeof argv[1] === "string") {
68
+ this.setTLBR(argv[0], argv[1]);
69
+ }
45
70
  break;
46
71
  case 1: {
47
72
  const value = argv[0];
@@ -55,11 +80,15 @@ class Range {
55
80
  sheetName: value.sheetName
56
81
  };
57
82
  }
58
- else if (value instanceof Array) {
83
+ else if (Array.isArray(value)) {
59
84
  // an arguments array
60
85
  this.decode(value);
61
86
  }
62
- else if (value.top && value.left && value.bottom && value.right) {
87
+ else if (typeof value === "object" &&
88
+ "top" in value &&
89
+ "left" in value &&
90
+ "bottom" in value &&
91
+ "right" in value) {
63
92
  // a model
64
93
  this.model = {
65
94
  top: value.top,
@@ -69,25 +98,27 @@ class Range {
69
98
  sheetName: value.sheetName
70
99
  };
71
100
  }
72
- else {
101
+ else if (typeof value === "string") {
73
102
  // [sheetName!]tl:br
74
- const tlbr = colCache.decodeEx(value);
75
- if (tlbr.top) {
103
+ const decoded = colCache.decodeEx(value);
104
+ if ("top" in decoded) {
105
+ // It's a DecodedRange
76
106
  this.model = {
77
- top: tlbr.top,
78
- left: tlbr.left,
79
- bottom: tlbr.bottom,
80
- right: tlbr.right,
81
- sheetName: tlbr.sheetName
107
+ top: decoded.top,
108
+ left: decoded.left,
109
+ bottom: decoded.bottom,
110
+ right: decoded.right,
111
+ sheetName: decoded.sheetName
82
112
  };
83
113
  }
84
- else {
114
+ else if ("row" in decoded) {
115
+ // It's an Address
85
116
  this.model = {
86
- top: tlbr.row,
87
- left: tlbr.col,
88
- bottom: tlbr.row,
89
- right: tlbr.col,
90
- sheetName: tlbr.sheetName
117
+ top: decoded.row,
118
+ left: decoded.col,
119
+ bottom: decoded.row,
120
+ right: decoded.col,
121
+ sheetName: decoded.sheetName
91
122
  };
92
123
  }
93
124
  }
@@ -169,7 +200,9 @@ class Range {
169
200
  }
170
201
  expandToAddress(addressStr) {
171
202
  const address = colCache.decodeEx(addressStr);
172
- this.expand(address.row, address.col, address.row, address.col);
203
+ if ("row" in address && "col" in address) {
204
+ this.expand(address.row, address.col, address.row, address.col);
205
+ }
173
206
  }
174
207
  get tl() {
175
208
  return colCache.n2l(this.left) + this.top;
@@ -221,7 +254,10 @@ class Range {
221
254
  }
222
255
  contains(addressStr) {
223
256
  const address = colCache.decodeEx(addressStr);
224
- return this.containsEx(address);
257
+ if ("row" in address && "col" in address) {
258
+ return this.containsEx(address);
259
+ }
260
+ return false;
225
261
  }
226
262
  containsEx(address) {
227
263
  if (address.sheetName && this.sheetName && address.sheetName !== this.sheetName) {
@@ -9,19 +9,29 @@ class Row {
9
9
  this.style = {};
10
10
  this.outlineLevel = 0;
11
11
  }
12
- // return the row number
12
+ /**
13
+ * The row number
14
+ */
13
15
  get number() {
14
16
  return this._number;
15
17
  }
18
+ /**
19
+ * The worksheet that contains this row
20
+ */
16
21
  get worksheet() {
17
22
  return this._worksheet;
18
23
  }
19
- // Inform Streaming Writer that this row (and all rows before it) are complete
20
- // and ready to write. Has no effect on Worksheet document
24
+ /**
25
+ * Commit a completed row to stream.
26
+ * Inform Streaming Writer that this row (and all rows before it) are complete
27
+ * and ready to write. Has no effect on Worksheet document.
28
+ */
21
29
  commit() {
22
30
  this._worksheet._commitRow(this);
23
31
  }
24
- // helps GC by breaking cyclic references
32
+ /**
33
+ * Helps GC by breaking cyclic references
34
+ */
25
35
  destroy() {
26
36
  delete this._worksheet;
27
37
  delete this._cells;
@@ -40,7 +50,9 @@ class Row {
40
50
  }
41
51
  return cell;
42
52
  }
43
- // get cell by key, letter or column number
53
+ /**
54
+ * Get cell by number, column letter or column key
55
+ */
44
56
  getCell(col) {
45
57
  let colNum;
46
58
  if (typeof col === "string") {
@@ -63,7 +75,11 @@ class Row {
63
75
  col: colNum
64
76
  }));
65
77
  }
66
- // remove cell(s) and shift all higher cells down by count
78
+ /**
79
+ * Cut one or more cells (cells to the right are shifted left)
80
+ *
81
+ * Note: this operation will not affect other rows
82
+ */
67
83
  splice(start, count, ...inserts) {
68
84
  const nKeep = start + count;
69
85
  const nExpand = inserts.length - count;
@@ -80,12 +96,12 @@ class Row {
80
96
  cDst = this.getCell(i);
81
97
  cDst.value = cSrc.value;
82
98
  cDst.style = cSrc.style;
83
- cDst._comment = cSrc._comment;
99
+ cDst.comment = cSrc.comment;
84
100
  }
85
101
  else if (cDst) {
86
102
  cDst.value = null;
87
103
  cDst.style = {};
88
- cDst._comment = undefined;
104
+ cDst.comment = undefined;
89
105
  }
90
106
  }
91
107
  }
@@ -97,7 +113,7 @@ class Row {
97
113
  cDst = this.getCell(i + nExpand);
98
114
  cDst.value = cSrc.value;
99
115
  cDst.style = cSrc.style;
100
- cDst._comment = cSrc._comment;
116
+ cDst.comment = cSrc.comment;
101
117
  }
102
118
  else {
103
119
  this._cells[i + nExpand - 1] = undefined;
@@ -109,29 +125,29 @@ class Row {
109
125
  cDst = this.getCell(start + i);
110
126
  cDst.value = inserts[i];
111
127
  cDst.style = {};
112
- cDst._comment = undefined;
128
+ cDst.comment = undefined;
113
129
  }
114
130
  }
115
- eachCell(optionsOrIteratee, maybeIteratee) {
131
+ eachCell(optOrCallback, maybeCallback) {
116
132
  let options = null;
117
- let iteratee;
118
- if (typeof optionsOrIteratee === "function") {
119
- iteratee = optionsOrIteratee;
133
+ let callback;
134
+ if (typeof optOrCallback === "function") {
135
+ callback = optOrCallback;
120
136
  }
121
137
  else {
122
- options = optionsOrIteratee;
123
- iteratee = maybeIteratee;
138
+ options = optOrCallback;
139
+ callback = maybeCallback;
124
140
  }
125
141
  if (options && options.includeEmpty) {
126
142
  const n = this._cells.length;
127
143
  for (let i = 1; i <= n; i++) {
128
- iteratee(this.getCell(i), i);
144
+ callback(this.getCell(i), i);
129
145
  }
130
146
  }
131
147
  else {
132
148
  this._cells.forEach((cell, index) => {
133
149
  if (cell && cell.type !== Enums.ValueType.Null) {
134
- iteratee(cell, index + 1);
150
+ callback(cell, index + 1);
135
151
  }
136
152
  });
137
153
  }
@@ -152,7 +168,9 @@ class Row {
152
168
  }
153
169
  ws.rowBreaks.push(pb);
154
170
  }
155
- // return a sparse array of cell values
171
+ /**
172
+ * Get a row as a sparse array
173
+ */
156
174
  get values() {
157
175
  const values = [];
158
176
  this._cells.forEach(cell => {
@@ -162,7 +180,9 @@ class Row {
162
180
  });
163
181
  return values;
164
182
  }
165
- // set the values by contiguous or sparse array, or by key'd object literal
183
+ /**
184
+ * Set the values by contiguous or sparse array, or by key'd object literal
185
+ */
166
186
  set values(value) {
167
187
  // this operation is not additive - any prior cells are removed
168
188
  this._cells = [];
@@ -198,13 +218,21 @@ class Row {
198
218
  });
199
219
  }
200
220
  }
201
- // returns true if the row includes at least one cell with a value
221
+ /**
222
+ * Returns true if the row includes at least one cell with a value
223
+ */
202
224
  get hasValues() {
203
- return this._cells.some((cell) => cell && cell.type !== Enums.ValueType.Null);
225
+ return this._cells.some(cell => cell && cell.type !== Enums.ValueType.Null);
204
226
  }
227
+ /**
228
+ * Number of cells including empty ones
229
+ */
205
230
  get cellCount() {
206
231
  return this._cells.length;
207
232
  }
233
+ /**
234
+ * Number of non-empty cells
235
+ */
208
236
  get actualCellCount() {
209
237
  let count = 0;
210
238
  this.eachCell(() => {
@@ -212,7 +240,9 @@ class Row {
212
240
  });
213
241
  return count;
214
242
  }
215
- // get the min and max column number for the non-null cells in this row or null
243
+ /**
244
+ * Get the min and max column number for the non-null cells in this row or null
245
+ */
216
246
  get dimensions() {
217
247
  let min = 0;
218
248
  let max = 0;
@@ -239,46 +269,57 @@ class Row {
239
269
  this.style[name] = value;
240
270
  this._cells.forEach(cell => {
241
271
  if (cell) {
242
- cell[name] = value;
272
+ cell.style[name] = value;
243
273
  }
244
274
  });
245
- return value;
246
275
  }
247
276
  get numFmt() {
248
277
  return this.style.numFmt;
249
278
  }
250
279
  set numFmt(value) {
251
- this._applyStyle("numFmt", value);
280
+ if (value !== undefined) {
281
+ this._applyStyle("numFmt", value);
282
+ }
252
283
  }
253
284
  get font() {
254
285
  return this.style.font;
255
286
  }
256
287
  set font(value) {
257
- this._applyStyle("font", value);
288
+ if (value !== undefined) {
289
+ this._applyStyle("font", value);
290
+ }
258
291
  }
259
292
  get alignment() {
260
293
  return this.style.alignment;
261
294
  }
262
295
  set alignment(value) {
263
- this._applyStyle("alignment", value);
296
+ if (value !== undefined) {
297
+ this._applyStyle("alignment", value);
298
+ }
264
299
  }
265
300
  get protection() {
266
301
  return this.style.protection;
267
302
  }
268
303
  set protection(value) {
269
- this._applyStyle("protection", value);
304
+ if (value !== undefined) {
305
+ this._applyStyle("protection", value);
306
+ }
270
307
  }
271
308
  get border() {
272
309
  return this.style.border;
273
310
  }
274
311
  set border(value) {
275
- this._applyStyle("border", value);
312
+ if (value !== undefined) {
313
+ this._applyStyle("border", value);
314
+ }
276
315
  }
277
316
  get fill() {
278
317
  return this.style.fill;
279
318
  }
280
319
  set fill(value) {
281
- this._applyStyle("fill", value);
320
+ if (value !== undefined) {
321
+ this._applyStyle("fill", value);
322
+ }
282
323
  }
283
324
  get hidden() {
284
325
  return !!this._hidden;
@@ -154,9 +154,7 @@ class Table {
154
154
  // the sheet...
155
155
  const assignStyle = (cell, style) => {
156
156
  if (style) {
157
- Object.keys(style).forEach(key => {
158
- cell.style[key] = style[key];
159
- });
157
+ Object.assign(cell.style, style);
160
158
  }
161
159
  };
162
160
  const { worksheet, table } = this;
@@ -374,10 +372,10 @@ class Table {
374
372
  this._assign(this.table, "totalsRow", value);
375
373
  }
376
374
  get theme() {
377
- return this.table.style.name;
375
+ return this.table.style.theme;
378
376
  }
379
377
  set theme(value) {
380
- this.table.style.name = value;
378
+ this.table.style.theme = value;
381
379
  }
382
380
  get showFirstColumn() {
383
381
  return this.table.style.showFirstColumn;
@@ -26,12 +26,18 @@ class Workbook {
26
26
  this.pivotTables = [];
27
27
  this._definedNames = new DefinedNames();
28
28
  }
29
+ /**
30
+ * xlsx file format operations
31
+ */
29
32
  get xlsx() {
30
33
  if (!this._xlsx) {
31
34
  this._xlsx = new XLSX(this);
32
35
  }
33
36
  return this._xlsx;
34
37
  }
38
+ /**
39
+ * csv file format operations
40
+ */
35
41
  get csv() {
36
42
  if (!this._csv) {
37
43
  this._csv = new CSV(this);
@@ -47,15 +53,19 @@ class Workbook {
47
53
  }
48
54
  return this._worksheets.length || 1;
49
55
  }
56
+ /**
57
+ * Add a new worksheet and return a reference to it
58
+ */
50
59
  addWorksheet(name, options) {
51
60
  const id = this.nextId;
52
61
  const lastOrderNo = this._worksheets.reduce((acc, ws) => ((ws && ws.orderNo) > acc ? ws.orderNo : acc), 0);
53
- const worksheetOptions = Object.assign({}, options, {
62
+ const worksheetOptions = {
63
+ ...options,
54
64
  id,
55
65
  name,
56
66
  orderNo: lastOrderNo + 1,
57
67
  workbook: this
58
- });
68
+ };
59
69
  const worksheet = new Worksheet(worksheetOptions);
60
70
  this._worksheets[id] = worksheet;
61
71
  return worksheet;
@@ -69,6 +79,9 @@ class Workbook {
69
79
  worksheet.destroy();
70
80
  }
71
81
  }
82
+ /**
83
+ * Fetch sheet by name or id
84
+ */
72
85
  getWorksheet(id) {
73
86
  if (id === undefined) {
74
87
  return this._worksheets.find(Boolean);
@@ -81,6 +94,9 @@ class Workbook {
81
94
  }
82
95
  return undefined;
83
96
  }
97
+ /**
98
+ * Return a clone of worksheets in order
99
+ */
84
100
  get worksheets() {
85
101
  // return a clone of _worksheets
86
102
  return this._worksheets
@@ -88,9 +104,14 @@ class Workbook {
88
104
  .sort((a, b) => a.orderNo - b.orderNo)
89
105
  .filter(Boolean);
90
106
  }
91
- eachSheet(iteratee) {
107
+ /**
108
+ * Iterate over all sheets.
109
+ *
110
+ * Note: `workbook.worksheets.forEach` will still work but this is better.
111
+ */
112
+ eachSheet(callback) {
92
113
  this.worksheets.forEach(sheet => {
93
- iteratee(sheet, sheet.id);
114
+ callback(sheet, sheet.id);
94
115
  });
95
116
  }
96
117
  get definedNames() {
@@ -100,14 +121,17 @@ class Workbook {
100
121
  // Note: themes are not an exposed feature, meddle at your peril!
101
122
  this._themes = undefined;
102
123
  }
124
+ /**
125
+ * Add Image to Workbook and return the id
126
+ */
103
127
  addImage(image) {
104
128
  // TODO: validation?
105
129
  const id = this.media.length;
106
- this.media.push(Object.assign({}, image, { type: "image" }));
130
+ this.media.push({ ...image, type: "image" });
107
131
  return id;
108
132
  }
109
133
  getImage(id) {
110
- return this.media[id];
134
+ return this.media[Number(id)];
111
135
  }
112
136
  get model() {
113
137
  return {