@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.
- package/LICENSE +22 -0
- package/README.md +3024 -0
- package/README_zh.md +2878 -0
- package/excel.js +13 -0
- package/index.d.ts +2040 -0
- package/index.ts +2 -0
- package/lib/csv/csv.js +191 -0
- package/lib/csv/line-buffer.js +74 -0
- package/lib/csv/stream-converter.js +135 -0
- package/lib/doc/anchor.js +91 -0
- package/lib/doc/cell.js +1124 -0
- package/lib/doc/column.js +320 -0
- package/lib/doc/data/theme1.json +234 -0
- package/lib/doc/data-validations.js +19 -0
- package/lib/doc/defined-names.js +196 -0
- package/lib/doc/enums.js +48 -0
- package/lib/doc/image.js +59 -0
- package/lib/doc/modelcontainer.js +18 -0
- package/lib/doc/note.js +65 -0
- package/lib/doc/pivot-table.js +132 -0
- package/lib/doc/range.js +257 -0
- package/lib/doc/row.js +415 -0
- package/lib/doc/table.js +465 -0
- package/lib/doc/workbook.js +224 -0
- package/lib/doc/worksheet.js +949 -0
- package/lib/exceljs.bare.js +13 -0
- package/lib/exceljs.browser.js +36 -0
- package/lib/exceljs.nodejs.js +14 -0
- package/lib/stream/xlsx/hyperlink-reader.js +83 -0
- package/lib/stream/xlsx/sheet-comments-writer.js +121 -0
- package/lib/stream/xlsx/sheet-rels-writer.js +119 -0
- package/lib/stream/xlsx/workbook-reader.js +337 -0
- package/lib/stream/xlsx/workbook-writer.js +347 -0
- package/lib/stream/xlsx/worksheet-reader.js +374 -0
- package/lib/stream/xlsx/worksheet-writer.js +717 -0
- package/lib/utils/auto-drain.js +15 -0
- package/lib/utils/browser-buffer-decode.js +14 -0
- package/lib/utils/browser-buffer-encode.js +15 -0
- package/lib/utils/cell-matrix.js +165 -0
- package/lib/utils/col-cache.js +287 -0
- package/lib/utils/copy-style.js +43 -0
- package/lib/utils/encryptor.js +55 -0
- package/lib/utils/iterate-stream.js +48 -0
- package/lib/utils/parse-sax.js +30 -0
- package/lib/utils/shared-formula.js +44 -0
- package/lib/utils/shared-strings.js +35 -0
- package/lib/utils/stream-base64.js +72 -0
- package/lib/utils/stream-buf.js +364 -0
- package/lib/utils/string-buf.js +82 -0
- package/lib/utils/string-builder.js +35 -0
- package/lib/utils/stuttered-pipe.js +67 -0
- package/lib/utils/typed-stack.js +24 -0
- package/lib/utils/under-dash.js +184 -0
- package/lib/utils/utils.js +205 -0
- package/lib/utils/xml-stream.js +169 -0
- package/lib/utils/zip-stream.js +87 -0
- package/lib/xlsx/.rels +11 -0
- package/lib/xlsx/calcChain.xml +6 -0
- package/lib/xlsx/core.xml +7 -0
- package/lib/xlsx/defaultnumformats.js +153 -0
- package/lib/xlsx/rel-type.js +20 -0
- package/lib/xlsx/styles.xml +41 -0
- package/lib/xlsx/workbook.xml +16 -0
- package/lib/xlsx/xform/base-xform.js +145 -0
- package/lib/xlsx/xform/book/defined-name-xform.js +91 -0
- package/lib/xlsx/xform/book/sheet-xform.js +34 -0
- package/lib/xlsx/xform/book/workbook-calc-properties-xform.js +26 -0
- package/lib/xlsx/xform/book/workbook-pivot-cache-xform.js +29 -0
- package/lib/xlsx/xform/book/workbook-properties-xform.js +29 -0
- package/lib/xlsx/xform/book/workbook-view-xform.js +53 -0
- package/lib/xlsx/xform/book/workbook-xform.js +259 -0
- package/lib/xlsx/xform/comment/comment-xform.js +105 -0
- package/lib/xlsx/xform/comment/comments-xform.js +82 -0
- package/lib/xlsx/xform/comment/style/vml-position-xform.js +39 -0
- package/lib/xlsx/xform/comment/style/vml-protection-xform.js +36 -0
- package/lib/xlsx/xform/comment/vml-anchor-xform.js +60 -0
- package/lib/xlsx/xform/comment/vml-client-data-xform.js +95 -0
- package/lib/xlsx/xform/comment/vml-notes-xform.js +107 -0
- package/lib/xlsx/xform/comment/vml-shape-xform.js +95 -0
- package/lib/xlsx/xform/comment/vml-textbox-xform.js +64 -0
- package/lib/xlsx/xform/composite-xform.js +56 -0
- package/lib/xlsx/xform/core/app-heading-pairs-xform.js +32 -0
- package/lib/xlsx/xform/core/app-titles-of-parts-xform.js +28 -0
- package/lib/xlsx/xform/core/app-xform.js +100 -0
- package/lib/xlsx/xform/core/content-types-xform.js +135 -0
- package/lib/xlsx/xform/core/core-xform.js +136 -0
- package/lib/xlsx/xform/core/relationship-xform.js +25 -0
- package/lib/xlsx/xform/core/relationships-xform.js +73 -0
- package/lib/xlsx/xform/drawing/base-cell-anchor-xform.js +48 -0
- package/lib/xlsx/xform/drawing/blip-fill-xform.js +71 -0
- package/lib/xlsx/xform/drawing/blip-xform.js +42 -0
- package/lib/xlsx/xform/drawing/c-nv-pic-pr-xform.js +38 -0
- package/lib/xlsx/xform/drawing/c-nv-pr-xform.js +68 -0
- package/lib/xlsx/xform/drawing/cell-position-xform.js +77 -0
- package/lib/xlsx/xform/drawing/drawing-xform.js +109 -0
- package/lib/xlsx/xform/drawing/ext-lst-xform.js +43 -0
- package/lib/xlsx/xform/drawing/ext-xform.js +44 -0
- package/lib/xlsx/xform/drawing/hlink-click-xform.js +41 -0
- package/lib/xlsx/xform/drawing/nv-pic-pr-xform.js +65 -0
- package/lib/xlsx/xform/drawing/one-cell-anchor-xform.js +63 -0
- package/lib/xlsx/xform/drawing/pic-xform.js +77 -0
- package/lib/xlsx/xform/drawing/sp-pr.js +17 -0
- package/lib/xlsx/xform/drawing/two-cell-anchor-xform.js +62 -0
- package/lib/xlsx/xform/list-xform.js +95 -0
- package/lib/xlsx/xform/pivot-table/cache-field.js +43 -0
- package/lib/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +77 -0
- package/lib/xlsx/xform/pivot-table/pivot-cache-records-xform.js +103 -0
- package/lib/xlsx/xform/pivot-table/pivot-table-xform.js +189 -0
- package/lib/xlsx/xform/sheet/auto-filter-xform.js +38 -0
- package/lib/xlsx/xform/sheet/cell-xform.js +498 -0
- package/lib/xlsx/xform/sheet/cf/cf-rule-xform.js +301 -0
- package/lib/xlsx/xform/sheet/cf/cfvo-xform.js +27 -0
- package/lib/xlsx/xform/sheet/cf/color-scale-xform.js +45 -0
- package/lib/xlsx/xform/sheet/cf/conditional-formatting-xform.js +48 -0
- package/lib/xlsx/xform/sheet/cf/conditional-formattings-xform.js +92 -0
- package/lib/xlsx/xform/sheet/cf/databar-xform.js +49 -0
- package/lib/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +87 -0
- package/lib/xlsx/xform/sheet/cf/formula-xform.js +25 -0
- package/lib/xlsx/xform/sheet/cf/icon-set-xform.js +47 -0
- package/lib/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +27 -0
- package/lib/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +98 -0
- package/lib/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +43 -0
- package/lib/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +62 -0
- package/lib/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +50 -0
- package/lib/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +98 -0
- package/lib/xlsx/xform/sheet/cf-ext/f-ext-xform.js +25 -0
- package/lib/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +73 -0
- package/lib/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +25 -0
- package/lib/xlsx/xform/sheet/col-xform.js +86 -0
- package/lib/xlsx/xform/sheet/data-validations-xform.js +257 -0
- package/lib/xlsx/xform/sheet/dimension-xform.js +29 -0
- package/lib/xlsx/xform/sheet/drawing-xform.js +33 -0
- package/lib/xlsx/xform/sheet/ext-lst-xform.js +86 -0
- package/lib/xlsx/xform/sheet/header-footer-xform.js +146 -0
- package/lib/xlsx/xform/sheet/hyperlink-xform.js +54 -0
- package/lib/xlsx/xform/sheet/merge-cell-xform.js +27 -0
- package/lib/xlsx/xform/sheet/merges.js +56 -0
- package/lib/xlsx/xform/sheet/outline-properties-xform.js +43 -0
- package/lib/xlsx/xform/sheet/page-breaks-xform.js +27 -0
- package/lib/xlsx/xform/sheet/page-margins-xform.js +49 -0
- package/lib/xlsx/xform/sheet/page-setup-properties-xform.js +35 -0
- package/lib/xlsx/xform/sheet/page-setup-xform.js +103 -0
- package/lib/xlsx/xform/sheet/picture-xform.js +33 -0
- package/lib/xlsx/xform/sheet/print-options-xform.js +49 -0
- package/lib/xlsx/xform/sheet/row-breaks-xform.js +39 -0
- package/lib/xlsx/xform/sheet/row-xform.js +142 -0
- package/lib/xlsx/xform/sheet/sheet-format-properties-xform.js +55 -0
- package/lib/xlsx/xform/sheet/sheet-properties-xform.js +90 -0
- package/lib/xlsx/xform/sheet/sheet-protection-xform.js +89 -0
- package/lib/xlsx/xform/sheet/sheet-view-xform.js +202 -0
- package/lib/xlsx/xform/sheet/table-part-xform.js +33 -0
- package/lib/xlsx/xform/sheet/worksheet-xform.js +548 -0
- package/lib/xlsx/xform/simple/boolean-xform.js +31 -0
- package/lib/xlsx/xform/simple/date-xform.js +66 -0
- package/lib/xlsx/xform/simple/float-xform.js +51 -0
- package/lib/xlsx/xform/simple/integer-xform.js +57 -0
- package/lib/xlsx/xform/simple/string-xform.js +51 -0
- package/lib/xlsx/xform/static-xform.js +64 -0
- package/lib/xlsx/xform/strings/phonetic-text-xform.js +98 -0
- package/lib/xlsx/xform/strings/rich-text-xform.js +101 -0
- package/lib/xlsx/xform/strings/shared-string-xform.js +102 -0
- package/lib/xlsx/xform/strings/shared-strings-xform.js +127 -0
- package/lib/xlsx/xform/strings/text-xform.js +44 -0
- package/lib/xlsx/xform/style/alignment-xform.js +172 -0
- package/lib/xlsx/xform/style/border-xform.js +207 -0
- package/lib/xlsx/xform/style/color-xform.js +63 -0
- package/lib/xlsx/xform/style/dxf-xform.js +111 -0
- package/lib/xlsx/xform/style/fill-xform.js +364 -0
- package/lib/xlsx/xform/style/font-xform.js +102 -0
- package/lib/xlsx/xform/style/numfmt-xform.js +63 -0
- package/lib/xlsx/xform/style/protection-xform.js +60 -0
- package/lib/xlsx/xform/style/style-xform.js +125 -0
- package/lib/xlsx/xform/style/styles-xform.js +527 -0
- package/lib/xlsx/xform/style/underline-xform.js +47 -0
- package/lib/xlsx/xform/table/auto-filter-xform.js +81 -0
- package/lib/xlsx/xform/table/custom-filter-xform.js +33 -0
- package/lib/xlsx/xform/table/filter-column-xform.js +96 -0
- package/lib/xlsx/xform/table/filter-xform.js +31 -0
- package/lib/xlsx/xform/table/table-column-xform.js +44 -0
- package/lib/xlsx/xform/table/table-style-info-xform.js +41 -0
- package/lib/xlsx/xform/table/table-xform.js +131 -0
- package/lib/xlsx/xlsx.js +774 -0
- package/lib/xlsx/xml/theme1.js +3 -0
- package/lib/xlsx/xml/theme1.xml +318 -0
- package/package.json +149 -0
package/lib/doc/table.js
ADDED
|
@@ -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;
|