@office-kit/xlsx 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +29 -8
  2. package/dist/cell/cell.d.ts +12 -19
  3. package/dist/{cell-Df3cKRIl.mjs → cell-B5OUUdfI.mjs} +13 -7
  4. package/dist/cell-B5OUUdfI.mjs.map +1 -0
  5. package/dist/{cell-style-CNsET6WU.mjs → cell-style-DjKKPWDL.mjs} +2 -2
  6. package/dist/{cell-style-CNsET6WU.mjs.map → cell-style-DjKKPWDL.mjs.map} +1 -1
  7. package/dist/cell.mjs +1 -1
  8. package/dist/{coordinate-Bt5Gni2I.mjs → coordinate-CxC88uBk.mjs} +31 -2
  9. package/dist/coordinate-CxC88uBk.mjs.map +1 -0
  10. package/dist/{defined-names-Ctu3F6ls.mjs → defined-names-Cmp8rbvI.mjs} +2 -2
  11. package/dist/{defined-names-Ctu3F6ls.mjs.map → defined-names-Cmp8rbvI.mjs.map} +1 -1
  12. package/dist/{differential-BPKa7wXi.mjs → differential-7KGzbliB.mjs} +2 -2
  13. package/dist/{differential-BPKa7wXi.mjs.map → differential-7KGzbliB.mjs.map} +1 -1
  14. package/dist/{drawing-ZJ3h4VHD.mjs → drawing-Cv6UtInY.mjs} +2 -2
  15. package/dist/{drawing-ZJ3h4VHD.mjs.map → drawing-Cv6UtInY.mjs.map} +1 -1
  16. package/dist/drawing.mjs +1 -1
  17. package/dist/{escape-rnWSPpWY.mjs → escape-rA5UpibT.mjs} +26 -3
  18. package/dist/escape-rA5UpibT.mjs.map +1 -0
  19. package/dist/io/load.d.ts +28 -0
  20. package/dist/io.mjs +2 -2
  21. package/dist/{load-CspGc399.mjs → load-DIdQ_zum.mjs} +66 -39
  22. package/dist/{load-CspGc399.mjs.map → load-DIdQ_zum.mjs.map} +1 -1
  23. package/dist/{manifest-pLmx7KYh.mjs → manifest-BHUYpjUG.mjs} +3 -3
  24. package/dist/{manifest-pLmx7KYh.mjs.map → manifest-BHUYpjUG.mjs.map} +1 -1
  25. package/dist/node.mjs +1 -1
  26. package/dist/packaging.mjs +1 -1
  27. package/dist/{reader-DHMxLBQV.mjs → reader-pC7bxYAs.mjs} +30 -7
  28. package/dist/reader-pC7bxYAs.mjs.map +1 -0
  29. package/dist/{save-DgPf1DyF.mjs → save-ax11Gsw0.mjs} +7 -7
  30. package/dist/{save-DgPf1DyF.mjs.map → save-ax11Gsw0.mjs.map} +1 -1
  31. package/dist/schema.mjs +1 -1
  32. package/dist/{serialize-BC2Wu3bR.mjs → serialize-Dmb6Vtt9.mjs} +23 -6
  33. package/dist/serialize-Dmb6Vtt9.mjs.map +1 -0
  34. package/dist/{serializer-C6nm0mRJ.mjs → serializer-dhv07Z6F.mjs} +2 -2
  35. package/dist/{serializer-C6nm0mRJ.mjs.map → serializer-dhv07Z6F.mjs.map} +1 -1
  36. package/dist/streaming/string-table.d.ts +7 -0
  37. package/dist/streaming.mjs +189 -83
  38. package/dist/streaming.mjs.map +1 -1
  39. package/dist/styles.mjs +3 -3
  40. package/dist/{stylesheet-writer-TxsinwbO.mjs → stylesheet-writer-BBYjNSMA.mjs} +201 -118
  41. package/dist/stylesheet-writer-BBYjNSMA.mjs.map +1 -0
  42. package/dist/{table-BrP0RwUd.mjs → table-BFi2WmgG.mjs} +2 -2
  43. package/dist/{table-BrP0RwUd.mjs.map → table-BFi2WmgG.mjs.map} +1 -1
  44. package/dist/utils/cell-number.d.ts +10 -0
  45. package/dist/utils/coordinate.d.ts +11 -0
  46. package/dist/utils/escape.d.ts +17 -0
  47. package/dist/utils/xsd-boolean.d.ts +9 -0
  48. package/dist/utils.mjs +2 -2
  49. package/dist/workbook/shared-strings.d.ts +2 -0
  50. package/dist/{workbook-DQCslHzY.mjs → workbook-CMel6UcI.mjs} +13 -12
  51. package/dist/workbook-CMel6UcI.mjs.map +1 -0
  52. package/dist/workbook.mjs +2 -2
  53. package/dist/worksheet/writer.d.ts +9 -5
  54. package/dist/{worksheet-B2NOQ6dM.mjs → worksheet-Cxn2c-jz.mjs} +3 -3
  55. package/dist/{worksheet-B2NOQ6dM.mjs.map → worksheet-Cxn2c-jz.mjs.map} +1 -1
  56. package/dist/worksheet.mjs +2 -2
  57. package/dist/xml.mjs +2 -2
  58. package/dist/zip.mjs +1 -1
  59. package/package.json +1 -1
  60. package/dist/cell-Df3cKRIl.mjs.map +0 -1
  61. package/dist/coordinate-Bt5Gni2I.mjs.map +0 -1
  62. package/dist/escape-rnWSPpWY.mjs.map +0 -1
  63. package/dist/reader-DHMxLBQV.mjs.map +0 -1
  64. package/dist/serialize-BC2Wu3bR.mjs.map +0 -1
  65. package/dist/stylesheet-writer-TxsinwbO.mjs.map +0 -1
  66. package/dist/workbook-DQCslHzY.mjs.map +0 -1
