@yuanliwei/exceljs 4.4.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 (185) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +3024 -0
  3. package/README_zh.md +2878 -0
  4. package/excel.js +13 -0
  5. package/index.d.ts +2040 -0
  6. package/index.ts +2 -0
  7. package/lib/csv/csv.js +191 -0
  8. package/lib/csv/line-buffer.js +74 -0
  9. package/lib/csv/stream-converter.js +135 -0
  10. package/lib/doc/anchor.js +91 -0
  11. package/lib/doc/cell.js +1124 -0
  12. package/lib/doc/column.js +320 -0
  13. package/lib/doc/data/theme1.json +234 -0
  14. package/lib/doc/data-validations.js +19 -0
  15. package/lib/doc/defined-names.js +196 -0
  16. package/lib/doc/enums.js +48 -0
  17. package/lib/doc/image.js +59 -0
  18. package/lib/doc/modelcontainer.js +18 -0
  19. package/lib/doc/note.js +65 -0
  20. package/lib/doc/pivot-table.js +132 -0
  21. package/lib/doc/range.js +257 -0
  22. package/lib/doc/row.js +415 -0
  23. package/lib/doc/table.js +465 -0
  24. package/lib/doc/workbook.js +224 -0
  25. package/lib/doc/worksheet.js +949 -0
  26. package/lib/exceljs.bare.js +13 -0
  27. package/lib/exceljs.browser.js +36 -0
  28. package/lib/exceljs.nodejs.js +14 -0
  29. package/lib/stream/xlsx/hyperlink-reader.js +83 -0
  30. package/lib/stream/xlsx/sheet-comments-writer.js +121 -0
  31. package/lib/stream/xlsx/sheet-rels-writer.js +119 -0
  32. package/lib/stream/xlsx/workbook-reader.js +337 -0
  33. package/lib/stream/xlsx/workbook-writer.js +347 -0
  34. package/lib/stream/xlsx/worksheet-reader.js +374 -0
  35. package/lib/stream/xlsx/worksheet-writer.js +717 -0
  36. package/lib/utils/auto-drain.js +15 -0
  37. package/lib/utils/browser-buffer-decode.js +14 -0
  38. package/lib/utils/browser-buffer-encode.js +15 -0
  39. package/lib/utils/cell-matrix.js +165 -0
  40. package/lib/utils/col-cache.js +287 -0
  41. package/lib/utils/copy-style.js +43 -0
  42. package/lib/utils/encryptor.js +55 -0
  43. package/lib/utils/iterate-stream.js +48 -0
  44. package/lib/utils/parse-sax.js +30 -0
  45. package/lib/utils/shared-formula.js +44 -0
  46. package/lib/utils/shared-strings.js +35 -0
  47. package/lib/utils/stream-base64.js +72 -0
  48. package/lib/utils/stream-buf.js +364 -0
  49. package/lib/utils/string-buf.js +82 -0
  50. package/lib/utils/string-builder.js +35 -0
  51. package/lib/utils/stuttered-pipe.js +67 -0
  52. package/lib/utils/typed-stack.js +24 -0
  53. package/lib/utils/under-dash.js +184 -0
  54. package/lib/utils/utils.js +205 -0
  55. package/lib/utils/xml-stream.js +169 -0
  56. package/lib/utils/zip-stream.js +87 -0
  57. package/lib/xlsx/.rels +11 -0
  58. package/lib/xlsx/calcChain.xml +6 -0
  59. package/lib/xlsx/core.xml +7 -0
  60. package/lib/xlsx/defaultnumformats.js +153 -0
  61. package/lib/xlsx/rel-type.js +20 -0
  62. package/lib/xlsx/styles.xml +41 -0
  63. package/lib/xlsx/workbook.xml +16 -0
  64. package/lib/xlsx/xform/base-xform.js +145 -0
  65. package/lib/xlsx/xform/book/defined-name-xform.js +91 -0
  66. package/lib/xlsx/xform/book/sheet-xform.js +34 -0
  67. package/lib/xlsx/xform/book/workbook-calc-properties-xform.js +26 -0
  68. package/lib/xlsx/xform/book/workbook-pivot-cache-xform.js +29 -0
  69. package/lib/xlsx/xform/book/workbook-properties-xform.js +29 -0
  70. package/lib/xlsx/xform/book/workbook-view-xform.js +53 -0
  71. package/lib/xlsx/xform/book/workbook-xform.js +259 -0
  72. package/lib/xlsx/xform/comment/comment-xform.js +105 -0
  73. package/lib/xlsx/xform/comment/comments-xform.js +82 -0
  74. package/lib/xlsx/xform/comment/style/vml-position-xform.js +39 -0
  75. package/lib/xlsx/xform/comment/style/vml-protection-xform.js +36 -0
  76. package/lib/xlsx/xform/comment/vml-anchor-xform.js +60 -0
  77. package/lib/xlsx/xform/comment/vml-client-data-xform.js +95 -0
  78. package/lib/xlsx/xform/comment/vml-notes-xform.js +107 -0
  79. package/lib/xlsx/xform/comment/vml-shape-xform.js +95 -0
  80. package/lib/xlsx/xform/comment/vml-textbox-xform.js +64 -0
  81. package/lib/xlsx/xform/composite-xform.js +56 -0
  82. package/lib/xlsx/xform/core/app-heading-pairs-xform.js +32 -0
  83. package/lib/xlsx/xform/core/app-titles-of-parts-xform.js +28 -0
  84. package/lib/xlsx/xform/core/app-xform.js +100 -0
  85. package/lib/xlsx/xform/core/content-types-xform.js +135 -0
  86. package/lib/xlsx/xform/core/core-xform.js +136 -0
  87. package/lib/xlsx/xform/core/relationship-xform.js +25 -0
  88. package/lib/xlsx/xform/core/relationships-xform.js +73 -0
  89. package/lib/xlsx/xform/drawing/base-cell-anchor-xform.js +48 -0
  90. package/lib/xlsx/xform/drawing/blip-fill-xform.js +71 -0
  91. package/lib/xlsx/xform/drawing/blip-xform.js +42 -0
  92. package/lib/xlsx/xform/drawing/c-nv-pic-pr-xform.js +38 -0
  93. package/lib/xlsx/xform/drawing/c-nv-pr-xform.js +68 -0
  94. package/lib/xlsx/xform/drawing/cell-position-xform.js +77 -0
  95. package/lib/xlsx/xform/drawing/drawing-xform.js +109 -0
  96. package/lib/xlsx/xform/drawing/ext-lst-xform.js +43 -0
  97. package/lib/xlsx/xform/drawing/ext-xform.js +44 -0
  98. package/lib/xlsx/xform/drawing/hlink-click-xform.js +41 -0
  99. package/lib/xlsx/xform/drawing/nv-pic-pr-xform.js +65 -0
  100. package/lib/xlsx/xform/drawing/one-cell-anchor-xform.js +63 -0
  101. package/lib/xlsx/xform/drawing/pic-xform.js +77 -0
  102. package/lib/xlsx/xform/drawing/sp-pr.js +17 -0
  103. package/lib/xlsx/xform/drawing/two-cell-anchor-xform.js +62 -0
  104. package/lib/xlsx/xform/list-xform.js +95 -0
  105. package/lib/xlsx/xform/pivot-table/cache-field.js +43 -0
  106. package/lib/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +77 -0
  107. package/lib/xlsx/xform/pivot-table/pivot-cache-records-xform.js +103 -0
  108. package/lib/xlsx/xform/pivot-table/pivot-table-xform.js +189 -0
  109. package/lib/xlsx/xform/sheet/auto-filter-xform.js +38 -0
  110. package/lib/xlsx/xform/sheet/cell-xform.js +498 -0
  111. package/lib/xlsx/xform/sheet/cf/cf-rule-xform.js +301 -0
  112. package/lib/xlsx/xform/sheet/cf/cfvo-xform.js +27 -0
  113. package/lib/xlsx/xform/sheet/cf/color-scale-xform.js +45 -0
  114. package/lib/xlsx/xform/sheet/cf/conditional-formatting-xform.js +48 -0
  115. package/lib/xlsx/xform/sheet/cf/conditional-formattings-xform.js +92 -0
  116. package/lib/xlsx/xform/sheet/cf/databar-xform.js +49 -0
  117. package/lib/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +87 -0
  118. package/lib/xlsx/xform/sheet/cf/formula-xform.js +25 -0
  119. package/lib/xlsx/xform/sheet/cf/icon-set-xform.js +47 -0
  120. package/lib/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +27 -0
  121. package/lib/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +98 -0
  122. package/lib/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +43 -0
  123. package/lib/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +62 -0
  124. package/lib/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +50 -0
  125. package/lib/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +98 -0
  126. package/lib/xlsx/xform/sheet/cf-ext/f-ext-xform.js +25 -0
  127. package/lib/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +73 -0
  128. package/lib/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +25 -0
  129. package/lib/xlsx/xform/sheet/col-xform.js +86 -0
  130. package/lib/xlsx/xform/sheet/data-validations-xform.js +257 -0
  131. package/lib/xlsx/xform/sheet/dimension-xform.js +29 -0
  132. package/lib/xlsx/xform/sheet/drawing-xform.js +33 -0
  133. package/lib/xlsx/xform/sheet/ext-lst-xform.js +86 -0
  134. package/lib/xlsx/xform/sheet/header-footer-xform.js +146 -0
  135. package/lib/xlsx/xform/sheet/hyperlink-xform.js +54 -0
  136. package/lib/xlsx/xform/sheet/merge-cell-xform.js +27 -0
  137. package/lib/xlsx/xform/sheet/merges.js +56 -0
  138. package/lib/xlsx/xform/sheet/outline-properties-xform.js +43 -0
  139. package/lib/xlsx/xform/sheet/page-breaks-xform.js +27 -0
  140. package/lib/xlsx/xform/sheet/page-margins-xform.js +49 -0
  141. package/lib/xlsx/xform/sheet/page-setup-properties-xform.js +35 -0
  142. package/lib/xlsx/xform/sheet/page-setup-xform.js +103 -0
  143. package/lib/xlsx/xform/sheet/picture-xform.js +33 -0
  144. package/lib/xlsx/xform/sheet/print-options-xform.js +49 -0
  145. package/lib/xlsx/xform/sheet/row-breaks-xform.js +39 -0
  146. package/lib/xlsx/xform/sheet/row-xform.js +142 -0
  147. package/lib/xlsx/xform/sheet/sheet-format-properties-xform.js +55 -0
  148. package/lib/xlsx/xform/sheet/sheet-properties-xform.js +90 -0
  149. package/lib/xlsx/xform/sheet/sheet-protection-xform.js +89 -0
  150. package/lib/xlsx/xform/sheet/sheet-view-xform.js +202 -0
  151. package/lib/xlsx/xform/sheet/table-part-xform.js +33 -0
  152. package/lib/xlsx/xform/sheet/worksheet-xform.js +548 -0
  153. package/lib/xlsx/xform/simple/boolean-xform.js +31 -0
  154. package/lib/xlsx/xform/simple/date-xform.js +66 -0
  155. package/lib/xlsx/xform/simple/float-xform.js +51 -0
  156. package/lib/xlsx/xform/simple/integer-xform.js +57 -0
  157. package/lib/xlsx/xform/simple/string-xform.js +51 -0
  158. package/lib/xlsx/xform/static-xform.js +64 -0
  159. package/lib/xlsx/xform/strings/phonetic-text-xform.js +98 -0
  160. package/lib/xlsx/xform/strings/rich-text-xform.js +101 -0
  161. package/lib/xlsx/xform/strings/shared-string-xform.js +102 -0
  162. package/lib/xlsx/xform/strings/shared-strings-xform.js +127 -0
  163. package/lib/xlsx/xform/strings/text-xform.js +44 -0
  164. package/lib/xlsx/xform/style/alignment-xform.js +172 -0
  165. package/lib/xlsx/xform/style/border-xform.js +207 -0
  166. package/lib/xlsx/xform/style/color-xform.js +63 -0
  167. package/lib/xlsx/xform/style/dxf-xform.js +111 -0
  168. package/lib/xlsx/xform/style/fill-xform.js +364 -0
  169. package/lib/xlsx/xform/style/font-xform.js +102 -0
  170. package/lib/xlsx/xform/style/numfmt-xform.js +63 -0
  171. package/lib/xlsx/xform/style/protection-xform.js +60 -0
  172. package/lib/xlsx/xform/style/style-xform.js +125 -0
  173. package/lib/xlsx/xform/style/styles-xform.js +527 -0
  174. package/lib/xlsx/xform/style/underline-xform.js +47 -0
  175. package/lib/xlsx/xform/table/auto-filter-xform.js +81 -0
  176. package/lib/xlsx/xform/table/custom-filter-xform.js +33 -0
  177. package/lib/xlsx/xform/table/filter-column-xform.js +96 -0
  178. package/lib/xlsx/xform/table/filter-xform.js +31 -0
  179. package/lib/xlsx/xform/table/table-column-xform.js +44 -0
  180. package/lib/xlsx/xform/table/table-style-info-xform.js +41 -0
  181. package/lib/xlsx/xform/table/table-xform.js +131 -0
  182. package/lib/xlsx/xlsx.js +774 -0
  183. package/lib/xlsx/xml/theme1.js +3 -0
  184. package/lib/xlsx/xml/theme1.xml +318 -0
  185. package/package.json +149 -0
