@node-projects/excelforge 2.3.0 → 3.0.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/.github/FUNDING.yml +4 -0
- package/MISSING.md +326 -0
- package/README.md +484 -12
- package/dist/core/SharedStrings.js +6 -2
- package/dist/core/SharedStrings.js.map +1 -1
- package/dist/core/Workbook.d.ts +41 -1
- package/dist/core/Workbook.js +773 -57
- package/dist/core/Workbook.js.map +1 -1
- package/dist/core/WorkbookReader.d.ts +18 -4
- package/dist/core/WorkbookReader.js +1386 -20
- package/dist/core/WorkbookReader.js.map +1 -1
- package/dist/core/Worksheet.d.ts +130 -2
- package/dist/core/Worksheet.js +792 -66
- package/dist/core/Worksheet.js.map +1 -1
- package/dist/core/types.d.ts +287 -5
- package/dist/core/types.js +12 -1
- package/dist/core/types.js.map +1 -1
- package/dist/features/ChartBuilder.d.ts +9 -1
- package/dist/features/ChartBuilder.js +140 -14
- package/dist/features/ChartBuilder.js.map +1 -1
- package/dist/features/CsvModule.d.ts +11 -0
- package/dist/features/CsvModule.js +137 -0
- package/dist/features/CsvModule.js.map +1 -0
- package/dist/features/Encryption.d.ts +6 -0
- package/dist/features/Encryption.js +806 -0
- package/dist/features/Encryption.js.map +1 -0
- package/dist/features/FormControlBuilder.d.ts +6 -0
- package/dist/features/FormControlBuilder.js +135 -0
- package/dist/features/FormControlBuilder.js.map +1 -0
- package/dist/features/FormulaEngine.d.ts +22 -0
- package/dist/features/FormulaEngine.js +498 -0
- package/dist/features/FormulaEngine.js.map +1 -0
- package/dist/features/HtmlModule.d.ts +21 -0
- package/dist/features/HtmlModule.js +1417 -0
- package/dist/features/HtmlModule.js.map +1 -0
- package/dist/features/JsonModule.d.ts +10 -0
- package/dist/features/JsonModule.js +76 -0
- package/dist/features/JsonModule.js.map +1 -0
- package/dist/features/PivotTableBuilder.d.ts +7 -0
- package/dist/features/PivotTableBuilder.js +170 -0
- package/dist/features/PivotTableBuilder.js.map +1 -0
- package/dist/features/Signing.d.ts +12 -0
- package/dist/features/Signing.js +318 -0
- package/dist/features/Signing.js.map +1 -0
- package/dist/features/TableBuilder.js +2 -2
- package/dist/features/TableBuilder.js.map +1 -1
- package/dist/index-min.js +579 -144
- package/dist/index.d.ts +17 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/styles/StyleRegistry.d.ts +14 -0
- package/dist/styles/StyleRegistry.js +95 -30
- package/dist/styles/StyleRegistry.js.map +1 -1
- package/dist/utils/helpers.d.ts +4 -0
- package/dist/utils/helpers.js +64 -14
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/zip.js +145 -73
- package/dist/utils/zip.js.map +1 -1
- package/dist/vba/VbaProject.d.ts +19 -0
- package/dist/vba/VbaProject.js +281 -0
- package/dist/vba/VbaProject.js.map +1 -0
- package/dist/vba/cfb.d.ts +7 -0
- package/dist/vba/cfb.js +352 -0
- package/dist/vba/cfb.js.map +1 -0
- package/dist/vba/ovba.d.ts +2 -0
- package/dist/vba/ovba.js +137 -0
- package/dist/vba/ovba.js.map +1 -0
- package/package.json +4 -3
- package/validator.cs +0 -155
- package/validatorEpplus.cs +0 -27
- package/validatorReadData.cs +0 -111
package/dist/core/Workbook.js
CHANGED
|
@@ -3,20 +3,30 @@ import { StyleRegistry } from '../styles/StyleRegistry.js';
|
|
|
3
3
|
import { SharedStrings } from './SharedStrings.js';
|
|
4
4
|
import { buildChartXml } from '../features/ChartBuilder.js';
|
|
5
5
|
import { buildTableXml } from '../features/TableBuilder.js';
|
|
6
|
+
import { buildPivotTableFiles } from '../features/PivotTableBuilder.js';
|
|
7
|
+
import { buildCtrlPropXml, buildFormControlVmlShape, buildVmlWithControls } from '../features/FormControlBuilder.js';
|
|
8
|
+
import { VbaProject } from '../vba/VbaProject.js';
|
|
6
9
|
import { buildZip } from '../utils/zip.js';
|
|
7
10
|
import { strToBytes, base64ToBytes, escapeXml, colIndexToLetter } from '../utils/helpers.js';
|
|
8
|
-
import { readWorkbook } from './WorkbookReader.js';
|
|
11
|
+
import { readWorkbook, connTypeToNum, cmdTypeToNum } from './WorkbookReader.js';
|
|
9
12
|
import { buildCoreXml, buildAppXml, buildCustomXml, } from './properties.js';
|
|
10
13
|
export class Workbook {
|
|
11
14
|
constructor() {
|
|
12
15
|
this.sheets = [];
|
|
13
16
|
this.namedRanges = [];
|
|
17
|
+
this.connections = [];
|
|
18
|
+
this.powerQueries = [];
|
|
19
|
+
this.externalLinks = [];
|
|
20
|
+
this.customPivotStyles = [];
|
|
21
|
+
this.pivotSlicers = [];
|
|
14
22
|
this.properties = {};
|
|
15
23
|
this.compressionLevel = 6;
|
|
16
24
|
this.coreProperties = {};
|
|
17
25
|
this.extendedProperties = {};
|
|
18
26
|
this.customProperties = [];
|
|
27
|
+
this.isTemplate = false;
|
|
19
28
|
this._dirtySheets = new Set();
|
|
29
|
+
this._customTableStyles = new Map();
|
|
20
30
|
}
|
|
21
31
|
markDirty(sheetIndexOrName) {
|
|
22
32
|
if (typeof sheetIndexOrName === 'string') {
|
|
@@ -49,6 +59,16 @@ export class Workbook {
|
|
|
49
59
|
status: result.core.contentStatus,
|
|
50
60
|
};
|
|
51
61
|
wb.sheets = result.sheets.map(s => s.ws);
|
|
62
|
+
wb.namedRanges = result.namedRanges;
|
|
63
|
+
wb.connections = result.connections;
|
|
64
|
+
wb.powerQueries = result.powerQueries;
|
|
65
|
+
const vbaData = result.unknownParts.get('xl/vbaProject.bin');
|
|
66
|
+
if (vbaData) {
|
|
67
|
+
try {
|
|
68
|
+
wb.vbaProject = VbaProject.fromBytes(vbaData);
|
|
69
|
+
}
|
|
70
|
+
catch { }
|
|
71
|
+
}
|
|
52
72
|
return wb;
|
|
53
73
|
}
|
|
54
74
|
static async fromBase64(b64) {
|
|
@@ -78,14 +98,102 @@ export class Workbook {
|
|
|
78
98
|
getSheetNames() {
|
|
79
99
|
return this.sheets.map(s => s.name);
|
|
80
100
|
}
|
|
101
|
+
getSheets() {
|
|
102
|
+
return this.sheets;
|
|
103
|
+
}
|
|
81
104
|
removeSheet(name) {
|
|
82
105
|
this.sheets = this.sheets.filter(s => s.name !== name);
|
|
83
106
|
return this;
|
|
84
107
|
}
|
|
108
|
+
addChartSheet(name, chart) {
|
|
109
|
+
const ws = this.addSheet(name);
|
|
110
|
+
ws._isChartSheet = true;
|
|
111
|
+
ws.addChart(chart);
|
|
112
|
+
return ws;
|
|
113
|
+
}
|
|
114
|
+
addDialogSheet(name) {
|
|
115
|
+
const ws = this.addSheet(name);
|
|
116
|
+
ws._isDialogSheet = true;
|
|
117
|
+
return ws;
|
|
118
|
+
}
|
|
119
|
+
copySheet(sourceName, newName) {
|
|
120
|
+
const src = this.getSheet(sourceName);
|
|
121
|
+
if (!src)
|
|
122
|
+
throw new Error(`Sheet "${sourceName}" not found`);
|
|
123
|
+
const ws = this.addSheet(newName);
|
|
124
|
+
const cells = src.readAllCells();
|
|
125
|
+
for (const { row, col, cell } of cells) {
|
|
126
|
+
const target = ws.getCell(row, col);
|
|
127
|
+
if (cell.value != null)
|
|
128
|
+
target.value = cell.value;
|
|
129
|
+
if (cell.formula)
|
|
130
|
+
target.formula = cell.formula;
|
|
131
|
+
if (cell.arrayFormula)
|
|
132
|
+
target.arrayFormula = cell.arrayFormula;
|
|
133
|
+
if (cell.richText)
|
|
134
|
+
target.richText = cell.richText.map(r => ({ ...r, font: r.font ? { ...r.font } : undefined }));
|
|
135
|
+
if (cell.style)
|
|
136
|
+
target.style = { ...cell.style };
|
|
137
|
+
if (cell.comment)
|
|
138
|
+
target.comment = { ...cell.comment };
|
|
139
|
+
if (cell.hyperlink)
|
|
140
|
+
target.hyperlink = { ...cell.hyperlink };
|
|
141
|
+
}
|
|
142
|
+
for (const m of src.getMerges()) {
|
|
143
|
+
ws.merge(m.startRow, m.startCol, m.endRow, m.endCol);
|
|
144
|
+
}
|
|
145
|
+
const range = src.getUsedRange();
|
|
146
|
+
if (range) {
|
|
147
|
+
for (let c = range.startCol; c <= range.endCol; c++) {
|
|
148
|
+
const cd = src.getColumn(c);
|
|
149
|
+
if (cd)
|
|
150
|
+
ws.setColumn(c, { ...cd });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (src.pageSetup)
|
|
154
|
+
ws.pageSetup = { ...src.pageSetup };
|
|
155
|
+
if (src.printArea)
|
|
156
|
+
ws.printArea = src.printArea;
|
|
157
|
+
return ws;
|
|
158
|
+
}
|
|
159
|
+
registerTableStyle(name, def) {
|
|
160
|
+
this._customTableStyles.set(name, def);
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
85
163
|
addNamedRange(nr) {
|
|
86
164
|
this.namedRanges.push(nr);
|
|
87
165
|
return this;
|
|
88
166
|
}
|
|
167
|
+
getNamedRanges() {
|
|
168
|
+
return this.namedRanges;
|
|
169
|
+
}
|
|
170
|
+
getNamedRange(name) {
|
|
171
|
+
return this.namedRanges.find(nr => nr.name === name);
|
|
172
|
+
}
|
|
173
|
+
removeNamedRange(name) {
|
|
174
|
+
this.namedRanges = this.namedRanges.filter(nr => nr.name !== name);
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
addConnection(conn) {
|
|
178
|
+
this.connections.push(conn);
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
getConnections() {
|
|
182
|
+
return this.connections;
|
|
183
|
+
}
|
|
184
|
+
getConnection(name) {
|
|
185
|
+
return this.connections.find(c => c.name === name);
|
|
186
|
+
}
|
|
187
|
+
removeConnection(name) {
|
|
188
|
+
this.connections = this.connections.filter(c => c.name !== name);
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
getPowerQueries() {
|
|
192
|
+
return this.powerQueries;
|
|
193
|
+
}
|
|
194
|
+
getPowerQuery(name) {
|
|
195
|
+
return this.powerQueries.find(q => q.name === name);
|
|
196
|
+
}
|
|
89
197
|
getCustomProperty(name) {
|
|
90
198
|
return this.customProperties.find(p => p.name === name);
|
|
91
199
|
}
|
|
@@ -101,6 +209,24 @@ export class Workbook {
|
|
|
101
209
|
this.customProperties = this.customProperties.filter(p => p.name !== name);
|
|
102
210
|
return this;
|
|
103
211
|
}
|
|
212
|
+
addExternalLink(link) {
|
|
213
|
+
this.externalLinks.push(link);
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
getExternalLinks() {
|
|
217
|
+
return this.externalLinks;
|
|
218
|
+
}
|
|
219
|
+
registerPivotStyle(style) {
|
|
220
|
+
this.customPivotStyles.push(style);
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
addPivotSlicer(slicer) {
|
|
224
|
+
this.pivotSlicers.push(slicer);
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
getPivotSlicers() {
|
|
228
|
+
return this.pivotSlicers;
|
|
229
|
+
}
|
|
104
230
|
async build() {
|
|
105
231
|
this._syncLegacyProperties();
|
|
106
232
|
return this._readResult ? this._buildPatched() : this._buildFresh();
|
|
@@ -113,6 +239,13 @@ export class Workbook {
|
|
|
113
239
|
const shared = new SharedStrings();
|
|
114
240
|
const sheetXmls = new Map();
|
|
115
241
|
if (hasDirty) {
|
|
242
|
+
const dxfRe = /<dxf>([\s\S]*?)<\/dxf>|<dxf\/>/g;
|
|
243
|
+
const rawDxfs = [];
|
|
244
|
+
let m;
|
|
245
|
+
while ((m = dxfRe.exec(rr.stylesXml)) !== null)
|
|
246
|
+
rawDxfs.push(m[1] ?? '');
|
|
247
|
+
if (rawDxfs.length)
|
|
248
|
+
styles.prependRawDxfs(rawDxfs);
|
|
116
249
|
for (let i = 0; i < this.sheets.length; i++) {
|
|
117
250
|
sheetXmls.set(i, this.sheets[i].toXml(styles, shared));
|
|
118
251
|
}
|
|
@@ -127,7 +260,7 @@ export class Workbook {
|
|
|
127
260
|
...rr.extended,
|
|
128
261
|
...this.extendedProperties,
|
|
129
262
|
titlesOfParts: this.sheets.map(s => s.name),
|
|
130
|
-
headingPairs:
|
|
263
|
+
headingPairs: this._headingPairs(),
|
|
131
264
|
}, rr.extendedUnknownRaw)),
|
|
132
265
|
});
|
|
133
266
|
const customProps = this.customProperties.length > 0
|
|
@@ -137,6 +270,10 @@ export class Workbook {
|
|
|
137
270
|
entries.push({ name: 'docProps/custom.xml', data: strToBytes(buildCustomXml(customProps)) });
|
|
138
271
|
}
|
|
139
272
|
entries.push({ name: 'xl/workbook.xml', data: strToBytes(this._patchWorkbookXml(rr.workbookXml)) });
|
|
273
|
+
const connectionsXml = this._connectionsXml(rr.connectionsXml);
|
|
274
|
+
if (connectionsXml) {
|
|
275
|
+
entries.push({ name: 'xl/connections.xml', data: strToBytes(connectionsXml) });
|
|
276
|
+
}
|
|
140
277
|
if (hasDirty) {
|
|
141
278
|
entries.push({ name: 'xl/styles.xml', data: strToBytes(styles.toXml()) });
|
|
142
279
|
entries.push({ name: 'xl/sharedStrings.xml', data: strToBytes(shared.toXml()) });
|
|
@@ -146,38 +283,43 @@ export class Workbook {
|
|
|
146
283
|
entries.push({ name: 'xl/sharedStrings.xml', data: strToBytes(rr.sharedXml) });
|
|
147
284
|
}
|
|
148
285
|
for (let i = 0; i < this.sheets.length; i++) {
|
|
149
|
-
const
|
|
286
|
+
const ws = this.sheets[i];
|
|
287
|
+
const folder = ws._isChartSheet ? 'chartsheets' : ws._isDialogSheet ? 'dialogsheets' : 'worksheets';
|
|
288
|
+
const path = `xl/${folder}/sheet${i + 1}.xml`;
|
|
150
289
|
if (hasDirty) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const dirtyTablePaths = new Set();
|
|
160
|
-
if (hasDirty) {
|
|
161
|
-
for (let i = 0; i < this.sheets.length; i++) {
|
|
162
|
-
if (rr.sheets[i]?.tablePaths) {
|
|
163
|
-
for (const tp of rr.sheets[i].tablePaths)
|
|
164
|
-
dirtyTablePaths.add(tp);
|
|
290
|
+
if (ws._isChartSheet) {
|
|
291
|
+
entries.push({ name: path, data: strToBytes(ws.toChartSheetXml()) });
|
|
292
|
+
}
|
|
293
|
+
else if (ws._isDialogSheet) {
|
|
294
|
+
entries.push({ name: path, data: strToBytes(ws.toDialogSheetXml(styles, shared)) });
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
entries.push({ name: path, data: strToBytes(sheetXmls.get(i) ?? '') });
|
|
165
298
|
}
|
|
166
299
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (!dirtyTablePaths.has(path)) {
|
|
170
|
-
entries.push({ name: path, data });
|
|
300
|
+
else {
|
|
301
|
+
entries.push({ name: path, data: strToBytes(rr.sheets[i]?.originalXml ?? '') });
|
|
171
302
|
}
|
|
172
303
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
304
|
+
const allTablePaths = new Set();
|
|
305
|
+
for (let i = 0; i < this.sheets.length; i++) {
|
|
306
|
+
const ws = this.sheets[i];
|
|
307
|
+
const tables = ws.getTables();
|
|
308
|
+
const paths = rr.sheets[i]?.tablePaths ?? [];
|
|
309
|
+
const xmls = rr.sheets[i]?.tableXmls ?? [];
|
|
310
|
+
for (let j = 0; j < tables.length; j++) {
|
|
311
|
+
const tblPath = paths[j];
|
|
312
|
+
if (tblPath) {
|
|
313
|
+
allTablePaths.add(tblPath);
|
|
314
|
+
if (j < xmls.length) {
|
|
315
|
+
let xml = xmls[j];
|
|
316
|
+
const origRefMatch = xml.match(/\bref="([^"]+)"/);
|
|
317
|
+
if (origRefMatch && origRefMatch[1] !== tables[j].ref) {
|
|
318
|
+
xml = xml.replace(`ref="${origRefMatch[1]}"`, `ref="${tables[j].ref}"`);
|
|
319
|
+
}
|
|
320
|
+
entries.push({ name: tblPath, data: strToBytes(xml) });
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
181
323
|
const idMatch = tblPath.match(/table(\d+)\.xml$/);
|
|
182
324
|
const tableId = idMatch ? parseInt(idMatch[1], 10) : j + 1;
|
|
183
325
|
entries.push({ name: tblPath, data: strToBytes(buildTableXml(tables[j], tableId)) });
|
|
@@ -185,8 +327,23 @@ export class Workbook {
|
|
|
185
327
|
}
|
|
186
328
|
}
|
|
187
329
|
}
|
|
330
|
+
for (const [path, data] of rr.unknownParts) {
|
|
331
|
+
if (allTablePaths.has(path))
|
|
332
|
+
continue;
|
|
333
|
+
if (path === 'xl/vbaProject.bin' && this.vbaProject)
|
|
334
|
+
continue;
|
|
335
|
+
if (rr.allRels.has(path))
|
|
336
|
+
continue;
|
|
337
|
+
if (hasDirty && path === 'xl/calcChain.xml')
|
|
338
|
+
continue;
|
|
339
|
+
entries.push({ name: path, data });
|
|
340
|
+
}
|
|
341
|
+
if (this.vbaProject) {
|
|
342
|
+
this._ensureVbaSheetModules();
|
|
343
|
+
entries.push({ name: 'xl/vbaProject.bin', data: this.vbaProject.build() });
|
|
344
|
+
}
|
|
188
345
|
entries.push({ name: '_rels/.rels', data: strToBytes(this._buildRootRels(customProps != null && customProps.length > 0)) });
|
|
189
|
-
entries.push({ name: 'xl/_rels/workbook.xml.rels', data: strToBytes(this._buildWorkbookRels(rr)) });
|
|
346
|
+
entries.push({ name: 'xl/_rels/workbook.xml.rels', data: strToBytes(this._buildWorkbookRels(rr, hasDirty)) });
|
|
190
347
|
for (const [relPath, relMap] of rr.allRels) {
|
|
191
348
|
if (relPath === 'xl/_rels/workbook.xml.rels' || relPath === '_rels/.rels')
|
|
192
349
|
continue;
|
|
@@ -194,7 +351,7 @@ export class Workbook {
|
|
|
194
351
|
}
|
|
195
352
|
entries.push({
|
|
196
353
|
name: '[Content_Types].xml',
|
|
197
|
-
data: strToBytes(this._patchContentTypes(rr.contentTypesXml, customProps != null && customProps.length > 0)),
|
|
354
|
+
data: strToBytes(this._patchContentTypes(rr.contentTypesXml, customProps != null && customProps.length > 0, hasDirty)),
|
|
198
355
|
});
|
|
199
356
|
return buildZip(entries, { level: this.compressionLevel });
|
|
200
357
|
}
|
|
@@ -202,29 +359,35 @@ export class Workbook {
|
|
|
202
359
|
const styles = new StyleRegistry();
|
|
203
360
|
const shared = new SharedStrings();
|
|
204
361
|
const entries = [];
|
|
362
|
+
for (const [name, def] of this._customTableStyles) {
|
|
363
|
+
styles.registerTableStyle(name, def);
|
|
364
|
+
}
|
|
205
365
|
let globalRId = 1;
|
|
206
366
|
for (const ws of this.sheets)
|
|
207
367
|
ws.rId = `rId${globalRId++}`;
|
|
208
368
|
const allImages = [];
|
|
209
369
|
const allCharts = [];
|
|
210
370
|
const allTables = [];
|
|
371
|
+
const allPivotTables = [];
|
|
211
372
|
const sheetImageRIds = new Map();
|
|
212
373
|
const sheetChartRIds = new Map();
|
|
213
374
|
const sheetTableRIds = new Map();
|
|
214
|
-
|
|
375
|
+
const sheetPivotRIds = new Map();
|
|
376
|
+
let imgCtr = 1, chartCtr = 1, tableCtr = 1, vmlCtr = 1, pivotCtr = 1, pivotCacheIdCtr = 0, ctrlPropGlobal = 0;
|
|
215
377
|
for (const ws of this.sheets) {
|
|
216
378
|
const imgs = ws.getImages();
|
|
217
379
|
const charts = ws.getCharts();
|
|
218
380
|
const tables = ws.getTables();
|
|
219
381
|
const imgRIds = [], chartRIds = [], tblRIds = [];
|
|
220
|
-
if (imgs.length || charts.length)
|
|
382
|
+
if (imgs.length || charts.length || ws.getShapes().length || ws.getWordArt().length || ws.getMathEquations().length || ws.getTableSlicers().length)
|
|
221
383
|
ws.drawingRId = `rId${globalRId++}`;
|
|
222
|
-
|
|
384
|
+
const controls = ws.getFormControls();
|
|
385
|
+
if (ws.getComments().length || controls.length)
|
|
223
386
|
ws.legacyDrawingRId = `rId${globalRId++}`;
|
|
224
387
|
for (const img of imgs) {
|
|
225
388
|
const r = `rId${globalRId++}`;
|
|
226
389
|
imgRIds.push(r);
|
|
227
|
-
allImages.push({ ws, img, ext: img.format
|
|
390
|
+
allImages.push({ ws, img, ext: imageExt(img.format), idx: imgCtr++ });
|
|
228
391
|
}
|
|
229
392
|
for (let i = 0; i < charts.length; i++) {
|
|
230
393
|
const r = `rId${globalRId++}`;
|
|
@@ -236,49 +399,200 @@ export class Workbook {
|
|
|
236
399
|
tblRIds.push(r);
|
|
237
400
|
allTables.push({ ws, tableIdx: i, globalTableId: tableCtr++ });
|
|
238
401
|
}
|
|
402
|
+
const ctrlPropRIds = [];
|
|
403
|
+
for (let ci = 0; ci < controls.length; ci++)
|
|
404
|
+
ctrlPropRIds.push(`rId${globalRId++}`);
|
|
405
|
+
ws.ctrlPropRIds = ctrlPropRIds;
|
|
239
406
|
sheetImageRIds.set(ws, imgRIds);
|
|
240
407
|
sheetChartRIds.set(ws, chartRIds);
|
|
241
408
|
sheetTableRIds.set(ws, tblRIds);
|
|
242
409
|
ws.tableRIds = tblRIds;
|
|
410
|
+
const ptRIds = [];
|
|
411
|
+
for (const pt of ws.getPivotTables()) {
|
|
412
|
+
const pivotRId = `rId${globalRId++}`;
|
|
413
|
+
const cacheRId = `rId${globalRId++}`;
|
|
414
|
+
ptRIds.push(pivotRId);
|
|
415
|
+
allPivotTables.push({ ws, pt, pivotIdx: pivotCtr++, cacheId: pivotCacheIdCtr++, pivotRId, cacheRId });
|
|
416
|
+
}
|
|
417
|
+
sheetPivotRIds.set(ws, ptRIds);
|
|
418
|
+
}
|
|
419
|
+
const allCellImages = [];
|
|
420
|
+
let cellImgCtr = imgCtr;
|
|
421
|
+
let vmCounter = 1;
|
|
422
|
+
for (const ws of this.sheets) {
|
|
423
|
+
ws._cellImageVm = new Map();
|
|
424
|
+
for (const ci of ws.getCellImages()) {
|
|
425
|
+
const ext = imageExt(ci.format);
|
|
426
|
+
allCellImages.push({ img: ci, ext, idx: cellImgCtr++ });
|
|
427
|
+
ws._cellImageVm.set(ci.cell, vmCounter++);
|
|
428
|
+
ws.getCellByRef(ci.cell);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const hasCellImages = allCellImages.length > 0;
|
|
432
|
+
const sheetSlicerMap = new Map();
|
|
433
|
+
const allSlicerCaches = [];
|
|
434
|
+
let slicerDefCtr = 0, slicerCacheCtr = 0;
|
|
435
|
+
for (const ws of this.sheets) {
|
|
436
|
+
const tSlicers = ws.getTableSlicers();
|
|
437
|
+
if (tSlicers.length) {
|
|
438
|
+
sheetSlicerMap.set(ws, { tableSlicers: [], pivotSlicers: [], slicerDefRId: '', slicerDefIdx: 0 });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
for (const ps of this.pivotSlicers) {
|
|
442
|
+
for (const ws of this.sheets) {
|
|
443
|
+
if (ws.getPivotTables().some(p => p.name === ps.pivotTableName)) {
|
|
444
|
+
if (!sheetSlicerMap.has(ws)) {
|
|
445
|
+
sheetSlicerMap.set(ws, { tableSlicers: [], pivotSlicers: [], slicerDefRId: '', slicerDefIdx: 0 });
|
|
446
|
+
}
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
for (const [ws, info] of sheetSlicerMap) {
|
|
452
|
+
if (!ws.drawingRId)
|
|
453
|
+
ws.drawingRId = `rId${globalRId++}`;
|
|
454
|
+
info.slicerDefRId = `rId${globalRId++}`;
|
|
455
|
+
info.slicerDefIdx = ++slicerDefCtr;
|
|
456
|
+
ws.slicerRId = info.slicerDefRId;
|
|
457
|
+
const drawingInfo = [];
|
|
458
|
+
for (const s of ws.getTableSlicers()) {
|
|
459
|
+
const table = ws.getTables().find(t => t.name === s.tableName);
|
|
460
|
+
const tableEntry = allTables.find(t => t.ws === ws && ws.getTables()[t.tableIdx] === table);
|
|
461
|
+
const tableId = tableEntry?.globalTableId ?? 1;
|
|
462
|
+
const columnIndex = table ? (table.columns?.findIndex(c => c.name === s.columnName) ?? 0) + 1 : 1;
|
|
463
|
+
info.tableSlicers.push({ slicer: s, tableId, columnIndex });
|
|
464
|
+
drawingInfo.push({ name: s.name, cell: s.cell });
|
|
465
|
+
allSlicerCaches.push({
|
|
466
|
+
name: s.name + '_cache', sourceName: s.columnName, type: 'table',
|
|
467
|
+
rId: `rId${globalRId++}`, idx: ++slicerCacheCtr,
|
|
468
|
+
tableId, columnIndex, sortOrder: s.sortOrder ?? 'ascending',
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
for (const ps of this.pivotSlicers) {
|
|
472
|
+
const pt = ws.getPivotTables().find(p => p.name === ps.pivotTableName);
|
|
473
|
+
if (!pt)
|
|
474
|
+
continue;
|
|
475
|
+
const ptEntry = allPivotTables.find(p => p.ws === ws && p.pt === pt);
|
|
476
|
+
const sheetIdx = this.sheets.indexOf(ws) + 1;
|
|
477
|
+
let items = [];
|
|
478
|
+
const sourceWs = this.sheets.find(s => s.name === pt.sourceSheet);
|
|
479
|
+
if (sourceWs) {
|
|
480
|
+
const sourceData = sourceWs.readRange(pt.sourceRef);
|
|
481
|
+
const headers = (sourceData[0] ?? []).map(v => String(v ?? ''));
|
|
482
|
+
const fieldIdx = headers.indexOf(ps.fieldName);
|
|
483
|
+
if (fieldIdx >= 0) {
|
|
484
|
+
const uniqueSet = new Set();
|
|
485
|
+
for (let r = 1; r < sourceData.length; r++)
|
|
486
|
+
uniqueSet.add(String(sourceData[r][fieldIdx] ?? ''));
|
|
487
|
+
items = [...uniqueSet];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
info.pivotSlicers.push({ slicer: ps, pivotCacheId: ptEntry?.cacheId ?? 0 });
|
|
491
|
+
drawingInfo.push({ name: ps.name, cell: ps.cell });
|
|
492
|
+
allSlicerCaches.push({
|
|
493
|
+
name: ps.name + '_cache', sourceName: ps.fieldName, type: 'pivot',
|
|
494
|
+
rId: `rId${globalRId++}`, idx: ++slicerCacheCtr,
|
|
495
|
+
pivotTableName: ps.pivotTableName, pivotCacheId: ptEntry?.cacheId ?? 0,
|
|
496
|
+
tabId: sheetIdx, items,
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
ws._slicerDrawingInfo = drawingInfo;
|
|
243
500
|
}
|
|
501
|
+
const hasSlicers = sheetSlicerMap.size > 0;
|
|
244
502
|
const hasCustom = this.customProperties.length > 0;
|
|
503
|
+
const hasVba = !!this.vbaProject;
|
|
245
504
|
const imgCTs = new Set();
|
|
246
|
-
for (const { ext } of allImages) {
|
|
247
|
-
const ct = ext
|
|
505
|
+
for (const { ext } of [...allImages, ...allCellImages]) {
|
|
506
|
+
const ct = imageContentType(ext);
|
|
248
507
|
imgCTs.add(`<Default Extension="${ext}" ContentType="${ct}"/>`);
|
|
249
508
|
}
|
|
250
509
|
const sheetsWithComments = this.sheets.filter(ws => ws.getComments().length);
|
|
251
|
-
const
|
|
510
|
+
const sheetsWithVml = this.sheets.filter(ws => ws.getComments().length || ws.getFormControls().length);
|
|
511
|
+
const vmlCT = sheetsWithVml.length ? '<Default Extension="vml" ContentType="application/vnd.openxmlformats-officedocument.vmlDrawing"/>' : '';
|
|
252
512
|
let vmlIdx = 0;
|
|
253
513
|
const commentsCTs = sheetsWithComments.map(() => `<Override PartName="/xl/comments${++vmlIdx}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"/>`).join('');
|
|
514
|
+
let ctrlPropCtr = 0;
|
|
515
|
+
const ctrlPropCTs = [];
|
|
516
|
+
for (const ws of this.sheets) {
|
|
517
|
+
if (ws._isDialogSheet)
|
|
518
|
+
continue;
|
|
519
|
+
for (let ci = 0; ci < ws.getFormControls().length; ci++) {
|
|
520
|
+
ctrlPropCTs.push(`<Override PartName="/xl/ctrlProps/ctrlProp${++ctrlPropCtr}.xml" ContentType="application/vnd.ms-excel.controlproperties+xml"/>`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
254
523
|
entries.push({ name: '[Content_Types].xml', data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
255
524
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
256
525
|
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
|
257
526
|
<Default Extension="xml" ContentType="application/xml"/>
|
|
258
527
|
${vmlCT}
|
|
259
528
|
${[...imgCTs].join('')}
|
|
260
|
-
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
|
|
529
|
+
<Override PartName="/xl/workbook.xml" ContentType="${hasVba ? 'application/vnd.ms-excel.sheet.macroEnabled.main+xml' : this.isTemplate ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml'}"/>
|
|
530
|
+
${hasVba ? '<Override PartName="/xl/vbaProject.bin" ContentType="application/vnd.ms-office.vbaProject"/>' : ''}
|
|
261
531
|
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
|
|
262
532
|
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
|
|
263
|
-
|
|
533
|
+
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
|
|
534
|
+
${this.sheets.filter(ws => !ws._isChartSheet && !ws._isDialogSheet).map(ws => { const idx = this.sheets.indexOf(ws); return `<Override PartName="/xl/worksheets/sheet${idx + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`; }).join('')}
|
|
535
|
+
${this.sheets.filter(ws => ws._isChartSheet).map(ws => { const idx = this.sheets.indexOf(ws); return `<Override PartName="/xl/chartsheets/sheet${idx + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml"/>`; }).join('')}
|
|
536
|
+
${this.sheets.filter(ws => ws._isDialogSheet).map(ws => { const idx = this.sheets.indexOf(ws); return `<Override PartName="/xl/dialogsheets/sheet${idx + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml"/>`; }).join('')}
|
|
264
537
|
${this.sheets.filter(ws => ws.drawingRId).map((_, i) => `<Override PartName="/xl/drawings/drawing${i + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.drawing+xml"/>`).join('')}
|
|
265
538
|
${allCharts.map(({ globalIdx }) => `<Override PartName="/xl/charts/chart${globalIdx}.xml" ContentType="application/vnd.openxmlformats-officedocument.drawingml.chart+xml"/>`).join('')}
|
|
266
539
|
${allTables.map(({ globalTableId }) => `<Override PartName="/xl/tables/table${globalTableId}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"/>`).join('')}
|
|
540
|
+
${allPivotTables.map(p => `<Override PartName="/xl/pivotTables/pivotTable${p.pivotIdx}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`).join('\n')}
|
|
541
|
+
${allPivotTables.map(p => `<Override PartName="/xl/pivotCache/pivotCacheDefinition${p.pivotIdx}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`).join('\n')}
|
|
542
|
+
${allPivotTables.map(p => `<Override PartName="/xl/pivotCache/pivotCacheRecords${p.pivotIdx}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`).join('\n')}
|
|
267
543
|
${commentsCTs}
|
|
544
|
+
${ctrlPropCTs.join('')}
|
|
268
545
|
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
|
|
269
546
|
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
|
|
270
547
|
${hasCustom ? '<Override PartName="/docProps/custom.xml" ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>' : ''}
|
|
548
|
+
${this.connections.length ? '<Override PartName="/xl/connections.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml"/>' : ''}
|
|
549
|
+
${this.externalLinks.map((_, i) => `<Override PartName="/xl/externalLinks/externalLink${i + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml"/>`).join('\n')}
|
|
550
|
+
${[...sheetSlicerMap.values()].map(info => `<Override PartName="/xl/slicers/slicer${info.slicerDefIdx}.xml" ContentType="application/vnd.ms-excel.slicer+xml"/>`).join('\n')}
|
|
551
|
+
${allSlicerCaches.map(sc => `<Override PartName="/xl/slicerCaches/slicerCache${sc.idx}.xml" ContentType="application/vnd.ms-excel.slicerCache+xml"/>`).join('\n')}
|
|
552
|
+
${this.sheets.flatMap(ws => ws.getQueryTables()).map((_, i) => `<Override PartName="/xl/queryTables/queryTable${i + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml"/>`).join('\n')}
|
|
553
|
+
${hasCellImages ? `<Override PartName="/xl/metadata.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml"/>
|
|
554
|
+
<Override PartName="/xl/richData/rdrichvalue.xml" ContentType="application/vnd.ms-excel.rdrichvalue+xml"/>
|
|
555
|
+
<Override PartName="/xl/richData/rdRichValueStructure.xml" ContentType="application/vnd.ms-excel.rdrichvaluestructure+xml"/>
|
|
556
|
+
<Override PartName="/xl/richData/richValueRel.xml" ContentType="application/vnd.ms-excel.richvaluerel+xml"/>
|
|
557
|
+
<Override PartName="/xl/richData/rdRichValueTypes.xml" ContentType="application/vnd.ms-excel.rdrichvaluetypes+xml"/>
|
|
558
|
+
<Override PartName="/xl/richData/rdarray.xml" ContentType="application/vnd.ms-excel.rdarray+xml"/>` : ''}
|
|
271
559
|
</Types>`) });
|
|
272
560
|
entries.push({ name: '_rels/.rels', data: strToBytes(this._buildRootRels(hasCustom)) });
|
|
273
561
|
entries.push({ name: 'xl/_rels/workbook.xml.rels', data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
274
562
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
275
|
-
${this.sheets.map((ws, i) =>
|
|
563
|
+
${this.sheets.map((ws, i) => {
|
|
564
|
+
const type = ws._isChartSheet ? 'chartsheet' : ws._isDialogSheet ? 'dialogsheet' : 'worksheet';
|
|
565
|
+
const folder = ws._isChartSheet ? 'chartsheets' : ws._isDialogSheet ? 'dialogsheets' : 'worksheets';
|
|
566
|
+
return `<Relationship Id="${ws.rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/${type}" Target="${folder}/sheet${i + 1}.xml"/>`;
|
|
567
|
+
}).join('')}
|
|
276
568
|
<Relationship Id="rIdStyles" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
|
277
569
|
<Relationship Id="rIdShared" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
|
|
570
|
+
<Relationship Id="rIdTheme" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
|
|
571
|
+
${allPivotTables.map(p => `<Relationship Id="${p.cacheRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" Target="pivotCache/pivotCacheDefinition${p.pivotIdx}.xml"/>`).join('\n')}
|
|
572
|
+
${allSlicerCaches.map(sc => `<Relationship Id="${sc.rId}" Type="http://schemas.microsoft.com/office/2007/relationships/slicerCache" Target="slicerCaches/slicerCache${sc.idx}.xml"/>`).join('\n')}
|
|
573
|
+
${hasVba ? '<Relationship Id="rIdVBA" Type="http://schemas.microsoft.com/office/2006/relationships/vbaProject" Target="vbaProject.bin"/>' : ''}
|
|
574
|
+
${this.connections.length ? '<Relationship Id="rIdConns" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections" Target="connections.xml"/>' : ''}
|
|
575
|
+
${this.externalLinks.map((_, i) => `<Relationship Id="rIdExtLink${i + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink" Target="externalLinks/externalLink${i + 1}.xml"/>`).join('\n')}
|
|
576
|
+
${hasCellImages ? '<Relationship Id="rIdMeta" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata" Target="metadata.xml"/>' : ''}
|
|
577
|
+
${hasCellImages ? '<Relationship Id="rIdRichValueRel" Type="http://schemas.microsoft.com/office/2022/10/relationships/richValueRel" Target="richData/richValueRel.xml"/>' : ''}
|
|
578
|
+
${hasCellImages ? '<Relationship Id="rIdRichValue" Type="http://schemas.microsoft.com/office/2017/06/relationships/rdRichValue" Target="richData/rdrichvalue.xml"/>' : ''}
|
|
579
|
+
${hasCellImages ? '<Relationship Id="rIdRichValueStruct" Type="http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueStructure" Target="richData/rdRichValueStructure.xml"/>' : ''}
|
|
580
|
+
${hasCellImages ? '<Relationship Id="rIdRichValueTypes" Type="http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueTypes" Target="richData/rdRichValueTypes.xml"/>' : ''}
|
|
581
|
+
${hasCellImages ? '<Relationship Id="rIdRdArray" Type="http://schemas.microsoft.com/office/2017/06/relationships/rdArray" Target="richData/rdarray.xml"/>' : ''}
|
|
278
582
|
</Relationships>`) });
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
583
|
+
if (hasVba) {
|
|
584
|
+
this._ensureVbaSheetModules();
|
|
585
|
+
entries.push({ name: 'xl/vbaProject.bin', data: this.vbaProject.build() });
|
|
586
|
+
}
|
|
587
|
+
const wbPrAttrs = [
|
|
588
|
+
this.properties.date1904 ? 'date1904="1"' : '',
|
|
589
|
+
hasVba ? 'codeName="ThisWorkbook"' : '',
|
|
590
|
+
].filter(Boolean).join(' ');
|
|
591
|
+
const date1904 = `<workbookPr${wbPrAttrs ? ' ' + wbPrAttrs : ''}/>`;
|
|
592
|
+
const namedRangesXml = this._definedNamesXml(allSlicerCaches);
|
|
593
|
+
const pivotCachesXml = allPivotTables.length
|
|
594
|
+
? `<pivotCaches>${allPivotTables.map(p => `<pivotCache cacheId="${p.cacheId}" r:id="${p.cacheRId}"/>`).join('')}</pivotCaches>`
|
|
595
|
+
: '';
|
|
282
596
|
entries.push({ name: 'xl/workbook.xml', data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
283
597
|
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
|
284
598
|
${date1904}
|
|
@@ -286,14 +600,39 @@ ${date1904}
|
|
|
286
600
|
<sheets>${this.sheets.map((ws, i) => `<sheet name="${escapeXml(ws.name)}" sheetId="${i + 1}" r:id="${ws.rId}"${ws.options?.state && ws.options.state !== 'visible' ? ` state="${ws.options.state}"` : ''}/>`).join('')}</sheets>
|
|
287
601
|
${namedRangesXml}
|
|
288
602
|
<calcPr calcId="191028"/>
|
|
603
|
+
${pivotCachesXml}
|
|
604
|
+
${hasSlicers ? (() => {
|
|
605
|
+
const tableSlicers = allSlicerCaches.filter(sc => sc.type === 'table');
|
|
606
|
+
const pivotSlicers = allSlicerCaches.filter(sc => sc.type === 'pivot');
|
|
607
|
+
let xml = '<extLst>';
|
|
608
|
+
if (pivotSlicers.length)
|
|
609
|
+
xml += `<ext uri="{BBE1A952-AA13-448e-AADC-164F8A28A991}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"><x14:slicerCaches>${pivotSlicers.map(sc => `<x14:slicerCache r:id="${sc.rId}"/>`).join('')}</x14:slicerCaches></ext>`;
|
|
610
|
+
if (tableSlicers.length)
|
|
611
|
+
xml += `<ext uri="{46BE6895-7355-4a93-B00E-2C351335B9C9}" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"><x15:slicerCaches>${tableSlicers.map(sc => `<x14:slicerCache r:id="${sc.rId}"/>`).join('')}</x15:slicerCaches></ext>`;
|
|
612
|
+
xml += '</extLst>';
|
|
613
|
+
return xml;
|
|
614
|
+
})() : ''}
|
|
289
615
|
</workbook>`) });
|
|
616
|
+
if (this.connections.length) {
|
|
617
|
+
entries.push({ name: 'xl/connections.xml', data: strToBytes(this._connectionsXml()) });
|
|
618
|
+
}
|
|
290
619
|
for (let i = 0; i < this.sheets.length; i++) {
|
|
291
620
|
const ws = this.sheets[i];
|
|
292
621
|
const imgRIds = sheetImageRIds.get(ws) ?? [];
|
|
293
622
|
const cRIds = sheetChartRIds.get(ws) ?? [];
|
|
294
623
|
const tblEntries = allTables.filter(t => t.ws === ws);
|
|
295
624
|
const tblRIds_ = sheetTableRIds.get(ws) ?? [];
|
|
296
|
-
|
|
625
|
+
const sheetFolder = ws._isChartSheet ? 'chartsheets' : ws._isDialogSheet ? 'dialogsheets' : 'worksheets';
|
|
626
|
+
const sheetPath = `xl/${sheetFolder}/sheet${i + 1}.xml`;
|
|
627
|
+
if (ws._isChartSheet) {
|
|
628
|
+
entries.push({ name: sheetPath, data: strToBytes(ws.toChartSheetXml()) });
|
|
629
|
+
}
|
|
630
|
+
else if (ws._isDialogSheet) {
|
|
631
|
+
entries.push({ name: sheetPath, data: strToBytes(ws.toDialogSheetXml(styles, shared)) });
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
entries.push({ name: sheetPath, data: strToBytes(ws.toXml(styles, shared)) });
|
|
635
|
+
}
|
|
297
636
|
const wsRels = [];
|
|
298
637
|
if (ws.drawingRId) {
|
|
299
638
|
const dIdx = this.sheets.filter((s, j) => j <= i && s.drawingRId).length;
|
|
@@ -307,17 +646,51 @@ ${namedRangesXml}
|
|
|
307
646
|
for (let j = 0; j < tblEntries.length; j++) {
|
|
308
647
|
wsRels.push(`<Relationship Id="${tblRIds_[j]}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" Target="../tables/table${tblEntries[j].globalTableId}.xml"/>`);
|
|
309
648
|
}
|
|
649
|
+
const ptRIds_ = sheetPivotRIds.get(ws) ?? [];
|
|
650
|
+
const ptEntries = allPivotTables.filter(p => p.ws === ws);
|
|
651
|
+
for (let j = 0; j < ptEntries.length; j++) {
|
|
652
|
+
wsRels.push(`<Relationship Id="${ptRIds_[j]}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable" Target="../pivotTables/pivotTable${ptEntries[j].pivotIdx}.xml"/>`);
|
|
653
|
+
}
|
|
654
|
+
const slicerInfo = sheetSlicerMap.get(ws);
|
|
655
|
+
if (slicerInfo) {
|
|
656
|
+
wsRels.push(`<Relationship Id="${slicerInfo.slicerDefRId}" Type="http://schemas.microsoft.com/office/2007/relationships/slicer" Target="../slicers/slicer${slicerInfo.slicerDefIdx}.xml"/>`);
|
|
657
|
+
}
|
|
310
658
|
const sheetComments = ws.getComments();
|
|
311
|
-
|
|
659
|
+
const sheetControls = ws.getFormControls();
|
|
660
|
+
if ((sheetComments.length || sheetControls.length) && ws.legacyDrawingRId) {
|
|
312
661
|
const vIdx = vmlCtr++;
|
|
313
|
-
const commRId = `rId${globalRId++}`;
|
|
314
662
|
wsRels.push(`<Relationship Id="${ws.legacyDrawingRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing" Target="../drawings/vmlDrawing${vIdx}.vml"/>`);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
663
|
+
if (sheetComments.length) {
|
|
664
|
+
const commRId = `rId${globalRId++}`;
|
|
665
|
+
wsRels.push(`<Relationship Id="${commRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" Target="../comments${vIdx}.xml"/>`);
|
|
666
|
+
entries.push({ name: `xl/comments${vIdx}.xml`, data: strToBytes(this._buildCommentsXml(sheetComments)) });
|
|
667
|
+
}
|
|
668
|
+
const commentShapes = sheetComments.map(({ row, col }, ci) => {
|
|
669
|
+
const left = (col + 1) * 64;
|
|
670
|
+
const top = (row - 1) * 20;
|
|
671
|
+
const sid = 1025 + i * 1000 + ci;
|
|
672
|
+
return `<v:shape id="_x0000_s${sid}" type="#_x0000_t202" style="position:absolute;margin-left:${left}pt;margin-top:${top}pt;width:108pt;height:59.25pt;z-index:${ci + 1};visibility:hidden" fillcolor="#ffffe1" o:insetmode="auto">
|
|
673
|
+
<v:fill color2="#ffffe1"/>
|
|
674
|
+
<v:shadow color="black" obscured="t"/>
|
|
675
|
+
<v:path o:connecttype="none"/>
|
|
676
|
+
<v:textbox style="mso-direction-alt:auto"><div style="text-align:left"/></v:textbox>
|
|
677
|
+
<x:ClientData ObjectType="Note"><x:MoveWithCells/><x:SizeWithCells/><x:Anchor>${col + 1},15,${row - 1},10,${col + 3},15,${row + 4},4</x:Anchor><x:AutoFill>False</x:AutoFill><x:Row>${row - 1}</x:Row><x:Column>${col - 1}</x:Column></x:ClientData>
|
|
678
|
+
</v:shape>`;
|
|
679
|
+
});
|
|
680
|
+
const ctrlBaseId = 1025 + ws.sheetIndex * 1000 + sheetComments.length;
|
|
681
|
+
const controlShapes = sheetControls.map((ctrl, ci) => buildFormControlVmlShape(ctrl, ctrlBaseId + ci));
|
|
682
|
+
entries.push({ name: `xl/drawings/vmlDrawing${vIdx}.vml`, data: strToBytes(buildVmlWithControls(commentShapes, controlShapes)) });
|
|
683
|
+
if (!ws._isDialogSheet) {
|
|
684
|
+
const ctrlRIds = ws.ctrlPropRIds;
|
|
685
|
+
for (let ci = 0; ci < sheetControls.length; ci++) {
|
|
686
|
+
const ctrlPropIdx = ++ctrlPropGlobal;
|
|
687
|
+
wsRels.push(`<Relationship Id="${ctrlRIds[ci]}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp" Target="../ctrlProps/ctrlProp${ctrlPropIdx}.xml"/>`);
|
|
688
|
+
entries.push({ name: `xl/ctrlProps/ctrlProp${ctrlPropIdx}.xml`, data: strToBytes(buildCtrlPropXml(sheetControls[ci])) });
|
|
689
|
+
}
|
|
690
|
+
}
|
|
318
691
|
}
|
|
319
692
|
if (wsRels.length) {
|
|
320
|
-
entries.push({ name: `xl/
|
|
693
|
+
entries.push({ name: `xl/${sheetFolder}/_rels/sheet${i + 1}.xml.rels`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
321
694
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
322
695
|
${wsRels.join('\n')}
|
|
323
696
|
</Relationships>`) });
|
|
@@ -347,14 +720,105 @@ ${dRels.join('\n')}
|
|
|
347
720
|
for (const { img, ext, idx } of allImages) {
|
|
348
721
|
entries.push({ name: `xl/media/image${idx}.${ext}`, data: typeof img.data === 'string' ? base64ToBytes(img.data) : img.data });
|
|
349
722
|
}
|
|
723
|
+
if (hasCellImages) {
|
|
724
|
+
const cellImgRIds = [];
|
|
725
|
+
const cellImgRels = [];
|
|
726
|
+
for (let ci = 0; ci < allCellImages.length; ci++) {
|
|
727
|
+
const { img, ext, idx } = allCellImages[ci];
|
|
728
|
+
const rId = `rId${ci + 1}`;
|
|
729
|
+
cellImgRIds.push(rId);
|
|
730
|
+
cellImgRels.push(`<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="/xl/media/image${idx}.${ext}"/>`);
|
|
731
|
+
entries.push({ name: `xl/media/image${idx}.${ext}`, data: typeof img.data === 'string' ? base64ToBytes(img.data) : img.data });
|
|
732
|
+
}
|
|
733
|
+
entries.push({ name: 'xl/metadata.xml', data: strToBytes(buildMetadataXml(allCellImages.length)) });
|
|
734
|
+
entries.push({ name: 'xl/richData/rdrichvalue.xml', data: strToBytes(buildRichValueXml(allCellImages.length)) });
|
|
735
|
+
entries.push({ name: 'xl/richData/richValueRel.xml', data: strToBytes(buildRichValueRelXml(cellImgRIds)) });
|
|
736
|
+
entries.push({ name: 'xl/richData/rdRichValueStructure.xml', data: strToBytes(buildRichValueStructureXml()) });
|
|
737
|
+
entries.push({ name: 'xl/richData/rdRichValueTypes.xml', data: strToBytes(buildRichValueTypesXml()) });
|
|
738
|
+
entries.push({ name: 'xl/richData/rdarray.xml', data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><arrayData xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2" count="0"></arrayData>`) });
|
|
739
|
+
entries.push({ name: 'xl/richData/_rels/richValueRel.xml.rels', data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
740
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
741
|
+
${cellImgRels.join('\n')}
|
|
742
|
+
</Relationships>`) });
|
|
743
|
+
}
|
|
350
744
|
for (const { ws, chartIdx, globalIdx } of allCharts) {
|
|
351
745
|
entries.push({ name: `xl/charts/chart${globalIdx}.xml`, data: strToBytes(buildChartXml(ws.getCharts()[chartIdx])) });
|
|
352
746
|
}
|
|
353
747
|
for (const { ws, tableIdx, globalTableId } of allTables) {
|
|
354
748
|
entries.push({ name: `xl/tables/table${globalTableId}.xml`, data: strToBytes(buildTableXml(ws.getTables()[tableIdx], globalTableId)) });
|
|
355
749
|
}
|
|
750
|
+
for (const { ws, pt, pivotIdx, cacheId: cId } of allPivotTables) {
|
|
751
|
+
const sourceWs = this.sheets.find(s => s.name === pt.sourceSheet);
|
|
752
|
+
const sourceData = sourceWs ? sourceWs.readRange(pt.sourceRef) : [[]];
|
|
753
|
+
const { pivotTableXml, cacheDefXml, cacheRecordsXml } = buildPivotTableFiles(pt, sourceData, pivotIdx, cId);
|
|
754
|
+
const wbRel = (type, target) => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/${type}" Target="${target}"/>\n</Relationships>`;
|
|
755
|
+
entries.push({ name: `xl/pivotTables/pivotTable${pivotIdx}.xml`, data: strToBytes(pivotTableXml) });
|
|
756
|
+
entries.push({ name: `xl/pivotTables/_rels/pivotTable${pivotIdx}.xml.rels`, data: strToBytes(wbRel('pivotCacheDefinition', `../pivotCache/pivotCacheDefinition${pivotIdx}.xml`)) });
|
|
757
|
+
entries.push({ name: `xl/pivotCache/pivotCacheDefinition${pivotIdx}.xml`, data: strToBytes(cacheDefXml) });
|
|
758
|
+
entries.push({ name: `xl/pivotCache/_rels/pivotCacheDefinition${pivotIdx}.xml.rels`, data: strToBytes(wbRel('pivotCacheRecords', `pivotCacheRecords${pivotIdx}.xml`)) });
|
|
759
|
+
entries.push({ name: `xl/pivotCache/pivotCacheRecords${pivotIdx}.xml`, data: strToBytes(cacheRecordsXml) });
|
|
760
|
+
}
|
|
356
761
|
entries.push({ name: 'xl/styles.xml', data: strToBytes(styles.toXml()) });
|
|
357
762
|
entries.push({ name: 'xl/sharedStrings.xml', data: strToBytes(shared.toXml()) });
|
|
763
|
+
entries.push({ name: 'xl/theme/theme1.xml', data: strToBytes(this._buildThemeXml()) });
|
|
764
|
+
for (let i = 0; i < this.externalLinks.length; i++) {
|
|
765
|
+
const link = this.externalLinks[i];
|
|
766
|
+
const idx = i + 1;
|
|
767
|
+
const sheetsXml = link.sheets.map(s => {
|
|
768
|
+
const dNames = s.definedNames?.map(d => `<definedName name="${escapeXml(d.name)}" refersTo="${escapeXml(d.ref)}"/>`).join('') ?? '';
|
|
769
|
+
return `<sheetName val="${escapeXml(s.name)}"/>${dNames ? `<sheetDataSet>${dNames}</sheetDataSet>` : ''}`;
|
|
770
|
+
}).join('');
|
|
771
|
+
entries.push({ name: `xl/externalLinks/externalLink${idx}.xml`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
772
|
+
<externalLink xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
|
773
|
+
<externalBook r:id="rId1"><sheetNames>${sheetsXml}</sheetNames></externalBook>
|
|
774
|
+
</externalLink>`) });
|
|
775
|
+
entries.push({ name: `xl/externalLinks/_rels/externalLink${idx}.xml.rels`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
776
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
777
|
+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath" Target="${escapeXml(link.target)}" TargetMode="External"/>
|
|
778
|
+
</Relationships>`) });
|
|
779
|
+
}
|
|
780
|
+
for (const [ws, info] of sheetSlicerMap) {
|
|
781
|
+
const allSheetSlicerItems = [];
|
|
782
|
+
for (const ts of info.tableSlicers) {
|
|
783
|
+
const s = ts.slicer;
|
|
784
|
+
allSheetSlicerItems.push(`<slicer name="${escapeXml(s.name)}" cache="${escapeXml(s.name + '_cache')}" caption="${escapeXml(s.caption ?? s.columnName)}" rowHeight="241300" columnCount="${s.columnCount ?? 1}" style="${s.style ?? 'SlicerStyleLight1'}"/>`);
|
|
785
|
+
}
|
|
786
|
+
for (const ps of info.pivotSlicers) {
|
|
787
|
+
const s = ps.slicer;
|
|
788
|
+
allSheetSlicerItems.push(`<slicer name="${escapeXml(s.name)}" cache="${escapeXml(s.name + '_cache')}" caption="${escapeXml(s.caption ?? s.fieldName)}" rowHeight="241300" columnCount="${s.columnCount ?? 1}" style="${s.style ?? 'SlicerStyleLight1'}"/>`);
|
|
789
|
+
}
|
|
790
|
+
entries.push({ name: `xl/slicers/slicer${info.slicerDefIdx}.xml`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
791
|
+
<slicers xmlns="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" mc:Ignorable="x">
|
|
792
|
+
${allSheetSlicerItems.join('\n')}
|
|
793
|
+
</slicers>`) });
|
|
794
|
+
}
|
|
795
|
+
for (const sc of allSlicerCaches) {
|
|
796
|
+
let cacheBody;
|
|
797
|
+
if (sc.type === 'table') {
|
|
798
|
+
cacheBody = `<extLst><x:ext uri="{2F2917AC-EB37-4324-AD4E-5DD8C200BD13}" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"><x15:tableSlicerCache tableId="${sc.tableId}" column="${sc.columnIndex}" sortOrder="${sc.sortOrder ?? 'ascending'}"/></x:ext></extLst>`;
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
const itemsXml = (sc.items ?? []).map((_, xi) => `<i x="${xi}" s="1"/>`).join('');
|
|
802
|
+
cacheBody = `<pivotTables><pivotTable tabId="${sc.tabId}" name="${escapeXml(sc.pivotTableName ?? '')}"/></pivotTables>` +
|
|
803
|
+
(sc.items?.length ? `<data><tabular pivotCacheId="${sc.pivotCacheId}" showMissing="0"><items count="${sc.items.length}">${itemsXml}</items></tabular></data>` : '');
|
|
804
|
+
}
|
|
805
|
+
entries.push({ name: `xl/slicerCaches/slicerCache${sc.idx}.xml`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
806
|
+
<slicerCacheDefinition xmlns="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x" name="${escapeXml(sc.name)}" sourceName="${escapeXml(sc.sourceName)}">
|
|
807
|
+
${cacheBody}
|
|
808
|
+
</slicerCacheDefinition>`) });
|
|
809
|
+
}
|
|
810
|
+
const allQueryTables = this.sheets.flatMap(ws => ws.getQueryTables());
|
|
811
|
+
for (let i = 0; i < allQueryTables.length; i++) {
|
|
812
|
+
const qt = allQueryTables[i];
|
|
813
|
+
entries.push({ name: `xl/queryTables/queryTable${i + 1}.xml`, data: strToBytes(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
814
|
+
<queryTable xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" name="${escapeXml(qt.name)}" connectionId="${qt.connectionId}" autoFormatId="16" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="0">
|
|
815
|
+
<queryTableRefresh nextId="${(qt.columns?.length ?? 0) + 1}">
|
|
816
|
+
<queryTableFields count="${qt.columns?.length ?? 0}">
|
|
817
|
+
${(qt.columns ?? []).map((c, ci) => `<queryTableField id="${ci + 1}" name="${escapeXml(c)}" tableColumnId="${ci + 1}"/>`).join('\n')}
|
|
818
|
+
</queryTableFields>
|
|
819
|
+
</queryTableRefresh>
|
|
820
|
+
</queryTable>`) });
|
|
821
|
+
}
|
|
358
822
|
const cp = { ...this.coreProperties, created: this.coreProperties.created ?? new Date(), modified: new Date() };
|
|
359
823
|
if (!cp.creator && this.properties.author)
|
|
360
824
|
cp.creator = this.properties.author;
|
|
@@ -364,12 +828,27 @@ ${dRels.join('\n')}
|
|
|
364
828
|
application: this.extendedProperties.application ?? 'ExcelForge',
|
|
365
829
|
company: this.extendedProperties.company ?? this.properties.company,
|
|
366
830
|
titlesOfParts: this.sheets.map(s => s.name),
|
|
367
|
-
headingPairs:
|
|
831
|
+
headingPairs: this._headingPairs(),
|
|
368
832
|
})) });
|
|
369
833
|
if (hasCustom)
|
|
370
834
|
entries.push({ name: 'docProps/custom.xml', data: strToBytes(buildCustomXml(this.customProperties)) });
|
|
371
835
|
return buildZip(entries, { level: this.compressionLevel });
|
|
372
836
|
}
|
|
837
|
+
_headingPairs() {
|
|
838
|
+
const normalCount = this.sheets.filter(ws => !ws._isChartSheet && !ws._isDialogSheet).length;
|
|
839
|
+
const chartCount = this.sheets.filter(ws => ws._isChartSheet).length;
|
|
840
|
+
const dialogCount = this.sheets.filter(ws => ws._isDialogSheet).length;
|
|
841
|
+
const pairs = [];
|
|
842
|
+
if (normalCount)
|
|
843
|
+
pairs.push({ name: 'Worksheets', count: normalCount });
|
|
844
|
+
if (chartCount)
|
|
845
|
+
pairs.push({ name: 'Charts', count: chartCount });
|
|
846
|
+
if (dialogCount)
|
|
847
|
+
pairs.push({ name: 'Dialogs', count: dialogCount });
|
|
848
|
+
if (!pairs.length)
|
|
849
|
+
pairs.push({ name: 'Worksheets', count: 0 });
|
|
850
|
+
return pairs;
|
|
851
|
+
}
|
|
373
852
|
_syncLegacyProperties() {
|
|
374
853
|
const p = this.properties;
|
|
375
854
|
if (p.title)
|
|
@@ -393,19 +872,101 @@ ${dRels.join('\n')}
|
|
|
393
872
|
if (p.status)
|
|
394
873
|
this.coreProperties.contentStatus ??= p.status;
|
|
395
874
|
}
|
|
875
|
+
_ensureVbaSheetModules() {
|
|
876
|
+
if (!this.vbaProject)
|
|
877
|
+
return;
|
|
878
|
+
const existingDocModules = this.vbaProject.modules.filter(m => m.type === 'document' && m.name !== 'ThisWorkbook');
|
|
879
|
+
if (existingDocModules.length >= this.sheets.length)
|
|
880
|
+
return;
|
|
881
|
+
for (const ws of this.sheets) {
|
|
882
|
+
const sheetCodeName = ws.name.replace(/[^A-Za-z0-9_]/g, '_');
|
|
883
|
+
if (!this.vbaProject.getModule(sheetCodeName)) {
|
|
884
|
+
this.vbaProject.addModule({ name: sheetCodeName, type: 'document', code: '' });
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
396
888
|
_patchWorkbookXml(originalXml) {
|
|
397
889
|
let xml = originalXml;
|
|
398
890
|
for (let i = 0; i < this.sheets.length; i++) {
|
|
399
891
|
xml = xml.replace(new RegExp(`(<sheet[^>]+sheetId="${i + 1}"[^>]+)name="[^"]*"`), `$1name="${escapeXml(this.sheets[i].name)}"`);
|
|
400
892
|
}
|
|
893
|
+
if (this.vbaProject && !xml.includes('codeName=')) {
|
|
894
|
+
xml = xml.replace('<workbookPr', '<workbookPr codeName="ThisWorkbook"');
|
|
895
|
+
if (!xml.includes('<workbookPr')) {
|
|
896
|
+
xml = xml.replace('<bookViews', '<workbookPr codeName="ThisWorkbook"/><bookViews');
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
const dnXml = this._definedNamesXml();
|
|
900
|
+
if (xml.includes('<definedNames')) {
|
|
901
|
+
xml = xml.replace(/<definedNames[\s\S]*?<\/definedNames>/, dnXml);
|
|
902
|
+
}
|
|
903
|
+
else if (dnXml) {
|
|
904
|
+
xml = xml.replace('</sheets>', `</sheets>${dnXml}`);
|
|
905
|
+
}
|
|
401
906
|
return xml;
|
|
402
907
|
}
|
|
403
|
-
|
|
404
|
-
const
|
|
908
|
+
_definedNamesXml(slicerCaches) {
|
|
909
|
+
const printAreaNames = [];
|
|
910
|
+
for (const ws of this.sheets) {
|
|
911
|
+
if (ws.printArea) {
|
|
912
|
+
const ref = ws.printArea.includes('!') ? ws.printArea : `'${ws.name}'!${ws.printArea}`;
|
|
913
|
+
printAreaNames.push({ name: '_xlnm.Print_Area', ref, scope: ws.name });
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
const slicerNames = (slicerCaches ?? []).map(sc => ({ name: sc.name, ref: '#N/A' }));
|
|
917
|
+
const all = [...this.namedRanges, ...printAreaNames, ...slicerNames];
|
|
918
|
+
if (!all.length)
|
|
919
|
+
return '';
|
|
920
|
+
return `<definedNames>${all.map(nr => {
|
|
921
|
+
let attrs = `name="${escapeXml(nr.name)}"`;
|
|
922
|
+
if (nr.scope) {
|
|
923
|
+
const idx = this.sheets.findIndex(s => s.name === nr.scope);
|
|
924
|
+
if (idx >= 0)
|
|
925
|
+
attrs += ` localSheetId="${idx}"`;
|
|
926
|
+
}
|
|
927
|
+
if (nr.comment)
|
|
928
|
+
attrs += ` comment="${escapeXml(nr.comment)}"`;
|
|
929
|
+
return `<definedName ${attrs}>${escapeXml(nr.ref)}</definedName>`;
|
|
930
|
+
}).join('')}</definedNames>`;
|
|
931
|
+
}
|
|
932
|
+
_connectionsXml(originalXml) {
|
|
933
|
+
if (!this.connections.length)
|
|
934
|
+
return '';
|
|
935
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
936
|
+
<connections xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">${this.connections.map(c => {
|
|
937
|
+
if (c._rawXml)
|
|
938
|
+
return c._rawXml;
|
|
939
|
+
let attrs = ` id="${c.id}" name="${escapeXml(c.name)}" type="${connTypeToNum(c.type)}" refreshedVersion="6"`;
|
|
940
|
+
if (c.description)
|
|
941
|
+
attrs += ` description="${escapeXml(c.description)}"`;
|
|
942
|
+
if (c.refreshOnLoad)
|
|
943
|
+
attrs += ' refreshOnLoad="1"';
|
|
944
|
+
if (c.background)
|
|
945
|
+
attrs += ' background="1"';
|
|
946
|
+
if (c.saveData)
|
|
947
|
+
attrs += ' saveData="1"';
|
|
948
|
+
if (c.keepAlive)
|
|
949
|
+
attrs += ' keepAlive="1"';
|
|
950
|
+
if (c.interval)
|
|
951
|
+
attrs += ` interval="${c.interval}"`;
|
|
952
|
+
const dbPr = c.connectionString || c.command
|
|
953
|
+
? `<dbPr${c.connectionString ? ` connection="${escapeXml(c.connectionString)}"` : ''}${c.command ? ` command="${escapeXml(c.command)}"` : ''}${c.commandType ? ` commandType="${cmdTypeToNum(c.commandType)}"` : ''}/>`
|
|
954
|
+
: '';
|
|
955
|
+
return `<connection${attrs}>${dbPr}</connection>`;
|
|
956
|
+
}).join('')}</connections>`;
|
|
957
|
+
}
|
|
958
|
+
_buildWorkbookRels(rr, dropCalcChain = false) {
|
|
959
|
+
const rels = [...rr.workbookRels.entries()]
|
|
960
|
+
.filter(([_, rel]) => !(dropCalcChain && rel.type.includes('/calcChain')))
|
|
961
|
+
.map(([id, rel]) => `<Relationship Id="${id}" Type="${rel.type}" Target="${rel.target}"/>`);
|
|
405
962
|
if (![...rr.workbookRels.values()].some(r => r.type.includes('/styles')))
|
|
406
963
|
rels.push(`<Relationship Id="rIdStyles" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>`);
|
|
407
964
|
if (![...rr.workbookRels.values()].some(r => r.type.includes('/sharedStrings')))
|
|
408
965
|
rels.push(`<Relationship Id="rIdShared" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>`);
|
|
966
|
+
if (this.vbaProject && ![...rr.workbookRels.values()].some(r => r.type.includes('vbaProject')))
|
|
967
|
+
rels.push(`<Relationship Id="rIdVBA" Type="http://schemas.microsoft.com/office/2006/relationships/vbaProject" Target="vbaProject.bin"/>`);
|
|
968
|
+
if (this.connections.length && ![...rr.workbookRels.values()].some(r => r.type.includes('/connections')))
|
|
969
|
+
rels.push(`<Relationship Id="rIdConns" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections" Target="connections.xml"/>`);
|
|
409
970
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
410
971
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
411
972
|
${rels.join('\n')}
|
|
@@ -414,8 +975,51 @@ ${rels.join('\n')}
|
|
|
414
975
|
_relsToXml(relMap) {
|
|
415
976
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
416
977
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
417
|
-
${[...relMap.entries()].map(([id, r]) => `<Relationship Id="${id}" Type="${r.type}" Target="${r.target}"/>`).join('\n')}
|
|
978
|
+
${[...relMap.entries()].map(([id, r]) => `<Relationship Id="${escapeXml(id)}" Type="${escapeXml(r.type)}" Target="${escapeXml(r.target)}"${r.targetMode ? ` TargetMode="${escapeXml(r.targetMode)}"` : ''}/>`).join('\n')}
|
|
418
979
|
</Relationships>`;
|
|
980
|
+
}
|
|
981
|
+
_buildThemeXml() {
|
|
982
|
+
const t = this.theme;
|
|
983
|
+
const majorFont = t?.majorFont ?? 'Calibri Light';
|
|
984
|
+
const minorFont = t?.minorFont ?? 'Calibri';
|
|
985
|
+
const defaultColors = [
|
|
986
|
+
{ name: 'dk1', color: '000000' }, { name: 'lt1', color: 'FFFFFF' },
|
|
987
|
+
{ name: 'dk2', color: '44546A' }, { name: 'lt2', color: 'E7E6E6' },
|
|
988
|
+
{ name: 'accent1', color: '4472C4' }, { name: 'accent2', color: 'ED7D31' },
|
|
989
|
+
{ name: 'accent3', color: 'A5A5A5' }, { name: 'accent4', color: 'FFC000' },
|
|
990
|
+
{ name: 'accent5', color: '5B9BD5' }, { name: 'accent6', color: '70AD47' },
|
|
991
|
+
{ name: 'hlink', color: '0563C1' }, { name: 'folHlink', color: '954F72' },
|
|
992
|
+
];
|
|
993
|
+
const colors = t?.colors?.map(c => {
|
|
994
|
+
let hex = c.color.replace(/^#/, '');
|
|
995
|
+
if (hex.length === 8)
|
|
996
|
+
hex = hex.substring(2);
|
|
997
|
+
return { name: c.name, color: hex };
|
|
998
|
+
}) ?? defaultColors;
|
|
999
|
+
const colorElements = colors.map(c => {
|
|
1000
|
+
if (c.name === 'dk1' || c.name === 'lt1') {
|
|
1001
|
+
return `<a:${c.name}><a:sysClr val="${c.name === 'dk1' ? 'windowText' : 'window'}" lastClr="${c.color}"/></a:${c.name}>`;
|
|
1002
|
+
}
|
|
1003
|
+
return `<a:${c.name}><a:srgbClr val="${c.color}"/></a:${c.name}>`;
|
|
1004
|
+
}).join('');
|
|
1005
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
1006
|
+
<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="${escapeXml(t?.name ?? 'Office Theme')}">
|
|
1007
|
+
<a:themeElements>
|
|
1008
|
+
<a:clrScheme name="Office">${colorElements}</a:clrScheme>
|
|
1009
|
+
<a:fontScheme name="Office">
|
|
1010
|
+
<a:majorFont><a:latin typeface="${escapeXml(majorFont)}"/><a:ea typeface=""/><a:cs typeface=""/></a:majorFont>
|
|
1011
|
+
<a:minorFont><a:latin typeface="${escapeXml(minorFont)}"/><a:ea typeface=""/><a:cs typeface=""/></a:minorFont>
|
|
1012
|
+
</a:fontScheme>
|
|
1013
|
+
<a:fmtScheme name="Office">
|
|
1014
|
+
<a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:lumMod val="110000"/><a:satMod val="105000"/><a:tint val="67000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="103000"/><a:tint val="73000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="105000"/><a:satMod val="109000"/><a:tint val="81000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:satMod val="103000"/><a:lumMod val="102000"/><a:tint val="94000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:satMod val="110000"/><a:lumMod val="100000"/><a:shade val="100000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:lumMod val="99000"/><a:satMod val="120000"/><a:shade val="78000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:fillStyleLst>
|
|
1015
|
+
<a:lnStyleLst><a:ln w="6350" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="12700" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln><a:ln w="19050" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln></a:lnStyleLst>
|
|
1016
|
+
<a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="63000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle></a:effectStyleLst>
|
|
1017
|
+
<a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:solidFill><a:schemeClr val="phClr"><a:tint val="95000"/><a:satMod val="170000"/></a:schemeClr></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="93000"/><a:satMod val="150000"/><a:shade val="98000"/><a:lumMod val="102000"/></a:schemeClr></a:gs><a:gs pos="50000"><a:schemeClr val="phClr"><a:tint val="98000"/><a:satMod val="130000"/><a:shade val="90000"/><a:lumMod val="103000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="63000"/><a:satMod val="120000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="5400000" scaled="0"/></a:gradFill></a:bgFillStyleLst>
|
|
1018
|
+
</a:fmtScheme>
|
|
1019
|
+
</a:themeElements>
|
|
1020
|
+
<a:objectDefaults/>
|
|
1021
|
+
<a:extraClrSchemeLst/>
|
|
1022
|
+
</a:theme>`;
|
|
419
1023
|
}
|
|
420
1024
|
_buildRootRels(hasCustom) {
|
|
421
1025
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -426,12 +1030,24 @@ ${[...relMap.entries()].map(([id, r]) => `<Relationship Id="${id}" Type="${r.typ
|
|
|
426
1030
|
${hasCustom ? `<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties" Target="docProps/custom.xml"/>` : ''}
|
|
427
1031
|
</Relationships>`;
|
|
428
1032
|
}
|
|
429
|
-
_patchContentTypes(originalXml, addCustom) {
|
|
1033
|
+
_patchContentTypes(originalXml, addCustom, dropCalcChain = false) {
|
|
430
1034
|
let xml = originalXml;
|
|
1035
|
+
if (dropCalcChain)
|
|
1036
|
+
xml = xml.replace(/<Override[^>]*calcChain[^>]*\/>/g, '');
|
|
431
1037
|
if (!xml.includes('sharedStrings'))
|
|
432
1038
|
xml = xml.replace('</Types>', `<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>\n</Types>`);
|
|
433
1039
|
if (addCustom && !xml.includes('custom-properties'))
|
|
434
1040
|
xml = xml.replace('</Types>', `<Override PartName="/docProps/custom.xml" ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>\n</Types>`);
|
|
1041
|
+
if (this.vbaProject) {
|
|
1042
|
+
if (!xml.includes('vbaProject.bin'))
|
|
1043
|
+
xml = xml.replace('</Types>', `<Override PartName="/xl/vbaProject.bin" ContentType="application/vnd.ms-office.vbaProject"/>\n</Types>`);
|
|
1044
|
+
xml = xml.replace('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml', 'application/vnd.ms-excel.sheet.macroEnabled.main+xml');
|
|
1045
|
+
}
|
|
1046
|
+
if (this.isTemplate && !this.vbaProject) {
|
|
1047
|
+
xml = xml.replace('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml');
|
|
1048
|
+
}
|
|
1049
|
+
if (this.connections.length && !xml.includes('connections.xml'))
|
|
1050
|
+
xml = xml.replace('</Types>', `<Override PartName="/xl/connections.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml"/>\n</Types>`);
|
|
435
1051
|
return xml;
|
|
436
1052
|
}
|
|
437
1053
|
async buildBase64() {
|
|
@@ -452,7 +1068,37 @@ ${hasCustom ? `<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/o
|
|
|
452
1068
|
const commentsXml = comments.map(({ row, col, comment }) => {
|
|
453
1069
|
const ref = `${colIndexToLetter(col)}${row}`;
|
|
454
1070
|
const authorIdx = authors.indexOf(comment.author ?? '');
|
|
455
|
-
|
|
1071
|
+
let textXml;
|
|
1072
|
+
if (comment.richText && comment.richText.length > 0) {
|
|
1073
|
+
textXml = comment.richText.map(run => {
|
|
1074
|
+
let rPr = '';
|
|
1075
|
+
if (run.font) {
|
|
1076
|
+
const f = run.font;
|
|
1077
|
+
if (f.bold)
|
|
1078
|
+
rPr += '<b/>';
|
|
1079
|
+
if (f.italic)
|
|
1080
|
+
rPr += '<i/>';
|
|
1081
|
+
if (f.underline && f.underline !== 'none')
|
|
1082
|
+
rPr += `<u val="${f.underline === 'single' ? 'single' : f.underline}"/>`;
|
|
1083
|
+
if (f.strike)
|
|
1084
|
+
rPr += '<strike/>';
|
|
1085
|
+
if (f.size)
|
|
1086
|
+
rPr += `<sz val="${f.size}"/>`;
|
|
1087
|
+
if (f.color)
|
|
1088
|
+
rPr += `<color rgb="${f.color}"/>`;
|
|
1089
|
+
if (f.name)
|
|
1090
|
+
rPr += `<rFont val="${escapeXml(f.name)}"/>`;
|
|
1091
|
+
if (f.family != null)
|
|
1092
|
+
rPr += `<family val="${f.family}"/>`;
|
|
1093
|
+
}
|
|
1094
|
+
const rPrTag = rPr ? `<rPr>${rPr}</rPr>` : '';
|
|
1095
|
+
return `<r>${rPrTag}<t xml:space="preserve">${escapeXml(run.text)}</t></r>`;
|
|
1096
|
+
}).join('');
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
textXml = `<r><t>${escapeXml(comment.text)}</t></r>`;
|
|
1100
|
+
}
|
|
1101
|
+
return `<comment ref="${ref}" authorId="${authorIdx}"><text>${textXml}</text></comment>`;
|
|
456
1102
|
}).join('');
|
|
457
1103
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
458
1104
|
<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
@@ -489,4 +1135,74 @@ ${shapes}
|
|
|
489
1135
|
URL.revokeObjectURL(url);
|
|
490
1136
|
}
|
|
491
1137
|
}
|
|
1138
|
+
function imageContentType(ext) {
|
|
1139
|
+
switch (ext) {
|
|
1140
|
+
case 'jpg': return 'image/jpeg';
|
|
1141
|
+
case 'png': return 'image/png';
|
|
1142
|
+
case 'gif': return 'image/gif';
|
|
1143
|
+
case 'bmp': return 'image/bmp';
|
|
1144
|
+
case 'tiff': return 'image/tiff';
|
|
1145
|
+
case 'emf': return 'image/x-emf';
|
|
1146
|
+
case 'wmf': return 'image/x-wmf';
|
|
1147
|
+
case 'svg': return 'image/svg+xml';
|
|
1148
|
+
case 'ico': return 'image/x-icon';
|
|
1149
|
+
case 'webp': return 'image/webp';
|
|
1150
|
+
default: return `image/${ext}`;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
function imageExt(format) {
|
|
1154
|
+
return format === 'jpeg' ? 'jpg' : format;
|
|
1155
|
+
}
|
|
1156
|
+
function buildMetadataXml(count) {
|
|
1157
|
+
const bks = Array.from({ length: count }, (_, i) => `<bk><extLst><ext uri="{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}"><xlrd:rvb i="${i}"/></ext></extLst></bk>`).join('');
|
|
1158
|
+
const cellBks = Array.from({ length: count }, (_, i) => `<bk><rc t="1" v="${i}"/></bk>`).join('');
|
|
1159
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
1160
|
+
`<metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"` +
|
|
1161
|
+
` xmlns:xlrd="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata">` +
|
|
1162
|
+
`<metadataTypes count="1">` +
|
|
1163
|
+
`<metadataType name="XLRICHVALUE" minSupportedVersion="120000" copy="1" pasteAll="1" pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1" clearComments="1" assign="1" coerce="1"/>` +
|
|
1164
|
+
`</metadataTypes>` +
|
|
1165
|
+
`<futureMetadata name="XLRICHVALUE" count="${count}">${bks}</futureMetadata>` +
|
|
1166
|
+
`<valueMetadata count="${count}">${cellBks}</valueMetadata>` +
|
|
1167
|
+
`</metadata>`;
|
|
1168
|
+
}
|
|
1169
|
+
function buildRichValueXml(count) {
|
|
1170
|
+
const rvs = Array.from({ length: count }, (_, i) => `<rv s="0"><v>${i}</v><v>5</v><v></v></rv>`).join('');
|
|
1171
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
1172
|
+
`<rvData xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="${count}">${rvs}</rvData>`;
|
|
1173
|
+
}
|
|
1174
|
+
function buildRichValueRelXml(rIds) {
|
|
1175
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
1176
|
+
`<richValueRels xmlns="http://schemas.microsoft.com/office/spreadsheetml/2022/richvaluerel"` +
|
|
1177
|
+
` xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">` +
|
|
1178
|
+
rIds.map(id => `<rel r:id="${id}"/>`).join('') +
|
|
1179
|
+
`</richValueRels>`;
|
|
1180
|
+
}
|
|
1181
|
+
function buildRichValueStructureXml() {
|
|
1182
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
1183
|
+
`<rvStructures xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="1">` +
|
|
1184
|
+
`<s t="_localImage"><k n="_rvRel:LocalImageIdentifier" t="i"/><k n="CalcOrigin" t="i"/><k n="Text" t="s"/></s>` +
|
|
1185
|
+
`</rvStructures>`;
|
|
1186
|
+
}
|
|
1187
|
+
function buildRichValueTypesXml() {
|
|
1188
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
1189
|
+
`<rvTypesInfo xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2"` +
|
|
1190
|
+
` xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"` +
|
|
1191
|
+
` mc:Ignorable="x"` +
|
|
1192
|
+
` xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">` +
|
|
1193
|
+
`<global><keyFlags>` +
|
|
1194
|
+
`<key name="_Self"><flag name="ExcludeFromFile" value="1"/><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1195
|
+
`<key name="_DisplayString"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1196
|
+
`<key name="_Flags"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1197
|
+
`<key name="_Format"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1198
|
+
`<key name="_SubLabel"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1199
|
+
`<key name="_Attribution"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1200
|
+
`<key name="_Icon"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1201
|
+
`<key name="_Display"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1202
|
+
`<key name="_CanonicalPropertyNames"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1203
|
+
`<key name="_ClassificationId"><flag name="ExcludeFromCalcComparison" value="1"/></key>` +
|
|
1204
|
+
`</keyFlags></global>` +
|
|
1205
|
+
`<types></types>` +
|
|
1206
|
+
`</rvTypesInfo>`;
|
|
1207
|
+
}
|
|
492
1208
|
//# sourceMappingURL=Workbook.js.map
|