@office-open/xlsx 0.12.1 → 0.12.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.
package/dist/index.mjs CHANGED
@@ -2917,6 +2917,18 @@ function letterToColumn(letters) {
2917
2917
  for (let i = 0; i < letters.length; i++) col = col * 26 + (letters.charCodeAt(i) - 64);
2918
2918
  return col;
2919
2919
  }
2920
+ const A1_CELL = /^([A-Z]+)(\d+)$/;
2921
+ /**
2922
+ * Parse a single A1 cell reference ("B12") into 1-based column/row numbers.
2923
+ * Returns undefined when the reference is not letters-then-digits.
2924
+ */
2925
+ function parseA1Cell(ref) {
2926
+ const m = ref.match(A1_CELL);
2927
+ return m ? {
2928
+ col: letterToColumn(m[1]),
2929
+ row: parseInt(m[2], 10)
2930
+ } : void 0;
2931
+ }
2920
2932
  /**
2921
2933
  * Convert a JavaScript Date to an Excel serial number.
2922
2934
  * Excel epoch: January 1, 1900 = 1 (with the 1900 leap year bug).
@@ -3049,31 +3061,44 @@ function parseOlapPr(el) {
3049
3061
  if (String(attr(el, "serverFontColor")) === "0") ol.serverFontColor = false;
3050
3062
  return Object.keys(ol).length > 0 ? ol : void 0;
3051
3063
  }
3064
+ const profileCache = /* @__PURE__ */ new WeakMap();
3052
3065
  /**
3053
- * Extract unique values from source data for a given field index.
3066
+ * Profile every field of the source records in one pass numericity, unique
3067
+ * values, and numeric min/max/integer flags together. Memoized per source
3068
+ * object so the cache-definition and cache-records stringifiers share a
3069
+ * single scan instead of each re-walking the records per field.
3054
3070
  */
