@extend-ai/react-xlsx 0.16.1 → 0.16.3

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.
@@ -3808,6 +3808,7 @@ function parseWorkbookStyles(archive) {
3808
3808
  const xml = readArchiveText2(archive, "xl/styles.xml");
3809
3809
  if (!xml) {
3810
3810
  return {
3811
+ differentialStyles: [],
3811
3812
  defaultFont: null,
3812
3813
  namedCellStyleByName: {},
3813
3814
  styleById: {},
@@ -3817,6 +3818,7 @@ function parseWorkbookStyles(archive) {
3817
3818
  const document2 = parseXml2(xml);
3818
3819
  if (!document2) {
3819
3820
  return {
3821
+ differentialStyles: [],
3820
3822
  defaultFont: null,
3821
3823
  namedCellStyleByName: {},
3822
3824
  styleById: {},
@@ -3833,6 +3835,7 @@ function parseWorkbookStyles(archive) {
3833
3835
  const tableStylesNode = getFirstDescendant(document2, "tableStyles");
3834
3836
  if (!cellXfsNode) {
3835
3837
  return {
3838
+ differentialStyles: [],
3836
3839
  defaultFont: null,
3837
3840
  namedCellStyleByName: {},
3838
3841
  styleById: {},
@@ -3889,6 +3892,7 @@ function parseWorkbookStyles(archive) {
3889
3892
  sizePt: typeof normalFont.size === "number" ? normalFont.size : void 0
3890
3893
  } : null;
3891
3894
  return {
3895
+ differentialStyles,
3892
3896
  defaultFont,
3893
3897
  namedCellStyleByName,
3894
3898
  styleById,
@@ -3929,10 +3933,11 @@ function parseSpreadsheetBooleanAttribute(node, name) {
3929
3933
  }
3930
3934
  return value !== "0" && value !== "false";
3931
3935
  }
3932
- function parseStandardConditionalFormatRule(cfRuleNode, ranges) {
3936
+ function parseStandardConditionalFormatRule(cfRuleNode, ranges, differentialStyles = []) {
3933
3937
  const type = cfRuleNode.getAttribute("type");
3934
3938
  const rawPriority = Number(cfRuleNode.getAttribute("priority") ?? Number.NaN);
3935
3939
  const priority = Number.isFinite(rawPriority) ? rawPriority : Number.MAX_SAFE_INTEGER;
3940
+ const formulas = getChildElements(cfRuleNode, "formula").map((formulaNode) => (formulaNode.textContent ?? "").trim()).filter((formula) => formula.length > 0);
3936
3941
  if (type === "colorScale") {
3937
3942
  const colorScaleNode = getFirstChild(cfRuleNode, "colorScale");
3938
3943
  if (!colorScaleNode) {
@@ -3993,7 +3998,34 @@ function parseStandardConditionalFormatRule(cfRuleNode, ranges) {
3993
3998
  showValue: parseSpreadsheetBooleanAttribute(iconSetNode, "showValue")
3994
3999
  };
3995
4000
  }
3996
- return null;
4001
+ const rawDxfId = Number(cfRuleNode.getAttribute("dxfId") ?? Number.NaN);
4002
+ if (!type || !Number.isFinite(rawDxfId)) {
4003
+ return null;
4004
+ }
4005
+ const style = differentialStyles[rawDxfId];
4006
+ if (!style) {
4007
+ return null;
4008
+ }
4009
+ const rawRank = Number(cfRuleNode.getAttribute("rank") ?? Number.NaN);
4010
+ const rawStdDev = Number(cfRuleNode.getAttribute("stdDev") ?? Number.NaN);
4011
+ return {
4012
+ aboveAverage: parseSpreadsheetBooleanAttribute(cfRuleNode, "aboveAverage"),
4013
+ bottom: parseSpreadsheetBooleanAttribute(cfRuleNode, "bottom"),
4014
+ equalAverage: parseSpreadsheetBooleanAttribute(cfRuleNode, "equalAverage"),
4015
+ formulas,
4016
+ kind: "styled",
4017
+ operator: cfRuleNode.getAttribute("operator") ?? void 0,
4018
+ percent: parseSpreadsheetBooleanAttribute(cfRuleNode, "percent"),
4019
+ priority,
4020
+ rank: Number.isFinite(rawRank) ? rawRank : void 0,
4021
+ ranges,
4022
+ ruleType: type,
4023
+ stdDev: Number.isFinite(rawStdDev) ? rawStdDev : void 0,
4024
+ stopIfTrue: parseSpreadsheetBooleanAttribute(cfRuleNode, "stopIfTrue"),
4025
+ style,
4026
+ text: cfRuleNode.getAttribute("text") ?? void 0,
4027
+ timePeriod: cfRuleNode.getAttribute("timePeriod") ?? void 0
4028
+ };
3997
4029
  }
3998
4030
  function parseExtendedConditionalFormatRule(cfRuleNode, ranges) {
3999
4031
  const type = cfRuleNode.getAttribute("type");
@@ -4104,14 +4136,14 @@ function mergeConditionalFormatRule(baseRule, extendedRule) {
4104
4136
  }
4105
4137
  return baseRule;
4106
4138
  }
4107
- function parseConditionalFormatRules(document2) {
4139
+ function parseConditionalFormatRules(document2, differentialStyles = []) {
4108
4140
  const standardRules = [];
4109
4141
  const extendedRules = [];
4110
4142
  getLocalElements(document2, "conditionalFormatting").forEach((conditionalFormattingNode) => {
4111
4143
  const isExtended = conditionalFormattingNode.namespaceURI !== SPREADSHEET_NS;
4112
4144
  const ranges = isExtended ? parseSqrefRanges(getFirstChild(conditionalFormattingNode, "sqref")?.textContent ?? "") : parseSqrefRanges(conditionalFormattingNode.getAttribute("sqref"));
4113
4145
  getChildElements(conditionalFormattingNode, "cfRule").forEach((cfRuleNode) => {
4114
- const parsedRule = isExtended ? parseExtendedConditionalFormatRule(cfRuleNode, ranges) : parseStandardConditionalFormatRule(cfRuleNode, ranges);
4146
+ const parsedRule = isExtended ? parseExtendedConditionalFormatRule(cfRuleNode, ranges) : parseStandardConditionalFormatRule(cfRuleNode, ranges, differentialStyles);
4115
4147
  if (parsedRule) {
4116
4148
  if (isExtended) {
4117
4149
  extendedRules.push(parsedRule);
@@ -4157,8 +4189,9 @@ function parseSheetState(archive, path, options) {
4157
4189
  return null;
4158
4190
  }
4159
4191
  const includeCachedFormulaValues = options?.includeCachedFormulaValues ?? true;
4192
+ const autoFilterRanges = parseSqrefRanges(getLocalElements(document2, "autoFilter")[0]?.getAttribute("ref"));
4160
4193
  const cachedFormulaValues = {};
4161
- const conditionalFormatRules = parseConditionalFormatRules(document2);
4194
+ const conditionalFormatRules = parseConditionalFormatRules(document2, options?.differentialStyles ?? []);
4162
4195
  const sparklines = parseSheetSparklines(document2, options?.themePalette);
4163
4196
  const sheetFormatNode = getLocalElements(document2, "sheetFormatPr")[0] ?? null;
4164
4197
  const sheetViewNode = getLocalElements(document2, "sheetView")[0] ?? null;
@@ -4250,6 +4283,7 @@ function parseSheetState(archive, path, options) {
4250
4283
  }
4251
4284
  });
4252
4285
  return {
4286
+ autoFilterRanges,
4253
4287
  cachedFormulaValues,
4254
4288
  columnWidthCharacterWidthPx,
4255
4289
  colWidthOverridesPx,
@@ -4461,9 +4495,7 @@ function mapDukeFormControlKind(kind, themePalette) {
4461
4495
  ...resolveDukeDrawingText(kind.caption, themePalette),
4462
4496
  kind: kind.objectType.toLowerCase() === "editbox" ? "editbox" : "unknown",
4463
4497
  legacyObjectType: kind.legacyObjectType,
4464
- objectType: kind.objectType,
4465
- rawObj: kind.rawObj,
4466
- rawProperties: kind.rawProperties
4498
+ objectType: kind.objectType
4467
4499
  };
4468
4500
  }
4469
4501
  }
@@ -4480,6 +4512,8 @@ function mapDukeFormControl(control, controlIndex, workbookSheetIndex, themePale
4480
4512
  name: control.name,
4481
4513
  printable: control.printable,
4482
4514
  rawClientData: control.formControl.rawClientData,
4515
+ rawObj: control.formControl.rawObj,
4516
+ rawProperties: control.formControl.rawProperties,
4483
4517
  sheetIndex: workbookSheetIndex,
4484
4518
  title: control.title,
4485
4519
  workbookSheetIndex,
@@ -4509,12 +4543,13 @@ function parseWorkbookStructureAssetsFromArchive(archive, options) {
4509
4543
  const workbookSheets = parseWorkbookSheets(archive);
4510
4544
  const theme = parseWorkbookTheme(archive);
4511
4545
  const themePalette = buildThemePalette(theme);
4512
- const { defaultFont, namedCellStyleByName, styleById, tableStyleByName } = parseWorkbookStyles(archive);
4546
+ const { defaultFont, differentialStyles, namedCellStyleByName, styleById, tableStyleByName } = parseWorkbookStyles(archive);
4513
4547
  return {
4514
4548
  contentTypes,
4515
4549
  namedCellStyleByName,
4516
4550
  sheetStatesByWorkbookSheetIndex: workbookSheets.map((sheet) => parseSheetState(archive, sheet.path, {
4517
4551
  ...options,
4552
+ differentialStyles,
4518
4553
  defaultFont,
4519
4554
  themePalette
4520
4555
  })),
@@ -5011,6 +5046,7 @@ function buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHi
5011
5046
  const usedRange = worksheet.usedRange();
5012
5047
  if (!usedRange) {
5013
5048
  sheetsByWorkbookSheetIndex.push({
5049
+ autoFilterRanges: sheetState?.autoFilterRanges ?? [],
5014
5050
  cachedFormulaValues: sheetState?.cachedFormulaValues ?? {},
5015
5051
  columnWidthCharacterWidthPx: sheetState?.columnWidthCharacterWidthPx,
5016
5052
  colCount: 0,
@@ -5071,6 +5107,7 @@ function buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHi
5071
5107
  }
5072
5108
  }
5073
5109
  sheetsByWorkbookSheetIndex.push({
5110
+ autoFilterRanges: sheetState?.autoFilterRanges ?? [],
5074
5111
  cachedFormulaValues: sheetState?.cachedFormulaValues ?? {},
5075
5112
  columnWidthCharacterWidthPx: sheetState?.columnWidthCharacterWidthPx,
5076
5113
  colCount: visibleCols.length,
@@ -5112,9 +5149,9 @@ function buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHi
5112
5149
  }
5113
5150
  return sheetsByWorkbookSheetIndex;
5114
5151
  }
5115
- function mapWorksheetTables(worksheet) {
5152
+ function mapWorksheetTables(worksheet, autoFilterRanges = []) {
5116
5153
  const rawTables = worksheet?.tables ?? [];
5117
- return rawTables.flatMap((table, index) => {
5154
+ const mappedTables = rawTables.flatMap((table, index) => {
5118
5155
  const rawColumns = Array.isArray(table.columns) ? table.columns : [];
5119
5156
  const rawName = typeof table.name === "string" ? table.name : `Table${index + 1}`;
5120
5157
  const rawDisplayName = typeof table.displayName === "string" ? table.displayName : typeof table.name === "string" ? table.name : `Table ${index + 1}`;
@@ -5142,6 +5179,34 @@ function mapWorksheetTables(worksheet) {
5142
5179
  totalsRowShown: resolveWorkbookTableBoolean(table.totalsRowShown)
5143
5180
  }];
5144
5181
  });
5182
+ const existingReferences = new Set(mappedTables.map((table) => table.reference));
5183
+ const mappedAutoFilterTables = autoFilterRanges.flatMap((range, index) => {
5184
+ const reference = `${cellAddressToA1(range.start)}:${cellAddressToA1(range.end)}`;
5185
+ if (existingReferences.has(reference)) {
5186
+ return [];
5187
+ }
5188
+ const columnCount = Math.max(0, range.end.col - range.start.col + 1);
5189
+ const columns = Array.from({ length: columnCount }, (_, columnIndex) => {
5190
+ const headerValue = worksheet ? decodeHtmlEntities(worksheet.getFormattedValueAt(range.start.row, range.start.col + columnIndex) ?? "") : "";
5191
+ return {
5192
+ id: columnIndex + 1,
5193
+ index: columnIndex,
5194
+ name: headerValue.trim().length > 0 ? headerValue : `Column ${columnIndex + 1}`
5195
+ };
5196
+ });
5197
+ return [{
5198
+ columns,
5199
+ displayName: `AutoFilter ${index + 1}`,
5200
+ end: range.end,
5201
+ headerRowCount: 1,
5202
+ name: `__autofilter_${index + 1}_${reference}`,
5203
+ reference,
5204
+ start: range.start,
5205
+ totalsRowCount: 0,
5206
+ totalsRowShown: false
5207
+ }];
5208
+ });
5209
+ return [...mappedTables, ...mappedAutoFilterTables];
5145
5210
  }
5146
5211
  function resolveWorkbookTableCount(value, fallback) {
5147
5212
  if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
@@ -5239,7 +5304,10 @@ async function loadWorkbook(buffer, skipXmlParsing = false, showHiddenSheets = f
5239
5304
  sheets = buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHiddenSheets);
5240
5305
  tablesByWorkbookSheetIndex = Array.from(
5241
5306
  { length: nextWorkbook.sheetCount },
5242
- (_, workbookSheetIndex) => mapWorksheetTables(nextWorkbook.getSheet(workbookSheetIndex))
5307
+ (_, workbookSheetIndex) => mapWorksheetTables(
5308
+ nextWorkbook.getSheet(workbookSheetIndex),
5309
+ structureAssets?.sheetStatesByWorkbookSheetIndex[workbookSheetIndex]?.autoFilterRanges ?? []
5310
+ )
5243
5311
  );
5244
5312
  const visibleSheetIndexByWorkbookSheetIndex = new Map(sheets.map((sheet, index) => [sheet.workbookSheetIndex, index]));
5245
5313
  const hasCharts = Array.from({ length: nextWorkbook.sheetCount }, (_, workbookSheetIndex) => {