@@ -0,0 +1,465 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ const colCache = require('../utils/col-cache');
3
+
4
+ class Column {
5
+ // wrapper around column model, allowing access and manipulation
6
+ constructor(table, column, index) {
7
+ this.table = table;
8
+ this.column = column;
9
+ this.index = index;
10
+ }
11
+
12
+ _set(name, value) {
13
+ this.table.cacheState();
14
+ this.column[name] = value;
15
+ }
16
+
17
+ /* eslint-disable lines-between-class-members */
18
+ get name() {
19
+ return this.column.name;
20
+ }
21
+ set name(value) {
22
+ this._set('name', value);
23
+ }
24
+
25
+ get filterButton() {
26
+ return this.column.filterButton;
27
+ }
28
+ set filterButton(value) {
29
+ this.column.filterButton = value;
30
+ }
31
+
32
+ get style() {
33
+ return this.column.style;
34
+ }
35
+ set style(value) {
36
+ this.column.style = value;
37
+ }
38
+
39
+ get totalsRowLabel() {
40
+ return this.column.totalsRowLabel;
41
+ }
42
+ set totalsRowLabel(value) {
43
+ this._set('totalsRowLabel', value);
44
+ }
45
+
46
+ get totalsRowFunction() {
47
+ return this.column.totalsRowFunction;
48
+ }
49
+ set totalsRowFunction(value) {
50
+ this._set('totalsRowFunction', value);
51
+ }
52
+
53
+ get totalsRowResult() {
54
+ return this.column.totalsRowResult;
55
+ }
56
+ set totalsRowResult(value) {
57
+ this._set('totalsRowResult', value);
58
+ }
59
+
60
+ get totalsRowFormula() {
61
+ return this.column.totalsRowFormula;
62
+ }
63
+ set totalsRowFormula(value) {
64
+ this._set('totalsRowFormula', value);
65
+ }
66
+ /* eslint-enable lines-between-class-members */
67
+ }
68
+
69
+ class Table {
70
+ constructor(worksheet, table) {
71
+ this.worksheet = worksheet;
72
+ if (table) {
73
+ this.table = table;
74
+ // check things are ok first
75
+ this.validate();
76
+
77
+ this.store();
78
+ }
79
+ }
80
+
81
+ getFormula(column) {
82
+ // get the correct formula to apply to the totals row
83
+ switch (column.totalsRowFunction) {
84
+ case 'none':
85
+ return null;
86
+ case 'average':
87
+ return `SUBTOTAL(101,${this.table.name}[${column.name}])`;
88
+ case 'countNums':
89
+ return `SUBTOTAL(102,${this.table.name}[${column.name}])`;
90
+ case 'count':
91
+ return `SUBTOTAL(103,${this.table.name}[${column.name}])`;
92
+ case 'max':
93
+ return `SUBTOTAL(104,${this.table.name}[${column.name}])`;
94
+ case 'min':
95
+ return `SUBTOTAL(105,${this.table.name}[${column.name}])`;
96
+ case 'stdDev':
97
+ return `SUBTOTAL(106,${this.table.name}[${column.name}])`;
98
+ case 'var':
99
+ return `SUBTOTAL(107,${this.table.name}[${column.name}])`;
100
+ case 'sum':
101
+ return `SUBTOTAL(109,${this.table.name}[${column.name}])`;
102
+ case 'custom':
103
+ return column.totalsRowFormula;
104
+ default:
105
+ throw new Error(`Invalid Totals Row Function: ${column.totalsRowFunction}`);
106
+ }
107
+ }
108
+
109
+ get width() {
110
+ // width of the table
111
+ return this.table.columns.length;
112
+ }
113
+
114
+ get height() {
115
+ // height of the table data
116
+ return this.table.rows.length;
117
+ }
118
+
119
+ get filterHeight() {
120
+ // height of the table data plus optional header row
121
+ return this.height + (this.table.headerRow ? 1 : 0);
122
+ }
123
+
124
+ get tableHeight() {
125
+ // full height of the table on the sheet
126
+ return this.filterHeight + (this.table.totalsRow ? 1 : 0);
127
+ }
128
+
129
+ validate() {
130
+ const {table} = this;
131
+ // set defaults and check is valid
132
+ const assign = (o, name, dflt) => {
133
+ if (o[name] === undefined) {
134
+ o[name] = dflt;
135
+ }
136
+ };
137
+ assign(table, 'headerRow', true);
138
+ assign(table, 'totalsRow', false);
139
+
140
+ assign(table, 'style', {});
141
+ assign(table.style, 'theme', 'TableStyleMedium2');
142
+ assign(table.style, 'showFirstColumn', false);
143
+ assign(table.style, 'showLastColumn', false);
144
+ assign(table.style, 'showRowStripes', false);
145
+ assign(table.style, 'showColumnStripes', false);
146
+
147
+ const assert = (test, message) => {
148
+ if (!test) {
149
+ throw new Error(message);
150
+ }
151
+ };
152
+ assert(table.ref, 'Table must have ref');
153
+ assert(table.columns, 'Table must have column definitions');
154
+ assert(table.rows, 'Table must have row definitions');
155
+
156
+ table.tl = colCache.decodeAddress(table.ref);
157
+ const {row, col} = table.tl;
158
+ assert(row > 0, 'Table must be on valid row');
159
+ assert(col > 0, 'Table must be on valid col');
160
+
161
+ const {width, filterHeight, tableHeight} = this;
162
+
163
+ // autoFilterRef is a range that includes optional headers only
164
+ table.autoFilterRef = colCache.encode(row, col, row + filterHeight - 1, col + width - 1);
165
+
166
+ // tableRef is a range that includes optional headers and totals
167
+ table.tableRef = colCache.encode(row, col, row + tableHeight - 1, col + width - 1);
168
+
169
+ table.columns.forEach((column, i) => {
170
+ assert(column.name, `Column ${i} must have a name`);
171
+ if (i === 0) {
172
+ assign(column, 'totalsRowLabel', 'Total');
173
+ } else {
174
+ assign(column, 'totalsRowFunction', 'none');
175
+ column.totalsRowFormula = this.getFormula(column);
176
+ }
177
+ });
178
+ }
179
+
180
+ store() {
181
+ // where the table needs to store table data, headers, footers in
182
+ // the sheet...
183
+ const assignStyle = (cell, style) => {
184
+ if (style) {
185
+ Object.keys(style).forEach(key => {
186
+ cell.style[key] = style[key];
187
+ });
188
+ }
189
+ };
190
+
191
+ const {worksheet, table} = this;
192
+ const {row, col} = table.tl;
193
+ let count = 0;
194
+ if (table.headerRow) {
195
+ const r = worksheet.getRow(row + count++);
196
+ table.columns.forEach((column, j) => {
197
+ const {style, name} = column;
198
+ const cell = r.getCell(col + j);
199
+ cell.value = name;
200
+ assignStyle(cell, style);
201
+ });
202
+ }
203
+ table.rows.forEach(data => {
204
+ const r = worksheet.getRow(row + count++);
205
+ data.forEach((value, j) => {
206
+ const cell = r.getCell(col + j);
207
+ cell.value = value;
208
+
209
+ assignStyle(cell, table.columns[j].style);
210
+ });
211
+ });
212
+
213
+ if (table.totalsRow) {
214
+ const r = worksheet.getRow(row + count++);
215
+ table.columns.forEach((column, j) => {
216
+ const cell = r.getCell(col + j);
217
+ if (j === 0) {
218
+ cell.value = column.totalsRowLabel;
219
+ } else {
220
+ const formula = this.getFormula(column);
221
+ if (formula) {
222
+ cell.value = {
223
+ formula: column.totalsRowFormula,
224
+ result: column.totalsRowResult,
225
+ };
226
+ } else {
227
+ cell.value = null;
228
+ }
229
+ }
230
+
231
+ assignStyle(cell, column.style);
232
+ });
233
+ }
234
+ }
235
+
236
+ load(worksheet) {
237
+ // where the table will read necessary features from a loaded sheet
238
+ const {table} = this;
239
+ const {row, col} = table.tl;
240
+ let count = 0;
241
+ if (table.headerRow) {
242
+ const r = worksheet.getRow(row + count++);
243
+ table.columns.forEach((column, j) => {
244
+ const cell = r.getCell(col + j);
245
+ cell.value = column.name;
246
+ });
247
+ }
248
+ table.rows.forEach(data => {
249
+ const r = worksheet.getRow(row + count++);
250
+ data.forEach((value, j) => {
251
+ const cell = r.getCell(col + j);
252
+ cell.value = value;
253
+ });
254
+ });
255
+
256
+ if (table.totalsRow) {
257
+ const r = worksheet.getRow(row + count++);
258
+ table.columns.forEach((column, j) => {
259
+ const cell = r.getCell(col + j);
260
+ if (j === 0) {
261
+ cell.value = column.totalsRowLabel;
262
+ } else {
263
+ const formula = this.getFormula(column);
264
+ if (formula) {
265
+ cell.value = {
266
+ formula: column.totalsRowFormula,
267
+ result: column.totalsRowResult,
268
+ };
269
+ }
270
+ }
271
+ });
272
+ }
273
+ }
274
+
275
+ get model() {
276
+ return this.table;
277
+ }
278
+
279
+ set model(value) {
280
+ this.table = value;
281
+ }
282
+
283
+ // ================================================================
284
+ // TODO: Mutating methods
285
+ cacheState() {
286
+ if (!this._cache) {
287
+ this._cache = {
288
+ ref: this.ref,
289
+ width: this.width,
290
+ tableHeight: this.tableHeight,
291
+ };
292
+ }
293
+ }
294
+
295
+ commit() {
296
+ // changes may have been made that might have on-sheet effects
297
+ if (!this._cache) {
298
+ return;
299
+ }
300
+
301
+ // check things are ok first
302
+ this.validate();
303
+
304
+ const ref = colCache.decodeAddress(this._cache.ref);
305
+ if (this.ref !== this._cache.ref) {
306
+ // wipe out whole table footprint at previous location
307
+ for (let i = 0; i < this._cache.tableHeight; i++) {
308
+ const row = this.worksheet.getRow(ref.row + i);
309
+ for (let j = 0; j < this._cache.width; j++) {
310
+ const cell = row.getCell(ref.col + j);
311
+ cell.value = null;
312
+ }
313
+ }
314
+ } else {
315
+ // clear out below table if it has shrunk
316
+ for (let i = this.tableHeight; i < this._cache.tableHeight; i++) {
317
+ const row = this.worksheet.getRow(ref.row + i);
318
+ for (let j = 0; j < this._cache.width; j++) {
319
+ const cell = row.getCell(ref.col + j);
320
+ cell.value = null;
321
+ }
322
+ }
323
+
324
+ // clear out to right of table if it has lost columns
325
+ for (let i = 0; i < this.tableHeight; i++) {
326
+ const row = this.worksheet.getRow(ref.row + i);
327
+ for (let j = this.width; j < this._cache.width; j++) {
328
+ const cell = row.getCell(ref.col + j);
329
+ cell.value = null;
330
+ }
331
+ }
332
+ }
333
+
334
+ this.store();
335
+ }
336
+
337
+ addRow(values, rowNumber) {
338
+ // Add a row of data, either insert at rowNumber or append
339
+ this.cacheState();
340
+
341
+ if (rowNumber === undefined) {
342
+ this.table.rows.push(values);
343
+ } else {
344
+ this.table.rows.splice(rowNumber, 0, values);
345
+ }
346
+ }
347
+
348
+ removeRows(rowIndex, count = 1) {
349
+ // Remove a rows of data
350
+ this.cacheState();
351
+ this.table.rows.splice(rowIndex, count);
352
+ }
353
+
354
+ getColumn(colIndex) {
355
+ const column = this.table.columns[colIndex];
356
+ return new Column(this, column, colIndex);
357
+ }
358
+
359
+ addColumn(column, values, colIndex) {
360
+ // Add a new column, including column defn and values
361
+ // Inserts at colNumber or adds to the right
362
+ this.cacheState();
363
+
364
+ if (colIndex === undefined) {
365
+ this.table.columns.push(column);
366
+ this.table.rows.forEach((row, i) => {
367
+ row.push(values[i]);
368
+ });
369
+ } else {
370
+ this.table.columns.splice(colIndex, 0, column);
371
+ this.table.rows.forEach((row, i) => {
372
+ row.splice(colIndex, 0, values[i]);
373
+ });
374
+ }
375
+ }
376
+
377
+ removeColumns(colIndex, count = 1) {
378
+ // Remove a column with data
379
+ this.cacheState();
380
+
381
+ this.table.columns.splice(colIndex, count);
382
+ this.table.rows.forEach(row => {
383
+ row.splice(colIndex, count);
384
+ });
385
+ }
386
+
387
+ _assign(target, prop, value) {
388
+ this.cacheState();
389
+ target[prop] = value;
390
+ }
391
+
392
+ /* eslint-disable lines-between-class-members */
393
+ get ref() {
394
+ return this.table.ref;
395
+ }
396
+ set ref(value) {
397
+ this._assign(this.table, 'ref', value);
398
+ }
399
+
400
+ get name() {
401
+ return this.table.name;
402
+ }
403
+ set name(value) {
404
+ this.table.name = value;
405
+ }
406
+
407
+ get displayName() {
408
+ return this.table.displyName || this.table.name;
409
+ }
410
+ set displayNamename(value) {
411
+ this.table.displayName = value;
412
+ }
413
+
414
+ get headerRow() {
415
+ return this.table.headerRow;
416
+ }
417
+ set headerRow(value) {
418
+ this._assign(this.table, 'headerRow', value);
419
+ }
420
+
421
+ get totalsRow() {
422
+ return this.table.totalsRow;
423
+ }
424
+ set totalsRow(value) {
425
+ this._assign(this.table, 'totalsRow', value);
426
+ }
427
+
428
+ get theme() {
429
+ return this.table.style.name;
430
+ }
431
+ set theme(value) {
432
+ this.table.style.name = value;
433
+ }
434
+
435
+ get showFirstColumn() {
436
+ return this.table.style.showFirstColumn;
437
+ }
438
+ set showFirstColumn(value) {
439
+ this.table.style.showFirstColumn = value;
440
+ }
441
+
442
+ get showLastColumn() {
443
+ return this.table.style.showLastColumn;
444
+ }
445
+ set showLastColumn(value) {
446
+ this.table.style.showLastColumn = value;
447
+ }
448
+
449
+ get showRowStripes() {
450
+ return this.table.style.showRowStripes;
451
+ }
452
+ set showRowStripes(value) {
453
+ this.table.style.showRowStripes = value;
454
+ }
455
+
456
+ get showColumnStripes() {
457
+ return this.table.style.showColumnStripes;
458
+ }
459
+ set showColumnStripes(value) {
460
+ this.table.style.showColumnStripes = value;
461
+ }
462
+ /* eslint-enable lines-between-class-members */
463
+ }
464
+
465
+ module.exports = Table;
@@ -0,0 +1,224 @@
1
+ 'use strict';
2
+
3
+ const Worksheet = require('./worksheet');
4
+ const DefinedNames = require('./defined-names');
5
+ const XLSX = require('../xlsx/xlsx');
6
+ const CSV = require('../csv/csv');
7
+
8
+ // Workbook requirements
9
+ // Load and Save from file and stream
10
+ // Access/Add/Delete individual worksheets
11
+ // Manage String table, Hyperlink table, etc.
12
+ // Manage scaffolding for contained objects to write to/read from
13
+
14
+ class Workbook {
15
+ constructor() {
16
+ this.category = '';
17
+ this.company = '';
18
+ this.created = new Date();
19
+ this.description = '';
20
+ this.keywords = '';
21
+ this.manager = '';
22
+ this.modified = this.created;
23
+ this.properties = {};
24
+ this.calcProperties = {};
25
+ this._worksheets = [];
26
+ this.subject = '';
27
+ this.title = '';
28
+ this.views = [];
29
+ this.media = [];
30
+ this.pivotTables = [];
31
+ this._definedNames = new DefinedNames();
32
+ }
33
+
34
+ get xlsx() {
35
+ if (!this._xlsx) this._xlsx = new XLSX(this);
36
+ return this._xlsx;
37
+ }
38
+
39
+ get csv() {
40
+ if (!this._csv) this._csv = new CSV(this);
41
+ return this._csv;
42
+ }
43
+
44
+ get nextId() {
45
+ // find the next unique spot to add worksheet
46
+ for (let i = 1; i < this._worksheets.length; i++) {
47
+ if (!this._worksheets[i]) {
48
+ return i;
49
+ }
50
+ }
51
+ return this._worksheets.length || 1;
52
+ }
53
+
54
+ addWorksheet(name, options) {
55
+ const id = this.nextId;
56
+
57
+ // if options is a color, call it tabColor (and signal deprecated message)
58
+ if (options) {
59
+ if (typeof options === 'string') {
60
+ // eslint-disable-next-line no-console
61
+ console.trace(
62
+ 'tabColor argument is now deprecated. Please use workbook.addWorksheet(name, {properties: { tabColor: { argb: "rbg value" } }'
63
+ );
64
+ options = {
65
+ properties: {
66
+ tabColor: {argb: options},
67
+ },
68
+ };
69
+ } else if (options.argb || options.theme || options.indexed) {
70
+ // eslint-disable-next-line no-console
71
+ console.trace(
72
+ 'tabColor argument is now deprecated. Please use workbook.addWorksheet(name, {properties: { tabColor: { ... } }'
73
+ );
74
+ options = {
75
+ properties: {
76
+ tabColor: options,
77
+ },
78
+ };
79
+ }
80
+ }
81
+
82
+ const lastOrderNo = this._worksheets.reduce((acc, ws) => ((ws && ws.orderNo) > acc ? ws.orderNo : acc), 0);
83
+ const worksheetOptions = Object.assign({}, options, {
84
+ id,
85
+ name,
86
+ orderNo: lastOrderNo + 1,
87
+ workbook: this,
88
+ });
89
+
90
+ const worksheet = new Worksheet(worksheetOptions);
91
+
92
+ this._worksheets[id] = worksheet;
93
+ return worksheet;
94
+ }
95
+
96
+ removeWorksheetEx(worksheet) {
97
+ delete this._worksheets[worksheet.id];
98
+ }
99
+
100
+ removeWorksheet(id) {
101
+ const worksheet = this.getWorksheet(id);
102
+ if (worksheet) {
103
+ worksheet.destroy();
104
+ }
105
+ }
106
+
107
+ getWorksheet(id) {
108
+ if (id === undefined) {
109
+ return this._worksheets.find(Boolean);
110
+ }
111
+ if (typeof id === 'number') {
112
+ return this._worksheets[id];
113
+ }
114
+ if (typeof id === 'string') {
115
+ return this._worksheets.find(worksheet => worksheet && worksheet.name === id);
116
+ }
117
+ return undefined;
118
+ }
119
+
120
+ get worksheets() {
121
+ // return a clone of _worksheets
122
+ return this._worksheets
123
+ .slice(1)
124
+ .sort((a, b) => a.orderNo - b.orderNo)
125
+ .filter(Boolean);
126
+ }
127
+
128
+ eachSheet(iteratee) {
129
+ this.worksheets.forEach(sheet => {
130
+ iteratee(sheet, sheet.id);
131
+ });
132
+ }
133
+
134
+ get definedNames() {
135
+ return this._definedNames;
136
+ }
137
+
138
+ clearThemes() {
139
+ // Note: themes are not an exposed feature, meddle at your peril!
140
+ this._themes = undefined;
141
+ }
142
+
143
+ addImage(image) {
144
+ // TODO: validation?
145
+ const id = this.media.length;
146
+ this.media.push(Object.assign({}, image, {type: 'image'}));
147
+ return id;
148
+ }
149
+
150
+ getImage(id) {
151
+ return this.media[id];
152
+ }
153
+
154
+ get model() {
155
+ return {
156
+ creator: this.creator || 'Unknown',
157
+ lastModifiedBy: this.lastModifiedBy || 'Unknown',
158
+ lastPrinted: this.lastPrinted,
159
+ created: this.created,
160
+ modified: this.modified,
161
+ properties: this.properties,
162
+ worksheets: this.worksheets.map(worksheet => worksheet.model),
163
+ sheets: this.worksheets.map(ws => ws.model).filter(Boolean),
164
+ definedNames: this._definedNames.model,
165
+ views: this.views,
166
+ company: this.company,
167
+ manager: this.manager,
168
+ title: this.title,
169
+ subject: this.subject,
170
+ keywords: this.keywords,
171
+ category: this.category,
172
+ description: this.description,
173
+ language: this.language,
174
+ revision: this.revision,
175
+ contentStatus: this.contentStatus,
176
+ themes: this._themes,
177
+ media: this.media,
178
+ pivotTables: this.pivotTables,
179
+ calcProperties: this.calcProperties,
180
+ };
181
+ }
182
+
183
+ set model(value) {
184
+ this.creator = value.creator;
185
+ this.lastModifiedBy = value.lastModifiedBy;
186
+ this.lastPrinted = value.lastPrinted;
187
+ this.created = value.created;
188
+ this.modified = value.modified;
189
+ this.company = value.company;
190
+ this.manager = value.manager;
191
+ this.title = value.title;
192
+ this.subject = value.subject;
193
+ this.keywords = value.keywords;
194
+ this.category = value.category;
195
+ this.description = value.description;
196
+ this.language = value.language;
197
+ this.revision = value.revision;
198
+ this.contentStatus = value.contentStatus;
199
+
200
+ this.properties = value.properties;
201
+ this.calcProperties = value.calcProperties;
202
+ this._worksheets = [];
203
+ value.worksheets.forEach(worksheetModel => {
204
+ const {id, name, state} = worksheetModel;
205
+ const orderNo = value.sheets && value.sheets.findIndex(ws => ws.id === id);
206
+ const worksheet = (this._worksheets[id] = new Worksheet({
207
+ id,
208
+ name,
209
+ orderNo,
210
+ state,
211
+ workbook: this,
212
+ }));
213
+ worksheet.model = worksheetModel;
214
+ });
215
+
216
+ this._definedNames.model = value.definedNames;
217
+ this.views = value.views;
218
+ this._themes = value.themes;
219
+ this.media = value.media || [];
220
+ this.pivotTables = value.pivotTables || [];
221
+ }
222
+ }
223
+
224
+ module.exports = Workbook;