ooxml.js 2.5.2 → 2.6.1

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 (42) hide show
  1. package/README.md +3 -2
  2. package/dist/index.cjs +22 -0
  3. package/dist/index.d.cts +3 -2
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.js +3 -2
  6. package/dist/typed/docx/numbering.cjs +86 -0
  7. package/dist/typed/docx/numbering.d.cts +23 -0
  8. package/dist/typed/docx/numbering.d.ts +23 -0
  9. package/dist/typed/docx/numbering.js +83 -0
  10. package/dist/typed/docx/read.cjs +115 -15
  11. package/dist/typed/docx/read.d.cts +8 -0
  12. package/dist/typed/docx/read.d.ts +8 -0
  13. package/dist/typed/docx/read.js +117 -17
  14. package/dist/typed/docx/styles.cjs +26 -2
  15. package/dist/typed/docx/styles.js +26 -2
  16. package/dist/typed/pptx/read.cjs +5 -20
  17. package/dist/typed/pptx/read.js +5 -20
  18. package/dist/typed/shared/drawingml.cjs +112 -5
  19. package/dist/typed/shared/drawingml.d.cts +19 -2
  20. package/dist/typed/shared/drawingml.d.ts +19 -2
  21. package/dist/typed/shared/drawingml.js +111 -6
  22. package/dist/typed/shared/units.cjs +10 -0
  23. package/dist/typed/shared/units.d.cts +4 -1
  24. package/dist/typed/shared/units.d.ts +4 -1
  25. package/dist/typed/shared/units.js +8 -1
  26. package/dist/typed/xlsx/build.cjs +83 -55
  27. package/dist/typed/xlsx/build.js +83 -55
  28. package/dist/typed/xlsx/content.cjs +85 -15
  29. package/dist/typed/xlsx/content.js +85 -15
  30. package/dist/typed/xlsx/number-format.cjs +324 -0
  31. package/dist/typed/xlsx/number-format.d.cts +52 -0
  32. package/dist/typed/xlsx/number-format.d.ts +52 -0
  33. package/dist/typed/xlsx/number-format.js +312 -0
  34. package/dist/typed/xlsx/serial.cjs +109 -0
  35. package/dist/typed/xlsx/serial.d.cts +11 -0
  36. package/dist/typed/xlsx/serial.d.ts +11 -0
  37. package/dist/typed/xlsx/serial.js +102 -0
  38. package/dist/typed/xlsx/styles.cjs +73 -0
  39. package/dist/typed/xlsx/styles.d.cts +21 -0
  40. package/dist/typed/xlsx/styles.d.ts +21 -0
  41. package/dist/typed/xlsx/styles.js +69 -0
  42. package/package.json +1 -1
@@ -4,8 +4,11 @@ import "../shared/units.js";
4
4
  import { SharedStringTable } from "./shared-strings.js";
5
5
  import { cellReference, rangeReference } from "./a1.js";
6
6
  import { XLNM_PRINT_AREA, XLNM_PRINT_TITLES, buildPrintAreaValue, buildPrintTitlesValue } from "./defined-names.js";
7
+ import { BOOLEAN_NUMBER_FORMAT, DATE_NUMBER_FORMAT, DATE_TIME_NUMBER_FORMAT, PERCENTAGE_NUMBER_FORMAT, TIME_NUMBER_FORMAT, currencyNumberFormat } from "./number-format.js";
7
8
  import { pageSizeToPaperSizeCode, ptToUniversalMeasure, writeXmlBool } from "./util.js";
8
9
  import { DEFAULT_HEADER_FOOTER_MARGIN_PT } from "./print-settings.js";
10
+ import { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial } from "./serial.js";
11
+ import { CellFormatTable } from "./styles.js";
9
12
  import { ptToColumnWidthChars } from "./units.js";
10
13
  //#region src/typed/xlsx/build.ts
11
14
  const SML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
@@ -179,36 +182,46 @@ function buildSharedStringsPart(sharedStrings) {
179
182
  uniqueCount: String(entries.length)
180
183
  }, siElements));
181
184
  }
