@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
@@ -184,11 +184,30 @@ class Cell {
184
184
  this._value = Value.create(Value.getType(v), this, v);
185
185
  }
186
186
  get note() {
187
- return this._comment && this._comment.note;
187
+ if (!this._comment) {
188
+ return undefined;
189
+ }
190
+ const noteValue = this._comment.note;
191
+ return noteValue;
188
192
  }
189
193
  set note(note) {
190
194
  this._comment = new Note(note);
191
195
  }
196
+ // Internal comment accessor for row operations
197
+ get comment() {
198
+ return this._comment;
199
+ }
200
+ set comment(comment) {
201
+ if (comment === undefined) {
202
+ this._comment = undefined;
203
+ }
204
+ else if (comment instanceof Note) {
205
+ this._comment = comment;
206
+ }
207
+ else {
208
+ this._comment = new Note(comment);
209
+ }
210
+ }
192
211
  get text() {
193
212
  return this._value.toString();
194
213
  }
@@ -202,7 +221,7 @@ class Cell {
202
221
  // if this cell is a string, turn it into a Hyperlink
203
222
  if (this.type === Cell.Types.String) {
204
223
  this._value = Value.create(Cell.Types.Hyperlink, this, {
205
- text: this._value.value,
224
+ text: String(this._value.value),
206
225
  hyperlink
207
226
  });
208
227
  }
@@ -295,8 +314,6 @@ class Cell {
295
314
  }
296
315
  }
297
316
  Cell.Types = Enums.ValueType;