3055
- function collectUniqueValues(records, fieldIdx) {
3056
- const seen = /* @__PURE__ */ new Set();
3057
- const result = [];
3058
- for (const row of records) {
3059
- const val = row[fieldIdx];
3071
+ function profilePivotFields(sourceData) {
3072
+ const cached = profileCache.get(sourceData);
3073
+ if (cached !== void 0) return cached;
3074
+ const cols = sourceData.fieldNames.map(() => ({
3075
+ profile: {
3076
+ numeric: true,
3077
+ unique: [],
3078
+ min: Infinity,
3079
+ max: -Infinity,
3080
+ allInteger: true
3081
+ },
3082
+ seen: /* @__PURE__ */ new Set()
3083
+ }));
3084
+ for (const row of sourceData.records) for (let i = 0; i < cols.length; i++) {
3085
+ const col = cols[i];
3086
+ const val = row[i];
3087
+ if (typeof val === "string" && val !== "") col.profile.numeric = false;
3060
3088
  const key = val instanceof Date ? val.toISOString() : String(val);
3061
- if (!seen.has(key)) {
3062
- seen.add(key);
3063
- result.push(val ?? null);
3089
+ if (!col.seen.has(key)) {
3090
+ col.seen.add(key);
3091
+ col.profile.unique.push(val ?? null);
3064
3092
  }
3093
+ if (typeof val === "number") {
3094
+ if (val < col.profile.min) col.profile.min = val;
3095
+ if (val > col.profile.max) col.profile.max = val;
3096
+ if (!Number.isInteger(val)) col.profile.allInteger = false;
3097
+ } else col.profile.allInteger = false;
3065
3098
  }
3066
- return result;
3067
- }
3068
- /**
3069
- * Check if a field is numeric (all non-empty values are numbers).
3070
- */
3071
- function isNumericField(records, fieldIdx) {
3072
- for (const row of records) {
3073
- const val = row[fieldIdx];
3074
- if (typeof val === "string" && val !== "") return false;
3075
- }
3076
- return true;
3099
+ const profiles = cols.map((c) => c.profile);
3100
+ profileCache.set(sourceData, profiles);
3101
+ return profiles;
3077
3102
  }
3078
3103
  /**
3079
3104
  * Aggregate values using the specified function.
@@ -3326,6 +3351,7 @@ function buildFieldOverrideAttrs(fo) {
3326
3351
  }
3327
3352
  function buildPivotFields(o, sd, rowIndices, colIndices, dataIndices, pageIndices) {
3328
3353
  const fieldNames = sd.fieldNames;
3354
+ const profiles = profilePivotFields(sd);
3329
3355
  const parts = [`<pivotFields count="${fieldNames.length}">`];
3330
3356
  for (let i = 0; i < fieldNames.length; i++) {
3331
3357
  const isRow = rowIndices.includes(i);
@@ -3345,7 +3371,7 @@ function buildPivotFields(o, sd, rowIndices, colIndices, dataIndices, pageIndice
3345
3371
  if (o.autoSortScope) parts.push(`<pivotField ${dfAttrs.join(" ")}><autoSortScope>${buildPivotAreaXml(o.autoSortScope)}</autoSortScope></pivotField>`);
3346
3372
  else parts.push(`<pivotField ${dfAttrs.join(" ")}/>`);
3347
3373
  } else if (isRow) {
3348
- const uniqueVals = collectUniqueValues(sd.records, i);
3374
+ const uniqueVals = profiles[i].unique;
3349
3375
  const rAttrs = extraAttrs ? ` axis="axisRow" showAll="0" ${extraAttrs}` : " axis=\"axisRow\" showAll=\"0\"";
3350
3376
  parts.push(`<pivotField${rAttrs}>`);
3351
3377
  parts.push(`<items count="${uniqueVals.length + 1}">`);
@@ -3353,7 +3379,7 @@ function buildPivotFields(o, sd, rowIndices, colIndices, dataIndices, pageIndice
3353
3379
  parts.push(`<item t="default"${override?.defaultItemSd === false ? " sd=\"0\"" : ""}/>`);
3354
3380
  parts.push("</items></pivotField>");
3355
3381
  } else if (isCol) {
3356
- const uniqueVals = collectUniqueValues(sd.records, i);
3382
+ const uniqueVals = profiles[i].unique;
3357
3383
  const cAttrs = extraAttrs ? ` axis="axisCol" showAll="0" ${extraAttrs}` : " axis=\"axisCol\" showAll=\"0\"";
3358
3384
  parts.push(`<pivotField${cAttrs}>`);
3359
3385
  parts.push(`<items count="${uniqueVals.length + 1}">`);
@@ -3361,7 +3387,7 @@ function buildPivotFields(o, sd, rowIndices, colIndices, dataIndices, pageIndice
3361
3387
  parts.push(`<item t="default"${override?.defaultItemSd === false ? " sd=\"0\"" : ""}/>`);
3362
3388
  parts.push("</items></pivotField>");
3363
3389
  } else if (isPage) {
3364
- const uniqueVals = collectUniqueValues(sd.records, i);
3390
+ const uniqueVals = profiles[i].unique;
3365
3391
  const pAttrs = extraAttrs ? ` axis="axisPage" showAll="0" ${extraAttrs}` : " axis=\"axisPage\" showAll=\"0\"";
3366
3392
  parts.push(`<pivotField${pAttrs}>`);
3367
3393
  parts.push(`<items count="${uniqueVals.length + 1}">`);
@@ -3397,10 +3423,16 @@ function buildRowFields(rowIndices) {
3397
3423
  parts.push("</rowFields>");
3398
3424
  return parts.join("");
3399
3425
  }
3426
+ /** Unique-value count of field `idx`; an out-of-range index (an indexOf miss,
3427
+ * -1) keeps collectUniqueValues' behavior of a single null value. */
3428
+ function uniqueCount(profiles, idx) {
3429
+ return profiles[idx]?.unique.length ?? 1;
3430
+ }
3400
3431
  function buildRowItems(sd, rowIndices) {
3401
3432
  if (rowIndices.length === 0) return "<rowItems count=\"1\"><i/></rowItems>";
3433
+ const profiles = profilePivotFields(sd);
3402
3434
  const allUniqueCounts = [];
3403
- for (const idx of rowIndices) allUniqueCounts.push(collectUniqueValues(sd.records, idx).length);
3435
+ for (const idx of rowIndices) allUniqueCounts.push(uniqueCount(profiles, idx));
3404
3436
  if (rowIndices.length === 1) {
3405
3437
  const count = allUniqueCounts[0] ?? 0;
3406
3438
  const parts = [`<rowItems count="${count + 1}">`];
@@ -3424,8 +3456,9 @@ function buildColFields(colIndices) {
3424
3456
  }
3425
3457
  function buildColItems(sd, colIndices, dataFields) {
3426
3458
  if (colIndices.length > 0) {
3459
+ const profiles = profilePivotFields(sd);
3427
3460
  const allUniqueCounts = [];
3428
- for (const idx of colIndices) allUniqueCounts.push(collectUniqueValues(sd.records, idx).length);
3461
+ for (const idx of colIndices) allUniqueCounts.push(uniqueCount(profiles, idx));
3429
3462
  const combos = cartesianOfCounts(allUniqueCounts);
3430
3463
  const items = [];
3431
3464
  for (const combo of combos) items.push(`<i>${combo.map((v) => `<x v="${v}"/>`).join("")}</i>`);
@@ -3458,20 +3491,20 @@ function buildDataFields(dataFields, dataFieldIndices) {
3458
3491
  return parts.join("");
3459
3492
  }
3460
3493
  function computeLocationRef(sd, location, rowFieldIndices, colFieldIndices, dataFields) {
3461
- const match = (location.split(":")[0] ?? location).match(/^([A-Z]+)(\d+)$/);
3462
- if (!match) return location;
3463
- const startCol = match[1] ?? "";
3464
- const startRow = parseInt(match[2] ?? "0", 10);
3494
+ const startCell = location.split(":")[0] ?? location;
3495
+ const start = parseA1Cell(startCell);
3496
+ if (!start) return location;
3497
+ const profiles = profilePivotFields(sd);
3465
3498
  let rowCount = 1;
3466
3499
  const rowFieldIndex0 = rowFieldIndices[0];
3467
- if (rowFieldIndex0 !== void 0) rowCount += collectUniqueValues(sd.records, rowFieldIndex0).length;
3500
+ if (rowFieldIndex0 !== void 0) rowCount += uniqueCount(profiles, rowFieldIndex0);
3468
3501
  rowCount += 1;
3469
3502
  let colCount = Math.max(rowFieldIndices.length, 1);
3470
3503
  const colFieldIndex0 = colFieldIndices[0];
3471
- if (colFieldIndex0 !== void 0) colCount += collectUniqueValues(sd.records, colFieldIndex0).length;
3504
+ if (colFieldIndex0 !== void 0) colCount += uniqueCount(profiles, colFieldIndex0);
3472
3505
  else if (dataFields.length > 1) colCount += dataFields.length - 1;
3473
3506
  colCount += 1;
3474
- return `${startCol}${startRow}:${columnToLetter(letterToColumn(startCol) + colCount - 1)}${startRow + rowCount - 1}`;
3507
+ return `${startCell}:${columnToLetter(start.col + colCount - 1)}${start.row + rowCount - 1}`;
3475
3508
  }
3476
3509
  function buildPivotHierarchies(hierarchies) {
3477
3510
  const parts = [`<pivotHierarchies count="${hierarchies.length}">`];
@@ -3565,6 +3598,22 @@ function cartesianOfCounts(counts) {
3565
3598
  *
3566
3599
  * @module
3567
3600
  */
3601
+ /** CT_Break list under rowBreaks/colBreaks — identical shape, only the tag differs. */
3602
+ function breaksXml(tag, list) {
3603
+ let manualCount = 0;
3604
+ const brkParts = list.map((b) => {
3605
+ const bAttrs = { id: b.id };
3606
+ if (b.min !== void 0) bAttrs.min = b.min;
3607
+ if (b.max !== void 0) bAttrs.max = b.max;
3608
+ if (b.manual) {
3609
+ bAttrs.man = 1;
3610
+ manualCount++;
3611
+ }
3612
+ if (b.pivot) bAttrs.pt = 1;
3613
+ return `<brk${attrs(bAttrs)}/>`;
3614
+ });
3615
+ return `<${tag} count="${list.length}" manualBreakCount="${manualCount}">${brkParts.join("")}</${tag}>`;
3616
+ }
3568
3617
  /**
3569
3618
  * Build the complete worksheet XML string.
3570
3619
  *
@@ -3718,9 +3767,10 @@ function stringifyWorksheet(opts, ctx) {
3718
3767
  prAttrs.saltValue = pr.saltValue ?? prDerived?.saltValue;
3719
3768
  if (pr.spinCount !== void 0) prAttrs.spinCount = pr.spinCount;
3720
3769
  else if (prDerived) prAttrs.spinCount = prDerived.spinCount;
3721
- if (pr.securityDescriptor) prAttrs.securityDescriptor = pr.securityDescriptor;
3722
- if (!!pr.securityDescriptor) prParts.push(`<protectedRange${attrs(prAttrs)}><securityDescriptor>${escapeXml(pr.securityDescriptor)}</securityDescriptor></protectedRange>`);
3723
- else prParts.push(selfCloseElement("protectedRange", attrs(prAttrs)));
3770
+ if (pr.securityDescriptor) {
3771
+ prAttrs.securityDescriptor = pr.securityDescriptor;
3772
+ prParts.push(`<protectedRange${attrs(prAttrs)}><securityDescriptor>${escapeXml(pr.securityDescriptor)}</securityDescriptor></protectedRange>`);
3773
+ } else prParts.push(selfCloseElement("protectedRange", attrs(prAttrs)));
3724
3774
  }
3725
3775
  prParts.push("</protectedRanges>");
3726
3776
  p.push(prParts.join(""));
@@ -3919,36 +3969,8 @@ function stringifyWorksheet(opts, ctx) {
3919
3969
  const hfXml = stringifyHeaderFooterXml(opts.headerFooter);
3920
3970
  if (hfXml) p.push(hfXml);
3921
3971
  }
3922
- if (rowBreaks.length > 0) {
3923
- let manualCount = 0;
3924
- const brkParts = rowBreaks.map((b) => {
3925
- const bAttrs = { id: b.id };
3926
- if (b.min !== void 0) bAttrs.min = b.min;
3927
- if (b.max !== void 0) bAttrs.max = b.max;
3928
- if (b.manual) {
3929
- bAttrs.man = 1;
3930
- manualCount++;
3931
- }
3932
- if (b.pivot) bAttrs.pt = 1;
3933
- return `<brk${attrs(bAttrs)}/>`;
3934
- });
3935
- p.push(`<rowBreaks count="${rowBreaks.length}" manualBreakCount="${manualCount}">${brkParts.join("")}</rowBreaks>`);
3936
- }
3937
- if (colBreaks.length > 0) {
3938
- let manualCount = 0;
3939
- const brkParts = colBreaks.map((b) => {
3940
- const bAttrs = { id: b.id };
3941
- if (b.min !== void 0) bAttrs.min = b.min;
3942
- if (b.max !== void 0) bAttrs.max = b.max;
3943
- if (b.manual) {
3944
- bAttrs.man = 1;
3945
- manualCount++;
3946
- }
3947
- if (b.pivot) bAttrs.pt = 1;
3948
- return `<brk${attrs(bAttrs)}/>`;
3949
- });
3950
- p.push(`<colBreaks count="${colBreaks.length}" manualBreakCount="${manualCount}">${brkParts.join("")}</colBreaks>`);
3951
- }
3972
+ if (rowBreaks.length > 0) p.push(breaksXml("rowBreaks", rowBreaks));
3973
+ if (colBreaks.length > 0) p.push(breaksXml("colBreaks", colBreaks));
3952
3974
  if (customProperties.length > 0) {
3953
3975
  const cpParts = ["<customProperties>"];
3954
3976
  for (const cp of customProperties) cpParts.push(`<customPr name="${escapeXml(cp.name)}" r:id="${escapeXml(cp.rId)}"/>`);
@@ -3999,25 +4021,27 @@ function stringifyWorksheet(opts, ctx) {
3999
4021
  if (opts.legacyDrawingHF) p.push(`<legacyDrawingHF r:id="${escapeXml(opts.legacyDrawingHF)}"/>`);
4000
4022
  if (opts.drawingHF) {
4001
4023
  const dhf = opts.drawingHF;
4002
- const dhfAttrs = { "r:id": dhf.rId };
4003
- if (dhf.lho !== void 0) dhfAttrs.lho = dhf.lho;
4004
- if (dhf.lhe !== void 0) dhfAttrs.lhe = dhf.lhe;
4005
- if (dhf.lhf !== void 0) dhfAttrs.lhf = dhf.lhf;
4006
- if (dhf.cho !== void 0) dhfAttrs.cho = dhf.cho;
4007
- if (dhf.che !== void 0) dhfAttrs.che = dhf.che;
4008
- if (dhf.chf !== void 0) dhfAttrs.chf = dhf.chf;
4009
- if (dhf.rho !== void 0) dhfAttrs.rho = dhf.rho;
4010
- if (dhf.rhe !== void 0) dhfAttrs.rhe = dhf.rhe;
4011
- if (dhf.rhf !== void 0) dhfAttrs.rhf = dhf.rhf;
4012
- if (dhf.lfo !== void 0) dhfAttrs.lfo = dhf.lfo;
4013
- if (dhf.lfe !== void 0) dhfAttrs.lfe = dhf.lfe;
4014
- if (dhf.lff !== void 0) dhfAttrs.lff = dhf.lff;
4015
- if (dhf.cfo !== void 0) dhfAttrs.cfo = dhf.cfo;
4016
- if (dhf.cfe !== void 0) dhfAttrs.cfe = dhf.cfe;
4017
- if (dhf.cff !== void 0) dhfAttrs.cff = dhf.cff;
4018
- if (dhf.rfo !== void 0) dhfAttrs.rfo = dhf.rfo;
4019
- if (dhf.rfe !== void 0) dhfAttrs.rfe = dhf.rfe;
4020
- if (dhf.rff !== void 0) dhfAttrs.rff = dhf.rff;
4024
+ const dhfAttrs = {
4025
+ "r:id": dhf.rId,
4026
+ lho: dhf.lho,
4027
+ lhe: dhf.lhe,
4028
+ lhf: dhf.lhf,
4029
+ cho: dhf.cho,
4030
+ che: dhf.che,
4031
+ chf: dhf.chf,
4032
+ rho: dhf.rho,
4033
+ rhe: dhf.rhe,
4034
+ rhf: dhf.rhf,
4035
+ lfo: dhf.lfo,
4036
+ lfe: dhf.lfe,
4037
+ lff: dhf.lff,
4038
+ cfo: dhf.cfo,
4039
+ cfe: dhf.cfe,
4040
+ cff: dhf.cff,
4041
+ rfo: dhf.rfo,
4042
+ rfe: dhf.rfe,
4043
+ rff: dhf.rff
4044
+ };
4021
4045
  p.push(selfCloseElement("drawingHF", attrs(dhfAttrs)));
4022
4046
  }
4023
4047
  if (opts.backgroundImage) p.push("<!--BACKGROUND_PICTURE-->");
@@ -4904,11 +4928,10 @@ function parseMarker(el) {
4904
4928
  };
4905
4929
  }
4906
4930
  function cellRefToVmlCoords(ref) {
4907
- let i = 0;
4908
- while (i < ref.length && ref.charCodeAt(i) >= 65 && ref.charCodeAt(i) <= 90) i++;
4931
+ const cell = parseA1Cell(ref);
4909
4932
  return {
4910
- col: letterToColumn(ref.slice(0, i)) - 1,
4911
- row: parseInt(ref.slice(i), 10) - 1
4933
+ col: (cell?.col ?? 1) - 1,
4934
+ row: (cell?.row ?? 1) - 1
4912
4935
  };
4913
4936
  }
4914
4937
  /** Parse rich text element into a plain string or rich runs. */
@@ -6940,25 +6963,18 @@ function stringifyPivotCacheDef(sourceRef, sourceSheet, sourceData, recordsRid,
6940
6963
  p.push(conParts.join(""));
6941
6964
  } else p.push(`<cacheSource type="worksheet"><worksheetSource ref="${escapeXml(sourceRef)}" sheet="${escapeXml(sourceSheet)}"/></cacheSource>`);
6942
6965
  const fieldNames = sourceData.fieldNames;
6966
+ const profiles = profilePivotFields(sourceData);
6943
6967
  p.push(`<cacheFields count="${fieldNames.length}">`);
6944
6968
  for (let i = 0; i < fieldNames.length; i++) {
6945
6969
  const fieldName = fieldNames[i] ?? "";
6946
- const numeric = isNumericField(sourceData.records, i);
6947
- const uniqueVals = collectUniqueValues(sourceData.records, i);
6970
+ const { numeric, unique: uniqueVals } = profiles[i];
6948
6971
  if (numeric) {
6949
- let min = Infinity, max = -Infinity;
6950
- for (const row of sourceData.records) {
6951
- const v = row[i];
6952
- if (typeof v === "number") {
6953
- if (v < min) min = v;
6954
- if (v > max) max = v;
6955
- }
6956
- }
6972
+ let min = profiles[i].min, max = profiles[i].max;
6957
6973
  if (!isFinite(min)) {
6958
6974
  min = 0;
6959
6975
  max = 0;
6960
6976
  }
6961
- const allInteger = sourceData.records.every((row) => typeof row[i] === "number" && Number.isInteger(row[i]));
6977
+ const allInteger = profiles[i].allInteger;
6962
6978
  const cfOverride = cacheDefOpts?.cacheFieldOverrides?.get(i);
6963
6979
  const cfExtraAttrs = [];
6964
6980
  const siExtraAttrs = [];
@@ -7233,12 +7249,11 @@ function stringifyPivotCacheDef(sourceRef, sourceSheet, sourceData, recordsRid,
7233
7249
  return p.join("");
7234
7250
  }
7235
7251
  function stringifyPivotCacheRecords(sourceData) {
7236
- const numericFields = sourceData.fieldNames.map((_, i) => isNumericField(sourceData.records, i));
7237
- const fieldIndexMaps = sourceData.fieldNames.map((_, i) => {
7238
- if (numericFields[i]) return /* @__PURE__ */ new Map();
7239
- const unique = collectUniqueValues(sourceData.records, i);
7252
+ const profiles = profilePivotFields(sourceData);
7253
+ const fieldIndexMaps = profiles.map((f) => {
7254
+ if (f.numeric) return /* @__PURE__ */ new Map();
7240
7255
  const map = /* @__PURE__ */ new Map();
7241
- for (let j = 0; j < unique.length; j++) map.set(String(unique[j]), j);
7256
+ for (let j = 0; j < f.unique.length; j++) map.set(String(f.unique[j]), j);
7242
7257
  return map;
7243
7258
  });
7244
7259
  const p = [];
@@ -7249,7 +7264,7 @@ function stringifyPivotCacheRecords(sourceData) {
7249
7264
  const val = row[i];
7250
7265
  if (val === null) p.push("<m/>");
7251
7266
  else if (val instanceof Date) p.push(`<d v="${val.toISOString().replace(/\.\d{3}Z$/, "Z")}"/>`);
7252
- else if (numericFields[i]) p.push(`<n v="${val}"/>`);
7267
+ else if (profiles[i].numeric) p.push(`<n v="${val}"/>`);
7253
7268
  else p.push(`<x v="${fieldIndexMaps[i]?.get(String(val)) ?? 0}"/>`);
7254
7269
  }
7255
7270
  p.push("</r>");
@@ -7268,10 +7283,12 @@ function stringifyPivotCacheRecords(sourceData) {
7268
7283
  */
7269
7284
  function tableRefWidth(ref) {
7270
7285
  const sep = ref.indexOf(":");
7271
- const first = (sep === -1 ? ref : ref.slice(0, sep)).trim();
7272
- const last = sep === -1 ? first : ref.slice(sep + 1).trim();
7273
- const toCol = (cell) => letterToColumn(cell.replace(/[^A-Za-z]/g, "").toUpperCase());
7274
- const width = toCol(last) - toCol(first) + 1;
7286
+ const first = (sep === -1 ? ref : ref.slice(0, sep)).trim().toUpperCase();
7287
+ const last = sep === -1 ? first : ref.slice(sep + 1).trim().toUpperCase();
7288
+ const startCol = parseA1Cell(first)?.col;
7289
+ const endCol = parseA1Cell(last)?.col;
7290
+ if (startCol === void 0 || endCol === void 0) return void 0;
7291
+ const width = endCol - startCol + 1;
7275
7292
  return width >= 1 ? width : void 0;
7276
7293
  }
7277
7294
  const TotalsRowFunction = {
@@ -9284,10 +9301,12 @@ var XlsxReadContext = class {
9284
9301
  *
9285
9302
  * @module
9286
9303
  */
9304
+ const LEADING_PATH_NUMBER = /(\d+)/;
9287
9305
  function sortByNumber(paths) {
9288
- return paths.sort((a, b) => {
9289
- return parseInt(a.match(/(\d+)/)?.[1] ?? "0", 10) - parseInt(b.match(/(\d+)/)?.[1] ?? "0", 10);
9290
- });
9306
+ return paths.map((p) => ({
9307
+ p,
9308
+ n: parseInt(p.match(LEADING_PATH_NUMBER)?.[1] ?? "0", 10)
9309
+ })).sort((a, b) => a.n - b.n).map(({ p }) => p);
9291
9310
  }
9292
9311
  /**
9293
9312
  * Fill a parsed chart's userShapes anchors from the companion part body —
@@ -10161,7 +10180,7 @@ function rebuildSharedStrings(xmlMap) {
10161
10180
  /** Re-serialize the shared-strings part (called after worksheets are built). */
10162
10181
  function rewriteSharedStrings(xmlMap, ss) {
10163
10182
  if (ss.count === 0) return;
10164
- xmlMap.set("xl/sharedStrings.xml", toJson(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${ss.serialize()}`));
10183
+ xmlMap.set("xl/sharedStrings.xml", toJson(OOXML_XML_DECLARATION + ss.serialize()));
10165
10184
  }
10166
10185
  /**
10167
10186
  * Append a worksheet: serialize it (registering strings into the shared-strings
@@ -10339,9 +10358,9 @@ function appendCommentsToMap(xmlMap, vmlFiles, sheetName, commentOpts) {
10339
10358
  let merged = commentOpts;
10340
10359
  if (existingPart) merged = [...commentsDesc.parse(existingPart, STUB_READ_CTX).comments, ...commentOpts];
10341
10360
  const commentsXml = commentsDesc.stringify({ comments: merged }, STUB_WRITE_CTX);
10342
- if (commentsXml) xmlMap.set(commentsPath, toJson(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${commentsXml}`));
10361
+ if (commentsXml) xmlMap.set(commentsPath, toJson(OOXML_XML_DECLARATION + commentsXml));
10343
10362
  const vmlXml = vmlNotesDesc.stringify({ comments: merged }, STUB_WRITE_CTX);
10344
- if (vmlXml) vmlFiles.set(vmlPath, `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${vmlXml}`);
10363
+ if (vmlXml) vmlFiles.set(vmlPath, OOXML_XML_DECLARATION + vmlXml);
10345
10364
  if (!existingComments) {
10346
10365
  const n = getNextRelationshipIndex(wsRels);
10347
10366
  appendRelationship(wsRels, n, COMMENTS_REL_TYPE, `../comments${commentsN}.xml`);
@@ -10603,18 +10622,20 @@ function compileWorkbook(options, overrides = [], mediaLevel = 0) {
10603
10622
  wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", extRefsXml);
10604
10623
  } else wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", "");
10605
10624
  mapping["Workbook"] = {
10606
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${wbXml}`,
10625
+ data: XML_DECL + wbXml,
10607
10626
  path: "xl/workbook.xml"
10608
10627
  };
10609
10628
  if (ctx.sharedStrings.count > 0) {
10610
10629
  ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "sharedStrings.xml");
10630
+ const ssXml = sharedStringsDesc.stringify(ctx.sharedStrings.toDescriptorOptions(), ctx);
10611
10631
  mapping["SharedStrings"] = {
10612
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${sharedStringsDesc.stringify(ctx.sharedStrings.toDescriptorOptions(), ctx)}`,
10632
+ data: XML_DECL + ssXml,
10613
10633
  path: "xl/sharedStrings.xml"
10614
10634
  };
10615
10635
  }
10636
+ const stylesXml = stylesDesc.stringify({ styles: ctx.styles }, ctx);
10616
10637
  mapping["Styles"] = {
10617
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${stylesDesc.stringify({ styles: ctx.styles }, ctx)}`,
10638
+ data: XML_DECL + stylesXml,
10618
10639
  path: "xl/styles.xml"
10619
10640
  };
10620
10641
  const themeRels = new Relationships();
@@ -10876,7 +10897,7 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
10876
10897
  resolvedDrawingXml = bindMediaPlaceholders(resolvedDrawingXml, ctx.media, drawingRels);
10877
10898
  const drawingIdx = i + 1;
10878
10899
  mapping[`Drawing${i}`] = {
10879
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${resolvedDrawingXml}`,
10900
+ data: XML_DECL + resolvedDrawingXml,
10880
10901
  path: `xl/drawings/drawing${drawingIdx}.xml`
10881
10902
  };
10882
10903
  mapping[`DrawingRels${i}`] = {
@@ -10891,12 +10912,12 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
10891
10912
  const commentsIdx = i + 1;
10892
10913
  const commentsXml = commentsDesc.stringify({ comments: commentOpts }, ctx);
10893
10914
  mapping[`Comments${i}`] = {
10894
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${commentsXml}`,
10915
+ data: XML_DECL + commentsXml,
10895
10916
  path: `xl/comments${commentsIdx}.xml`
10896
10917
  };
10897
10918
  const vmlXml = vmlNotesDesc.stringify({ comments: commentOpts }, ctx);
10898
10919
  mapping[`VmlDrawing${i}`] = {
10899
- data: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${vmlXml}`,
10920
+ data: XML_DECL + vmlXml,
10900
10921
  path: `xl/drawings/vmlDrawing${commentsIdx}.vml`
10901
10922
  };
10902
10923
  const commentsRid = ++nextRid;
@@ -10969,7 +10990,7 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
10969
10990
  });
10970
10991
  const cacheDefRels = new Relationships();
10971
10992
  cacheDefRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords", "pivotCacheRecords1.xml");
10972
- const cacheDefXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + pivotCacheDefDesc.stringify({
10993
+ const cacheDefXml = XML_DECL + pivotCacheDefDesc.stringify({
10973
10994
  sourceRef: pt.source.split(":")[0] ? pt.source : "A1",
10974
10995
  sourceSheet,
10975
10996
  sourceData,
@@ -10983,7 +11004,7 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
10983
11004
  data: XML_DECL + cacheDefRels.serialize(),
10984
11005
  path: `xl/pivotCache/_rels/pivotCacheDefinition${cacheIdx}.xml.rels`
10985
11006
  };
10986
- const cacheRecordsXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + pivotCacheRecordsDesc.stringify({ sourceData }, ctx);
11007
+ const cacheRecordsXml = XML_DECL + pivotCacheRecordsDesc.stringify({ sourceData }, ctx);
10987
11008
  mapping[`PivotCacheRecords${cacheIdx}`] = {
10988
11009
  data: cacheRecordsXml,
10989
11010
  path: `xl/pivotCache/pivotCacheRecords${cacheIdx}.xml`
@@ -11018,7 +11039,7 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
11018
11039
  state.globalTableIdx++;
11019
11040
  const tableIdx = state.globalTableIdx;
11020
11041
  if (!tbl.columns?.length) continue;
11021
- const tableXmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + tableDesc.stringify({
11042
+ const tableXmlStr = XML_DECL + tableDesc.stringify({
11022
11043
  ...tbl,
11023
11044
  id: tbl.id ?? tableIdx
11024
11045
  }, ctx);
@@ -11215,16 +11236,16 @@ function hasMetadataContent(metadata) {
11215
11236
  }
11216
11237
  function extractPivotSourceData(rows, sourceRef) {
11217
11238
  const parts = sourceRef.split(":");
11218
- const startMatch = parts[0]?.match(/^([A-Z]+)(\d+)$/);
11219
- const endMatch = parts[1]?.match(/^([A-Z]+)(\d+)$/);
11220
- if (!startMatch) return {
11239
+ const start = parseA1Cell(parts[0] ?? "");
11240
+ if (!start) return {
11221
11241
  fieldNames: [],
11222
11242
  records: []
11223
11243
  };
11224
- const startRow = parseInt(startMatch[2] ?? "1", 10) - 1;
11225
- const endRow = endMatch ? parseInt(endMatch[2] ?? "1", 10) - 1 : startRow;
11226
- const startCol = letterToColumn(startMatch[1] ?? "A") - 1;
11227
- const endCol = endMatch ? letterToColumn(endMatch[1] ?? "A") - 1 : startCol;
11244
+ const end = parts[1] !== void 0 ? parseA1Cell(parts[1]) : void 0;
11245
+ const startRow = start.row - 1;
11246
+ const endRow = (end?.row ?? start.row) - 1;
11247
+ const startCol = start.col - 1;
11248
+ const endCol = (end?.col ?? start.col) - 1;
11228
11249
  const colCount = endCol - startCol + 1;
11229
11250
  const headerRow = rows[startRow];
11230
11251
  const fieldNames = [];
@@ -11262,10 +11283,10 @@ function renderPivotSheetData(pivotOpts, worksheetConfigs, sharedStrings, curren
11262
11283
  let minRow = Infinity;
11263
11284
  let minCol = Infinity;
11264
11285
  for (const pt of pivotOpts) {
11265
- const locMatch = (pt.location ?? "A3").match(/^([A-Z]+)(\d+)$/);
11266
- if (!locMatch) continue;
11267
- const startCol = letterToColumn(locMatch[1] ?? "A") - 1;
11268
- const startRow = parseInt(locMatch[2] ?? "1", 10);
11286
+ const loc = parseA1Cell(pt.location ?? "A3");
11287
+ if (!loc) continue;
11288
+ const startCol = loc.col - 1;
11289
+ const startRow = loc.row;
11269
11290
  const rowFieldNames = pt.rows;
11270
11291
  const dataFields = pt.data;
11271
11292
  const sourceWsIdx = findWorksheetIndex(worksheetConfigs, pt.sourceSheet ?? currentSheetName);
@@ -11308,7 +11329,7 @@ function renderPivotSheetData(pivotOpts, worksheetConfigs, sharedStrings, curren
11308
11329
  maxRow = Math.max(maxRow, rowIdx);
11309
11330
  };
11310
11331
  if (colFieldIndices.length > 0 && !colFieldIndices.some((idx) => idx === -1)) {
11311
- const colUniqueVals = collectUniqueValues(sourceData.records, colFieldIndices[0] ?? 0).map((v) => typeof v === "string" || typeof v === "number" ? String(v) : String(v ?? ""));
11332
+ const colUniqueVals = profilePivotFields(sourceData)[colFieldIndices[0] ?? 0].unique.map((v) => typeof v === "string" || typeof v === "number" ? String(v) : String(v ?? ""));
11312
11333
  const crossTabMap = /* @__PURE__ */ new Map();
11313
11334
  for (const record of sourceData.records) {
11314
11335
  const rowKey = rowFieldIndices.map((fi) => String(record[fi])).join("|");
@@ -11720,6 +11741,6 @@ function generateWorkbookStream(options, packerOptions) {
11720
11741
  } });
11721
11742
  }
11722
11743
  //#endregion
11723
- export { Media, PivotFilterType as PivotFilterTypeValue, SharedStrings, Styles, TableType, TotalsRowFunction, XlsxReadContext, XlsxWriteContext, buildExternalReferencesXml, buildTablePartsXml, stringifyWorksheet as buildWorksheetXml, stringifyWorksheet, calcChainDesc, chartsheetDesc, columnToLetter, commentsDesc, compileWorkbook, connectionsDesc, createThemeXml, dateToSerialNumber, dialogsheetDesc, drawingDesc, externalLinkDesc, generateWorkbook, generateWorkbookStream, generateWorkbookSync, hashPassword, letterToColumn, lintWorkbookFormulas, mapInfoDesc, metadataDesc, parseWorkbook, parseXlsx, patchWorkbook, pickAnchorOptions, pivotCacheDefDesc, pivotCacheRecordsDesc, pivotTableDesc, queryTableDesc, sharedStringsDesc, singleXmlCellsDesc, stylesDesc, tableDesc, vmlNotesDesc, workbookDesc, worksheetDesc };
11744
+ export { Media, PivotFilterType as PivotFilterTypeValue, SharedStrings, Styles, TableType, TotalsRowFunction, XlsxReadContext, XlsxWriteContext, buildExternalReferencesXml, buildTablePartsXml, stringifyWorksheet as buildWorksheetXml, stringifyWorksheet, calcChainDesc, chartsheetDesc, columnToLetter, commentsDesc, compileWorkbook, connectionsDesc, createThemeXml, dateToSerialNumber, dialogsheetDesc, drawingDesc, externalLinkDesc, generateWorkbook, generateWorkbookStream, generateWorkbookSync, hashPassword, letterToColumn, lintWorkbookFormulas, mapInfoDesc, metadataDesc, parseA1Cell, parseWorkbook, parseXlsx, patchWorkbook, pickAnchorOptions, pivotCacheDefDesc, pivotCacheRecordsDesc, pivotTableDesc, queryTableDesc, sharedStringsDesc, singleXmlCellsDesc, stylesDesc, tableDesc, vmlNotesDesc, workbookDesc, worksheetDesc };
11724
11745
 
11725
11746
  //# sourceMappingURL=index.mjs.map