182
- function buildStylesPart() {
183
- return xmlPart(el("styleSheet", { xmlns: SML_NS }, [
184
- el("fonts", { count: "1" }, [el("font", {}, [el("sz", { val: "11" }), el("name", { val: "Calibri" })])]),
185
- el("fills", { count: "2" }, [el("fill", {}, [el("patternFill", { patternType: "none" })]), el("fill", {}, [el("patternFill", { patternType: "gray125" })])]),
186
- el("borders", { count: "1" }, [el("border", {}, [
187
- el("left"),
188
- el("right"),
189
- el("top"),
190
- el("bottom"),
191
- el("diagonal")
192
- ])]),
193
- el("cellStyleXfs", { count: "1" }, [el("xf", {
194
- numFmtId: "0",
195
- fontId: "0",
196
- fillId: "0",
197
- borderId: "0"
198
- })]),
199
- el("cellXfs", { count: "1" }, [el("xf", {
200
- numFmtId: "0",
185
+ function buildStylesPart(cellFormats) {
186
+ const children = [];
187
+ const declarations = cellFormats.declarations();
188
+ if (declarations.length > 0) {
189
+ const numFmtElements = declarations.map((declaration) => el("numFmt", {
190
+ numFmtId: String(declaration.id),
191
+ formatCode: encodeXmlText(declaration.code)
192
+ }));
193
+ children.push(el("numFmts", { count: String(numFmtElements.length) }, numFmtElements));
194
+ }
195
+ children.push(el("fonts", { count: "1" }, [el("font", {}, [el("sz", { val: "11" }), el("name", { val: "Calibri" })])]), el("fills", { count: "2" }, [el("fill", {}, [el("patternFill", { patternType: "none" })]), el("fill", {}, [el("patternFill", { patternType: "gray125" })])]), el("borders", { count: "1" }, [el("border", {}, [
196
+ el("left"),
197
+ el("right"),
198
+ el("top"),
199
+ el("bottom"),
200
+ el("diagonal")
201
+ ])]), el("cellStyleXfs", { count: "1" }, [el("xf", {
202
+ numFmtId: "0",
203
+ fontId: "0",
204
+ fillId: "0",
205
+ borderId: "0"
206
+ })]));
207
+ const xfElements = cellFormats.cellFormats().map((numFmtId) => {
208
+ const attrs = {
209
+ numFmtId: String(numFmtId),
201
210
  fontId: "0",
202
211
  fillId: "0",
203
212
  borderId: "0",
204
213
  xfId: "0"
205
- })]),
206
- el("cellStyles", { count: "1" }, [el("cellStyle", {
207
- name: "Normal",
208
- xfId: "0",
209
- builtinId: "0"
210
- })])
211
- ]));
214
+ };
215
+ if (numFmtId !== 0) attrs.applyNumberFormat = writeXmlBool(true);
216
+ return el("xf", attrs);
217
+ });
218
+ children.push(el("cellXfs", { count: String(xfElements.length) }, xfElements));
219
+ children.push(el("cellStyles", { count: "1" }, [el("cellStyle", {
220
+ name: "Normal",
221
+ xfId: "0",
222
+ builtinId: "0"
223
+ })]));
224
+ return xmlPart(el("styleSheet", { xmlns: SML_NS }, children));
212
225
  }
213
226
  function buildCorePropertiesPart(metadata) {
214
227
  const children = [];
@@ -271,28 +284,24 @@ function buildColsElement(columns) {
271
284
  }
272
285
  function renderCellValue(value, isFormulaResult, sharedStrings) {
273
286
  switch (value.kind) {
274
- case "string":
275
- if (isFormulaResult) return {
276
- type: "str",
277
- content: encodeXmlText(value.value)
278
- };
279
- return {
280
- type: "s",
281
- content: String(sharedStrings.intern(value.value))
282
- };
283
- case "number":
284
- case "percentage":
285
- case "currency": return { content: String(value.value) };
287
+ case "string": return renderString(value.value, isFormulaResult, sharedStrings);
288
+ case "number": return { content: String(value.value) };
289
+ case "percentage": return {
290
+ content: String(value.value),
291
+ format: PERCENTAGE_NUMBER_FORMAT
292
+ };
293
+ case "currency": return {
294
+ content: String(value.value),
295
+ format: currencyNumberFormat(value.currency)
296
+ };
286
297
  case "boolean": return {
287
298
  type: "b",
288
- content: value.value ? "1" : "0"
289
- };
290
- case "date":
291
- case "time":
292
- case "dateTime": return {
293
- type: "d",
294
- content: encodeXmlText(value.value)
299
+ content: value.value ? "1" : "0",
300
+ format: BOOLEAN_NUMBER_FORMAT
295
301
  };
302
+ case "date": return renderTemporal(isoDateToSerial(value.value), value.value, DATE_NUMBER_FORMAT, isFormulaResult, sharedStrings);
303
+ case "time": return renderTemporal(isoTimeToSerial(value.value), value.value, TIME_NUMBER_FORMAT, isFormulaResult, sharedStrings);
304
+ case "dateTime": return renderTemporal(isoDateTimeToSerial(value.value), value.value, DATE_TIME_NUMBER_FORMAT, isFormulaResult, sharedStrings);
296
305
  case "error": return {
297
306
  type: "e",
298
307
  content: encodeXmlText(value.value)
@@ -300,21 +309,39 @@ function renderCellValue(value, isFormulaResult, sharedStrings) {
300
309
  case "empty": return;
301
310
  }
302
311
  }
303
- function buildCellElement(cell, sharedStrings) {
312
+ function renderString(text, isFormulaResult, sharedStrings) {
313
+ if (isFormulaResult) return {
314
+ type: "str",
315
+ content: encodeXmlText(text)
316
+ };
317
+ return {
318
+ type: "s",
319
+ content: String(sharedStrings.intern(text))
320
+ };
321
+ }
322
+ function renderTemporal(serial, iso, format, isFormulaResult, sharedStrings) {
323
+ if (serial === void 0) return renderString(iso, isFormulaResult, sharedStrings);
324
+ return {
325
+ content: String(serial),
326
+ format
327
+ };
328
+ }
329
+ function buildCellElement(cell, sharedStrings, cellFormats) {
330
+ const children = [];
331
+ const rendered = renderCellValue(cell.value, cell.formula !== void 0, sharedStrings);
332
+ const styleIndex = rendered?.format === void 0 ? 0 : cellFormats.intern(rendered.format);
304
333
  const attrs = {
305
334
  r: cellReference(cell.row, cell.column),
306
- s: "0"
335
+ s: String(styleIndex)
307
336
  };
308
- const children = [];
309
337
  if (cell.formula !== void 0) children.push(el("f", {}, [txt(encodeXmlText(cell.formula))]));
310
- const rendered = renderCellValue(cell.value, cell.formula !== void 0, sharedStrings);
311
338
  if (rendered !== void 0) {
312
339
  if (rendered.type !== void 0) attrs.t = rendered.type;
313
340
  children.push(el("v", {}, [txt(rendered.content)]));
314
341
  }
315
342
  return el("c", attrs, children);
316
343
  }
317
- function buildSheetDataElement(sheet, sharedStrings) {
344
+ function buildSheetDataElement(sheet, sharedStrings, cellFormats) {
318
345
  const cellsByRow = /* @__PURE__ */ new Map();
319
346
  for (const cell of sheet.cells) {
320
347
  const existing = cellsByRow.get(cell.row);
@@ -334,7 +361,7 @@ function buildSheetDataElement(sheet, sharedStrings) {
334
361
  }
335
362
  if (rowInfo.hidden === true) attrs.hidden = "true";
336
363
  }
337
- return el("row", attrs, cells.map((cell) => buildCellElement(cell, sharedStrings)));
364
+ return el("row", attrs, cells.map((cell) => buildCellElement(cell, sharedStrings, cellFormats)));
338
365
  }));
339
366
  }
340
367
  function buildMergeCellsElement(cells) {
@@ -420,11 +447,11 @@ function buildBreaksElements(settings) {
420
447
  }
421
448
  return result;
422
449
  }
423
- function buildWorksheetPart(sheet, sharedStrings) {
450
+ function buildWorksheetPart(sheet, sharedStrings, cellFormats) {
424
451
  const children = [buildSheetPrElement(sheet.printSettings), el("dimension", { ref: computeDimension(sheet) })];
425
452
  const colsElement = buildColsElement(sheet.columns);
426
453
  if (colsElement !== void 0) children.push(colsElement);
427
- children.push(buildSheetDataElement(sheet, sharedStrings));
454
+ children.push(buildSheetDataElement(sheet, sharedStrings, cellFormats));
428
455
  const mergeCellsElement = buildMergeCellsElement(sheet.cells);
429
456
  if (mergeCellsElement !== void 0) children.push(mergeCellsElement);
430
457
  children.push(buildPrintOptionsElement(sheet.printSettings), buildPageMarginsElement(sheet.printSettings), buildPageSetupElement(sheet.printSettings));
@@ -440,13 +467,14 @@ function buildXlsxPackage(document) {
440
467
  if (document.kind !== "spreadsheet") throw new Error(`buildXlsxPackage: expected a ContentDocument of kind "spreadsheet", got "${document.kind}"`);
441
468
  const sheets = document.sheets;
442
469
  const sharedStrings = new SharedStringTable();
443
- const worksheetParts = sheets.map((sheet) => buildWorksheetPart(sheet, sharedStrings));
470
+ const cellFormats = new CellFormatTable();
471
+ const worksheetParts = sheets.map((sheet) => buildWorksheetPart(sheet, sharedStrings, cellFormats));
444
472
  const parts = {
445
473
  "[Content_Types].xml": buildContentTypesPart(sheets.length),
446
474
  "_rels/.rels": buildPackageRelsPart(),
447
475
  "xl/workbook.xml": buildWorkbookPart(sheets),
448
476
  "xl/_rels/workbook.xml.rels": buildWorkbookRelsPart(sheets.length),
449
- "xl/styles.xml": buildStylesPart(),
477
+ "xl/styles.xml": buildStylesPart(cellFormats),
450
478
  "xl/sharedStrings.xml": buildSharedStringsPart(sharedStrings),
451
479
  "docProps/core.xml": buildCorePropertiesPart(document.metadata),
452
480
  "docProps/app.xml": buildAppPropertiesPart(document.metadata)
@@ -4,8 +4,11 @@ const require_typed_shared_metadata = require("../shared/metadata.cjs");
4
4
  const require_typed_xlsx_shared_strings = require("./shared-strings.cjs");
5
5
  const require_typed_xlsx_a1 = require("./a1.cjs");
6
6
  const require_typed_xlsx_defined_names = require("./defined-names.cjs");
7
+ const require_typed_xlsx_number_format = require("./number-format.cjs");
7
8
  const require_typed_xlsx_util = require("./util.cjs");
8
9
  const require_typed_xlsx_print_settings = require("./print-settings.cjs");
10
+ const require_typed_xlsx_serial = require("./serial.cjs");
11
+ const require_typed_xlsx_styles = require("./styles.cjs");
9
12
  const require_typed_xlsx_units = require("./units.cjs");
10
13
  let document_schema_js = require("document-schema.js");
11
14
  //#region src/typed/xlsx/content.ts
@@ -81,19 +84,88 @@ function readInlineOrSharedStringText(container) {
81
84
  }
82
85
  function deriveDisplayText(value) {
83
86
  switch (value.kind) {
84
- case "number": return String(value.value);
87
+ case "number":
88
+ case "percentage":
89
+ case "currency": return String(value.value);
85
90
  case "boolean": return value.value ? "TRUE" : "FALSE";
86
91
  case "string":
87
92
  case "error":
88
93
  case "date":
89
94
  case "time":
90
95
  case "dateTime": return value.value;
91
- case "percentage":
92
- case "currency": return String(value.value);
93
96
  case "empty": return "";
94
97
  }
95
98
  }
96
- function readCellValue(cell, sharedStrings) {
99
+ const DEFAULT_CELL_STYLE_INDEX = 0;
100
+ const PLAIN_NUMBER = { kind: "number" };
101
+ function readNumericFormatContext(pkg) {
102
+ return {
103
+ classes: require_typed_xlsx_styles.readCellFormatCodes(pkg).map((code) => code === void 0 ? PLAIN_NUMBER : require_typed_xlsx_number_format.classifyNumberFormat(code)),
104
+ date1904: require_typed_xlsx_serial.readDate1904(pkg)
105
+ };
106
+ }
107
+ function numberFormatOf(cell, context) {
108
+ const raw = require_typed_util.attr(cell, "s");
109
+ const index = raw === void 0 ? DEFAULT_CELL_STYLE_INDEX : Number.parseInt(raw, 10);
110
+ return (Number.isInteger(index) ? context.classes[index] : void 0) ?? PLAIN_NUMBER;
111
+ }
112
+ function resolveNumericValue(num, cell, context) {
113
+ const format = numberFormatOf(cell, context);
114
+ switch (format.kind) {
115
+ case "percentage": return {
116
+ kind: "percentage",
117
+ value: num
118
+ };
119
+ case "currency": return format.code === void 0 ? {
120
+ kind: "currency",
121
+ value: num
122
+ } : {
123
+ kind: "currency",
124
+ value: num,
125
+ currency: format.code
126
+ };
127
+ case "date": {
128
+ const iso = require_typed_xlsx_serial.serialToIsoDate(num, context.date1904);
129
+ return iso === void 0 ? {
130
+ kind: "number",
131
+ value: num
132
+ } : {
133
+ kind: "date",
134
+ value: iso
135
+ };
136
+ }
137
+ case "time": {
138
+ const iso = require_typed_xlsx_serial.serialToIsoTime(num);
139
+ return iso === void 0 ? {
140
+ kind: "number",
141
+ value: num
142
+ } : {
143
+ kind: "time",
144
+ value: iso
145
+ };
146
+ }
147
+ case "dateTime": {
148
+ const iso = require_typed_xlsx_serial.serialToIsoDateTime(num, context.date1904);
149
+ return iso === void 0 ? {
150
+ kind: "number",
151
+ value: num
152
+ } : {
153
+ kind: "dateTime",
154
+ value: iso
155
+ };
156
+ }
157
+ case "elapsedTime": return {
158
+ kind: "number",
159
+ value: num
160
+ };
161
+ case "text":
162
+ case "number": return {
163
+ kind: "number",
164
+ value: num
165
+ };
166
+ }
167
+ }
168
+ function readCellValue(cell, sharedStrings, numericFormats) {
97
169
  const type = require_typed_util.attr(cell, "t");
98
170
  if (type === "inlineStr") {
99
171
  const is = require_typed_util.childrenWithTag(cell, "is")[0];
@@ -153,22 +225,19 @@ function readCellValue(cell, sharedStrings) {
153
225
  };
154
226
  const num = Number(raw);
155
227
  if (Number.isNaN(num)) return;
156
- const value = {
157
- kind: "number",
158
- value: num
159
- };
228
+ const value = resolveNumericValue(num, cell, numericFormats);
160
229
  return {
161
230
  value,
162
231
  displayText: deriveDisplayText(value)
163
232
  };
164
233
  }
165
- function readCell(cell, sharedStrings) {
234
+ function readCell(cell, sharedStrings, numericFormats) {
166
235
  const reference = require_typed_util.attr(cell, "r");
167
236
  const position = reference === void 0 ? void 0 : require_typed_xlsx_a1.parseCellReference(reference);
168
237
  if (position === void 0) return;
169
238
  const formulaEl = require_typed_util.childrenWithTag(cell, "f")[0];
170
239
  const formula = formulaEl === void 0 ? void 0 : require_typed_util.textContent(formulaEl);
171
- const resolved = readCellValue(cell, sharedStrings);
240
+ const resolved = readCellValue(cell, sharedStrings, numericFormats);
172
241
  if (resolved === void 0) {
173
242
  if (formula === void 0) return;
174
243
  return {
@@ -205,18 +274,18 @@ function applyMergedRanges(worksheet, cells) {
205
274
  if (rowSpan > 1) anchor.rowSpan = rowSpan;
206
275
  }
207
276
  }
208
- function readCells(worksheet, sharedStrings) {
277
+ function readCells(worksheet, sharedStrings, numericFormats) {
209
278
  const sheetData = require_typed_util.childrenWithTag(worksheet, "sheetData")[0];
210
279
  if (sheetData === void 0) return [];
211
280
  const cells = [];
212
281
  for (const row of require_typed_util.childrenWithTag(sheetData, "row")) for (const cell of require_typed_util.childrenWithTag(row, "c")) {
213
- const read = readCell(cell, sharedStrings);
282
+ const read = readCell(cell, sharedStrings, numericFormats);
214
283
  if (read !== void 0) cells.push(read);
215
284
  }
216
285
  applyMergedRanges(worksheet, cells);
217
286
  return cells;
218
287
  }
219
- function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet) {
288
+ function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet, numericFormats) {
220
289
  const worksheet = require_typed_util.rootElement(pkg.parts[entry.path]);
221
290
  if (worksheet === void 0) return {
222
291
  name: entry.name,
@@ -228,7 +297,7 @@ function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet) {
228
297
  };
229
298
  return {
230
299
  name: entry.name,
231
- cells: readCells(worksheet, sharedStrings),
300
+ cells: readCells(worksheet, sharedStrings, numericFormats),
232
301
  columns: readColumns(worksheet),
233
302
  rows: readRows(worksheet),
234
303
  images: [],
@@ -246,7 +315,8 @@ function fallbackEmptyWorksheet() {
246
315
  function readXlsxContent(pkg) {
247
316
  const sharedStrings = require_typed_xlsx_shared_strings.loadSharedStrings(pkg);
248
317
  const definedNamesBySheet = require_typed_xlsx_defined_names.readDefinedNamesBySheet(pkg);
249
- const sheets = resolveSheetEntries(pkg).map((entry, sheetIndex) => readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet));
318
+ const numericFormats = readNumericFormatContext(pkg);
319
+ const sheets = resolveSheetEntries(pkg).map((entry, sheetIndex) => readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet, numericFormats));
250
320
  return {
251
321
  kind: "spreadsheet",
252
322
  formatVersion: document_schema_js.CONTENT_FORMAT_VERSION,
@@ -3,8 +3,11 @@ import { readCoreProperties } from "../shared/metadata.js";
3
3
  import { loadSharedStrings } from "./shared-strings.js";
4
4
  import { parseCellReference, parseRangeReference } from "./a1.js";
5
5
  import { readDefinedNamesBySheet } from "./defined-names.js";
6
+ import { classifyNumberFormat } from "./number-format.js";
6
7
  import { readXmlBool } from "./util.js";
7
8
  import { readPrintSettings } from "./print-settings.js";
9
+ import { readDate1904, serialToIsoDate, serialToIsoDateTime, serialToIsoTime } from "./serial.js";
10
+ import { readCellFormatCodes } from "./styles.js";
8
11
  import { columnWidthCharsToPt } from "./units.js";
9
12
  import { CONTENT_FORMAT_VERSION } from "document-schema.js";
10
13
  //#region src/typed/xlsx/content.ts
@@ -80,19 +83,88 @@ function readInlineOrSharedStringText(container) {
80
83
  }
81
84
  function deriveDisplayText(value) {
82
85
  switch (value.kind) {
83
- case "number": return String(value.value);
86
+ case "number":
87
+ case "percentage":
88
+ case "currency": return String(value.value);
84
89
  case "boolean": return value.value ? "TRUE" : "FALSE";
85
90
  case "string":
86
91
  case "error":
87
92
  case "date":
88
93
  case "time":
89
94
  case "dateTime": return value.value;
90
- case "percentage":
91
- case "currency": return String(value.value);
92
95
  case "empty": return "";
93
96
  }
94
97
  }
95
- function readCellValue(cell, sharedStrings) {
98
+ const DEFAULT_CELL_STYLE_INDEX = 0;
99
+ const PLAIN_NUMBER = { kind: "number" };
100
+ function readNumericFormatContext(pkg) {
101
+ return {
102
+ classes: readCellFormatCodes(pkg).map((code) => code === void 0 ? PLAIN_NUMBER : classifyNumberFormat(code)),
103
+ date1904: readDate1904(pkg)
104
+ };
105
+ }
106
+ function numberFormatOf(cell, context) {
107
+ const raw = attr(cell, "s");
108
+ const index = raw === void 0 ? DEFAULT_CELL_STYLE_INDEX : Number.parseInt(raw, 10);
109
+ return (Number.isInteger(index) ? context.classes[index] : void 0) ?? PLAIN_NUMBER;
110
+ }
111
+ function resolveNumericValue(num, cell, context) {
112
+ const format = numberFormatOf(cell, context);
113
+ switch (format.kind) {
114
+ case "percentage": return {
115
+ kind: "percentage",
116
+ value: num
117
+ };
118
+ case "currency": return format.code === void 0 ? {
119
+ kind: "currency",
120
+ value: num
121
+ } : {
122
+ kind: "currency",
123
+ value: num,
124
+ currency: format.code
125
+ };
126
+ case "date": {
127
+ const iso = serialToIsoDate(num, context.date1904);
128
+ return iso === void 0 ? {
129
+ kind: "number",
130
+ value: num
131
+ } : {
132
+ kind: "date",
133
+ value: iso
134
+ };
135
+ }
136
+ case "time": {
137
+ const iso = serialToIsoTime(num);
138
+ return iso === void 0 ? {
139
+ kind: "number",
140
+ value: num
141
+ } : {
142
+ kind: "time",
143
+ value: iso
144
+ };
145
+ }
146
+ case "dateTime": {
147
+ const iso = serialToIsoDateTime(num, context.date1904);
148
+ return iso === void 0 ? {
149
+ kind: "number",
150
+ value: num
151
+ } : {
152
+ kind: "dateTime",
153
+ value: iso
154
+ };
155
+ }
156
+ case "elapsedTime": return {
157
+ kind: "number",
158
+ value: num
159
+ };
160
+ case "text":
161
+ case "number": return {
162
+ kind: "number",
163
+ value: num
164
+ };
165
+ }
166
+ }
167
+ function readCellValue(cell, sharedStrings, numericFormats) {
96
168
  const type = attr(cell, "t");
97
169
  if (type === "inlineStr") {
98
170
  const is = childrenWithTag(cell, "is")[0];
@@ -152,22 +224,19 @@ function readCellValue(cell, sharedStrings) {
152
224
  };
153
225
  const num = Number(raw);
154
226
  if (Number.isNaN(num)) return;
155
- const value = {
156
- kind: "number",
157
- value: num
158
- };
227
+ const value = resolveNumericValue(num, cell, numericFormats);
159
228
  return {
160
229
  value,
161
230
  displayText: deriveDisplayText(value)
162
231
  };
163
232
  }
164
- function readCell(cell, sharedStrings) {
233
+ function readCell(cell, sharedStrings, numericFormats) {
165
234
  const reference = attr(cell, "r");
166
235
  const position = reference === void 0 ? void 0 : parseCellReference(reference);
167
236
  if (position === void 0) return;
168
237
  const formulaEl = childrenWithTag(cell, "f")[0];
169
238
  const formula = formulaEl === void 0 ? void 0 : textContent(formulaEl);
170
- const resolved = readCellValue(cell, sharedStrings);
239
+ const resolved = readCellValue(cell, sharedStrings, numericFormats);
171
240
  if (resolved === void 0) {
172
241
  if (formula === void 0) return;
173
242
  return {
@@ -204,18 +273,18 @@ function applyMergedRanges(worksheet, cells) {
204
273
  if (rowSpan > 1) anchor.rowSpan = rowSpan;
205
274
  }
206
275
  }
207
- function readCells(worksheet, sharedStrings) {
276
+ function readCells(worksheet, sharedStrings, numericFormats) {
208
277
  const sheetData = childrenWithTag(worksheet, "sheetData")[0];
209
278
  if (sheetData === void 0) return [];
210
279
  const cells = [];
211
280
  for (const row of childrenWithTag(sheetData, "row")) for (const cell of childrenWithTag(row, "c")) {
212
- const read = readCell(cell, sharedStrings);
281
+ const read = readCell(cell, sharedStrings, numericFormats);
213
282
  if (read !== void 0) cells.push(read);
214
283
  }
215
284
  applyMergedRanges(worksheet, cells);
216
285
  return cells;
217
286
  }
218
- function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet) {
287
+ function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet, numericFormats) {
219
288
  const worksheet = rootElement(pkg.parts[entry.path]);
220
289
  if (worksheet === void 0) return {
221
290
  name: entry.name,
@@ -227,7 +296,7 @@ function readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet) {
227
296
  };
228
297
  return {
229
298
  name: entry.name,
230
- cells: readCells(worksheet, sharedStrings),
299
+ cells: readCells(worksheet, sharedStrings, numericFormats),
231
300
  columns: readColumns(worksheet),
232
301
  rows: readRows(worksheet),
233
302
  images: [],
@@ -245,7 +314,8 @@ function fallbackEmptyWorksheet() {
245
314
  function readXlsxContent(pkg) {
246
315
  const sharedStrings = loadSharedStrings(pkg);
247
316
  const definedNamesBySheet = readDefinedNamesBySheet(pkg);
248
- const sheets = resolveSheetEntries(pkg).map((entry, sheetIndex) => readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet));
317
+ const numericFormats = readNumericFormatContext(pkg);
318
+ const sheets = resolveSheetEntries(pkg).map((entry, sheetIndex) => readSheet(pkg, entry, sheetIndex, sharedStrings, definedNamesBySheet, numericFormats));
249
319
  return {
250
320
  kind: "spreadsheet",
251
321
  formatVersion: CONTENT_FORMAT_VERSION,