@@ -1,23 +1,23 @@
1
1
  import { n as OpenXmlError, o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
2
- import { a as columnLetterFromIndex, g as tupleToCoordinate, i as columnIndexFromLetter, s as coordinateToTuple } from "./coordinate-Bt5Gni2I.mjs";
2
+ import { _ as rowNumberFromAttr, a as columnLetterFromIndex, c as derivedRowNumber, i as columnIndexFromLetter, l as formatSheetQualifiedRef, s as coordinateToTuple, v as tupleToCoordinate } from "./coordinate-CxC88uBk.mjs";
3
3
  import { r as normalizeFormulaText, t as ERROR_CODES$1 } from "./inference-BMvv9cUY.mjs";
4
- import { A as setSharedFormula, E as setArrayFormula, O as setDataTableFormula, c as getCoordinate, k as setFormula } from "./cell-Df3cKRIl.mjs";
4
+ import { A as setSharedFormula, E as setArrayFormula, N as richTextToString, O as setDataTableFormula, c as getCoordinate, k as setFormula } from "./cell-B5OUUdfI.mjs";
5
5
  import { C as makeSurface3DChart, S as makeStockChart, _ as makePie3DChart, a as makeArea3DChart, b as makeScatterChart, c as makeBarChart, d as makeBubbleSeries, f as makeChartSpace, g as makeOfPieChart, h as makeLineChart, l as makeBarSeries, m as makeLine3DChart, n as makeChartDrawing, o as makeAreaChart, p as makeDoughnutChart, s as makeBar3DChart, u as makeBubbleChart, v as makePieChart, w as makeSurfaceChart, x as makeScatterSeries, y as makeRadarChart } from "./user-shapes-DfmCGKB0.mjs";
6
6
  import { t as makeChartsheet } from "./chartsheet-C3-tqkPy.mjs";
7
- import { o as makeDrawing } from "./drawing-ZJ3h4VHD.mjs";
7
+ import { o as makeDrawing } from "./drawing-Cv6UtInY.mjs";
8
8
  import { n as VALUED_COLOR_MOD_KINDS, r as VALUELESS_COLOR_MOD_KINDS, t as SCHEME_COLOR_NAMES } from "./colors-ovWAwnZI.mjs";
9
- import { n as escapeXmlAttr$1, r as escapeXmlText$1, t as escapeCellString } from "./escape-rnWSPpWY.mjs";
9
+ import { i as escapeXmlTextVerbatim, n as escapeXmlAttr$1, r as escapeXmlText$1 } from "./escape-rA5UpibT.mjs";
10
10
  import { H as DRAWING_NS, I as CX_NS, T as CHART_NS, a as findChildren, bt as X14_NS, dt as SHEET_DRAWING_NS, ft as SHEET_MAIN_NS, i as findChild, jt as qname, lt as REL_NS, n as el, q as MARKUP_COMPAT_NS, w as CHART_DRAWING_NS } from "./tree-BX-sRRVp.mjs";
11
11
  import { t as parseXml } from "./parser-By6RWZVW.mjs";
12
- import { n as toTree, r as defineSchema, t as fromTree } from "./serialize-BC2Wu3bR.mjs";
13
- import { t as serializeXml } from "./serializer-C6nm0mRJ.mjs";
14
- import { Q as findById } from "./manifest-pLmx7KYh.mjs";
15
- import { Dn as makeColor, Zt as makeLegacyComment, cn as multiCellRangeToString, en as makeSheetView, ln as parseMultiCellRange, mn as rangeToString, nn as makeRowDimension, ot as makeWorksheet, tn as makeColumnDimension, un as parseRange, xt as setCell } from "./worksheet-B2NOQ6dM.mjs";
16
- import { Bt as PATTERN_TYPES, Ft as FONT_SCHEMES, It as UNDERLINE_STYLES, Kt as SIDE_STYLES, Lt as VERT_ALIGNS, Xt as HORIZONTAL_ALIGNMENTS, Zt as VERTICAL_ALIGNMENTS } from "./cell-style-CNsET6WU.mjs";
17
- import { C as addSharedRichText, O as parseRichString, w as addSharedString } from "./workbook-DQCslHzY.mjs";
18
- import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-BrP0RwUd.mjs";
12
+ import { i as defineSchema, n as toTree, r as parseXsdBoolean, t as fromTree } from "./serialize-Dmb6Vtt9.mjs";
13
+ import { t as serializeXml } from "./serializer-dhv07Z6F.mjs";
14
+ import { Q as findById } from "./manifest-BHUYpjUG.mjs";
15
+ import { Dn as makeColor, Zt as makeLegacyComment, cn as multiCellRangeToString, en as makeSheetView, ln as parseMultiCellRange, mn as rangeToString, nn as makeRowDimension, ot as makeWorksheet, tn as makeColumnDimension, un as parseRange, xt as setCell } from "./worksheet-Cxn2c-jz.mjs";
16
+ import { Bt as PATTERN_TYPES, Ft as FONT_SCHEMES, It as UNDERLINE_STYLES, Kt as SIDE_STYLES, Lt as VERT_ALIGNS, Xt as HORIZONTAL_ALIGNMENTS, Zt as VERTICAL_ALIGNMENTS } from "./cell-style-DjKKPWDL.mjs";
17
+ import { C as addSharedRichText, O as parseRichString, w as addSharedString } from "./workbook-CMel6UcI.mjs";
18
+ import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-BFi2WmgG.mjs";
19
19
  import { i as durationToExcel, r as dateToExcel } from "./datetime-B2ySVlXt.mjs";
20
- import { n as getDxfs } from "./differential-BPKa7wXi.mjs";
20
+ import { n as getDxfs } from "./differential-7KGzbliB.mjs";
21
21
  //#region src/drawing/dml/effect.ts
22
22
  const PRESET_SHADOW_NAMES = [
23
23
  "shdw1",
@@ -4968,6 +4968,26 @@ function translateFormula(formula, origin, opts = {}) {
4968
4968
  return out;
4969
4969
  }
4970
4970
  //#endregion
4971
+ //#region src/utils/cell-number.ts
4972
+ /** How much of an offending value the error echoes. Cell text is untrusted and unbounded. */
4973
+ const MAX_QUOTED_LENGTH = 40;
4974
+ /**
4975
+ * Value of a numeric cell's `<v>`: a finite number, or `null` when the element
4976
+ * is absent or blank, which is an empty cell.
4977
+ *
4978
+ * `Number.parseFloat` answers NaN for text and ±Infinity for an exponent past
4979
+ * the double range. The writer refuses to serialise either, so a file carrying
4980
+ * one is rejected here, while the sheet and cell that hold it are still known,
4981
+ * rather than at the far end of the pipeline on save.
4982
+ */
4983
+ function parseCellNumber(raw, sheet, col, row) {
4984
+ if (raw === void 0) return null;
4985
+ const n = Number.parseFloat(raw);
4986
+ if (Number.isFinite(n)) return n;
4987
+ if (raw.trim() === "") return null;
4988
+ throw new OpenXmlSchemaError(`worksheet: <v>${raw.length <= MAX_QUOTED_LENGTH ? raw : `${raw.slice(0, MAX_QUOTED_LENGTH)}... (${raw.length} chars)`}</v> at ${formatSheetQualifiedRef(sheet, tupleToCoordinate(col, row))} is not a finite number`);
4989
+ }
4990
+ //#endregion
4971
4991
  //#region src/worksheet/reader.ts
4972
4992
  const WORKSHEET_TAG = `{${SHEET_MAIN_NS}}worksheet`;
4973
4993
  const SHEETDATA_TAG = `{${SHEET_MAIN_NS}}sheetData`;
@@ -5079,13 +5099,13 @@ function parseWorksheetXml(bytes, title, ctx) {
5079
5099
  if (outlineLevelRow !== void 0) ws.outlineLevelRow = outlineLevelRow;
5080
5100
  const outlineLevelCol = parseIntegerAttr(sheetFormatEl.attrs["outlineLevelCol"]);
5081
5101
  if (outlineLevelCol !== void 0) ws.outlineLevelCol = outlineLevelCol;
5082
- const customHeight = parseBoolXmlAttr(sheetFormatEl.attrs["customHeight"]);
5102
+ const customHeight = parseXsdBoolean(sheetFormatEl.attrs["customHeight"]);
5083
5103
  if (customHeight !== void 0) ws.customHeight = customHeight;
5084
- const zeroHeight = parseBoolXmlAttr(sheetFormatEl.attrs["zeroHeight"]);
5104
+ const zeroHeight = parseXsdBoolean(sheetFormatEl.attrs["zeroHeight"]);
5085
5105
  if (zeroHeight !== void 0) ws.zeroHeight = zeroHeight;
5086
- const thickTop = parseBoolXmlAttr(sheetFormatEl.attrs["thickTop"]);
5106
+ const thickTop = parseXsdBoolean(sheetFormatEl.attrs["thickTop"]);
5087
5107
  if (thickTop !== void 0) ws.thickTop = thickTop;
5088
- const thickBottom = parseBoolXmlAttr(sheetFormatEl.attrs["thickBottom"]);
5108
+ const thickBottom = parseXsdBoolean(sheetFormatEl.attrs["thickBottom"]);
5089
5109
  if (thickBottom !== void 0) ws.thickBottom = thickBottom;
5090
5110
  const baseColWidth = parseIntegerAttr(sheetFormatEl.attrs["baseColWidth"]);
5091
5111
  if (baseColWidth !== void 0) ws.baseColWidth = baseColWidth;
@@ -5098,8 +5118,10 @@ function parseWorksheetXml(bytes, title, ctx) {
5098
5118
  const sheetData = findChild(root, SHEETDATA_TAG);
5099
5119
  if (sheetData) {
5100
5120
  const sharedFormulas = /* @__PURE__ */ new Map();
5121
+ let nextRow = 1;
5101
5122
  for (const rowNode of findChildren(sheetData, ROW_TAG$1)) {
5102
- const rowIdx = parseRowIndex(rowNode);
5123
+ const rowIdx = parseRowIndex(rowNode, nextRow);
5124
+ nextRow = Math.max(nextRow, rowIdx + 1);
5103
5125
  maybeRecordRowDimension(ws, rowNode, rowIdx);
5104
5126
  let nextCol = 1;
5105
5127
  for (const cNode of findChildren(rowNode, C_TAG)) {
@@ -5215,9 +5237,9 @@ function parseWorksheetXml(bytes, title, ctx) {
5215
5237
  type,
5216
5238
  properties: []
5217
5239
  };
5218
- const deleted = parseBoolXmlAttr(tagNode.attrs["deleted"]);
5240
+ const deleted = parseXsdBoolean(tagNode.attrs["deleted"]);
5219
5241
  if (deleted !== void 0) tag.deleted = deleted;
5220
- const xmlBased = parseBoolXmlAttr(tagNode.attrs["xmlBased"]);
5242
+ const xmlBased = parseXsdBoolean(tagNode.attrs["xmlBased"]);
5221
5243
  if (xmlBased !== void 0) tag.xmlBased = xmlBased;
5222
5244
  for (const prop of findChildren(tagNode, CELL_SMART_TAG_PR_TAG)) {
5223
5245
  const key = prop.attrs["key"];
@@ -5338,9 +5360,9 @@ const parseSortState = (node) => {
5338
5360
  ref,
5339
5361
  conditions: []
5340
5362
  };
5341
- const cs = parseBoolXmlAttr(node.attrs["columnSort"]);
5363
+ const cs = parseXsdBoolean(node.attrs["columnSort"]);
5342
5364
  if (cs !== void 0) out.columnSort = cs;
5343
- const cse = parseBoolXmlAttr(node.attrs["caseSensitive"]);
5365
+ const cse = parseXsdBoolean(node.attrs["caseSensitive"]);
5344
5366
  if (cse !== void 0) out.caseSensitive = cse;
5345
5367
  const sm = node.attrs["sortMethod"];
5346
5368
  if (sm && SORT_METHODS.includes(sm)) out.sortMethod = sm;
@@ -5348,7 +5370,7 @@ const parseSortState = (node) => {
5348
5370
  const cRef = sc.attrs["ref"];
5349
5371
  if (!cRef) continue;
5350
5372
  const c = { ref: cRef };
5351
- const desc = parseBoolXmlAttr(sc.attrs["descending"]);
5373
+ const desc = parseXsdBoolean(sc.attrs["descending"]);
5352
5374
  if (desc !== void 0) c.descending = desc;
5353
5375
  const sb = sc.attrs["sortBy"];
5354
5376
  if (sb && SORT_BY_VALUES.includes(sb)) c.sortBy = sb;
@@ -5388,9 +5410,9 @@ const parseScenario = (node) => {
5388
5410
  name,
5389
5411
  inputCells: []
5390
5412
  };
5391
- const locked = parseBoolXmlAttr(node.attrs["locked"]);
5413
+ const locked = parseXsdBoolean(node.attrs["locked"]);
5392
5414
  if (locked !== void 0) out.locked = locked;
5393
- const hidden = parseBoolXmlAttr(node.attrs["hidden"]);
5415
+ const hidden = parseXsdBoolean(node.attrs["hidden"]);
5394
5416
  if (hidden !== void 0) out.hidden = hidden;
5395
5417
  if (node.attrs["user"] !== void 0) out.user = node.attrs["user"];
5396
5418
  if (node.attrs["comment"] !== void 0) out.comment = node.attrs["comment"];
@@ -5408,9 +5430,9 @@ const parseScenarioInputCell = (node) => {
5408
5430
  ref,
5409
5431
  val
5410
5432
  };
5411
- const deleted = parseBoolXmlAttr(node.attrs["deleted"]);
5433
+ const deleted = parseXsdBoolean(node.attrs["deleted"]);
5412
5434
  if (deleted !== void 0) out.deleted = deleted;
5413
- const undone = parseBoolXmlAttr(node.attrs["undone"]);
5435
+ const undone = parseXsdBoolean(node.attrs["undone"]);
5414
5436
  if (undone !== void 0) out.undone = undone;
5415
5437
  const numFmtId = parseIntegerAttr(node.attrs["numFmtId"]);
5416
5438
  if (numFmtId !== void 0) out.numFmtId = numFmtId;
@@ -5433,11 +5455,11 @@ const parseDataConsolidate = (node) => {
5433
5455
  const out = {};
5434
5456
  const f = node.attrs["function"];
5435
5457
  if (f && DATA_CONSOLIDATE_FUNCTIONS.includes(f)) out.function = f;
5436
- const topLabels = parseBoolXmlAttr(node.attrs["topLabels"]);
5458
+ const topLabels = parseXsdBoolean(node.attrs["topLabels"]);
5437
5459
  if (topLabels !== void 0) out.topLabels = topLabels;
5438
- const leftLabels = parseBoolXmlAttr(node.attrs["leftLabels"]);
5460
+ const leftLabels = parseXsdBoolean(node.attrs["leftLabels"]);
5439
5461
  if (leftLabels !== void 0) out.leftLabels = leftLabels;
5440
- const link = parseBoolXmlAttr(node.attrs["link"]);
5462
+ const link = parseXsdBoolean(node.attrs["link"]);
5441
5463
  if (link !== void 0) out.link = link;
5442
5464
  if (node.attrs["startLabels"] !== void 0) out.startLabels = node.attrs["startLabels"];
5443
5465
  const refsEl = findChild(node, DATA_REFS_TAG);
@@ -5506,7 +5528,7 @@ const parseWebPublishItem = (node) => {
5506
5528
  if (node.attrs["sourceRef"] !== void 0) out.sourceRef = node.attrs["sourceRef"];
5507
5529
  if (node.attrs["sourceObject"] !== void 0) out.sourceObject = node.attrs["sourceObject"];
5508
5530
  if (node.attrs["title"] !== void 0) out.title = node.attrs["title"];
5509
- const auto = parseBoolXmlAttr(node.attrs["autoRepublish"]);
5531
+ const auto = parseXsdBoolean(node.attrs["autoRepublish"]);
5510
5532
  if (auto !== void 0) out.autoRepublish = auto;
5511
5533
  return out;
5512
5534
  };
@@ -5545,7 +5567,7 @@ const parseCustomSheetView = (node) => {
5545
5567
  "filterUnique",
5546
5568
  "showRuler"
5547
5569
  ]) {
5548
- const v = parseBoolXmlAttr(node.attrs[k]);
5570
+ const v = parseXsdBoolean(node.attrs[k]);
5549
5571
  if (v !== void 0) out[k] = v;
5550
5572
  }
5551
5573
  const stateRaw = node.attrs["state"];
@@ -5608,7 +5630,7 @@ const parseOleObject = (node) => {
5608
5630
  if (node.attrs["link"] !== void 0) out.link = node.attrs["link"];
5609
5631
  const oleUpdate = node.attrs["oleUpdate"];
5610
5632
  if (oleUpdate && OLE_UPDATE_MODES.includes(oleUpdate)) out.oleUpdate = oleUpdate;
5611
- const autoLoad = parseBoolXmlAttr(node.attrs["autoLoad"]);
5633
+ const autoLoad = parseXsdBoolean(node.attrs["autoLoad"]);
5612
5634
  if (autoLoad !== void 0) out.autoLoad = autoLoad;
5613
5635
  const objectPr = findChild(node, OBJECT_PR_TAG);
5614
5636
  if (objectPr) out.objectPr = objectPr;
@@ -5635,9 +5657,9 @@ const parsePageBreak = (node) => {
5635
5657
  if (min !== void 0) out.min = min;
5636
5658
  const max = parseIntegerAttr(node.attrs["max"]);
5637
5659
  if (max !== void 0) out.max = max;
5638
- const man = parseBoolXmlAttr(node.attrs["man"]);
5660
+ const man = parseXsdBoolean(node.attrs["man"]);
5639
5661
  if (man !== void 0) out.man = man;
5640
- const pt = parseBoolXmlAttr(node.attrs["pt"]);
5662
+ const pt = parseXsdBoolean(node.attrs["pt"]);
5641
5663
  if (pt !== void 0) out.pt = pt;
5642
5664
  return out;
5643
5665
  };
@@ -5999,24 +6021,19 @@ const parseIntegerAttr = (raw) => {
5999
6021
  const n = Number.parseInt(raw, 10);
6000
6022
  return Number.isInteger(n) ? n : void 0;
6001
6023
  };
6002
- const parseBoolXmlAttr = (raw) => {
6003
- if (raw === void 0) return void 0;
6004
- if (raw === "1" || raw === "true") return true;
6005
- if (raw === "0" || raw === "false") return false;
6006
- };
6007
6024
  const parseSheetView$1 = (node) => {
6008
6025
  const opts = { workbookViewId: parseIntegerAttr(node.attrs["workbookViewId"]) ?? 0 };
6009
- const tabSelected = parseBoolXmlAttr(node.attrs["tabSelected"]);
6026
+ const tabSelected = parseXsdBoolean(node.attrs["tabSelected"]);
6010
6027
  if (tabSelected !== void 0) opts.tabSelected = tabSelected;
6011
- const showGridLines = parseBoolXmlAttr(node.attrs["showGridLines"]);
6028
+ const showGridLines = parseXsdBoolean(node.attrs["showGridLines"]);
6012
6029
  if (showGridLines !== void 0) opts.showGridLines = showGridLines;
6013
- const showRowColHeaders = parseBoolXmlAttr(node.attrs["showRowColHeaders"]);
6030
+ const showRowColHeaders = parseXsdBoolean(node.attrs["showRowColHeaders"]);
6014
6031
  if (showRowColHeaders !== void 0) opts.showRowColHeaders = showRowColHeaders;
6015
- const showFormulas = parseBoolXmlAttr(node.attrs["showFormulas"]);
6032
+ const showFormulas = parseXsdBoolean(node.attrs["showFormulas"]);
6016
6033
  if (showFormulas !== void 0) opts.showFormulas = showFormulas;
6017
- const showZeros = parseBoolXmlAttr(node.attrs["showZeros"]);
6034
+ const showZeros = parseXsdBoolean(node.attrs["showZeros"]);
6018
6035
  if (showZeros !== void 0) opts.showZeros = showZeros;
6019
- const rightToLeft = parseBoolXmlAttr(node.attrs["rightToLeft"]);
6036
+ const rightToLeft = parseXsdBoolean(node.attrs["rightToLeft"]);
6020
6037
  if (rightToLeft !== void 0) opts.rightToLeft = rightToLeft;
6021
6038
  const view = node.attrs["view"];
6022
6039
  if (view !== void 0 && SHEET_VIEW_MODES.includes(view)) opts.view = view;
@@ -6051,12 +6068,24 @@ const parseSelection = (node) => {
6051
6068
  if (node.attrs["sqref"]) sel.sqref = node.attrs["sqref"];
6052
6069
  return sel;
6053
6070
  };
6054
- const parseRowIndex = (rowNode) => {
6071
+ /** Row named by the first cell that carries an `@r`, if the row holds one. */
6072
+ const firstLocatedCellRow = (rowNode) => {
6073
+ for (const cNode of rowNode.children) {
6074
+ if (cNode.name !== C_TAG) continue;
6075
+ const ref = cNode.attrs["r"];
6076
+ if (ref) return coordinateToTuple(ref).row;
6077
+ }
6078
+ };
6079
+ /**
6080
+ * Row number for a `<row>`. `@r` is optional on CT_Row (ECMA-376 §18.3.1.73);
6081
+ * without it the row is the one its first located cell names, which is the only
6082
+ * record a generator that omits `@r` leaves of a gap, and is how openpyxl's
6083
+ * reader places such a row too. With neither, the row takes `fallbackRow`.
6084
+ */
6085
+ const parseRowIndex = (rowNode, fallbackRow) => {
6055
6086
  const rAttr = rowNode.attrs["r"];
6056
- if (rAttr === void 0) throw new OpenXmlSchemaError("worksheet: <row> missing required @r");
6057
- const r = Number.parseInt(rAttr, 10);
6058
- if (!Number.isInteger(r) || r < 1) throw new OpenXmlSchemaError(`worksheet: <row r="${rAttr}"> is not a positive integer`);
6059
- return r;
6087
+ if (rAttr !== void 0) return rowNumberFromAttr(rAttr, "worksheet");
6088
+ return firstLocatedCellRow(rowNode) ?? derivedRowNumber(fallbackRow, "worksheet");
6060
6089
  };
6061
6090
  const parseCellCoord = (cNode, rowIdx, fallbackCol) => {
6062
6091
  const rAttr = cNode.attrs["r"];
@@ -6065,7 +6094,7 @@ const parseCellCoord = (cNode, rowIdx, fallbackCol) => {
6065
6094
  col: fallbackCol
6066
6095
  };
6067
6096
  const t = coordinateToTuple(rAttr);
6068
- if (t.row !== rowIdx) throw new OpenXmlSchemaError(`worksheet: <c r="${rAttr}"> row ${t.row} disagrees with <row r="${rowIdx}">`);
6097
+ if (t.row !== rowIdx) throw new OpenXmlSchemaError(`worksheet: <c r="${rAttr}"> row ${t.row} disagrees with row ${rowIdx}`);
6069
6098
  return {
6070
6099
  row: t.row,
6071
6100
  col: t.col
@@ -6081,30 +6110,35 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6081
6110
  if (fNode) {
6082
6111
  const cell = setCell(ws, coord.row, coord.col, null, styleId);
6083
6112
  const cachedRaw = vNode === void 0 ? void 0 : vNode.text ?? "";
6084
- const cached = decodeCachedValue(cachedRaw, t);
6085
- handleFormula(cell, fNode, coord, cached, sharedFormulas);
6113
+ const cached = decodeCachedValue(cachedRaw, t, ctx, ws.title, coord);
6114
+ handleFormula(cell, fNode, coord, cached, sharedFormulas, t);
6086
6115
  return;
6087
6116
  }
6088
6117
  let value = null;
6089
6118
  switch (t) {
6090
6119
  case "n":
6091
- value = vNode?.text !== void 0 && vNode.text !== "" ? Number.parseFloat(vNode.text) : null;
6120
+ value = parseCellNumber(vNode?.text, ws.title, coord.col, coord.row);
6092
6121
  break;
6093
6122
  case "s": {
6094
6123
  if (vNode?.text === void 0) throw new OpenXmlSchemaError("worksheet: <c t=\"s\"> missing <v>");
6095
- const idx = Number.parseInt(vNode.text, 10);
6096
- if (!Number.isInteger(idx) || idx < 0) throw new OpenXmlSchemaError(`worksheet: <c t="s"><v>${vNode.text}</v> is not a valid index`);
6097
- const sst = ctx.sharedStrings[idx];
6098
- if (sst === void 0) throw new OpenXmlSchemaError(`worksheet: shared-string index ${idx} out of range [0, ${ctx.sharedStrings.length})`);
6124
+ const sst = resolveSharedString(vNode.text, ctx);
6099
6125
  value = typeof sst === "string" ? sst : {
6100
6126
  kind: "rich-text",
6101
6127
  runs: sst.runs
6102
6128
  };
6103
6129
  break;
6104
6130
  }
6105
- case "b":
6106
- value = vNode?.text === "1";
6131
+ case "b": {
6132
+ const raw = vNode?.text?.trim();
6133
+ if (raw === void 0 || raw === "") {
6134
+ value = null;
6135
+ break;
6136
+ }
6137
+ const parsed = parseXsdBoolean(raw);
6138
+ if (parsed === void 0) throw new OpenXmlSchemaError(`worksheet: <c r="${tupleToCoordinate(coord.col, coord.row)}" t="b"><v>${clipCellText(raw)}</v></c> is not a boolean`);
6139
+ value = parsed;
6107
6140
  break;
6141
+ }
6108
6142
  case "e": {
6109
6143
  const code = vNode?.text;
6110
6144
  if (code === void 0 || !ERROR_CODES$1.has(code)) throw new OpenXmlSchemaError(`worksheet: unknown error code "${code}" in <c t="e">`);
@@ -6124,6 +6158,16 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6124
6158
  }
6125
6159
  setCell(ws, coord.row, coord.col, value, styleId);
6126
6160
  };
6161
+ const MAX_REPORTED_TEXT = 40;
6162
+ /**
6163
+ * Cell text quoted into an error message is untrusted input of unbounded
6164
+ * length, and nothing stops it from spanning lines, so keep the message one
6165
+ * short line whatever the part holds.
6166
+ */
6167
+ const clipCellText = (raw) => {
6168
+ const oneLine = raw.replace(/\s+/g, " ");
6169
+ return oneLine.length > MAX_REPORTED_TEXT ? `${oneLine.slice(0, MAX_REPORTED_TEXT)}…` : oneLine;
6170
+ };
6127
6171
  const parseStyleId = (raw) => {
6128
6172
  const n = Number.parseInt(raw, 10);
6129
6173
  if (!Number.isInteger(n) || n < 0) throw new OpenXmlSchemaError(`worksheet: <c s="${raw}"> is not a non-negative integer`);
@@ -6143,21 +6187,39 @@ const readInlineString = (isNode) => {
6143
6187
  runs: entry.runs
6144
6188
  };
6145
6189
  };
6146
- const decodeCachedValue = (raw, t) => {
6190
+ const resolveSharedString = (raw, ctx) => {
6191
+ const idx = Number.parseInt(raw, 10);
6192
+ if (!Number.isInteger(idx) || idx < 0) throw new OpenXmlSchemaError(`worksheet: <c t="s"><v>${raw}</v> is not a valid index`);
6193
+ const sst = ctx.sharedStrings[idx];
6194
+ if (sst === void 0) throw new OpenXmlSchemaError(`worksheet: shared-string index ${idx} out of range [0, ${ctx.sharedStrings.length})`);
6195
+ return sst;
6196
+ };
6197
+ const decodeCachedValue = (raw, t, ctx, sheet, coord) => {
6147
6198
  if (raw === void 0) return void 0;
6148
6199
  switch (t) {
6149
- case "n": return raw === "" ? void 0 : Number.parseFloat(raw);
6150
- case "b": return raw === "" ? void 0 : raw === "1";
6151
- case "str": return raw;
6152
- case "e": return raw;
6153
- case "s": return raw;
6200
+ case "n": return parseCellNumber(raw, sheet, coord.col, coord.row) ?? void 0;
6201
+ case "b": {
6202
+ const text = raw.trim();
6203
+ if (text === "") return void 0;
6204
+ const parsed = parseXsdBoolean(text);
6205
+ if (parsed === void 0) throw new OpenXmlSchemaError(`worksheet: <c r="${tupleToCoordinate(coord.col, coord.row)}" t="b"><v>${clipCellText(text)}</v></c> cached result is not a boolean`);
6206
+ return parsed;
6207
+ }
6208
+ case "s": {
6209
+ if (raw === "") return void 0;
6210
+ const sst = resolveSharedString(raw, ctx);
6211
+ return typeof sst === "string" ? sst : richTextToString(sst.runs);
6212
+ }
6154
6213
  default: return raw;
6155
6214
  }
6156
6215
  };
6157
- const handleFormula = (cell, fNode, coord, cached, sharedFormulas) => {
6216
+ const handleFormula = (cell, fNode, coord, cached, sharedFormulas, cachedType) => {
6158
6217
  const tAttr = fNode.attrs["t"] ?? "normal";
6159
6218
  const formula = normalizeFormulaText(fNode.text ?? "");
6160
- const opts = cached !== void 0 ? { cachedValue: cached } : void 0;
6219
+ const opts = cached !== void 0 ? {
6220
+ cachedValue: cached,
6221
+ ...cachedType === "e" ? { cachedValueType: "error" } : {}
6222
+ } : void 0;
6161
6223
  switch (tAttr) {
6162
6224
  case "normal":
6163
6225
  if (formula.length === 0) throw new OpenXmlSchemaError(`worksheet: <f> at ${tupleToCoordinate(coord.col, coord.row)} has no formula text`);
@@ -6194,25 +6256,21 @@ const handleFormula = (cell, fNode, coord, cached, sharedFormulas) => {
6194
6256
  if (!ref) throw new OpenXmlSchemaError("worksheet: <f t=\"dataTable\"> missing @ref");
6195
6257
  setDataTableFormula(cell, formula, {
6196
6258
  ref,
6197
- ...cached !== void 0 ? { cachedValue: cached } : {},
6259
+ ...opts,
6198
6260
  ...fNode.attrs["r1"] !== void 0 ? { r1: fNode.attrs["r1"] } : {},
6199
6261
  ...fNode.attrs["r2"] !== void 0 ? { r2: fNode.attrs["r2"] } : {},
6200
- ...parseDataTableBool(fNode.attrs["dt2D"]) ? { dt2D: true } : {},
6201
- ...parseDataTableBool(fNode.attrs["dtr"]) ? { dtr: true } : {},
6202
- ...parseDataTableBool(fNode.attrs["del1"]) ? { del1: true } : {},
6203
- ...parseDataTableBool(fNode.attrs["del2"]) ? { del2: true } : {},
6204
- ...parseDataTableBool(fNode.attrs["aca"]) ? { aca: true } : {},
6205
- ...parseDataTableBool(fNode.attrs["ca"]) ? { ca: true } : {}
6262
+ ...parseXsdBoolean(fNode.attrs["dt2D"]) ? { dt2D: true } : {},
6263
+ ...parseXsdBoolean(fNode.attrs["dtr"]) ? { dtr: true } : {},
6264
+ ...parseXsdBoolean(fNode.attrs["del1"]) ? { del1: true } : {},
6265
+ ...parseXsdBoolean(fNode.attrs["del2"]) ? { del2: true } : {},
6266
+ ...parseXsdBoolean(fNode.attrs["aca"]) ? { aca: true } : {},
6267
+ ...parseXsdBoolean(fNode.attrs["ca"]) ? { ca: true } : {}
6206
6268
  });
6207
6269
  return;
6208
6270
  }
6209
6271
  default: throw new OpenXmlSchemaError(`worksheet: <f t="${tAttr}"> unknown formula kind`);
6210
6272
  }
6211
6273
  };
6212
- const parseDataTableBool = (raw) => {
6213
- if (raw === void 0) return false;
6214
- return raw === "1" || raw === "true";
6215
- };
6216
6274
  const parseColumnDimension = (node) => {
6217
6275
  const minRaw = node.attrs["min"];
6218
6276
  const maxRaw = node.attrs["max"];
@@ -6223,17 +6281,17 @@ const parseColumnDimension = (node) => {
6223
6281
  const opts = {};
6224
6282
  const width = parseFloatAttr(node.attrs["width"]);
6225
6283
  if (width !== void 0) opts.width = width;
6226
- const customWidth = parseBoolXmlAttr(node.attrs["customWidth"]);
6284
+ const customWidth = parseXsdBoolean(node.attrs["customWidth"]);
6227
6285
  if (customWidth !== void 0) opts.customWidth = customWidth;
6228
- const hidden = parseBoolXmlAttr(node.attrs["hidden"]);
6286
+ const hidden = parseXsdBoolean(node.attrs["hidden"]);
6229
6287
  if (hidden !== void 0) opts.hidden = hidden;
6230
- const bestFit = parseBoolXmlAttr(node.attrs["bestFit"]);
6288
+ const bestFit = parseXsdBoolean(node.attrs["bestFit"]);
6231
6289
  if (bestFit !== void 0) opts.bestFit = bestFit;
6232
6290
  const outlineLevel = parseIntegerAttr(node.attrs["outlineLevel"]);
6233
6291
  if (outlineLevel !== void 0) opts.outlineLevel = outlineLevel;
6234
6292
  const style = parseIntegerAttr(node.attrs["style"]);
6235
6293
  if (style !== void 0) opts.style = style;
6236
- const collapsed = parseBoolXmlAttr(node.attrs["collapsed"]);
6294
+ const collapsed = parseXsdBoolean(node.attrs["collapsed"]);
6237
6295
  if (collapsed !== void 0) opts.collapsed = collapsed;
6238
6296
  return {
6239
6297
  ...makeColumnDimension(min, opts),
@@ -6275,13 +6333,13 @@ const parseDataValidation = (node) => {
6275
6333
  };
6276
6334
  const operator = node.attrs["operator"];
6277
6335
  if (operator && DV_OPERATORS.includes(operator)) opts.operator = operator;
6278
- const allowBlank = parseBoolXmlAttr(node.attrs["allowBlank"]);
6336
+ const allowBlank = parseXsdBoolean(node.attrs["allowBlank"]);
6279
6337
  if (allowBlank !== void 0) opts.allowBlank = allowBlank;
6280
- const showInputMessage = parseBoolXmlAttr(node.attrs["showInputMessage"]);
6338
+ const showInputMessage = parseXsdBoolean(node.attrs["showInputMessage"]);
6281
6339
  if (showInputMessage !== void 0) opts.showInputMessage = showInputMessage;
6282
- const showErrorMessage = parseBoolXmlAttr(node.attrs["showErrorMessage"]);
6340
+ const showErrorMessage = parseXsdBoolean(node.attrs["showErrorMessage"]);
6283
6341
  if (showErrorMessage !== void 0) opts.showErrorMessage = showErrorMessage;
6284
- const showDropDown = parseBoolXmlAttr(node.attrs["showDropDown"]);
6342
+ const showDropDown = parseXsdBoolean(node.attrs["showDropDown"]);
6285
6343
  if (showDropDown !== void 0) opts.showDropDown = showDropDown;
6286
6344
  const errorTitle = node.attrs["errorTitle"];
6287
6345
  if (errorTitle !== void 0) opts.errorTitle = errorTitle;
@@ -6336,7 +6394,7 @@ const parseConditionalFormatting = (node) => {
6336
6394
  sqref: parseMultiCellRange(sqrefRaw),
6337
6395
  rules
6338
6396
  };
6339
- const pivot = parseBoolXmlAttr(node.attrs["pivot"]);
6397
+ const pivot = parseXsdBoolean(node.attrs["pivot"]);
6340
6398
  if (pivot !== void 0) opts.pivot = pivot;
6341
6399
  return makeConditionalFormatting(opts);
6342
6400
  };
@@ -6354,19 +6412,19 @@ const parseCfRule = (node) => {
6354
6412
  };
6355
6413
  const dxf = parseIntegerAttr(node.attrs["dxfId"]);
6356
6414
  if (dxf !== void 0) opts.dxfId = dxf;
6357
- const stop = parseBoolXmlAttr(node.attrs["stopIfTrue"]);
6415
+ const stop = parseXsdBoolean(node.attrs["stopIfTrue"]);
6358
6416
  if (stop !== void 0) opts.stopIfTrue = stop;
6359
6417
  if (node.attrs["operator"]) opts.operator = node.attrs["operator"];
6360
6418
  if (node.attrs["text"] !== void 0) opts.text = node.attrs["text"];
6361
- const percent = parseBoolXmlAttr(node.attrs["percent"]);
6419
+ const percent = parseXsdBoolean(node.attrs["percent"]);
6362
6420
  if (percent !== void 0) opts.percent = percent;
6363
- const bottom = parseBoolXmlAttr(node.attrs["bottom"]);
6421
+ const bottom = parseXsdBoolean(node.attrs["bottom"]);
6364
6422
  if (bottom !== void 0) opts.bottom = bottom;
6365
6423
  const rank = parseIntegerAttr(node.attrs["rank"]);
6366
6424
  if (rank !== void 0) opts.rank = rank;
6367
- const aboveAverage = parseBoolXmlAttr(node.attrs["aboveAverage"]);
6425
+ const aboveAverage = parseXsdBoolean(node.attrs["aboveAverage"]);
6368
6426
  if (aboveAverage !== void 0) opts.aboveAverage = aboveAverage;
6369
- const equalAverage = parseBoolXmlAttr(node.attrs["equalAverage"]);
6427
+ const equalAverage = parseXsdBoolean(node.attrs["equalAverage"]);
6370
6428
  if (equalAverage !== void 0) opts.equalAverage = equalAverage;
6371
6429
  const stdDev = parseIntegerAttr(node.attrs["stdDev"]);
6372
6430
  if (stdDev !== void 0) opts.stdDev = stdDev;
@@ -6399,7 +6457,7 @@ const parseAutoFilter = (node) => {
6399
6457
  const v = f.attrs["val"];
6400
6458
  if (v !== void 0) values.push(v);
6401
6459
  }
6402
- const blank = parseBoolXmlAttr(filtersEl.attrs["blank"]);
6460
+ const blank = parseXsdBoolean(filtersEl.attrs["blank"]);
6403
6461
  const fc2 = {
6404
6462
  kind: "filters",
6405
6463
  colId,
@@ -6432,13 +6490,13 @@ const maybeRecordRowDimension = (ws, node, rowIdx) => {
6432
6490
  const opts = {};
6433
6491
  const ht = parseFloatAttr(node.attrs["ht"]);
6434
6492
  if (ht !== void 0) opts.height = ht;
6435
- const customHeight = parseBoolXmlAttr(node.attrs["customHeight"]);
6493
+ const customHeight = parseXsdBoolean(node.attrs["customHeight"]);
6436
6494
  if (customHeight !== void 0) opts.customHeight = customHeight;
6437
- const hidden = parseBoolXmlAttr(node.attrs["hidden"]);
6495
+ const hidden = parseXsdBoolean(node.attrs["hidden"]);
6438
6496
  if (hidden !== void 0) opts.hidden = hidden;
6439
6497
  const outlineLevel = parseIntegerAttr(node.attrs["outlineLevel"]);
6440
6498
  if (outlineLevel !== void 0) opts.outlineLevel = outlineLevel;
6441
- const collapsed = parseBoolXmlAttr(node.attrs["collapsed"]);
6499
+ const collapsed = parseXsdBoolean(node.attrs["collapsed"]);
6442
6500
  if (collapsed !== void 0) opts.collapsed = collapsed;
6443
6501
  const style = parseIntegerAttr(node.attrs["s"]);
6444
6502
  if (style !== void 0) opts.style = style;
@@ -6617,11 +6675,10 @@ const colLetters = (n) => {
6617
6675
  * streaming write-only path can emit cells row-by-row without going through the
6618
6676
  * full Worksheet model — see src/streaming/write-only.ts.
6619
6677
  *
6620
- * Only `ctx.sharedStrings` is consulted for plain-string cells; the other
6621
- * context fields are used by the worksheet-level serializer that wraps this
6622
- * helper.
6678
+ * String cells use the optional writer or the model's shared-string table.
6679
+ * Date cells also consult the shared style pool.
6623
6680
  */
6624
- const serializeCell = (cell, ctx) => {
6681
+ const serializeCell = (cell, ctx, stringWriter) => {
6625
6682
  const ref = getCoordinate(cell);
6626
6683
  const styleAttr = cell.styleId === 0 ? "" : ` s="${cell.styleId}"`;
6627
6684
  const value = cell.value;
@@ -6630,26 +6687,37 @@ const serializeCell = (cell, ctx) => {
6630
6687
  if (typeof value === "object" && value !== null && value.kind === "error") return `<c r="${ref}"${styleAttr} t="e"><v>${value.code}</v></c>`;
6631
6688
  if (typeof value === "object" && value !== null && value.kind === "rich-text") {
6632
6689
  const runs = value.runs;
6690
+ if (stringWriter) {
6691
+ const text = stringWriter({
6692
+ kind: "rich-text",
6693
+ runs
6694
+ });
6695
+ return `<c r="${ref}"${styleAttr} t="${text.type}">${text.xml}</c>`;
6696
+ }
6633
6697
  return `<c r="${ref}"${styleAttr} t="s"><v>${addSharedRichText(ctx.sharedStrings, runs)}</v></c>`;
6634
6698
  }
6635
- if (typeof value === "number") {
6636
- if (!Number.isFinite(value)) throw new OpenXmlSchemaError(`worksheet: cannot serialise non-finite number at ${ref}`);
6637
- return `<c r="${ref}"${styleAttr}><v>${serializeNumber(value)}</v></c>`;
6638
- }
6699
+ if (typeof value === "number") return `<c r="${ref}"${styleAttr}><v>${serializeNumber(value, ref)}</v></c>`;
6639
6700
  if (typeof value === "boolean") return `<c r="${ref}"${styleAttr} t="b"><v>${value ? "1" : "0"}</v></c>`;
6640
- if (typeof value === "string") return `<c r="${ref}"${styleAttr} t="s"><v>${addSharedString(ctx.sharedStrings, value)}</v></c>`;
6701
+ if (typeof value === "string") {
6702
+ if (stringWriter) {
6703
+ const text = stringWriter(value);
6704
+ return `<c r="${ref}"${styleAttr} t="${text.type}">${text.xml}</c>`;
6705
+ }
6706
+ return `<c r="${ref}"${styleAttr} t="s"><v>${addSharedString(ctx.sharedStrings, value)}</v></c>`;
6707
+ }
6641
6708
  if (value instanceof Date) {
6642
6709
  const serial = dateToExcel(value, { epoch: ctx.date1904 ? "mac" : "windows" });
6643
- return `<c r="${ref}"${styleAttr}><v>${serializeNumber(serial)}</v></c>`;
6710
+ return `<c r="${ref}"${styleAttr}><v>${serializeNumber(serial, ref)}</v></c>`;
6644
6711
  }
6645
6712
  if (typeof value === "object" && value !== null && value.kind === "duration") {
6646
6713
  const ms = value.ms;
6647
6714
  const serial = durationToExcel(ms);
6648
- return `<c r="${ref}"${styleAttr}><v>${serializeNumber(serial)}</v></c>`;
6715
+ return `<c r="${ref}"${styleAttr}><v>${serializeNumber(serial, ref)}</v></c>`;
6649
6716
  }
6650
6717
  throw new OpenXmlSchemaError(`worksheet: unsupported cell value kind at ${ref}: ${describeValue(value)}`);
6651
6718
  };
6652
- const serializeNumber = (n) => {
6719
+ const serializeNumber = (n, ref) => {
6720
+ if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`worksheet: cannot serialise non-finite number at ${ref}`);
6653
6721
  return Number.isInteger(n) ? n.toFixed(0) : String(n);
6654
6722
  };
6655
6723
  const serializeFormulaCell = (ref, styleAttr, f) => {
@@ -6668,18 +6736,22 @@ const serializeFormulaCell = (ref, styleAttr, f) => {
6668
6736
  const fAttrStr = fAttrs.length > 0 ? ` ${fAttrs.join(" ")}` : "";
6669
6737
  const normalized = normalizeFormulaText(f.formula);
6670
6738
  if ((f.t === "normal" || f.t === "array") && normalized.length === 0) throw new OpenXmlSchemaError(`worksheet: ${f.t} formula must not be empty at ${ref}`);
6671
- const formulaText = escapeXmlText(escapeCellString(normalized));
6739
+ const formulaText = escapeXmlTextVerbatim(normalized, "worksheet: formula", ref);
6672
6740
  const fEl = formulaText.length > 0 ? `<f${fAttrStr}>${formulaText}</f>` : `<f${fAttrStr}/>`;
6673
6741
  let valueAttr = "";
6674
6742
  let vEl = "";
6675
6743
  const cached = f.cachedValue;
6676
- if (cached !== void 0) if (typeof cached === "number") vEl = `<v>${serializeNumber(cached)}</v>`;
6744
+ if (f.cachedValueType === "error") {
6745
+ if (typeof cached !== "string" || !ERROR_CODES$1.has(cached)) throw new OpenXmlSchemaError(`worksheet: invalid cached formula error at ${ref}`);
6746
+ valueAttr = " t=\"e\"";
6747
+ vEl = `<v>${cached}</v>`;
6748
+ } else if (cached !== void 0) if (typeof cached === "number") vEl = `<v>${serializeNumber(cached, ref)}</v>`;
6677
6749
  else if (typeof cached === "boolean") {
6678
6750
  valueAttr = " t=\"b\"";
6679
6751
  vEl = `<v>${cached ? "1" : "0"}</v>`;
6680
6752
  } else {
6681
6753
  valueAttr = " t=\"str\"";
6682
- const text = escapeXmlText(escapeCellString(cached));
6754
+ const text = escapeXmlTextVerbatim(cached, "worksheet: cached formula result", ref);
6683
6755
  vEl = text.length > 0 ? `<v>${text}</v>` : "<v/>";
6684
6756
  }
6685
6757
  return `<c r="${ref}"${styleAttr}${valueAttr}>${fEl}${vEl}</c>`;
@@ -6815,7 +6887,11 @@ const serializeCfRule = (rule) => {
6815
6887
  if (rule.stdDev !== void 0) attrs += ` stdDev="${rule.stdDev}"`;
6816
6888
  if (rule.timePeriod !== void 0) attrs += ` timePeriod="${rule.timePeriod}"`;
6817
6889
  const inner = [];
6818
- for (const f of rule.formulas) inner.push(`<formula>${escapeXmlText(normalizeFormulaText(f))}</formula>`);
6890
+ for (const f of rule.formulas) {
6891
+ const at = `priority ${rule.priority}`;
6892
+ const text = escapeXmlTextVerbatim(normalizeFormulaText(f), "worksheet: conditional-formatting formula", at);
6893
+ inner.push(`<formula>${text}</formula>`);
6894
+ }
6819
6895
  if (rule.innerXml) inner.push(rule.innerXml);
6820
6896
  if (inner.length === 0) return `<cfRule${attrs}/>`;
6821
6897
  return `<cfRule${attrs}>${inner.join("")}</cfRule>`;
@@ -6838,10 +6914,17 @@ const serializeDataValidation = (dv) => {
6838
6914
  if (dv.error !== void 0) attrs += ` error="${escapeXmlAttr(dv.error)}"`;
6839
6915
  if (dv.promptTitle !== void 0) attrs += ` promptTitle="${escapeXmlAttr(dv.promptTitle)}"`;
6840
6916
  if (dv.prompt !== void 0) attrs += ` prompt="${escapeXmlAttr(dv.prompt)}"`;
6841
- attrs += ` sqref="${escapeXmlAttr(multiCellRangeToString(dv.sqref))}"`;
6917
+ const sqref = multiCellRangeToString(dv.sqref);
6918
+ attrs += ` sqref="${escapeXmlAttr(sqref)}"`;
6842
6919
  const formulas = [];
6843
- if (dv.formula1 !== void 0) formulas.push(`<formula1>${escapeXmlText(normalizeFormulaText(dv.formula1))}</formula1>`);
6844
- if (dv.formula2 !== void 0) formulas.push(`<formula2>${escapeXmlText(normalizeFormulaText(dv.formula2))}</formula2>`);
6920
+ if (dv.formula1 !== void 0) {
6921
+ const text = escapeXmlTextVerbatim(normalizeFormulaText(dv.formula1), "worksheet: data-validation formula1", sqref);
6922
+ formulas.push(`<formula1>${text}</formula1>`);
6923
+ }
6924
+ if (dv.formula2 !== void 0) {
6925
+ const text = escapeXmlTextVerbatim(normalizeFormulaText(dv.formula2), "worksheet: data-validation formula2", sqref);
6926
+ formulas.push(`<formula2>${text}</formula2>`);
6927
+ }
6845
6928
  if (formulas.length === 0) return `<dataValidation${attrs}/>`;
6846
6929
  return `<dataValidation${attrs}>${formulas.join("")}</dataValidation>`;
6847
6930
  };
@@ -8724,6 +8807,6 @@ const cellXfToTree = (xf) => {
8724
8807
  return node;
8725
8808
  };
8726
8809
  //#endregion
8727
- export { chartExToBytes as C, findUserShapesRId as D, chartToBytes as E, parseChartXml as O, userShapesToBytes as S, parseChartExXml as T, parseChartsheetXml as _, parseCommentsXml as a, parseWorksheetXml as b, NumberFormatSchema as c, BorderSchema as d, AlignmentSchema as f, chartsheetToBytes as g, parseDrawingXml as h, commentsToBytes as i, FontSchema as l, drawingToBytes as m, parseTableXml as n, placeholderVmlDrawing as o, collectRawRelIds as p, tableToBytes as r, ProtectionSchema as s, stylesheetToBytes as t, fillFromTree as u, serializeCell as v, isChartExBytes as w, parseUserShapesXml as x, writeWorksheetXml as y };
8810
+ export { userShapesToBytes as C, chartToBytes as D, parseChartExXml as E, findUserShapesRId as O, parseUserShapesXml as S, isChartExBytes as T, parseChartsheetXml as _, parseCommentsXml as a, parseWorksheetXml as b, NumberFormatSchema as c, BorderSchema as d, AlignmentSchema as f, chartsheetToBytes as g, parseDrawingXml as h, commentsToBytes as i, parseChartXml as k, FontSchema as l, drawingToBytes as m, parseTableXml as n, placeholderVmlDrawing as o, collectRawRelIds as p, tableToBytes as r, ProtectionSchema as s, stylesheetToBytes as t, fillFromTree as u, serializeCell as v, chartExToBytes as w, parseCellNumber as x, writeWorksheetXml as y };
8728
8811
 
8729
- //# sourceMappingURL=stylesheet-writer-TxsinwbO.mjs.map
8812
+ //# sourceMappingURL=stylesheet-writer-BBYjNSMA.mjs.map