@office-open/xlsx 0.6.6 → 0.6.8

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,4 +1,4 @@
1
- import { AppProperties, BaseXmlComponent, ChartCollection, ChartSpace, Formatter, IgnoreIfEmptyXmlComponent, OoxmlMimeType, Relationships, buildCorePropertiesXml, compileMapping, createPacker, parseArchive, parseCorePropsElement, strFromU8, toJson, unzipSync, zipAndConvert } from "@office-open/core";
1
+ import { AppProperties, BaseXmlComponent, ChartCollection, ChartSpace, Formatter, IgnoreIfEmptyXmlComponent, OoxmlMimeType, Relationships, buildCorePropertiesXmlString, compileMapping, createPacker, parseArchive, parseCorePropsElement, strFromU8, toJson, unzipSync, zipAndConvert } from "@office-open/core";
2
2
  import { attr, attrNum, attrs, escapeXml, findChild, js2xml, selfCloseElement, textOf } from "@office-open/xml";
3
3
  import { toUint8Array } from "undio";
4
4
  //#region src/file/content-types.ts
@@ -13,7 +13,7 @@ const XLSX_STYLES = "application/vnd.openxmlformats-officedocument.spreadsheetml
13
13
  const XLSX_SHARED_STRINGS = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
14
14
  const XLSX_THEME = "application/vnd.openxmlformats-officedocument.theme+xml";
15
15
  const XLSX_CHART = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml";
