@office-open/xlsx 0.10.15 → 0.11.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.
@@ -1,842 +0,0 @@
1
- import { n as vmlNotesDesc, o as sharedStringsDesc, r as stringifyWorksheet, t as commentsDesc } from "./comments-CUChd469.mjs";
2
- import { S as calcChainDesc, _ as aggregate, a as usersDesc, b as drawingDesc, c as buildTablePartsXml, f as tableDesc, h as pivotTableDesc, i as revisionLogDesc, l as workbookDesc, m as pivotCacheRecordsDesc, n as XlsxWriteContext, p as pivotCacheDefDesc, r as revisionHeadersDesc, s as buildExternalReferencesXml, v as collectUniqueValues, w as stylesDesc, x as chartsheetDesc, y as externalLinkDesc } from "./context-eqnGd7of.mjs";
3
- import { OoxmlMimeType, Relationships, TargetModeType, appPropertiesDesc, buildCorePropertiesXmlString, compileMapping, createPacker, customPropertiesDesc, toUint8Array } from "@office-open/core";
4
- import { createThemeXml } from "@office-open/core/theme";
5
- import { chartSpaceDesc } from "@office-open/core/chart";
6
- //#region src/compiler.ts
7
- /**
8
- * XLSX Compiler — compiles WorkbookOptions into a Zippable structure.
9
- *
10
- * Accepts pure JSON WorkbookOptions — no intermediate File class needed.
11
- * Uses XlsxWriteContext for shared state (strings, styles, media, charts).
12
- *
13
- * @module
14
- */
15
- const XML_DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
16
- /**
17
- * Compile workbook options into a Zippable structure.
18
- */
19
- function compileWorkbook(options, overrides = [], mediaLevel = 0) {
20
- const ctx = new XlsxWriteContext();
21
- const mapping = {};
22
- const worksheetConfigs = options.worksheets ?? [];
23
- const chartsheetConfigs = options.chartsheets ?? [];
24
- const hasCustomProperties = !!options.customProperties && options.customProperties.length > 0;
25
- mapping["Properties"] = {
26
- data: XML_DECL + buildCorePropertiesXmlString(options),
27
- path: "docProps/core.xml"
28
- };
29
- mapping["AppProperties"] = {
30
- data: XML_DECL + (appPropertiesDesc.stringify(options.appProperties ?? {}, ctx) ?? ""),
31
- path: "docProps/app.xml"
32
- };
33
- if (hasCustomProperties) mapping["CustomProperties"] = {
34
- data: XML_DECL + (customPropertiesDesc.stringify({ properties: options.customProperties ?? [] }, ctx) ?? ""),
35
- path: "docProps/custom.xml"
36
- };
37
- mapping["FileRelationships"] = {
38
- data: XML_DECL + buildFileRelationships(hasCustomProperties).serialize(),
39
- path: "_rels/.rels"
40
- };
41
- for (let i = 0; i < worksheetConfigs.length; i++) ctx.contentTypes.addWorksheet(i + 1);
42
- ctx.contentTypes.addStyles();
43
- ctx.contentTypes.addSharedStrings();
44
- ctx.contentTypes.addTheme();
45
- if (hasCustomProperties) ctx.contentTypes.addCustomProperties();
46
- for (const dxf of options.dxfs ?? []) ctx.registerDxf(dxf);
47
- if (options.colors) ctx.styles.setColors(options.colors);
48
- if (options.tableStyles) ctx.styles.setTableStyles(options.tableStyles);
49
- if (options.cellStyles) ctx.styles.setCustomCellStyles(options.cellStyles);
50
- if (options.styleExtensions) ctx.styles.setExtensions(options.styleExtensions);
51
- buildWorkbookRelationships(ctx.workbookRels, worksheetConfigs.length, chartsheetConfigs.length);
52
- const sheets = [];
53
- let sheetId = 1;
54
- let rId = 1;
55
- for (const ws of worksheetConfigs) sheets.push({
56
- name: ws.name ?? `Sheet${sheetId}`,
57
- sheetId: sheetId++,
58
- rId: `rId${rId++}`
59
- });
60
- for (const cs of chartsheetConfigs) sheets.push({
61
- name: cs.name ?? `Chart${sheetId}`,
62
- sheetId: sheetId++,
63
- rId: `rId${rId++}`
64
- });
65
- let globalMediaIdx = 0;
66
- let globalChartIdx = 0;
67
- let globalPivotIdx = 0;
68
- let globalPivotCacheIdx = 0;
69
- let globalTableIdx = 0;
70
- const pivotCacheDataMap = /* @__PURE__ */ new Map();
71
- const calcCells = [];
72
- const allTableParts = [];
73
- const wsContext = {
74
- sharedStrings: ctx.sharedStrings,
75
- styles: ctx.styles
76
- };
77
- for (const [i, wsOpts] of worksheetConfigs.entries()) {
78
- const imgOpts = wsOpts.images ?? [];
79
- const chartOpts = wsOpts.charts ?? [];
80
- const hlOpts = wsOpts.hyperlinks ?? [];
81
- const sheetName = wsOpts.name ?? `Sheet${i + 1}`;
82
- let sheetXml = stringifyWorksheet(wsOpts, wsContext);
83
- const sheetIdx = i + 1;
84
- const wsRows = wsOpts.rows ?? [];
85
- for (const [ri, rowOpts] of wsRows.entries()) {
86
- const rowNumber = rowOpts.rowNumber ?? ri + 1;
87
- if (!rowOpts.cells) continue;
88
- for (const [ci, cell] of rowOpts.cells.entries()) {
89
- if (!cell.formula) continue;
90
- const ref = cell.reference ?? columnToLetter(ci + 1) + rowNumber;
91
- calcCells.push({
92
- reference: ref,
93
- sheetIndex: sheetIdx,
94
- array: cell.formula.type === "array"
95
- });
96
- }
97
- }
98
- const hasMedia = imgOpts.length > 0 || chartOpts.length > 0;
99
- const hasExternalHyperlinks = hlOpts.some((h) => h.target.type === "external");
100
- const commentOpts = wsOpts.comments ?? [];
101
- const hasComments = commentOpts.length > 0;
102
- const pivotOpts = wsOpts.pivotTables ?? [];
103
- const hasPivots = pivotOpts.length > 0;
104
- const tableOpts = wsOpts.tables ?? [];
105
- const hasTables = tableOpts.length > 0;
106
- const bgImg = wsOpts.backgroundImage;
107
- let wsRels;
108
- let nextRid = 0;
109
- if (hasMedia || hasExternalHyperlinks || hasComments || hasPivots || hasTables || bgImg) wsRels = new Relationships();
110
- if (hasExternalHyperlinks) for (const hl of hlOpts) {
111
- if (hl.target.type !== "external") continue;
112
- const rid = ++nextRid;
113
- wsRels.addRelationship(rid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", hl.target.url, "External");
114
- }
115
- if (hasMedia) {
116
- const drawingImages = [];
117
- const drawingCharts = [];
118
- const drawingRels = new Relationships();
119
- let rid = 1;
120
- for (const img of imgOpts) {
121
- const ext = img.type === "jpg" ? "jpeg" : "png";
122
- const rawBytes = toUint8Array(img.data, { encoding: "base64" });
123
- const entry = ctx.media.addMedia(rawBytes, ext, (fileName) => ({
124
- fileName,
125
- type: ext,
126
- data: rawBytes,
127
- width: 0,
128
- height: 0
129
- }));
130
- drawingRels.addRelationship(rid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `../media/${entry.fileName}`);
131
- drawingImages.push({
132
- col: img.col,
133
- row: img.row,
134
- rId: `rId${rid}`
135
- });
136
- rid++;
137
- globalMediaIdx++;
138
- }
139
- for (const chart of chartOpts) {
140
- const chartKey = `chart_${globalChartIdx}`;
141
- ctx.charts.addChart(chartKey, {
142
- key: chartKey,
143
- chartSpaceXml: chartSpaceDesc.stringify(chart, ctx) ?? ""
144
- });
145
- drawingRels.addRelationship(rid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", `../charts/chart${globalChartIdx + 1}.xml`);
146
- drawingCharts.push({
147
- col: chart.col,
148
- row: chart.row,
149
- rId: `rId${rid}`
150
- });
151
- rid++;
152
- globalChartIdx++;
153
- }
154
- const drawingXml = drawingDesc.stringify({
155
- images: drawingImages,
156
- charts: drawingCharts
157
- }, ctx);
158
- const drawingIdx = i + 1;
159
- mapping[`Drawing${i}`] = {
160
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${drawingXml}`,
161
- path: `xl/drawings/drawing${drawingIdx}.xml`
162
- };
163
- mapping[`DrawingRels${i}`] = {
164
- data: XML_DECL + drawingRels.serialize(),
165
- path: `xl/drawings/_rels/drawing${drawingIdx}.xml.rels`
166
- };
167
- const drawingRid = ++nextRid;
168
- sheetXml = sheetXml.slice(0, -12) + `<drawing r:id="rId${drawingRid}"/></worksheet>`;
169
- wsRels.addRelationship(drawingRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", `../drawings/drawing${drawingIdx}.xml`);
170
- ctx.contentTypes.addDrawing(drawingIdx);
171
- }
172
- if (hasComments) {
173
- const commentsIdx = i + 1;
174
- const commentsXml = commentsDesc.stringify({ comments: commentOpts }, ctx);
175
- mapping[`Comments${i}`] = {
176
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${commentsXml}`,
177
- path: `xl/comments${commentsIdx}.xml`
178
- };
179
- const vmlXml = vmlNotesDesc.stringify({ comments: commentOpts }, ctx);
180
- mapping[`VmlDrawing${i}`] = {
181
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${vmlXml}`,
182
- path: `xl/drawings/vmlDrawing${commentsIdx}.vml`
183
- };
184
- const commentsRid = ++nextRid;
185
- wsRels.addRelationship(commentsRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", `../comments${commentsIdx}.xml`);
186
- const vmlRid = ++nextRid;
187
- wsRels.addRelationship(vmlRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", `../drawings/vmlDrawing${commentsIdx}.vml`);
188
- sheetXml = sheetXml.slice(0, -12) + `<legacyDrawing r:id="rId${vmlRid}"/></worksheet>`;
189
- ctx.contentTypes.addComments(commentsIdx);
190
- ctx.contentTypes.addVmlDrawing();
191
- }
192
- if (bgImg) {
193
- const ext = bgImg.type === "jpg" ? "jpeg" : bgImg.type;
194
- const rawBytes = toUint8Array(bgImg.data, { encoding: "base64" });
195
- const entry = ctx.media.addMedia(rawBytes, ext, (fileName) => ({
196
- fileName,
197
- type: ext,
198
- data: rawBytes,
199
- width: 0,
200
- height: 0
201
- }));
202
- globalMediaIdx++;
203
- const bgRid = ++nextRid;
204
- wsRels.addRelationship(bgRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `../media/${entry.fileName}`);
205
- sheetXml = sheetXml.replace("<!--BACKGROUND_PICTURE-->", `<picture r:id="rId${bgRid}"/>`);
206
- }
207
- if (hasPivots) for (const pt of pivotOpts) {
208
- globalPivotIdx++;
209
- const pivotIdx = globalPivotIdx;
210
- const sourceSheet = pt.sourceSheet ?? sheetName;
211
- const sourceWsIdx = worksheetConfigs.findIndex((ws) => (ws.name ?? `Sheet${worksheetConfigs.indexOf(ws) + 1}`) === sourceSheet);
212
- if (sourceWsIdx === -1) continue;
213
- const sourceWs = worksheetConfigs[sourceWsIdx];
214
- if (!sourceWs) continue;
215
- const sourceData = extractPivotSourceData(sourceWs.rows ?? [], pt.source);
216
- const cacheKey = `${sourceSheet}:${pt.source}`;
217
- let cacheId;
218
- let cacheIdx;
219
- const existing = pivotCacheDataMap.get(cacheKey);
220
- if (existing) {
221
- cacheId = existing.cacheId;
222
- cacheIdx = existing.cacheIdx;
223
- } else {
224
- globalPivotCacheIdx++;
225
- cacheIdx = globalPivotCacheIdx;
226
- cacheId = cacheIdx;
227
- pivotCacheDataMap.set(cacheKey, {
228
- cacheId,
229
- cacheIdx
230
- });
231
- const cacheDefRels = new Relationships();
232
- cacheDefRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords", "pivotCacheRecords1.xml");
233
- const cacheDefXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + pivotCacheDefDesc.stringify({
234
- sourceRef: pt.source.split(":")[0] ? pt.source : "A1",
235
- sourceSheet,
236
- sourceData,
237
- recordsRid: "rId1"
238
- }, ctx);
239
- mapping[`PivotCacheDef${cacheIdx}`] = {
240
- data: cacheDefXml,
241
- path: `xl/pivotCache/pivotCacheDefinition${cacheIdx}.xml`
242
- };
243
- mapping[`PivotCacheDefRels${cacheIdx}`] = {
244
- data: XML_DECL + cacheDefRels.serialize(),
245
- path: `xl/pivotCache/_rels/pivotCacheDefinition${cacheIdx}.xml.rels`
246
- };
247
- const cacheRecordsXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + pivotCacheRecordsDesc.stringify({ sourceData }, ctx);
248
- mapping[`PivotCacheRecords${cacheIdx}`] = {
249
- data: cacheRecordsXml,
250
- path: `xl/pivotCache/pivotCacheRecords${cacheIdx}.xml`
251
- };
252
- ctx.contentTypes.addPivotCacheDefinition(cacheIdx);
253
- ctx.contentTypes.addPivotCacheRecords(cacheIdx);
254
- const wbPivotRid = ctx.workbookRels.relationshipCount + 1;
255
- ctx.workbookRels.addRelationship(wbPivotRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition", `pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
256
- ctx.pivotCacheRefs.push({
257
- cacheId,
258
- rId: `rId${wbPivotRid}`
259
- });
260
- }
261
- const pivotTableXml = XML_DECL + pivotTableDesc.stringify({
262
- options: pt,
263
- sourceData,
264
- cacheId
265
- }, ctx);
266
- mapping[`PivotTable${pivotIdx}`] = {
267
- data: pivotTableXml,
268
- path: `xl/pivotTables/pivotTable${pivotIdx}.xml`
269
- };
270
- const ptRels = new Relationships();
271
- ptRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition", `../pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
272
- mapping[`PivotTableRels${pivotIdx}`] = {
273
- data: XML_DECL + ptRels.serialize(),
274
- path: `xl/pivotTables/_rels/pivotTable${pivotIdx}.xml.rels`
275
- };
276
- const ptRid = ++nextRid;
277
- wsRels.addRelationship(ptRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable", `../pivotTables/pivotTable${pivotIdx}.xml`);
278
- ctx.contentTypes.addPivotTable(pivotIdx);
279
- }
280
- const wsTableParts = [];
281
- if (hasTables) for (const tbl of tableOpts) {
282
- globalTableIdx++;
283
- const tableIdx = globalTableIdx;
284
- const tableXmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + tableDesc.stringify({
285
- ...tbl,
286
- id: tbl.id ?? tableIdx
287
- }, ctx);
288
- mapping[`Table${tableIdx}`] = {
289
- data: tableXmlStr,
290
- path: `xl/tables/table${tableIdx}.xml`
291
- };
292
- const tblRid = ++nextRid;
293
- wsRels.addRelationship(tblRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", `../tables/table${tableIdx}.xml`);
294
- wsTableParts.push({ rId: `rId${tblRid}` });
295
- allTableParts.push({ rId: `rId${tblRid}` });
296
- ctx.contentTypes.addTable(tableIdx);
297
- }
298
- if (hasPivots) {
299
- const rendered = renderPivotSheetData(pivotOpts, worksheetConfigs, ctx.sharedStrings, sheetName);
300
- if (rendered.sheetData.length > 0) {
301
- sheetXml = sheetXml.replace(/<sheetData\/>|<sheetData><\/sheetData>/, rendered.sheetData);
302
- if (!sheetXml.includes("<dimension")) sheetXml = sheetXml.replace("<sheetViews", `<dimension ref="${rendered.dimensionRef}"/><sheetViews`);
303
- }
304
- }
305
- if (wsTableParts.length > 0) {
306
- const tablePartsXml = buildTablePartsXml(wsTableParts);
307
- sheetXml = sheetXml.slice(0, -12) + tablePartsXml + "</worksheet>";
308
- }
309
- if (wsRels) mapping[`WorksheetRels${i}`] = {
310
- data: XML_DECL + wsRels.serialize(),
311
- path: `xl/worksheets/_rels/sheet${i + 1}.xml.rels`
312
- };
313
- mapping[`Worksheet${i}`] = {
314
- data: sheetXml,
315
- path: `xl/worksheets/sheet${i + 1}.xml`
316
- };
317
- }
318
- for (const [i, csOpts] of chartsheetConfigs.entries()) {
319
- const chartDef = csOpts.chart;
320
- const csChartGlobalIdx = ctx.charts.array.length;
321
- const csChartKey = `cs_chart_${csChartGlobalIdx}`;
322
- ctx.charts.addChart(csChartKey, {
323
- key: csChartKey,
324
- chartSpaceXml: chartSpaceDesc.stringify({
325
- type: chartDef.type,
326
- title: chartDef.title,
327
- categories: chartDef.categories,
328
- series: chartDef.series
329
- }, ctx) ?? ""
330
- });
331
- const csRels = new Relationships();
332
- const csDrawingIdx = i + 1;
333
- csRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", `../drawings/drawing${csDrawingIdx}.xml`);
334
- const csDrawingRels = new Relationships();
335
- csDrawingRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", `../charts/chart${csChartGlobalIdx + 1}.xml`);
336
- const csDrawingXml = `<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><xdr:absoluteAnchor><xdr:pos x="0" y="0"/><xdr:ext cx="9308969" cy="6096000"/><xdr:graphicFrame><xdr:nvGraphicFramePr><xdr:cNvPr id="1" name="Chart ${i + 1}"/><xdr:cNvGraphicFramePr><a:graphicFrameLocks noGrp="1"/></xdr:cNvGraphicFramePr></xdr:nvGraphicFramePr><xdr:xfrm><a:off x="0" y="0"/><a:ext cx="9308969" cy="6096000"/></xdr:xfrm><a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" r:id="rId1"/></a:graphicData></a:graphic></xdr:graphicFrame><xdr:clientData/></xdr:absoluteAnchor></xdr:wsDr>`;
337
- mapping[`ChartsheetDrawing${i}`] = {
338
- data: csDrawingXml,
339
- path: `xl/drawings/drawing${csDrawingIdx}.xml`
340
- };
341
- mapping[`ChartsheetDrawingRels${i}`] = {
342
- data: XML_DECL + csDrawingRels.serialize(),
343
- path: `xl/drawings/_rels/drawing${csDrawingIdx}.xml.rels`
344
- };
345
- ctx.contentTypes.addDrawing(csDrawingIdx);
346
- mapping[`ChartsheetRels${i}`] = {
347
- data: XML_DECL + csRels.serialize(),
348
- path: `xl/chartsheets/_rels/sheet${i + 1}.xml.rels`
349
- };
350
- mapping[`Chartsheet${i}`] = {
351
- data: XML_DECL + chartsheetDesc.stringify({
352
- ...csOpts,
353
- drawingRId: "rId1"
354
- }, ctx),
355
- path: `xl/chartsheets/sheet${i + 1}.xml`
356
- };
357
- ctx.contentTypes.addChartsheet(i + 1);
358
- }
359
- let wbXml = workbookDesc.stringify({
360
- sheets,
361
- pivotCaches: ctx.pivotCacheRefs,
362
- protection: options.workbookProtection,
363
- customViews: options.customWorkbookViews,
364
- fileRecoveryPr: options.fileRecoveryPr,
365
- functionGroups: options.functionGroups,
366
- webPublishing: options.webPublishing,
367
- fileSharing: options.fileSharing,
368
- volTypes: options.volTypes,
369
- webPublishObjects: options.webPublishObjects
370
- }, ctx) ?? "";
371
- const extLinks = options.externalLinks ?? [];
372
- if (extLinks.length > 0) {
373
- const extRefs = [];
374
- for (let ei = 0; ei < extLinks.length; ei++) {
375
- const elIdx = ei + 1;
376
- const elRid = ctx.workbookRels.relationshipCount + 1;
377
- ctx.workbookRels.addRelationship(elRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink", `externalLinks/externalLink${elIdx}.xml`);
378
- const elOpts = extLinks[ei];
379
- if (!elOpts) continue;
380
- let bookRId;
381
- if (elOpts.externalBook?.target) {
382
- const elRels = new Relationships();
383
- elRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath", elOpts.externalBook.target, TargetModeType.EXTERNAL);
384
- bookRId = "rId1";
385
- mapping[`ExternalLinkRels${elIdx}`] = {
386
- data: XML_DECL + elRels.serialize(),
387
- path: `xl/externalLinks/_rels/externalLink${elIdx}.xml.rels`
388
- };
389
- }
390
- mapping[`ExternalLink${elIdx}`] = {
391
- data: XML_DECL + externalLinkDesc.stringify({
392
- ...elOpts,
393
- bookRId
394
- }, ctx),
395
- path: `xl/externalLinks/externalLink${elIdx}.xml`
396
- };
397
- extRefs.push({ rId: `rId${elRid}` });
398
- ctx.contentTypes.addExternalLink(elIdx);
399
- }
400
- const extRefsXml = buildExternalReferencesXml(extRefs);
401
- wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", extRefsXml);
402
- } else wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", "");
403
- mapping["Workbook"] = {
404
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${wbXml}`,
405
- path: "xl/workbook.xml"
406
- };
407
- if (ctx.sharedStrings.count > 0) mapping["SharedStrings"] = {
408
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${sharedStringsDesc.stringify(ctx.sharedStrings.toDescriptorOptions(), ctx)}`,
409
- path: "xl/sharedStrings.xml"
410
- };
411
- mapping["Styles"] = {
412
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${stylesDesc.stringify({ styles: ctx.styles }, ctx)}`,
413
- path: "xl/styles.xml"
414
- };
415
- mapping["Theme"] = {
416
- data: XML_DECL + createThemeXml(),
417
- path: "xl/theme/theme1.xml"
418
- };
419
- for (const [i, chartData] of ctx.charts.array.entries()) {
420
- mapping[`Chart${i}`] = {
421
- data: XML_DECL + chartData.chartSpaceXml,
422
- path: `xl/charts/chart${i + 1}.xml`
423
- };
424
- ctx.contentTypes.addChart(i + 1);
425
- }
426
- if (calcCells.length > 0) {
427
- mapping["CalcChain"] = {
428
- data: calcChainDesc.stringify({ cells: calcCells }, ctx) ?? "",
429
- path: "xl/calcChain.xml"
430
- };
431
- ctx.contentTypes.addCalcChain();
432
- const calcChainRid = ctx.workbookRels.relationshipCount + 1;
433
- ctx.workbookRels.addRelationship(calcChainRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain", "calcChain.xml");
434
- }
435
- if (options.revisionLog) {
436
- const rl = options.revisionLog;
437
- const REV_HEADERS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionHeaders";
438
- const REV_LOG_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog";
439
- const USERS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/users";
440
- mapping["RevisionHeaders"] = {
441
- data: XML_DECL + (revisionHeadersDesc.stringify(rl.headers, ctx) ?? ""),
442
- path: "xl/revisionHeaders.xml"
443
- };
444
- ctx.contentTypes.addRevisionHeaders();
445
- ctx.workbookRels.addRelationship(ctx.workbookRels.relationshipCount + 1, REV_HEADERS_REL, "revisionHeaders.xml");
446
- const revHeadersRels = new Relationships();
447
- for (const [i, log] of rl.logs.entries()) {
448
- mapping[`RevisionLog${i}`] = {
449
- data: XML_DECL + (revisionLogDesc.stringify(log, ctx) ?? ""),
450
- path: `xl/revisions/revision${i + 1}.xml`
451
- };
452
- ctx.contentTypes.addRevisionLog(i + 1);
453
- revHeadersRels.addRelationship(i + 1, REV_LOG_REL, `revisions/revision${i + 1}.xml`);
454
- }
455
- mapping["RevisionHeadersRels"] = {
456
- data: XML_DECL + revHeadersRels.serialize(),
457
- path: "xl/_rels/revisionHeaders.xml.rels"
458
- };
459
- if (rl.users) {
460
- const usersXml = usersDesc.stringify(rl.users, ctx);
461
- if (usersXml) {
462
- mapping["Users"] = {
463
- data: XML_DECL + usersXml,
464
- path: "xl/users.xml"
465
- };
466
- ctx.contentTypes.addUsers();
467
- ctx.workbookRels.addRelationship(ctx.workbookRels.relationshipCount + 1, USERS_REL, "users.xml");
468
- }
469
- }
470
- }
471
- mapping["WorkbookRelationships"] = {
472
- data: XML_DECL + ctx.workbookRels.serialize(),
473
- path: "xl/_rels/workbook.xml.rels"
474
- };
475
- const imageExts = /* @__PURE__ */ new Set();
476
- for (const img of ctx.media.array) {
477
- const ext = img.fileName.endsWith(".png") ? "png" : "jpeg";
478
- if (!imageExts.has(ext)) {
479
- imageExts.add(ext);
480
- ctx.contentTypes.addImageType(ext);
481
- }
482
- }
483
- mapping["ContentTypes"] = {
484
- data: XML_DECL + ctx.contentTypes.serialize(),
485
- path: "[Content_Types].xml"
486
- };
487
- const mediaFiles = [];
488
- for (const img of ctx.media.array) mediaFiles.push({
489
- data: img.data,
490
- path: `xl/media/${img.fileName}`
491
- });
492
- return compileMapping(mapping, overrides, mediaFiles, mediaLevel);
493
- }
494
- function buildFileRelationships(hasCustomProperties) {
495
- const rels = new Relationships();
496
- rels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", "xl/workbook.xml");
497
- rels.addRelationship(2, "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", "docProps/core.xml");
498
- rels.addRelationship(3, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", "docProps/app.xml");
499
- if (hasCustomProperties) rels.addRelationship(4, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties", "docProps/custom.xml");
500
- return rels;
501
- }
502
- function buildWorkbookRelationships(rels, wsCount, csCount) {
503
- let rid = 1;
504
- for (let i = 0; i < wsCount; i++) rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", `worksheets/sheet${i + 1}.xml`);
505
- for (let i = 0; i < csCount; i++) rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet", `chartsheets/sheet${i + 1}.xml`);
506
- rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", "styles.xml");
507
- rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
508
- rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "sharedStrings.xml");
509
- }
510
- function extractPivotSourceData(rows, sourceRef) {
511
- const parts = sourceRef.split(":");
512
- const startMatch = parts[0]?.match(/^([A-Z]+)(\d+)$/);
513
- const endMatch = parts[1]?.match(/^([A-Z]+)(\d+)$/);
514
- if (!startMatch) return {
515
- fieldNames: [],
516
- records: []
517
- };
518
- const startRow = parseInt(startMatch[2] ?? "1", 10) - 1;
519
- const endRow = endMatch ? parseInt(endMatch[2] ?? "1", 10) - 1 : startRow;
520
- const startCol = colLetterToIndex(startMatch[1] ?? "A");
521
- const endCol = endMatch ? colLetterToIndex(endMatch[1] ?? "A") : startCol;
522
- const colCount = endCol - startCol + 1;
523
- const headerRow = rows[startRow];
524
- const fieldNames = [];
525
- if (headerRow?.cells) for (let c = startCol; c <= endCol && c < headerRow.cells.length; c++) {
526
- const hv = headerRow.cells[c]?.value;
527
- fieldNames.push(typeof hv === "string" ? hv : typeof hv === "number" || typeof hv === "boolean" ? String(hv) : `Col${c}`);
528
- }
529
- const records = [];
530
- for (let r = startRow + 1; r <= endRow; r++) {
531
- const row = rows[r];
532
- if (!row?.cells) continue;
533
- const record = [];
534
- for (let c = startCol; c <= endCol; c++) {
535
- const val = row.cells[c]?.value;
536
- if (typeof val === "number") record.push(val);
537
- else if (val instanceof Date) record.push(val.getTime());
538
- else record.push(typeof val === "string" ? val : typeof val === "boolean" ? String(val) : "");
539
- }
540
- if (record.length === colCount) records.push(record);
541
- }
542
- return {
543
- fieldNames,
544
- records
545
- };
546
- }
547
- function colLetterToIndex(letters) {
548
- let col = 0;
549
- for (let i = 0; i < letters.length; i++) col = col * 26 + (letters.charCodeAt(i) - 64);
550
- return col - 1;
551
- }
552
- function renderPivotSheetData(pivotOpts, worksheetConfigs, sharedStrings, currentSheetName) {
553
- const rowCells = /* @__PURE__ */ new Map();
554
- let maxRow = 0;
555
- let maxCol = 0;
556
- let minRow = Infinity;
557
- let minCol = Infinity;
558
- for (const pt of pivotOpts) {
559
- const locMatch = (pt.location ?? "A3").match(/^([A-Z]+)(\d+)$/);
560
- if (!locMatch) continue;
561
- const startCol = colLetterToIndex(locMatch[1] ?? "A");
562
- const startRow = parseInt(locMatch[2] ?? "1", 10);
563
- const rowFieldNames = pt.rows;
564
- const dataFields = pt.data;
565
- const sourceSheetName = pt.sourceSheet ?? currentSheetName;
566
- const sourceWsIdx = worksheetConfigs.findIndex((ws) => (ws.name ?? `Sheet${worksheetConfigs.indexOf(ws) + 1}`) === sourceSheetName);
567
- if (sourceWsIdx === -1) continue;
568
- const sourceData = extractPivotSourceData(worksheetConfigs[sourceWsIdx]?.rows ?? [], pt.source);
569
- if (sourceData.fieldNames.length === 0) continue;
570
- const fields = sourceData.fieldNames;
571
- const rowFieldIndices = rowFieldNames.map((n) => fields.indexOf(n));
572
- const dataFieldIndices = dataFields.map((df) => fields.indexOf(df.field));
573
- if (rowFieldIndices.some((idx) => idx === -1)) continue;
574
- if (dataFieldIndices.some((idx) => idx === -1)) continue;
575
- const groupMap = /* @__PURE__ */ new Map();
576
- for (const record of sourceData.records) {
577
- const groupKey = rowFieldIndices.map((fi) => String(record[fi])).join("|");
578
- let group = groupMap.get(groupKey);
579
- if (!group) {
580
- group = {
581
- keys: rowFieldIndices.map((fi) => {
582
- const v = record[fi];
583
- return typeof v === "string" || typeof v === "number" ? v : String(v ?? "");
584
- }),
585
- values: dataFieldIndices.map(() => [])
586
- };
587
- groupMap.set(groupKey, group);
588
- }
589
- for (const [di, fi] of dataFieldIndices.entries()) {
590
- const val = record[fi];
591
- if (typeof val === "number") group.values[di]?.push(val);
592
- }
593
- }
594
- const colFieldIndices = (pt.columns ?? []).map((n) => fields.indexOf(n));
595
- const addCells = (rowIdx, cells) => {
596
- let arr = rowCells.get(rowIdx);
597
- if (!arr) {
598
- arr = [];
599
- rowCells.set(rowIdx, arr);
600
- }
601
- for (const c of cells) arr.push(c);
602
- minRow = Math.min(minRow, rowIdx);
603
- maxRow = Math.max(maxRow, rowIdx);
604
- };
605
- if (colFieldIndices.length > 0 && !colFieldIndices.some((idx) => idx === -1)) {
606
- const colUniqueVals = collectUniqueValues(sourceData.records, colFieldIndices[0] ?? 0).map((v) => typeof v === "string" || typeof v === "number" ? String(v) : String(v ?? ""));
607
- const crossTabMap = /* @__PURE__ */ new Map();
608
- for (const record of sourceData.records) {
609
- const rowKey = rowFieldIndices.map((fi) => String(record[fi])).join("|");
610
- const colKey = colFieldIndices.map((fi) => String(record[fi])).join("|");
611
- let entry = crossTabMap.get(rowKey);
612
- if (!entry) {
613
- entry = {
614
- rowKeys: rowFieldIndices.map((fi) => {
615
- const v = record[fi];
616
- return typeof v === "string" || typeof v === "number" ? v : String(v ?? "");
617
- }),
618
- colData: /* @__PURE__ */ new Map(),
619
- rowTotals: dataFieldIndices.map(() => [])
620
- };
621
- crossTabMap.set(rowKey, entry);
622
- }
623
- let colValues = entry.colData.get(colKey);
624
- if (!colValues) {
625
- colValues = dataFieldIndices.map(() => []);
626
- entry.colData.set(colKey, colValues);
627
- }
628
- for (const [di, fi] of dataFieldIndices.entries()) {
629
- const val = record[fi];
630
- if (typeof val === "number") {
631
- colValues[di]?.push(val);
632
- entry.rowTotals[di]?.push(val);
633
- }
634
- }
635
- }
636
- const numColVals = colUniqueVals.length;
637
- const endCol = startCol + (rowFieldNames.length + numColVals + 1) - 1;
638
- minCol = Math.min(minCol, startCol);
639
- maxCol = Math.max(maxCol, endCol);
640
- const headerCells = [];
641
- for (const rfName of rowFieldNames) {
642
- const cellRef = colIndexToLetter(startCol + headerCells.length) + startRow;
643
- const strIdx = sharedStrings.register(rfName);
644
- headerCells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
645
- }
646
- for (const cv of colUniqueVals) {
647
- const cellRef = colIndexToLetter(startCol + headerCells.length) + startRow;
648
- const strIdx = sharedStrings.register(cv);
649
- headerCells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
650
- }
651
- {
652
- const cellRef = colIndexToLetter(startCol + headerCells.length) + startRow;
653
- const df0 = dataFields[0];
654
- const subtotal = df0.summarize ?? "sum";
655
- const dfName = df0.name ?? `${subtotal === "sum" ? "Sum" : subtotal} of ${df0.field}`;
656
- const strIdx = sharedStrings.register(dfName);
657
- headerCells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
658
- }
659
- addCells(startRow, headerCells);
660
- let currentRow = startRow + 1;
661
- for (const [, entry] of crossTabMap) {
662
- const cells = [];
663
- for (const [ri, rowKey] of entry.rowKeys.entries()) {
664
- const cellRef = colIndexToLetter(startCol + ri) + currentRow;
665
- const strIdx = sharedStrings.register(String(rowKey));
666
- cells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
667
- }
668
- for (const [ci, colKey] of colUniqueVals.entries()) {
669
- const colValues = entry.colData.get(colKey);
670
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + ci)) + currentRow;
671
- const subtotal = dataFields[0].summarize ?? "sum";
672
- const result = colValues ? aggregate(colValues[0] ?? [], subtotal) : 0;
673
- cells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
674
- }
675
- {
676
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + numColVals)) + currentRow;
677
- const subtotal = dataFields[0].summarize ?? "sum";
678
- const result = aggregate(entry.rowTotals[0] ?? [], subtotal);
679
- cells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
680
- }
681
- addCells(currentRow, cells);
682
- currentRow++;
683
- }
684
- const gtCells = [];
685
- const gtStrIdx = sharedStrings.register("Grand Total");
686
- gtCells.push(`<c r="${colIndexToLetter(startCol)}${currentRow}" t="s"><v>${gtStrIdx}</v></c>`);
687
- for (const [ci, colKey] of colUniqueVals.entries()) {
688
- const subtotal = dataFields[0].summarize ?? "sum";
689
- const colAllValues = [];
690
- const dfIdx0 = dataFieldIndices[0];
691
- for (const record of sourceData.records) if (colFieldIndices.map((fi) => String(record[fi])).join("|") === colKey && dfIdx0 !== void 0) {
692
- const val = record[dfIdx0];
693
- if (typeof val === "number") colAllValues.push(val);
694
- }
695
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + ci)) + currentRow;
696
- const result = aggregate(colAllValues, subtotal);
697
- gtCells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
698
- }
699
- {
700
- const subtotal = dataFields[0].summarize ?? "sum";
701
- const dfIdx0 = dataFieldIndices[0];
702
- const allValues = sourceData.records.map((r) => dfIdx0 !== void 0 ? r[dfIdx0] : void 0).filter((v) => typeof v === "number");
703
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + numColVals)) + currentRow;
704
- const result = aggregate(allValues, subtotal);
705
- gtCells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
706
- }
707
- addCells(currentRow, gtCells);
708
- } else {
709
- const endCol = startCol + rowFieldNames.length + dataFields.length - 1;
710
- minCol = Math.min(minCol, startCol);
711
- maxCol = Math.max(maxCol, endCol);
712
- const headerCells = [];
713
- for (const rfName of rowFieldNames) {
714
- const cellRef = colIndexToLetter(startCol + headerCells.length) + startRow;
715
- const strIdx = sharedStrings.register(rfName);
716
- headerCells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
717
- }
718
- for (const df of dataFields) {
719
- const cellRef = colIndexToLetter(startCol + headerCells.length) + startRow;
720
- const subtotal = df.summarize ?? "sum";
721
- const dfName = df.name ?? `${subtotal === "sum" ? "Sum" : subtotal} of ${df.field}`;
722
- const strIdx = sharedStrings.register(dfName);
723
- headerCells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
724
- }
725
- addCells(startRow, headerCells);
726
- let currentRow = startRow + 1;
727
- for (const [, group] of groupMap) {
728
- const cells = [];
729
- for (const [ri, key] of group.keys.entries()) {
730
- const cellRef = colIndexToLetter(startCol + ri) + currentRow;
731
- const strIdx = sharedStrings.register(String(key));
732
- cells.push(`<c r="${cellRef}" t="s"><v>${strIdx}</v></c>`);
733
- }
734
- for (const [di, df] of dataFields.entries()) {
735
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + di)) + currentRow;
736
- const subtotal = df.summarize ?? "sum";
737
- const result = aggregate(group.values[di] ?? [], subtotal);
738
- cells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
739
- }
740
- addCells(currentRow, cells);
741
- currentRow++;
742
- }
743
- const gtCells = [];
744
- const gtStrIdx = sharedStrings.register("Grand Total");
745
- gtCells.push(`<c r="${colIndexToLetter(startCol)}${currentRow}" t="s"><v>${gtStrIdx}</v></c>`);
746
- for (const [di, df] of dataFields.entries()) {
747
- const cellRef = colIndexToLetter(startCol + (rowFieldNames.length + di)) + currentRow;
748
- const subtotal = df.summarize ?? "sum";
749
- const dfIdx = dataFieldIndices[di];
750
- const result = aggregate(sourceData.records.map((r) => dfIdx !== void 0 ? r[dfIdx] : void 0).filter((v) => typeof v === "number"), subtotal);
751
- gtCells.push(`<c r="${cellRef}"><v>${result}</v></c>`);
752
- }
753
- addCells(currentRow, gtCells);
754
- }
755
- }
756
- if (rowCells.size === 0) return {
757
- sheetData: "",
758
- dimensionRef: ""
759
- };
760
- const parts = ["<sheetData>"];
761
- const sortedRows = [...rowCells.entries()].sort((a, b) => a[0] - b[0]);
762
- for (const [rowIdx, cells] of sortedRows) {
763
- parts.push(`<row r="${rowIdx}" x14ac:dyDescent="0.25">`);
764
- for (const c of cells) parts.push(c);
765
- parts.push("</row>");
766
- }
767
- parts.push("</sheetData>");
768
- const dimensionRef = `${colIndexToLetter(minCol === Infinity ? 0 : minCol)}${minRow === Infinity ? 1 : minRow}:${colIndexToLetter(maxCol)}${maxRow}`;
769
- return {
770
- sheetData: parts.join(""),
771
- dimensionRef
772
- };
773
- }
774
- function colIndexToLetter(col) {
775
- let result = "";
776
- let n = col + 1;
777
- while (n > 0) {
778
- n--;
779
- result = String.fromCharCode(65 + n % 26) + result;
780
- n = Math.floor(n / 26);
781
- }
782
- return result;
783
- }
784
- function columnToLetter(col) {
785
- let result = "";
786
- let n = col;
787
- while (n > 0) {
788
- const remainder = (n - 1) % 26;
789
- result = String.fromCharCode(65 + remainder) + result;
790
- n = Math.floor((n - 1) / 26);
791
- }
792
- return result;
793
- }
794
- //#endregion
795
- //#region src/generate.ts
796
- /**
797
- * Pure function API for generating XLSX files.
798
- *
799
- * @module
800
- */
801
- /** @internal Packer instance for XLSX generation. */
802
- const Packer = createPacker({
803
- compile: (options, overrides, mediaLevel) => compileWorkbook(options, overrides, mediaLevel),
804
- mimeType: OoxmlMimeType.XLSX
805
- });
806
- /**
807
- * Generate an XLSX file from pure JSON options.
808
- *
809
- * The output format is controlled by `packerOptions.type` (default: `"nodebuffer"` → Buffer).
810
- * For synchronous generation, use {@link generateWorkbookSync}. For streaming, use {@link generateWorkbookStream}.
811
- *
812
- * @param options - Workbook options (worksheets, styles, etc.)
813
- * @param packerOptions - Optional packer configuration (type, compression, overrides, etc.)
814
- *
815
- * @example
816
- * ```typescript
817
- * import { generateWorkbook } from "@office-open/xlsx";
818
- *
819
- * const buffer = await generateWorkbook({ worksheets: [...] });
820
- * const bytes = await generateWorkbook({ worksheets: [...] }, { type: "uint8array" });
821
- * const blob = await generateWorkbook({ worksheets: [...] }, { type: "blob" });
822
- * ```
823
- */
824
- function generateWorkbook(options, packerOptions) {
825
- return Packer.pack(options, packerOptions);
826
- }
827
- /**
828
- * Synchronously generate an XLSX file from pure JSON options.
829
- */
830
- function generateWorkbookSync(options, packerOptions) {
831
- return Packer.packSync(options, packerOptions);
832
- }
833
- /**
834
- * Generate an XLSX file as a `ReadableStream<Uint8Array>`.
835
- */
836
- function generateWorkbookStream(options, packerOptions) {
837
- return Packer.toStream(options, packerOptions);
838
- }
839
- //#endregion
840
- export { compileWorkbook as i, generateWorkbookStream as n, generateWorkbookSync as r, generateWorkbook as t };
841
-
842
- //# sourceMappingURL=generate-CSB0G2BY.mjs.map