@extend-ai/react-xlsx 0.8.0 → 0.8.2

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.
@@ -3813,13 +3813,36 @@ function parseWorkbookTableMetadata(archive, workbookSheets) {
3813
3813
  }
3814
3814
  return [{
3815
3815
  displayName: tableNode.getAttribute("displayName") ?? void 0,
3816
+ headerRowCount: parseWorkbookTableCount(tableNode.getAttribute("headerRowCount"), 1),
3816
3817
  headerRowCellStyle: tableNode.getAttribute("headerRowCellStyle") ?? void 0,
3817
3818
  name: tableNode.getAttribute("name") ?? void 0,
3818
- reference: tableNode.getAttribute("ref") ?? void 0
3819
+ reference: tableNode.getAttribute("ref") ?? void 0,
3820
+ totalsRowCount: parseWorkbookTableCount(tableNode.getAttribute("totalsRowCount"), 0),
3821
+ totalsRowShown: parseWorkbookTableBoolean(tableNode.getAttribute("totalsRowShown"), false)
3819
3822
  }];
3820
3823
  });
3821
3824
  });
3822
3825
  }
3826
+ function parseWorkbookTableCount(value, fallback) {
3827
+ if (value === null) {
3828
+ return fallback;
3829
+ }
3830
+ const parsed = Number.parseInt(value, 10);
3831
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
3832
+ }
3833
+ function parseWorkbookTableBoolean(value, fallback) {
3834
+ if (value === null) {
3835
+ return fallback;
3836
+ }
3837
+ const normalized = value.trim().toLowerCase();
3838
+ if (normalized === "0" || normalized === "false" || normalized === "") {
3839
+ return false;
3840
+ }
3841
+ if (normalized === "1" || normalized === "true") {
3842
+ return true;
3843
+ }
3844
+ return fallback;
3845
+ }
3823
3846
  function parseSqrefRanges(sqref) {
3824
3847
  if (!sqref) {
3825
3848
  return [];
@@ -4285,6 +4308,75 @@ function resolveSheetColumnWidthPixels(width, columnWidthCharacterWidthPx) {
4285
4308
  return sheetColumnWidthToPixels(width, columnWidthCharacterWidthPx);
4286
4309
  }
4287
4310
 
4311
+ // src/safe-calculate.ts
4312
+ var SHEET_REF_REGEX = /'((?:[^']|'')+)'!|([A-Za-z_\u0080-\uFFFF][\w.\u0080-\uFFFF]*)!/g;
4313
+ function collectReferencedSheetNames(workbook2) {
4314
+ const referenced = /* @__PURE__ */ new Set();
4315
+ for (let sheetIdx = 0; sheetIdx < workbook2.sheetCount; sheetIdx += 1) {
4316
+ let sheet;
4317
+ try {
4318
+ sheet = workbook2.getSheet(sheetIdx);
4319
+ } catch {
4320
+ continue;
4321
+ }
4322
+ const cells = sheet.formulaCells;
4323
+ if (!Array.isArray(cells)) {
4324
+ continue;
4325
+ }
4326
+ for (const cell of cells) {
4327
+ const formula = cell?.formula;
4328
+ if (!formula) {
4329
+ continue;
4330
+ }
4331
+ SHEET_REF_REGEX.lastIndex = 0;
4332
+ let match;
4333
+ while ((match = SHEET_REF_REGEX.exec(formula)) !== null) {
4334
+ const raw = match[1] ?? match[2];
4335
+ if (!raw) {
4336
+ continue;
4337
+ }
4338
+ referenced.add(raw.replace(/''/g, "'"));
4339
+ }
4340
+ }
4341
+ }
4342
+ return referenced;
4343
+ }
4344
+ function hasUnresolvedSheetReferences(workbook2) {
4345
+ let names;
4346
+ try {
4347
+ names = workbook2.sheetNames;
4348
+ } catch {
4349
+ return false;
4350
+ }
4351
+ const known = new Set(names);
4352
+ const referenced = collectReferencedSheetNames(workbook2);
4353
+ for (const name of referenced) {
4354
+ if (!known.has(name)) {
4355
+ return true;
4356
+ }
4357
+ }
4358
+ return false;
4359
+ }
4360
+ function safeCalculate(workbook2, options = {}) {
4361
+ if (hasUnresolvedSheetReferences(workbook2)) {
4362
+ return { workbook: workbook2, calculated: false, skipReason: "unresolved-sheet-refs" };
4363
+ }
4364
+ try {
4365
+ workbook2.calculate();
4366
+ return { workbook: workbook2, calculated: true, skipReason: null };
4367
+ } catch (err) {
4368
+ console.warn("[react-xlsx] workbook.calculate() trapped; falling back to cached formula values", err);
4369
+ if (options.reparse) {
4370
+ try {
4371
+ return { workbook: options.reparse(), calculated: false, skipReason: "calculate-trapped" };
4372
+ } catch (reparseErr) {
4373
+ console.warn("[react-xlsx] workbook reparse after calculate trap failed", reparseErr);
4374
+ }
4375
+ }
4376
+ return { workbook: workbook2, calculated: false, skipReason: "calculate-trapped" };
4377
+ }
4378
+ }
4379
+
4288
4380
  // src/wasm.ts