16
- const STATIC_CHILDREN = [{ _attr: { xmlns: "http://schemas.openxmlformats.org/package/2006/content-types" } }, ...[
16
+ const STATIC_XML = [
17
17
  {
18
18
  type: "Default",
19
19
  contentType: "application/vnd.openxmlformats-package.relationships+xml",
@@ -24,16 +24,6 @@ const STATIC_CHILDREN = [{ _attr: { xmlns: "http://schemas.openxmlformats.org/pa
24
24
  contentType: "application/xml",
25
25
  key: "xml"
26
26
  },
27
- {
28
- type: "Default",
29
- contentType: "image/png",
30
- key: "png"
31
- },
32
- {
33
- type: "Default",
34
- contentType: "image/jpeg",
35
- key: "jpeg"
36
- },
37
27
  {
38
28
  type: "Override",
39
29
  contentType: XLSX_MAIN,
@@ -49,16 +39,7 @@ const STATIC_CHILDREN = [{ _attr: { xmlns: "http://schemas.openxmlformats.org/pa
49
39
  contentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
50
40
  key: "/docProps/app.xml"
51
41
  }
52
- ].map((e) => {
53
- if (e.type === "Default") return { Default: { _attr: {
54
- ContentType: e.contentType,
55
- Extension: e.key
56
- } } };
57
- return { Override: { _attr: {
58
- ContentType: e.contentType,
59
- PartName: e.key
60
- } } };
61
- })];
42
+ ].map((e) => e.type === "Default" ? `<Default ContentType="${e.contentType}" Extension="${e.key}"/>` : `<Override ContentType="${e.contentType}" PartName="${e.key}"/>`).join("");
62
43
  var ContentTypes = class extends BaseXmlComponent {
63
44
  dynamicEntries = [];
64
45
  constructor() {
@@ -106,17 +87,21 @@ var ContentTypes = class extends BaseXmlComponent {
106
87
  key: `/xl/drawings/drawing${index}.xml`
107
88
  });
108
89
  }
109
- prepForXml(_context) {
110
- const children = [...STATIC_CHILDREN];
111
- for (const e of this.dynamicEntries) if (e.type === "Default") children.push({ Default: { _attr: {
112
- ContentType: e.contentType,
113
- Extension: e.key
114
- } } });
115
- else children.push({ Override: { _attr: {
116
- ContentType: e.contentType,
117
- PartName: e.key
118
- } } });
119
- return { Types: children };
90
+ addImageType(extension) {
91
+ const contentType = extension === "png" ? "image/png" : "image/jpeg";
92
+ if (this.dynamicEntries.some((e) => e.type === "Default" && e.key === extension)) return;
93
+ this.dynamicEntries.push({
94
+ type: "Default",
95
+ contentType,
96
+ key: extension
97
+ });
98
+ }
99
+ toXml(_context) {
100
+ const p = ["<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">", STATIC_XML];
101
+ for (const e of this.dynamicEntries) if (e.type === "Default") p.push(`<Default ContentType="${e.contentType}" Extension="${e.key}"/>`);
102
+ else p.push(`<Override ContentType="${e.contentType}" PartName="${e.key}"/>`);
103
+ p.push("</Types>");
104
+ return p.join("");
120
105
  }
121
106
  };
122
107
  //#endregion
@@ -132,8 +117,8 @@ var CoreProperties = class extends BaseXmlComponent {
132
117
  super("cp:coreProperties");
133
118
  this.options = options;
134
119
  }
135
- prepForXml(_context) {
136
- return buildCorePropertiesXml(this.options);
120
+ toXml(_context) {
121
+ return buildCorePropertiesXmlString(this.options);
137
122
  }
138
123
  };
139
124
  //#endregion
@@ -188,15 +173,6 @@ var SharedStrings = class extends BaseXmlComponent {
188
173
  p.push("</sst>");
189
174
  return p.join("");
190
175
  }
191
- prepForXml(_context) {
192
- const children = [{ _attr: {
193
- xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
194
- count: this.strings.length,
195
- uniqueCount: this.indexMap.size
196
- } }];
197
- for (const s of this.strings) children.push({ si: [{ t: [s] }] });
198
- return { sst: children };
199
- }
200
176
  };
201
177
  //#endregion
202
178
  //#region src/file/styles.ts
@@ -356,7 +332,7 @@ var Styles = class extends BaseXmlComponent {
356
332
  for (const f of this.fills) {
357
333
  const patternAttrs = attrs({ patternType: f.patternType ?? "solid" });
358
334
  const fgColor = f.color ? `<fgColor rgb="FF${f.color}"/>` : "";
359
- p.push(`<fill><patternFill${patternAttrs}>${fgColor}</patternFill></fill>`);
335
+ p.push(fgColor ? `<fill><patternFill${patternAttrs}>${fgColor}</patternFill></fill>` : `<fill><patternFill${patternAttrs}/></fill>`);
360
336
  }
361
337
  p.push("</fills>");
362
338
  p.push(`<borders count="${this.borders.length}">`);
@@ -369,17 +345,21 @@ var Styles = class extends BaseXmlComponent {
369
345
  numFmtId: xf.numFmtId,
370
346
  fontId: xf.fontId,
371
347
  fillId: xf.fillId,
372
- borderId: xf.borderId
348
+ borderId: xf.borderId,
349
+ xfId: 0
373
350
  };
374
351
  if (xf.alignment) xAttrs.applyAlignment = 1;
375
352
  if (xf.fontId > 0) xAttrs.applyFont = 1;
376
353
  if (xf.fillId > 0) xAttrs.applyFill = 1;
377
354
  if (xf.borderId > 0) xAttrs.applyBorder = 1;
378
355
  const alignStr = xf.alignment ? this.alignmentXmlStr(xf.alignment) : "";
379
- p.push(`<xf${attrs(xAttrs)}>${alignStr}</xf>`);
356
+ p.push(alignStr ? `<xf${attrs(xAttrs)}>${alignStr}</xf>` : `<xf${attrs(xAttrs)}/>`);
380
357
  }
381
358
  p.push("</cellXfs>");
382
359
  p.push("<cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles>");
360
+ p.push("<dxfs count=\"0\"/>");
361
+ p.push("<tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium2\" defaultPivotStyle=\"PivotStyleLight16\"/>");
362
+ p.push("<extLst/>");
383
363
  p.push("</styleSheet>");
384
364
  return p.join("");
385
365
  }
@@ -420,105 +400,6 @@ var Styles = class extends BaseXmlComponent {
420
400
  if (a.indent !== void 0) aAttrs.indent = a.indent;
421
401
  return `<alignment${attrs(aAttrs)}/>`;
422
402
  }
423
- prepForXml(_context) {
424
- const children = [{ _attr: { xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main" } }];
425
- if (this.customNumFmts.size > 0) {
426
- const fmtElements = [{ _attr: { count: this.customNumFmts.size } }];
427
- for (const [fmt, id] of this.customNumFmts) fmtElements.push({ numFmt: { _attr: {
428
- numFmtId: id,
429
- formatCode: fmt
430
- } } });
431
- children.push({ numFmts: fmtElements });
432
- }
433
- children.push(this.buildFonts());
434
- children.push(this.buildFills());
435
- children.push(this.buildBorders());
436
- children.push({ cellStyleXfs: [{ _attr: { count: 1 } }, { xf: [{ _attr: {
437
- numFmtId: 0,
438
- fontId: 0,
439
- fillId: 0,
440
- borderId: 0
441
- } }] }] });
442
- children.push(this.buildCellXfs());
443
- children.push({ cellStyles: [{ _attr: { count: 1 } }, { cellStyle: [{ _attr: {
444
- name: "Normal",
445
- xfId: 0,
446
- builtinId: 0
447
- } }] }] });
448
- return { styleSheet: children };
449
- }
450
- buildFonts() {
451
- const elements = [{ _attr: { count: this.fonts.length } }];
452
- for (const f of this.fonts) elements.push({ font: this.fontXml(f) });
453
- return { fonts: elements };
454
- }
455
- fontXml(f) {
456
- const parts = [];
457
- if (f.bold) parts.push({ b: [] });
458
- if (f.italic) parts.push({ i: [] });
459
- if (f.underline) parts.push({ u: [] });
460
- if (f.strike) parts.push({ strike: [] });
461
- if (f.size) parts.push({ sz: [{ _attr: { val: f.size } }] });
462
- if (f.color) parts.push({ color: [{ _attr: { rgb: `FF${f.color}` } }] });
463
- if (f.fontName) parts.push({ name: [{ _attr: { val: f.fontName } }] });
464
- return parts;
465
- }
466
- buildFills() {
467
- const elements = [{ _attr: { count: this.fills.length } }];
468
- for (const f of this.fills) elements.push({ fill: [{ patternFill: [{ _attr: { patternType: f.patternType ?? "solid" } }, ...f.color ? [{ fgColor: [{ _attr: { rgb: `FF${f.color}` } }] }] : []] }] });
469
- return { fills: elements };
470
- }
471
- buildBorders() {
472
- const elements = [{ _attr: { count: this.borders.length } }];
473
- for (const b of this.borders) elements.push({ border: this.borderXml(b) });
474
- return { borders: elements };
475
- }
476
- borderXml(b) {
477
- const parts = [];
478
- for (const side of [
479
- "left",
480
- "right",
481
- "top",
482
- "bottom",
483
- "diagonal"
484
- ]) {
485
- const opts = b[side];
486
- if (opts && opts.style && opts.style !== "none") {
487
- const children = [{ _attr: { style: opts.style } }];
488
- if (opts.color) children.push({ color: [{ _attr: { rgb: `FF${opts.color}` } }] });
489
- parts.push({ [side]: children });
490
- } else parts.push({ [side]: [] });
491
- }
492
- return parts;
493
- }
494
- buildCellXfs() {
495
- const elements = [{ _attr: { count: this.cellXfs.length } }];
496
- for (const xf of this.cellXfs) {
497
- const attrs = {
498
- numFmtId: xf.numFmtId,
499
- fontId: xf.fontId,
500
- fillId: xf.fillId,
501
- borderId: xf.borderId
502
- };
503
- if (xf.alignment) attrs.applyAlignment = 1;
504
- if (xf.fontId > 0) attrs.applyFont = 1;
505
- if (xf.fillId > 0) attrs.applyFill = 1;
506
- if (xf.borderId > 0) attrs.applyBorder = 1;
507
- const children = [{ _attr: attrs }];
508
- if (xf.alignment) children.push(this.alignmentXml(xf.alignment));
509
- elements.push({ xf: children });
510
- }
511
- return { cellXfs: elements };
512
- }
513
- alignmentXml(a) {
514
- const attrs = {};
515
- if (a.horizontal) attrs.horizontal = a.horizontal;
516
- if (a.vertical) attrs.vertical = a.vertical;
517
- if (a.wrapText) attrs.wrapText = 1;
518
- if (a.textRotation !== void 0) attrs.textRotation = a.textRotation;
519
- if (a.indent !== void 0) attrs.indent = a.indent;
520
- return { alignment: [{ _attr: attrs }] };
521
- }
522
403
  };
523
404
  //#endregion
524
405
  //#region src/file/theme.ts
@@ -541,12 +422,6 @@ var DefaultTheme = class extends BaseXmlComponent {
541
422
  toXml(_context) {
542
423
  return THEME_XML;
543
424
  }
544
- prepForXml(_context) {
545
- return { "a:theme": [{ _attr: {
546
- "xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
547
- name: "Office Theme"
548
- } }] };
549
- }
550
425
  };
551
426
  //#endregion
552
427
  //#region src/file/workbook.ts
@@ -561,21 +436,18 @@ var WorkbookXml = class extends BaseXmlComponent {
561
436
  super("workbook");
562
437
  this.sheets = sheets;
563
438
  }
564
- prepForXml(_context) {
565
- const sheetElements = [];
439
+ toXml(_context) {
440
+ const p = [
441
+ "<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">",
442
+ "<bookViews><workbookView xWindow=\"0\" yWindow=\"0\" windowWidth=\"28800\" windowHeight=\"12300\"/></bookViews>",
443
+ "<sheets>"
444
+ ];
566
445
  for (const s of this.sheets) {
567
- const attrs = {
568
- name: s.name,
569
- sheetId: String(s.sheetId),
570
- "r:id": s.rId
571
- };
572
- if (s.state && s.state !== "visible") attrs.state = s.state;
573
- sheetElements.push({ sheet: { _attr: attrs } });
446
+ const stateAttr = s.state && s.state !== "visible" ? ` state="${s.state}"` : "";
447
+ p.push(`<sheet name="${escapeXml(s.name)}" sheetId="${s.sheetId}" r:id="${s.rId}"${stateAttr}/>`);
574
448
  }
575
- return { workbook: [{ _attr: {
576
- xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
577
- "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
578
- } }, { sheets: sheetElements }] };
449
+ p.push("</sheets><calcPr calcId=\"191029\"/></workbook>");
450
+ return p.join("");
579
451
  }
580
452
  };
581
453
  //#endregion
@@ -585,6 +457,12 @@ var WorkbookXml = class extends BaseXmlComponent {
585
457
  *
586
458
  * @module
587
459
  */
460
+ /** Cell formula type (maps to ST_CellFormulaType). */
461
+ const FormulaType = {
462
+ NORMAL: "normal",
463
+ ARRAY: "array",
464
+ SHARED: "shared"
465
+ };
588
466
  var Worksheet = class extends IgnoreIfEmptyXmlComponent {
589
467
  rows;
590
468
  columns;
@@ -613,116 +491,6 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
613
491
  get charts() {
614
492
  return this.chartOptions;
615
493
  }
616
- prepForXml(context) {
617
- const fileData = context.fileData;
618
- const sharedStrings = fileData?.sharedStrings;
619
- const styles = fileData?.styles;
620
- const children = [{ _attr: {
621
- xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
622
- "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
623
- } }];
624
- if (this.freezePanes) {
625
- const fp = this.freezePanes;
626
- const ySplit = fp.row ? fp.row : 0;
627
- const xSplit = fp.col ? fp.col : 0;
628
- const topRow = fp.row ? fp.row + 1 : 1;
629
- const leftCol = fp.col ? fp.col + 1 : 1;
630
- const attr = {
631
- ySplit,
632
- xSplit,
633
- topLeftCell: this.defaultCellRef(topRow, leftCol),
634
- activePane: ySplit > 0 && xSplit > 0 ? "bottomRight" : ySplit > 0 ? "bottomLeft" : "topRight",
635
- state: "frozen"
636
- };
637
- children.push({ sheetViews: [{ sheetView: [{ _attr: {
638
- tabSelected: 1,
639
- workbookViewId: 0
640
- } }, { pane: { _attr: attr } }] }] });
641
- }
642
- if (this.columns.length > 0) {
643
- const colElements = [];
644
- for (const col of this.columns) {
645
- const colAttrs = {
646
- min: col.min,
647
- max: col.max
648
- };
649
- if (col.width !== void 0) {
650
- colAttrs.width = col.width;
651
- colAttrs.customWidth = 1;
652
- }
653
- if (col.hidden) colAttrs.hidden = 1;
654
- colElements.push({ col: { _attr: colAttrs } });
655
- }
656
- children.push({ cols: colElements });
657
- }
658
- const sheetDataChildren = [];
659
- for (let i = 0; i < this.rows.length; i++) {
660
- const rowOpts = this.rows[i];
661
- const rowNumber = rowOpts.rowNumber ?? i + 1;
662
- const rowAttrs = { r: rowNumber };
663
- if (rowOpts.height !== void 0) {
664
- rowAttrs.ht = rowOpts.height;
665
- rowAttrs.customHeight = 1;
666
- }
667
- if (rowOpts.hidden) rowAttrs.hidden = 1;
668
- const cellElements = [];
669
- if (rowOpts.cells) for (let j = 0; j < rowOpts.cells.length; j++) {
670
- const cell = rowOpts.cells[j];
671
- const ref = cell.reference ?? this.defaultCellRef(rowNumber, j + 1);
672
- const cellObj = this.buildCell(ref, cell, sharedStrings, styles);
673
- if (cellObj) cellElements.push(cellObj);
674
- }
675
- sheetDataChildren.push({ row: [{ _attr: rowAttrs }, ...cellElements] });
676
- }
677
- children.push({ sheetData: sheetDataChildren });
678
- if (this.autoFilter) children.push({ autoFilter: { _attr: { ref: this.autoFilter } } });
679
- if (this.mergeCells.length > 0) {
680
- const mergeElements = [{ _attr: { count: this.mergeCells.length } }];
681
- for (const mc of this.mergeCells) {
682
- const fromRef = this.defaultCellRef(mc.from.row, mc.from.col);
683
- const toRef = this.defaultCellRef(mc.to.row, mc.to.col);
684
- mergeElements.push({ mergeCell: { _attr: { ref: `${fromRef}:${toRef}` } } });
685
- }
686
- children.push({ mergeCells: mergeElements });
687
- }
688
- if (this.conditionalFormats.length > 0) for (const cf of this.conditionalFormats) {
689
- const rules = [];
690
- for (let ri = 0; ri < cf.rules.length; ri++) {
691
- const rule = cf.rules[ri];
692
- const ruleAttrs = {
693
- type: rule.type,
694
- priority: rule.priority ?? ri + 1
695
- };
696
- if (rule.operator) ruleAttrs.operator = rule.operator;
697
- if (rule.dxfId !== void 0) ruleAttrs.dxfId = rule.dxfId;
698
- const ruleChildren = [{ _attr: ruleAttrs }];
699
- if (rule.formulas) for (const f of rule.formulas) ruleChildren.push({ formula: [f] });
700
- rules.push({ cfRule: ruleChildren });
701
- }
702
- children.push({ conditionalFormatting: [{ _attr: { sqref: cf.sqref } }, ...rules] });
703
- }
704
- if (this.dataValidations.length > 0) {
705
- const dvElements = [{ _attr: { count: this.dataValidations.length } }];
706
- for (const dv of this.dataValidations) {
707
- const dvAttrs = { sqref: dv.sqref };
708
- if (dv.type && dv.type !== "none") dvAttrs.type = dv.type;
709
- if (dv.operator) dvAttrs.operator = dv.operator;
710
- if (dv.allowBlank) dvAttrs.allowBlank = 1;
711
- if (dv.showErrorMessage) dvAttrs.showErrorMessage = 1;
712
- if (dv.showInputMessage) dvAttrs.showInputMessage = 1;
713
- if (dv.errorTitle) dvAttrs.errorTitle = dv.errorTitle;
714
- if (dv.error) dvAttrs.error = dv.error;
715
- if (dv.promptTitle) dvAttrs.promptTitle = dv.promptTitle;
716
- if (dv.prompt) dvAttrs.prompt = dv.prompt;
717
- const dvChildren = [{ _attr: dvAttrs }];
718
- if (dv.formula1 !== void 0) dvChildren.push({ formula1: [dv.formula1] });
719
- if (dv.formula2 !== void 0) dvChildren.push({ formula2: [dv.formula2] });
720
- dvElements.push({ dataValidation: dvChildren });
721
- }
722
- children.push({ dataValidations: dvElements });
723
- }
724
- return { worksheet: children };
725
- }
726
494
  /**
727
495
  * Zero-allocation fast path: directly concatenate XML string.
728
496
  * Bypasses the IXmlableObject intermediate tree entirely.
@@ -732,6 +500,13 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
732
500
  const sharedStrings = fileData?.sharedStrings;
733
501
  const styles = fileData?.styles;
734
502
  const p = ["<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"];
503
+ const maxRow = this.rows.length;
504
+ let maxCol = 0;
505
+ for (const row of this.rows) if (row.cells && row.cells.length > maxCol) maxCol = row.cells.length;
506
+ if (maxRow > 0 && maxCol > 0) {
507
+ const dimRef = `A1:${this.defaultCellRef(maxRow, maxCol)}`;
508
+ p.push(`<dimension ref="${dimRef}"/>`);
509
+ }
735
510
  if (this.freezePanes) {
736
511
  const fp = this.freezePanes;
737
512
  const ySplit = fp.row ? fp.row : 0;
@@ -741,7 +516,8 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
741
516
  const topLeftCell = this.defaultCellRef(topRow, leftCol);
742
517
  const activePane = ySplit > 0 && xSplit > 0 ? "bottomRight" : ySplit > 0 ? "bottomLeft" : "topRight";
743
518
  p.push("<sheetViews><sheetView tabSelected=\"1\" workbookViewId=\"0\">", `<pane ySplit="${ySplit}" xSplit="${xSplit}" topLeftCell="${topLeftCell}" activePane="${activePane}" state="frozen"/>`, "</sheetView></sheetViews>");
744
- }
519
+ } else p.push("<sheetViews><sheetView tabSelected=\"1\" workbookViewId=\"0\"/></sheetViews>");
520
+ p.push("<sheetFormatPr defaultRowHeight=\"15\"/>");
745
521
  if (this.columns.length > 0) {
746
522
  p.push("<cols>");
747
523
  for (const col of this.columns) {
@@ -777,7 +553,7 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
777
553
  if (cellStr) rowParts.push(cellStr);
778
554
  }
779
555
  p.push(`<row${attrs(rowAttrs)}>`, ...rowParts, "</row>");
780
- } else p.push(`<row${attrs(rowAttrs)}></row>`);
556
+ } else p.push(`<row${attrs(rowAttrs)}/>`);
781
557
  }
782
558
  p.push("</sheetData>");
783
559
  if (this.autoFilter) p.push(selfCloseElement("autoFilter", attrs({ ref: this.autoFilter })));
@@ -828,10 +604,23 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
828
604
  }
829
605
  p.push("</dataValidations>");
830
606
  }
607
+ p.push("<pageMargins left=\"0.75\" right=\"0.75\" top=\"1\" bottom=\"1\" header=\"0.5\" footer=\"0.5\"/>");
831
608
  p.push("</worksheet>");
832
609
  return p.join("");
833
610
  }
834
611
  /**
612
+ * Build the <f> element string for a cell formula.
613
+ */
614
+ buildFormulaString(fOpts) {
615
+ const fAttrs = {};
616
+ if (fOpts.type && fOpts.type !== FormulaType.NORMAL) fAttrs.t = fOpts.type;
617
+ if (fOpts.reference) fAttrs.ref = fOpts.reference;
618
+ if (fOpts.sharedIndex !== void 0) fAttrs.si = fOpts.sharedIndex;
619
+ if (fOpts.formula !== void 0 && fOpts.formula !== "") return `<f${attrs(fAttrs)}>${escapeXml(fOpts.formula)}</f>`;
620
+ if (Object.keys(fAttrs).length > 0) return selfCloseElement("f", attrs(fAttrs));
621
+ return "";
622
+ }
623
+ /**
835
624
  * Direct string serialization of a single cell — zero intermediate objects.
836
625
  */
837
626
  buildCellString(ref, cell, sharedStrings, styles) {
@@ -839,6 +628,21 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
839
628
  if (cell.style !== void 0 && styles) cellAttrs.s = styles.register(cell.style);
840
629
  else if (cell.styleIndex !== void 0) cellAttrs.s = cell.styleIndex;
841
630
  const value = cell.value;
631
+ if (cell.formula) {
632
+ const fStr = this.buildFormulaString(cell.formula);
633
+ let vStr = "";
634
+ if (value === null || value === void 0) return `<c${attrs(cellAttrs)}>${fStr}</c>`;
635
+ if (typeof value === "number") vStr = `<v>${value}</v>`;
636
+ else if (typeof value === "boolean") {
637
+ cellAttrs.t = "b";
638
+ vStr = `<v>${value ? 1 : 0}</v>`;
639
+ } else if (typeof value === "string") {
640
+ cellAttrs.t = "str";
641
+ vStr = `<v>${escapeXml(value)}</v>`;
642
+ } else if (value instanceof Date) vStr = `<v>${this.dateToSerialNumber(value)}</v>`;
643
+ if (vStr) return `<c${attrs(cellAttrs)}>${fStr}${vStr}</c>`;
644
+ return `<c${attrs(cellAttrs)}>${fStr}</c>`;
645
+ }
842
646
  if (value === null || value === void 0) {
843
647
  if (cell.styleIndex !== void 0) return selfCloseElement("c", attrs(cellAttrs));
844
648
  return "";
@@ -876,34 +680,6 @@ var Worksheet = class extends IgnoreIfEmptyXmlComponent {
876
680
  }
877
681
  return result;
878
682
  }
879
- buildCell(ref, cell, sharedStrings, styles) {
880
- const attrs = { r: ref };
881
- if (cell.style !== void 0 && styles) attrs.s = styles.register(cell.style);
882
- else if (cell.styleIndex !== void 0) attrs.s = cell.styleIndex;
883
- const value = cell.value;
884
- if (value === null || value === void 0) {
885
- if (cell.styleIndex !== void 0) return { c: [{ _attr: attrs }] };
886
- return;
887
- }
888
- if (typeof value === "string") {
889
- if (sharedStrings) {
890
- attrs.t = "s";
891
- const idx = sharedStrings.register(value);
892
- return { c: [{ _attr: attrs }, { v: [idx] }] };
893
- }
894
- attrs.t = "inlineStr";
895
- return { c: [{ _attr: attrs }, { is: [{ t: [value] }] }] };
896
- }
897
- if (typeof value === "number") return { c: [{ _attr: attrs }, { v: [value] }] };
898
- if (typeof value === "boolean") {
899
- attrs.t = "b";
900
- return { c: [{ _attr: attrs }, { v: [value ? 1 : 0] }] };
901
- }
902
- if (value instanceof Date) {
903
- const serial = this.dateToSerialNumber(value);
904
- return { c: [{ _attr: attrs }, { v: [serial] }] };
905
- }
906
- }
907
683
  dateToSerialNumber(date) {
908
684
  const epoch = new Date(1899, 11, 30);
909
685
  return (date.getTime() - epoch.getTime()) / 864e5;
@@ -1024,80 +800,19 @@ var Drawing = class extends BaseXmlComponent {
1024
800
  this.images = images;
1025
801
  this.charts = charts;
1026
802
  }
1027
- prepForXml(_context) {
1028
- const children = [{ _attr: {
1029
- xmlns: XDR_NS,
1030
- "xmlns:a": A_NS,
1031
- "xmlns:r": R_NS
1032
- } }];
1033
- let nextId = 1;
1034
- for (const img of this.images) children.push(this.buildImageAnchor(img, nextId++));
1035
- for (const chart of this.charts) children.push(this.buildChartAnchor(chart, nextId++));
1036
- return { wsDr: children };
1037
- }
1038
- buildFromAnchor(col, row, colOffset, rowOffset) {
1039
- return { from: [
1040
- { col: [col - 1] },
1041
- { colOff: [colOffset ?? 0] },
1042
- { row: [row - 1] },
1043
- { rowOff: [rowOffset ?? 0] }
1044
- ] };
1045
- }
1046
- buildToAnchor(col, row) {
1047
- return { to: [
1048
- { col: [col] },
1049
- { colOff: [0] },
1050
- { row: [row] },
1051
- { rowOff: [0] }
1052
- ] };
1053
- }
1054
- buildImageAnchor(img, id) {
1055
- return { twoCellAnchor: [
1056
- { _attr: { editAs: "oneCell" } },
1057
- this.buildFromAnchor(img.col, img.row, img.colOffset, img.rowOffset),
1058
- this.buildToAnchor(img.col, img.row),
1059
- { pic: [
1060
- { nvPicPr: [{ cNvPr: { _attr: {
1061
- id,
1062
- name: `Picture ${id}`
1063
- } } }, { cNvPicPr: [{ _attr: { preferRelativeResize: 1 } }] }] },
1064
- { blipFill: [{ "a:blip": { _attr: { "r:embed": img.rId } } }, { "a:stretch": [{ "a:fillRect": [] }] }] },
1065
- { spPr: [{ "a:xfrm": [{ "a:off": { _attr: {
1066
- x: 0,
1067
- y: 0
1068
- } } }, { "a:ext": { _attr: {
1069
- cx: 4e5,
1070
- cy: 3e5
1071
- } } }] }, { "a:prstGeom": [{ _attr: { prst: "rect" } }, { "a:avLst": [] }] }] }
1072
- ] },
1073
- { clientData: [] }
1074
- ] };
1075
- }
1076
- buildChartAnchor(chart, id) {
1077
- return { twoCellAnchor: [
1078
- { _attr: { editAs: "oneCell" } },
1079
- this.buildFromAnchor(chart.col, chart.row, chart.colOffset, chart.rowOffset),
1080
- this.buildToAnchor(chart.col + 8, chart.row + 15),
1081
- { graphicFrame: [
1082
- { nvGraphicFramePr: [{ cNvPr: { _attr: {
1083
- id,
1084
- name: `Chart ${id}`
1085
- } } }, { cNvGraphicFramePr: [{ "a:graphicFrameLocks": { _attr: { noGrp: 1 } } }] }] },
1086
- { xfrm: [{ "a:off": { _attr: {
1087
- x: 0,
1088
- y: 0
1089
- } } }, { "a:ext": { _attr: {
1090
- cx: 0,
1091
- cy: 0
1092
- } } }] },
1093
- { "a:graphic": [{ "a:graphicData": [{ _attr: { uri: C_URI } }, { "c:chart": { _attr: {
1094
- "xmlns:c": "http://schemas.openxmlformats.org/drawingml/2006/chart",
1095
- "xmlns:r": R_NS,
1096
- "r:id": chart.rId
1097
- } } }] }] }
1098
- ] },
1099
- { clientData: [] }
1100
- ] };
803
+ toXml(_context) {
804
+ const p = [`<wsDr xmlns="${XDR_NS}" xmlns:a="${A_NS}" xmlns:r="${R_NS}">`];
805
+ let id = 1;
806
+ for (const img of this.images) {
807
+ p.push(`<twoCellAnchor editAs="oneCell"><from><col>${img.col - 1}</col><colOff>${img.colOffset ?? 0}</colOff><row>${img.row - 1}</row><rowOff>${img.rowOffset ?? 0}</rowOff></from>`, `<to><col>${img.col}</col><colOff>0</colOff><row>${img.row}</row><rowOff>0</rowOff></to>`, `<pic><nvPicPr><cNvPr id="${id}" name="Picture ${id}"/><cNvPicPr preferRelativeResize="1"/></nvPicPr>`, `<blipFill><a:blip r:embed="${img.rId}"/><a:stretch><a:fillRect/></a:stretch></blipFill>`, `<spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="400000" cy="300000"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></spPr></pic>`, `<clientData/></twoCellAnchor>`);
808
+ id++;
809
+ }
810
+ for (const chart of this.charts) {
811
+ p.push(`<twoCellAnchor editAs="oneCell"><from><col>${chart.col - 1}</col><colOff>${chart.colOffset ?? 0}</colOff><row>${chart.row - 1}</row><rowOff>${chart.rowOffset ?? 0}</rowOff></from>`, `<to><col>${chart.col + 8}</col><colOff>0</colOff><row>${chart.row + 15}</row><rowOff>0</rowOff></to>`, `<graphicFrame><nvGraphicFramePr><cNvPr id="${id}" name="Chart ${id}"/><cNvGraphicFramePr><a:graphicFrameLocks noGrp="1"/></cNvGraphicFramePr></nvGraphicFramePr>`, `<xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></xfrm>`, `<a:graphic><a:graphicData uri="${C_URI}"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="${R_NS}" r:id="${chart.rId}"/></a:graphicData></a:graphic></graphicFrame>`, `<clientData/></twoCellAnchor>`);
812
+ id++;
813
+ }
814
+ p.push("</wsDr>");
815
+ return p.join("");
1101
816
  }
1102
817
  };
1103
818
  //#endregion
@@ -1116,13 +831,13 @@ var Compiler = class {
1116
831
  };
1117
832
  const f = this.formatter;
1118
833
  const mapping = {};
1119
- const fmt = (component, declaration) => f.formatToXml(component, context, declaration);
834
+ const fmt = (component) => f.formatToXml(component, context);
1120
835
  mapping["Properties"] = {
1121
- data: fmt(file.coreProperties, true),
836
+ data: fmt(file.coreProperties),
1122
837
  path: "docProps/core.xml"
1123
838
  };
1124
839
  mapping["AppProperties"] = {
1125
- data: fmt(file.appProperties, true),
840
+ data: fmt(file.appProperties),
1126
841
  path: "docProps/app.xml"
1127
842
  };
1128
843
  mapping["FileRelationships"] = {
@@ -1130,7 +845,7 @@ var Compiler = class {
1130
845
  path: "_rels/.rels"
1131
846
  };
1132
847
  mapping["Workbook"] = {
1133
- data: fmt(file.workbookXml, true),
848
+ data: fmt(file.workbookXml),
1134
849
  path: "xl/workbook.xml"
1135
850
  };
1136
851
  mapping["WorkbookRelationships"] = {
@@ -1144,7 +859,7 @@ var Compiler = class {
1144
859
  const ws = worksheets[i];
1145
860
  const imgOpts = ws.imageOptions;
1146
861
  const chartOpts = ws.charts;
1147
- let sheetXml = fmt(ws, true);
862
+ let sheetXml = fmt(ws);
1148
863
  if (imgOpts.length > 0 || chartOpts.length > 0) {
1149
864
  const drawingImages = [];
1150
865
  const drawingCharts = [];
@@ -1187,7 +902,7 @@ var Compiler = class {
1187
902
  const drawing = new Drawing(drawingImages, drawingCharts);
1188
903
  const drawingIdx = i + 1;
1189
904
  mapping[`Drawing${i}`] = {
1190
- data: fmt(drawing, true),
905
+ data: fmt(drawing),
1191
906
  path: `xl/drawings/drawing${drawingIdx}.xml`
1192
907
  };
1193
908
  mapping[`DrawingRels${i}`] = {
@@ -1210,33 +925,43 @@ var Compiler = class {
1210
925
  }
1211
926
  const sharedStrings = file.sharedStrings;
1212
927
  if (sharedStrings.count > 0) mapping["SharedStrings"] = {
1213
- data: fmt(sharedStrings, true),
928
+ data: fmt(sharedStrings),
1214
929
  path: "xl/sharedStrings.xml"
1215
930
  };
1216
931
  mapping["Styles"] = {
1217
- data: fmt(file.styles, true),
932
+ data: fmt(file.styles),
1218
933
  path: "xl/styles.xml"
1219
934
  };
1220
935
  mapping["Theme"] = {
1221
- data: fmt(file.theme, true),
936
+ data: fmt(file.theme),
1222
937
  path: "xl/theme/theme1.xml"
1223
938
  };
1224
939
  for (let i = 0; i < file.charts.array.length; i++) {
1225
940
  const chartData = file.charts.array[i];
1226
941
  mapping[`Chart${i}`] = {
1227
- data: fmt(chartData.chartSpace, true),
942
+ data: fmt(chartData.chartSpace),
1228
943
  path: `xl/charts/chart${i + 1}.xml`
1229
944
  };
1230
945
  file.contentTypes.addChart(i + 1);
1231
946
  }
947
+ const imageExts = /* @__PURE__ */ new Set();
948
+ for (const img of file.media.array) {
949
+ const ext = img.fileName.endsWith(".png") ? "png" : "jpeg";
950
+ if (!imageExts.has(ext)) {
951
+ imageExts.add(ext);
952
+ file.contentTypes.addImageType(ext);
953
+ }
954
+ }
1232
955
  mapping["ContentTypes"] = {
1233
956
  data: fmt(file.contentTypes),
1234
957
  path: "[Content_Types].xml"
1235
958
  };
1236
- return compileMapping(mapping, overrides, file.media.array.map((img) => ({
959
+ const mediaFiles = [];
960
+ for (const img of file.media.array) mediaFiles.push({
1237
961
  data: img.data,
1238
962
  path: `xl/media/${img.fileName}`
1239
- })));
963
+ });
964
+ return compileMapping(mapping, overrides, mediaFiles);
1240
965
  }
1241
966
  };
1242
967
  //#endregion
@@ -1625,4 +1350,4 @@ function findLocalChild(parent, name) {
1625
1350
  //#endregion
1626
1351
  export { File, File as Workbook, Packer, PatchType, SharedStrings, Styles, columnToLetter, dateToSerialNumber, letterToColumn, parseWorkbook, parseXlsx, patchWorkbook };
1627
1352
 
1628
- //# sourceMappingURL=index.js.map
1353
+ //# sourceMappingURL=index.mjs.map