298
- // =============================================================================
299
- // Internal Value Types
300
317
  class NullValue {
301
318
  constructor(cell) {
302
319
  this.model = {
@@ -413,7 +430,7 @@ class RichTextValue {
413
430
  this.model.value = value;
414
431
  }
415
432
  toString() {
416
- return this.model.value.richText.map((t) => t.text).join("");
433
+ return this.model.value.richText.map(t => t.text).join("");
417
434
  }
418
435
  get type() {
419
436
  return Cell.Types.RichText;
@@ -482,14 +499,11 @@ class HyperlinkValue {
482
499
  }
483
500
  }
484
501
  get value() {
485
- const v = {
486
- text: this.model.text,
487
- hyperlink: this.model.hyperlink
502
+ return {
503
+ text: this.model.text || "",
504
+ hyperlink: this.model.hyperlink || "",
505
+ tooltip: this.model.tooltip
488
506
  };
489
- if (this.model.tooltip) {
490
- v.tooltip = this.model.tooltip;
491
- }
492
- return v;
493
507
  }
494
508
  set value(value) {
495
509
  this.model.text = value.text;
@@ -600,24 +614,42 @@ class FormulaValue {
600
614
  }
601
615
  _copyModel(model) {
602
616
  const copy = {};
603
- const cp = (name) => {
604
- const value = model[name];
605
- if (value) {
606
- copy[name] = value;
607
- }
608
- };
609
- cp("formula");
610
- cp("result");
611
- cp("ref");
612
- cp("shareType");
613
- cp("sharedFormula");
617
+ if (model.formula) {
618
+ copy.formula = model.formula;
619
+ }
620
+ if (model.result !== undefined) {
621
+ copy.result = model.result;
622
+ }
623
+ if (model.ref) {
624
+ copy.ref = model.ref;
625
+ }
626
+ if (model.shareType) {
627
+ copy.shareType = model.shareType;
628
+ }
629
+ if (model.sharedFormula) {
630
+ copy.sharedFormula = model.sharedFormula;
631
+ }
614
632
  return copy;
615
633
  }
616
634
  get value() {
617
635
  return this._copyModel(this.model);
618
636
  }
619
637
  set value(value) {
620
- this.model = this._copyModel(value);
638
+ if (value.formula) {
639
+ this.model.formula = value.formula;
640
+ }
641
+ if (value.result !== undefined) {
642
+ this.model.result = value.result;
643
+ }
644
+ if (value.ref) {
645
+ this.model.ref = value.ref;
646
+ }
647
+ if (value.shareType) {
648
+ this.model.shareType = value.shareType;
649
+ }
650
+ if (value.sharedFormula) {
651
+ this.model.sharedFormula = value.sharedFormula;
652
+ }
621
653
  }
622
654
  validate(value) {
623
655
  switch (Value.getType(value)) {
@@ -681,11 +713,8 @@ class FormulaValue {
681
713
  if (v instanceof Date) {
682
714
  return Enums.ValueType.Date;
683
715
  }
684
- if (v.text && v.hyperlink) {
685
- return Enums.ValueType.Hyperlink;
686
- }
687
- if (v.formula) {
688
- return Enums.ValueType.Formula;
716
+ if (typeof v === "object" && "error" in v) {
717
+ return Enums.ValueType.Error;
689
718
  }
690
719
  return Enums.ValueType.Null;
691
720
  }
@@ -868,20 +897,23 @@ const Value = {
868
897
  if (value instanceof Date) {
869
898
  return Cell.Types.Date;
870
899
  }
871
- if (value.text && value.hyperlink) {
872
- return Cell.Types.Hyperlink;
873
- }
874
- if (value.formula || value.sharedFormula) {
875
- return Cell.Types.Formula;
876
- }
877
- if (value.richText) {
878
- return Cell.Types.RichText;
879
- }
880
- if (value.sharedString) {
881
- return Cell.Types.SharedString;
882
- }
883
- if (value.error) {
884
- return Cell.Types.Error;
900
+ if (typeof value === "object") {
901
+ if ("text" in value && value.text && "hyperlink" in value && value.hyperlink) {
902
+ return Cell.Types.Hyperlink;
903
+ }
904
+ if (("formula" in value && value.formula) ||
905
+ ("sharedFormula" in value && value.sharedFormula)) {
906
+ return Cell.Types.Formula;
907
+ }
908
+ if ("richText" in value && value.richText) {
909
+ return Cell.Types.RichText;
910
+ }
911
+ if ("sharedString" in value && value.sharedString) {
912
+ return Cell.Types.SharedString;
913
+ }
914
+ if ("error" in value && value.error) {
915
+ return Cell.Types.Error;
916
+ }
885
917
  }
886
918
  return Cell.Types.JSON;
887
919
  },
@@ -2,9 +2,11 @@ import { colCache } from "../utils/col-cache.js";
2
2
  import { isEqual } from "../utils/under-dash.js";
3
3
  import { Enums } from "./enums.js";
4
4
  const DEFAULT_COLUMN_WIDTH = 9;
5
- // Column defines the column properties for 1 column.
6
- // This includes header rows, widths, key, (style), etc.
7
- // Worksheet will condense the columns as appropriate during serialization
5
+ /**
6
+ * Column defines the column properties for 1 column.
7
+ * This includes header rows, widths, key, (style), etc.
8
+ * Worksheet will condense the columns as appropriate during serialization
9
+ */
8
10
  class Column {
9
11
  constructor(worksheet, number, defn) {
10
12
  this._worksheet = worksheet;
@@ -20,6 +22,9 @@ class Column {
20
22
  get worksheet() {
21
23
  return this._worksheet;
22
24
  }
25
+ /**
26
+ * Column letter key
27
+ */
23
28
  get letter() {
24
29
  return colCache.n2l(this._number);
25
30
  }
@@ -60,8 +65,17 @@ class Column {
60
65
  }
61
66
  }
62
67
  get headers() {
63
- return this._header && this._header instanceof Array ? this._header : [this._header];
68
+ if (Array.isArray(this._header)) {
69
+ return this._header;
70
+ }
71
+ if (this._header !== undefined) {
72
+ return [this._header];
73
+ }
74
+ return [];
64
75
  }
76
+ /**
77
+ * Can be a string to set one row high header or an array to set multi-row high header
78
+ */
65
79
  get header() {
66
80
  return this._header;
67
81
  }
@@ -76,6 +90,9 @@ class Column {
76
90
  this._header = undefined;
77
91
  }
78
92
  }
93
+ /**
94
+ * The name of the properties associated with this column in each row
95
+ */
79
96
  get key() {
80
97
  return this._key;
81
98
  }
@@ -89,18 +106,27 @@ class Column {
89
106
  this._worksheet.setColumnKey(this._key, this);
90
107
  }
91
108
  }
109
+ /**
110
+ * Hides the column
111
+ */
92
112
  get hidden() {
93
113
  return !!this._hidden;
94
114
  }
95
115
  set hidden(value) {
96
116
  this._hidden = value;
97
117
  }
118
+ /**
119
+ * Set an outline level for columns
120
+ */
98
121
  get outlineLevel() {
99
122
  return this._outlineLevel || 0;
100
123
  }
101
124
  set outlineLevel(value) {
102
125
  this._outlineLevel = value;
103
126
  }
127
+ /**
128
+ * Indicate the collapsed state based on outlineLevel
129
+ */
104
130
  get collapsed() {
105
131
  return !!(this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelCol);
106
132
  }
@@ -117,6 +143,12 @@ class Column {
117
143
  this.outlineLevel === other.outlineLevel &&
118
144
  isEqual(this.style, other.style));
119
145
  }
146
+ equivalentToModel(model) {
147
+ return (this.width === model.width &&
148
+ this.hidden === model.hidden &&
149
+ this.outlineLevel === model.outlineLevel &&
150
+ isEqual(this.style, model.style));
151
+ }
120
152
  get isDefault() {
121
153
  if (this.isCustomWidth) {
122
154
  return false;
@@ -136,16 +168,25 @@ class Column {
136
168
  get headerCount() {
137
169
  return this.headers.length;
138
170
  }
139
- eachCell(options, iteratee) {
171
+ eachCell(optionsOrCallback, maybeCallback) {
140
172
  const colNumber = this.number;
141
- if (!iteratee) {
142
- iteratee = options;
173
+ let options;
174
+ let callback;
175
+ if (typeof optionsOrCallback === "function") {
143
176
  options = {};
177
+ callback = optionsOrCallback;
178
+ }
179
+ else {
180
+ options = optionsOrCallback;
181
+ callback = maybeCallback;
144
182
  }
145
183
  this._worksheet.eachRow(options, (row, rowNumber) => {
146
- iteratee(row.getCell(colNumber), rowNumber);
184
+ callback(row.getCell(colNumber), rowNumber);
147
185
  });
148
186
  }
187
+ /**
188
+ * The cell values in the column
189
+ */
149
190
  get values() {
150
191
  const v = [];
151
192
  this.eachCell((cell, rowNumber) => {
@@ -171,48 +212,59 @@ class Column {
171
212
  }
172
213
  // =========================================================================
173
214
  // styles
174
- _applyStyle(name, value) {
175
- this.style[name] = value;
176
- this.eachCell((cell) => {
177
- cell[name] = value;
178
- });
179
- return value;
180
- }
181
215
  get numFmt() {
182
216
  return this.style.numFmt;
183
217
  }
184
218
  set numFmt(value) {
185
- this._applyStyle("numFmt", value);
219
+ this.style.numFmt = value;
220
+ this.eachCell(cell => {
221
+ cell.numFmt = value;
222
+ });
186
223
  }
187
224
  get font() {
188
225
  return this.style.font;
189
226
  }
190
227
  set font(value) {
191
- this._applyStyle("font", value);
228
+ this.style.font = value;
229
+ this.eachCell(cell => {
230
+ cell.font = value;
231
+ });
192
232
  }
193
233
  get alignment() {
194
234
  return this.style.alignment;
195
235
  }
196
236
  set alignment(value) {
197
- this._applyStyle("alignment", value);
237
+ this.style.alignment = value;
238
+ this.eachCell(cell => {
239
+ cell.alignment = value;
240
+ });
198
241
  }
199
242
  get protection() {
200
243
  return this.style.protection;
201
244
  }
202
245
  set protection(value) {
203
- this._applyStyle("protection", value);
246
+ this.style.protection = value;
247
+ this.eachCell(cell => {
248
+ cell.protection = value;
249
+ });
204
250
  }
205
251
  get border() {
206
252
  return this.style.border;
207
253
  }
208
254
  set border(value) {
209
- this._applyStyle("border", value);
255
+ this.style.border = value;
256
+ this.eachCell(cell => {
257
+ cell.border = value;
258
+ });
210
259
  }
211
260
  get fill() {
212
261
  return this.style.fill;
213
262
  }
214
263
  set fill(value) {
215
- this._applyStyle("fill", value);
264
+ this.style.fill = value;
265
+ this.eachCell(cell => {
266
+ cell.fill = value;
267
+ });
216
268
  }
217
269
  // =============================================================================
218
270
  // static functions
@@ -227,7 +279,7 @@ class Column {
227
279
  col = null;
228
280
  }
229
281
  }
230
- else if (!col || !column.equivalentTo(col)) {
282
+ else if (!col || !column.equivalentToModel(col)) {
231
283
  col = {
232
284
  min: index + 1,
233
285
  max: index + 1,
@@ -13,11 +13,15 @@ class DefinedNames {
13
13
  // add a name to a cell. locStr in the form SheetName!$col$row or SheetName!$c1$r1:$c2:$r2
14
14
  add(locStr, name) {
15
15
  const location = colCache.decodeEx(locStr);
16
+ if ("error" in location) {
17
+ return; // Invalid reference, skip
18
+ }
16
19
  this.addEx(location, name);
17
20
  }
18
21
  addEx(location, name) {
19
22
  const matrix = this.getMatrix(name);
20
- if (location.top) {
23
+ if ("top" in location) {
24
+ // It's a range (DecodedRange has top/left/bottom/right from Location)
21
25
  for (let col = location.left; col <= location.right; col++) {
22
26
  for (let row = location.top; row <= location.bottom; row++) {
23
27
  const address = {
@@ -31,20 +35,54 @@ class DefinedNames {
31
35
  }
32
36
  }
33
37
  else {
38
+ // It's a single cell address
34
39
  matrix.addCellEx(location);
35
40
  }
36
41
  }
37
42
  remove(locStr, name) {
38
43
  const location = colCache.decodeEx(locStr);
44
+ if ("error" in location) {
45
+ return; // Invalid reference, skip
46
+ }
39
47
  this.removeEx(location, name);
40
48
  }
41
49
  removeEx(location, name) {
42
50
  const matrix = this.getMatrix(name);
43
- matrix.removeCellEx(location);
51
+ if ("top" in location) {
52
+ // Range - remove each cell
53
+ for (let col = location.left; col <= location.right; col++) {
54
+ for (let row = location.top; row <= location.bottom; row++) {
55
+ matrix.removeCellEx({
56
+ sheetName: location.sheetName,
57
+ address: colCache.n2l(col) + row,
58
+ row,
59
+ col
60
+ });
61
+ }
62
+ }
63
+ }
64
+ else {
65
+ matrix.removeCellEx(location);
66
+ }
44
67
  }
45
68
  removeAllNames(location) {
46
69
  Object.values(this.matrixMap).forEach((matrix) => {
47
- matrix.removeCellEx(location);
70
+ if ("top" in location) {
71
+ // Range - remove each cell
72
+ for (let col = location.left; col <= location.right; col++) {
73
+ for (let row = location.top; row <= location.bottom; row++) {
74
+ matrix.removeCellEx({
75
+ sheetName: location.sheetName,
76
+ address: colCache.n2l(col) + row,
77
+ row,
78
+ col
79
+ });
80
+ }
81
+ }
82
+ }
83
+ else {
84
+ matrix.removeCellEx(location);
85
+ }
48
86
  });
49
87
  }
50
88
  forEach(callback) {
@@ -56,12 +94,16 @@ class DefinedNames {
56
94
  }
57
95
  // get all the names of a cell
58
96
  getNames(addressStr) {
59
- return this.getNamesEx(colCache.decodeEx(addressStr));
97
+ const location = colCache.decodeEx(addressStr);
98
+ if ("error" in location || "top" in location) {
99
+ return []; // Invalid reference or range not supported
100
+ }
101
+ return this.getNamesEx(location);
60
102
  }
61
103
  getNamesEx(address) {
62
104
  return Object.entries(this.matrixMap)
63
105
  .map(([name, matrix]) => matrix.findCellEx(address, false) && name)
64
- .filter(Boolean);
106
+ .filter((name) => Boolean(name));
65
107
  }
66
108
  _explore(matrix, cell) {
67
109
  cell.mark = false;
@@ -69,9 +111,13 @@ class DefinedNames {
69
111
  const range = new Range(cell.row, cell.col, cell.row, cell.col, sheetName);
70
112
  let x;
71
113
  let y;
114
+ // Helper to get cell with proper type
115
+ const getCell = (row, col) => {
116
+ return matrix.findCellAt(sheetName, row, col);
117
+ };
72
118
  // grow vertical - only one col to worry about
73
119
  function vGrow(yy, edge) {
74
- const c = matrix.findCellAt(sheetName, yy, cell.col);
120
+ const c = getCell(yy, cell.col);
75
121
  if (!c || !c.mark) {
76
122
  return false;
77
123
  }
@@ -85,7 +131,7 @@ class DefinedNames {
85
131
  function hGrow(xx, edge) {
86
132
  const cells = [];
87
133
  for (y = range.top; y <= range.bottom; y++) {
88
- const c = matrix.findCellAt(sheetName, y, xx);
134
+ const c = getCell(y, xx);
89
135
  if (c && c.mark) {
90
136
  cells.push(c);
91
137
  }
@@ -36,19 +36,22 @@ class Image {
36
36
  if (type === "image") {
37
37
  if (typeof range === "string") {
38
38
  const decoded = colCache.decode(range);
39
- this.range = {
40
- tl: new Anchor(this.worksheet, { col: decoded.left, row: decoded.top }, -1),
41
- br: new Anchor(this.worksheet, { col: decoded.right, row: decoded.bottom }, 0),
42
- editAs: "oneCell"
43
- };
39
+ if ("top" in decoded) {
40
+ // It's a Location (range like "A1:C3")
41
+ this.range = {
42
+ tl: new Anchor(this.worksheet, { col: decoded.left, row: decoded.top }, -1),
43
+ br: new Anchor(this.worksheet, { col: decoded.right, row: decoded.bottom }, 0),
44
+ editAs: "oneCell"
45
+ };
46
+ }
44
47
  }
45
- else {
48
+ else if (range) {
46
49
  this.range = {
47
50
  tl: new Anchor(this.worksheet, range.tl, 0),
48
- br: range.br && new Anchor(this.worksheet, range.br, 0),
51
+ br: range.br ? new Anchor(this.worksheet, range.br, 0) : undefined,
49
52
  ext: range.ext,
50
53
  editAs: range.editAs,
51
- hyperlinks: hyperlinks || range.hyperlinks
54
+ hyperlinks: hyperlinks || ("hyperlinks" in range ? range.hyperlinks : undefined)
52
55
  };
53
56
  }
54
57
  }