4289
4381
  var wasmModulePromise = null;
4290
4382
  function getSheetsWasmModule() {
@@ -4539,17 +4631,18 @@ function buildSheetList(nextWorkbook, structureAssets, showHiddenSheets = false)
4539
4631
  function mapWorksheetTables(worksheet, metadataForSheet) {
4540
4632
  const rawTables = worksheet?.tables ?? [];
4541
4633
  return rawTables.flatMap((table, index) => {
4542
- const reference = typeof table.reference === "string" ? table.reference : "";
4543
- const parsedRange = parseA1RangeReference2(reference);
4544
- if (!parsedRange) {
4545
- return [];
4546
- }
4547
4634
  const rawColumns = Array.isArray(table.columns) ? table.columns : [];
4548
4635
  const rawName = typeof table.name === "string" ? table.name : `Table${index + 1}`;
4549
4636
  const rawDisplayName = typeof table.displayName === "string" ? table.displayName : typeof table.name === "string" ? table.name : `Table ${index + 1}`;
4550
4637
  const metadata = metadataForSheet?.find(
4551
- (entry) => entry.name && entry.name === rawName || entry.displayName && entry.displayName === rawDisplayName || entry.reference && entry.reference === reference
4638
+ (entry) => entry.name && entry.name === rawName || entry.displayName && entry.displayName === rawDisplayName || entry.reference && entry.reference === table.reference
4552
4639
  );
4640
+ const rawReference = typeof table.reference === "string" ? table.reference : "";
4641
+ const reference = metadata?.reference ?? rawReference;
4642
+ const parsedRange = parseA1RangeReference2(reference);
4643
+ if (!parsedRange) {
4644
+ return [];
4645
+ }
4553
4646
  return [{
4554
4647
  columns: rawColumns.map((column, columnIndex) => ({
4555
4648
  id: typeof column.id === "number" ? column.id ?? columnIndex + 1 : columnIndex + 1,
@@ -4558,17 +4651,47 @@ function mapWorksheetTables(worksheet, metadataForSheet) {
4558
4651
  })),
4559
4652
  displayName: rawDisplayName,
4560
4653
  end: parsedRange.end,
4561
- headerRowCount: typeof table.headerRowCount === "number" ? table.headerRowCount : 1,
4654
+ headerRowCount: metadata?.headerRowCount ?? resolveWorkbookTableCount(table.headerRowCount, 1),
4562
4655
  headerRowCellStyle: metadata?.headerRowCellStyle,
4563
4656
  name: rawName,
4564
4657
  reference,
4565
4658
  start: parsedRange.start,
4566
4659
  styleInfo: table.styleInfo,
4567
- totalsRowCount: typeof table.totalsRowCount === "number" ? table.totalsRowCount : 0,
4568
- totalsRowShown: Boolean(table.totalsRowShown)
4660
+ totalsRowCount: metadata?.totalsRowCount ?? resolveWorkbookTableCount(table.totalsRowCount, 0),
4661
+ totalsRowShown: metadata?.totalsRowShown ?? resolveWorkbookTableBoolean(table.totalsRowShown)
4569
4662
  }];
4570
4663
  });
4571
4664
  }
4665
+ function resolveWorkbookTableCount(value, fallback) {
4666
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
4667
+ return value;
4668
+ }
4669
+ if (typeof value === "string") {
4670
+ const parsed = Number.parseInt(value, 10);
4671
+ if (Number.isFinite(parsed) && parsed >= 0) {
4672
+ return parsed;
4673
+ }
4674
+ }
4675
+ return fallback;
4676
+ }
4677
+ function resolveWorkbookTableBoolean(value) {
4678
+ if (typeof value === "boolean") {
4679
+ return value;
4680
+ }
4681
+ if (typeof value === "number") {
4682
+ return value !== 0;
4683
+ }
4684
+ if (typeof value === "string") {
4685
+ const normalized = value.trim().toLowerCase();
4686
+ if (normalized === "0" || normalized === "false" || normalized === "") {
4687
+ return false;
4688
+ }
4689
+ if (normalized === "1" || normalized === "true") {
4690
+ return true;
4691
+ }
4692
+ }
4693
+ return false;
4694
+ }
4572
4695
  function decodeHtmlEntities(value) {
4573
4696
  return value.replace(/&quot;/g, '"').replace(/&#34;/g, '"').replace(/&apos;/g, "'").replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
4574
4697
  }
@@ -4605,14 +4728,18 @@ async function loadWorkbook(buffer, skipXmlParsing = false, showHiddenSheets = f
4605
4728
  const wasmModule = await getSheetsWasmModule();
4606
4729
  const bytes = new Uint8Array(buffer);
4607
4730
  const effectiveSkipXmlParsing = shouldSkipXmlParsingForWorkbook(bytes, skipXmlParsing);
4608
- const nextWorkbook = wasmModule.Workbook.fromBytes(bytes);
4731
+ let activeWorkbook = wasmModule.Workbook.fromBytes(bytes);
4609
4732
  let totalFormulas = 0;
4610
- for (let index = 0; index < nextWorkbook.sheetCount; index += 1) {
4611
- totalFormulas += nextWorkbook.getSheet(index).formulaCount;
4733
+ for (let index = 0; index < activeWorkbook.sheetCount; index += 1) {
4734
+ totalFormulas += activeWorkbook.getSheet(index).formulaCount;
4612
4735
  }
4613
4736
  if (totalFormulas <= FORMULA_COUNT_THRESHOLD) {
4614
- nextWorkbook.calculate();
4737
+ const result = safeCalculate(activeWorkbook, {
4738
+ reparse: () => wasmModule.Workbook.fromBytes(bytes)
4739
+ });
4740
+ activeWorkbook = result.workbook;
4615
4741
  }
4742
+ const nextWorkbook = activeWorkbook;
4616
4743
  const shouldUseFastStructureParse = bytes.byteLength >= FAST_STRUCTURE_PARSE_THRESHOLD_BYTES && totalFormulas <= FORMULA_COUNT_THRESHOLD;
4617
4744
  const structureAssets = effectiveSkipXmlParsing || shouldUseFastStructureParse ? null : parseWorkbookStructureAssets(bytes, {
4618
4745
  includeCachedFormulaValues: true
@@ -4655,14 +4782,18 @@ async function parseCharts(buffer, skipXmlParsing = false, showHiddenSheets = fa
4655
4782
  const wasmModule = await getSheetsWasmModule();
4656
4783
  const bytes = new Uint8Array(buffer);
4657
4784
  const effectiveSkipXmlParsing = shouldSkipXmlParsingForWorkbook(bytes, skipXmlParsing);
4658
- const nextWorkbook = wasmModule.Workbook.fromBytes(bytes);
4785
+ let activeWorkbook = wasmModule.Workbook.fromBytes(bytes);
4659
4786
  let totalFormulas = 0;
4660
- for (let index = 0; index < nextWorkbook.sheetCount; index += 1) {
4661
- totalFormulas += nextWorkbook.getSheet(index).formulaCount;
4787
+ for (let index = 0; index < activeWorkbook.sheetCount; index += 1) {
4788
+ totalFormulas += activeWorkbook.getSheet(index).formulaCount;
4662
4789
  }
4663
4790
  if (totalFormulas <= FORMULA_COUNT_THRESHOLD) {
4664
- nextWorkbook.calculate();
4791
+ const result = safeCalculate(activeWorkbook, {
4792
+ reparse: () => wasmModule.Workbook.fromBytes(bytes)
4793
+ });
4794
+ activeWorkbook = result.workbook;
4665
4795
  }
4796
+ const nextWorkbook = activeWorkbook;
4666
4797
  const visibleSheetIndexByWorkbookSheetIndex = buildVisibleSheetIndexByWorkbookSheetIndex(nextWorkbook, showHiddenSheets);
4667
4798
  const chartStyleAssets = effectiveSkipXmlParsing ? null : parseWorkbookChartStyleAssets(bytes);
4668
4799
  const chartAssets = loadWorkbookChartAssets(