@lotics/cli 0.56.0 → 0.57.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.
package/dist/src/cli.js CHANGED
@@ -29586,6 +29586,19 @@ import readline from "node:readline";
29586
29586
  // src/client.ts
29587
29587
  import fs from "node:fs";
29588
29588
  import path from "node:path";
29589
+ function gatewayErrorMessage(status) {
29590
+ if (status === 524) {
29591
+ return "The request took too long to finish (gateway timeout). It may still be running \u2014 check back in a moment, or try again.";
29592
+ }
29593
+ if (status >= 500) {
29594
+ return "The service is temporarily unavailable. Please try again shortly.";
29595
+ }
29596
+ return "The service returned an unexpected response. Please try again.";
29597
+ }
29598
+ function transportErrorMessage(status, parsed) {
29599
+ const jsonMessage = parsed && typeof parsed.message === "string" ? parsed.message : null;
29600
+ return parsed === null || status >= 500 || jsonMessage === null ? gatewayErrorMessage(status) : jsonMessage;
29601
+ }
29589
29602
  function findAvailableFilename(dir, filename, reserved) {
29590
29603
  const isTaken = (name) => {
29591
29604
  const full = path.join(dir, name);
@@ -29785,11 +29798,25 @@ var LoticsClient = class {
29785
29798
  * Mirrors POST /v1/apps/{app_id}/workflows/{alias}/execute.
29786
29799
  */
29787
29800
  async appWorkflow(app_id, alias, inputs) {
29788
- return this.request(
29789
- "POST",
29790
- `/v1/apps/${encodeURIComponent(app_id)}/workflows/${encodeURIComponent(alias)}/execute`,
29791
- { inputs }
29792
- );
29801
+ const url = `${this.baseUrl}/v1/apps/${encodeURIComponent(app_id)}/workflows/${encodeURIComponent(alias)}/execute`;
29802
+ const headers = this.buildHeaders();
29803
+ headers["Content-Type"] = "application/json";
29804
+ let response;
29805
+ try {
29806
+ response = await fetch(url, { method: "POST", headers, body: JSON.stringify({ inputs }) });
29807
+ } catch (err2) {
29808
+ return { status: "error", message: err2 instanceof Error ? err2.message : "The workflow request failed." };
29809
+ }
29810
+ const text = await response.text();
29811
+ let parsed = null;
29812
+ if (text) {
29813
+ try {
29814
+ parsed = JSON.parse(text);
29815
+ } catch {
29816
+ }
29817
+ }
29818
+ if (response.ok) return parsed ?? {};
29819
+ return { status: "error", message: transportErrorMessage(response.status, parsed) };
29793
29820
  }
29794
29821
  /**
29795
29822
  * Open a streaming agent run and return the RAW streamed `Response` (the
@@ -38666,8 +38693,8 @@ function parseWorkbook(workbookXml) {
38666
38693
  }
38667
38694
  return { sheets, activeSheetIndex, date1904, namedRanges, printTitlesBySheet, fullCalcOnLoad };
38668
38695
  }
38669
- function parseWorkbookRels(relsXml) {
38670
- const doc = xmlParser3.parse(relsXml);
38696
+ function parseWorkbookRels(relsXml2) {
38697
+ const doc = xmlParser3.parse(relsXml2);
38671
38698
  const rels = doc?.["Relationships"];
38672
38699
  if (!rels) return /* @__PURE__ */ new Map();
38673
38700
  const relArr = rels["Relationship"];
@@ -39703,6 +39730,9 @@ function refToRowCol(ref) {
39703
39730
  function rowColToRef(row, col) {
39704
39731
  return colNumToLetters(col) + String(row);
39705
39732
  }
39733
+ function escapeXml(s) {
39734
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
39735
+ }
39706
39736
  var PACK_COL_BITS = 14;
39707
39737
  var PACK_COL_MULT = 1 << PACK_COL_BITS;
39708
39738
  function packRowCol(row, col) {
@@ -39874,8 +39904,8 @@ function parseHeaderFooterElement(worksheet) {
39874
39904
  if (hf["@_differentFirst"] === "1") out.differentFirst = true;
39875
39905
  return Object.keys(out).length > 0 ? out : void 0;
39876
39906
  }
39877
- function parseSheetRels(relsXml) {
39878
- const doc = relsParser.parse(relsXml);
39907
+ function parseSheetRels(relsXml2) {
39908
+ const doc = relsParser.parse(relsXml2);
39879
39909
  const relationships = doc?.["Relationships"];
39880
39910
  if (!relationships) return /* @__PURE__ */ new Map();
39881
39911
  const relArr = relationships["Relationship"];
@@ -40179,8 +40209,8 @@ function parseImages(rels, zipEntries) {
40179
40209
  }
40180
40210
  return images;
40181
40211
  }
40182
- function parseDrawingRels(relsXml) {
40183
- const doc = relsParser.parse(relsXml);
40212
+ function parseDrawingRels(relsXml2) {
40213
+ const doc = relsParser.parse(relsXml2);
40184
40214
  const relationships = doc?.["Relationships"];
40185
40215
  if (!relationships) return /* @__PURE__ */ new Map();
40186
40216
  const relArr = relationships["Relationship"];
@@ -41858,1505 +41888,1722 @@ function parsePrintTitlesRef(raw) {
41858
41888
  return result.repeatRows || result.repeatCols ? result : void 0;
41859
41889
  }
41860
41890
 
41861
- // ../xlsx/src/xlsx_writer.ts
41862
- function readWorkbookSheetOrder(originalZip) {
41863
- const wbBytes = originalZip["xl/workbook.xml"];
41864
- if (!wbBytes) return [];
41865
- const xml = decode(wbBytes);
41866
- const out = [];
41867
- const re = /<sheet\b[^>]*?r:id="([^"]+)"/g;
41868
- let m;
41869
- while ((m = re.exec(xml)) !== null) {
41870
- out.push(m[1]);
41891
+ // ../xlsx/src/pivot_recompute.ts
41892
+ var TOTAL_LABEL = "Grand Total";
41893
+ function recomputePivot(table, cache, source) {
41894
+ const records = filterByPageAxis(table, cache, source.records);
41895
+ const rowTuples = distinctTuples(records, table.rowFieldIndices);
41896
+ const colTuples = distinctTuples(records, table.colFieldIndices);
41897
+ const groupKey = (rec) => JSON.stringify([
41898
+ tupleOf(rec, table.rowFieldIndices),
41899
+ tupleOf(rec, table.colFieldIndices)
41900
+ ]);
41901
+ const groups = /* @__PURE__ */ new Map();
41902
+ for (const rec of records) {
41903
+ const key = groupKey(rec);
41904
+ let bucket = groups.get(key);
41905
+ if (!bucket) {
41906
+ bucket = [];
41907
+ groups.set(key, bucket);
41908
+ }
41909
+ bucket.push(rec);
41871
41910
  }
41872
- return out;
41911
+ return buildGrid(table, source, rowTuples, colTuples, groups, records);
41873
41912
  }
41874
- function readWorkbookRels(originalZip) {
41875
- const out = /* @__PURE__ */ new Map();
41876
- const bytes = originalZip["xl/_rels/workbook.xml.rels"];
41877
- if (!bytes) return out;
41878
- const xml = decode(bytes);
41879
- const re = /<Relationship\b([^/]*?)\/>/g;
41880
- let m;
41881
- while ((m = re.exec(xml)) !== null) {
41882
- const attrs = m[1];
41883
- const id = /\bId="([^"]+)"/.exec(attrs)?.[1];
41884
- const type = /\bType="([^"]+)"/.exec(attrs)?.[1] ?? "";
41885
- const target = /\bTarget="([^"]+)"/.exec(attrs)?.[1] ?? "";
41886
- if (id) out.set(id, { type, target });
41913
+ function filterByPageAxis(table, cache, records) {
41914
+ const filters = [];
41915
+ for (const fi of table.pageFieldIndices) {
41916
+ const cfg = table.fields[fi];
41917
+ if (cfg?.selectedPageItem == null) continue;
41918
+ const cacheField = cache.fields[fi];
41919
+ if (!cacheField) continue;
41920
+ const allowed = cacheField.items[cfg.selectedPageItem];
41921
+ if (allowed) filters.push({ fieldIndex: fi, allowed });
41887
41922
  }
41888
- return out;
41923
+ if (filters.length === 0) return records;
41924
+ return records.filter(
41925
+ (rec) => filters.every(
41926
+ ({ fieldIndex, allowed }) => cellMatchesItem(rec[fieldIndex], allowed)
41927
+ )
41928
+ );
41889
41929
  }
41890
- function readPivotCacheIdMap(originalZip) {
41891
- const out = /* @__PURE__ */ new Map();
41892
- const bytes = originalZip["xl/workbook.xml"];
41893
- if (!bytes) return out;
41894
- const xml = decode(bytes);
41895
- const re = /<pivotCache\b([^/]*?)\/>/g;
41896
- let m;
41897
- while ((m = re.exec(xml)) !== null) {
41898
- const attrs = m[1];
41899
- const cacheIdMatch = /\bcacheId="(\d+)"/.exec(attrs);
41900
- const ridMatch = /\br:id="([^"]+)"/.exec(attrs);
41901
- if (cacheIdMatch && ridMatch) {
41902
- out.set(parseInt(cacheIdMatch[1], 10), ridMatch[1]);
41903
- }
41930
+ function cellMatchesItem(cell, item) {
41931
+ switch (item.kind) {
41932
+ case "string":
41933
+ return typeof cell === "string" && cell === item.value;
41934
+ case "number":
41935
+ return typeof cell === "number" && cell === item.value;
41936
+ case "boolean":
41937
+ return typeof cell === "boolean" && cell === item.value;
41938
+ case "date":
41939
+ return typeof cell === "string" && cell === item.value;
41940
+ case "missing":
41941
+ return cell === void 0 || cell === null || cell === "";
41942
+ case "error":
41943
+ return typeof cell === "string" && cell === item.value;
41904
41944
  }
41905
- return out;
41906
41945
  }
41907
- function readSheetPivotPaths(originalZip, sheetTarget) {
41908
- const sheetPath = `xl/${sheetTarget}`;
41909
- const relsPath = sheetPath.replace(/([^/]+)$/, "_rels/$1.rels");
41910
- const bytes = originalZip[relsPath];
41911
- if (!bytes) return [];
41912
- const xml = decode(bytes);
41913
- const re = /<Relationship\b([^/]*?)\/>/g;
41946
+ function tupleOf(rec, indices) {
41947
+ return indices.map((i2) => rec[i2] ?? null);
41948
+ }
41949
+ function distinctTuples(records, indices) {
41950
+ const seen = /* @__PURE__ */ new Set();
41914
41951
  const out = [];
41915
- let m;
41916
- while ((m = re.exec(xml)) !== null) {
41917
- const attrs = m[1];
41918
- const type = /\bType="([^"]+)"/.exec(attrs)?.[1] ?? "";
41919
- if (!type.includes("/pivotTable")) continue;
41920
- const target = /\bTarget="([^"]+)"/.exec(attrs)?.[1];
41921
- if (target) out.push(target);
41952
+ for (const rec of records) {
41953
+ const t = tupleOf(rec, indices);
41954
+ const key = JSON.stringify(t);
41955
+ if (seen.has(key)) continue;
41956
+ seen.add(key);
41957
+ out.push(t);
41922
41958
  }
41959
+ out.sort((a, b) => {
41960
+ for (let i2 = 0; i2 < Math.max(a.length, b.length); i2++) {
41961
+ const av = a[i2];
41962
+ const bv = b[i2];
41963
+ if (av === bv) continue;
41964
+ const as = av === null || av === void 0 ? "" : String(av);
41965
+ const bs = bv === null || bv === void 0 ? "" : String(bv);
41966
+ if (as < bs) return -1;
41967
+ if (as > bs) return 1;
41968
+ }
41969
+ return 0;
41970
+ });
41923
41971
  return out;
41924
41972
  }
41925
- function extractPivotRoundTripInfo(originalZip) {
41926
- const empty = {
41927
- cachesByWorkbook: /* @__PURE__ */ new Map(),
41928
- pivotTablesBySheetIndex: /* @__PURE__ */ new Map(),
41929
- pivotXmlPaths: []
41930
- };
41931
- if (!originalZip) return empty;
41932
- const sheetRIds = readWorkbookSheetOrder(originalZip);
41933
- const wbRels = readWorkbookRels(originalZip);
41934
- const cacheRIds = readPivotCacheIdMap(originalZip);
41935
- const cachesByWorkbook = /* @__PURE__ */ new Map();
41936
- for (const [cacheId, rid] of cacheRIds) {
41937
- const rel = wbRels.get(rid);
41938
- if (!rel) continue;
41939
- cachesByWorkbook.set(cacheId, rel.target);
41940
- }
41941
- const pivotTablesBySheetIndex = /* @__PURE__ */ new Map();
41942
- for (let i2 = 0; i2 < sheetRIds.length; i2++) {
41943
- const sheetTarget = wbRels.get(sheetRIds[i2])?.target;
41944
- if (!sheetTarget) continue;
41945
- const paths = readSheetPivotPaths(originalZip, sheetTarget);
41946
- if (paths.length > 0) pivotTablesBySheetIndex.set(i2, paths);
41947
- }
41948
- const pivotXmlPaths = [];
41949
- for (const path7 of Object.keys(originalZip)) {
41950
- if (path7.startsWith("xl/pivotTables/") && path7.endsWith(".xml")) {
41951
- pivotXmlPaths.push(path7);
41952
- }
41953
- if (path7.startsWith("xl/pivotCache/") && path7.endsWith(".xml")) {
41954
- pivotXmlPaths.push(path7);
41955
- }
41973
+ function aggregate(values2, fn) {
41974
+ const numeric = values2.filter((v) => typeof v === "number");
41975
+ switch (fn) {
41976
+ case "count":
41977
+ return values2.filter((v) => v !== null && v !== void 0 && v !== "").length;
41978
+ case "countNums":
41979
+ return numeric.length;
41980
+ case "sum":
41981
+ return numeric.reduce((a, b) => a + b, 0);
41982
+ case "average":
41983
+ if (numeric.length === 0) return null;
41984
+ return numeric.reduce((a, b) => a + b, 0) / numeric.length;
41985
+ case "min":
41986
+ return numeric.length === 0 ? null : Math.min(...numeric);
41987
+ case "max":
41988
+ return numeric.length === 0 ? null : Math.max(...numeric);
41989
+ case "product":
41990
+ return numeric.length === 0 ? null : numeric.reduce((a, b) => a * b, 1);
41956
41991
  }
41957
- return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths };
41958
- }
41959
- function decode(bytes) {
41960
- return new TextDecoder().decode(bytes);
41961
41992
  }
41962
- function pivotContentTypeFor(path7) {
41963
- if (path7.startsWith("xl/pivotTables/") && path7.endsWith(".xml")) {
41964
- return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
41965
- }
41966
- if (path7.includes("/pivotCacheDefinition") && path7.endsWith(".xml")) {
41967
- return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
41968
- }
41969
- if (path7.includes("/pivotCacheRecords") && path7.endsWith(".xml")) {
41970
- return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
41993
+ function buildGrid(table, source, rowTuples, colTuples, groups, allRecords) {
41994
+ const numRowFields = table.rowFieldIndices.length;
41995
+ const numColFields = table.colFieldIndices.length;
41996
+ const numDataFields = Math.max(table.dataFields.length, 1);
41997
+ const showRowGrand = table.display.colGrandTotals;
41998
+ const showColGrand = table.display.rowGrandTotals;
41999
+ const rowLabelCols = Math.max(numRowFields, 1);
42000
+ const colHeaderRows = numColFields + (numDataFields > 0 ? 1 : 0);
42001
+ const headerRows = Math.max(colHeaderRows, 1);
42002
+ const dataCols = colTuples.length * numDataFields;
42003
+ const totalCols = rowLabelCols + dataCols + (showColGrand ? numDataFields : 0);
42004
+ const totalRows = headerRows + rowTuples.length + (showRowGrand ? 1 : 0);
42005
+ const cells = [];
42006
+ for (let r = 0; r < totalRows; r++) {
42007
+ cells.push(new Array(totalCols).fill({ kind: "blank" }));
41971
42008
  }
41972
- return void 0;
41973
- }
41974
- function exportWorkbook(workbook, originalZip) {
41975
- const entries = {};
41976
- const stylesPassthrough = !!originalZip && !workbook.styles.dirty && !!originalZip["xl/styles.xml"];
41977
- if (originalZip) {
41978
- const regeneratedPaths = /* @__PURE__ */ new Set();
41979
- regeneratedPaths.add("xl/sharedStrings.xml");
41980
- if (!stylesPassthrough) regeneratedPaths.add("xl/styles.xml");
41981
- regeneratedPaths.add("xl/workbook.xml");
41982
- regeneratedPaths.add("xl/_rels/workbook.xml.rels");
41983
- regeneratedPaths.add("[Content_Types].xml");
41984
- regeneratedPaths.add("_rels/.rels");
41985
- regeneratedPaths.add("docProps/core.xml");
41986
- regeneratedPaths.add("docProps/app.xml");
41987
- for (let i2 = 0; i2 < workbook.sheets.length + 10; i2++) {
41988
- regeneratedPaths.add(`xl/worksheets/sheet${i2 + 1}.xml`);
41989
- regeneratedPaths.add(`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`);
41990
- }
41991
- for (const path7 of Object.keys(originalZip)) {
41992
- if (path7.startsWith("xl/drawings/") || path7.startsWith("xl/charts/") || path7.startsWith("xl/tables/") || path7.startsWith("xl/media/")) {
41993
- regeneratedPaths.add(path7);
42009
+ for (let level = 0; level < numColFields; level++) {
42010
+ let col = rowLabelCols;
42011
+ for (const tuple of colTuples) {
42012
+ const text = formatCellLabel(tuple[level]);
42013
+ for (let i2 = 0; i2 < numDataFields; i2++) {
42014
+ cells[level][col + i2] = { kind: "colHeader", depth: level, text };
41994
42015
  }
41995
- }
41996
- for (const [path7, data] of Object.entries(originalZip)) {
41997
- if (!regeneratedPaths.has(path7)) entries[path7] = data;
42016
+ col += numDataFields;
41998
42017
  }
41999
42018
  }
42000
- const sharedStrings = buildSharedStrings(workbook);
42001
- entries["xl/sharedStrings.xml"] = strToU8(sharedStrings.xml);
42002
- const stylesResult = stylesPassthrough ? { xml: "", xfMap: /* @__PURE__ */ new Map(), numFmtMap: /* @__PURE__ */ new Map(), dxfMap: /* @__PURE__ */ new Map() } : buildStylesXml(workbook);
42003
- if (!stylesPassthrough) entries["xl/styles.xml"] = strToU8(stylesResult.xml);
42004
- const pivotInfo = extractPivotRoundTripInfo(originalZip);
42005
- entries["xl/workbook.xml"] = strToU8(buildWorkbookXml(workbook, pivotInfo));
42006
- entries["xl/_rels/workbook.xml.rels"] = strToU8(
42007
- buildWorkbookRels(workbook, pivotInfo)
42008
- );
42009
- const extraContentTypes = [];
42010
- for (const path7 of pivotInfo.pivotXmlPaths) {
42011
- const ct = pivotContentTypeFor(path7);
42012
- if (ct) extraContentTypes.push(ct);
42013
- }
42014
- let globalChartIndex = 1;
42015
- let globalImageIndex = 1;
42016
- let globalTableIndex = 1;
42017
- for (let i2 = 0; i2 < workbook.sheets.length; i2++) {
42018
- const sheet = workbook.sheets[i2];
42019
- const sheetRels = [];
42020
- let nextRId = 1;
42021
- const hasCharts = sheet.charts.length > 0;
42022
- const hasImages = sheet.images.length > 0;
42023
- const hasDrawings = sheet.drawings.length > 0;
42024
- const hasTables = sheet.tables.length > 0;
42025
- const hasHyperlinks = sheet.hyperlinks.size > 0;
42026
- const needsDrawing = hasCharts || hasImages || hasDrawings;
42027
- const hyperlinkRIds = /* @__PURE__ */ new Map();
42028
- if (hasHyperlinks) {
42029
- for (const [ref, url] of sheet.hyperlinks) {
42030
- const rId = `rId${nextRId++}`;
42031
- hyperlinkRIds.set(ref, rId);
42032
- sheetRels.push(`<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="${escapeXml(url)}" TargetMode="External"/>`);
42019
+ if (numDataFields > 0) {
42020
+ const labelRow = colHeaderRows - 1;
42021
+ let col = rowLabelCols;
42022
+ for (let _t = 0; _t < colTuples.length; _t++) {
42023
+ for (let d = 0; d < table.dataFields.length; d++) {
42024
+ cells[labelRow][col + d] = {
42025
+ kind: "valueLabel",
42026
+ text: table.dataFields[d].name
42027
+ };
42033
42028
  }
42029
+ col += numDataFields;
42034
42030
  }
42035
- let drawingRId = "";
42036
- if (needsDrawing) {
42037
- drawingRId = `rId${nextRId++}`;
42038
- sheetRels.push(`<Relationship Id="${drawingRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" Target="../drawings/drawing${i2 + 1}.xml"/>`);
42039
- const drawingRels = [];
42040
- let drawingRelId = 1;
42041
- const drawingAnchors = [];
42042
- for (const chart of sheet.charts) {
42043
- const chartRId = `rId${drawingRelId++}`;
42044
- const chartPath = `xl/charts/chart${globalChartIndex}.xml`;
42045
- entries[chartPath] = strToU8(buildChartXml(chart));
42046
- extraContentTypes.push(`<Override PartName="/${chartPath}" ContentType="application/vnd.openxmlformats-officedocument.drawingml.chart+xml"/>`);
42047
- drawingRels.push(`<Relationship Id="${chartRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart" Target="../charts/chart${globalChartIndex}.xml"/>`);
42048
- drawingAnchors.push(buildChartAnchorXml(chart, chartRId));
42049
- globalChartIndex++;
42050
- }
42051
- for (const image of sheet.images) {
42052
- const imgRId = `rId${drawingRelId++}`;
42053
- const ext = getImageExtension(image.dataUrl);
42054
- const imgPath = `xl/media/image${globalImageIndex}.${ext}`;
42055
- const imgBytes = dataUrlToBytes(image.dataUrl);
42056
- if (imgBytes) {
42057
- entries[imgPath] = imgBytes;
42058
- drawingRels.push(`<Relationship Id="${imgRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image${globalImageIndex}.${ext}"/>`);
42059
- drawingAnchors.push(buildImageAnchorXml(image, imgRId));
42060
- globalImageIndex++;
42061
- }
42031
+ if (showColGrand) {
42032
+ for (let d = 0; d < table.dataFields.length; d++) {
42033
+ cells[labelRow][rowLabelCols + dataCols + d] = {
42034
+ kind: "valueLabel",
42035
+ text: table.dataFields[d].name
42036
+ };
42062
42037
  }
42063
- for (const drawing of sheet.drawings) {
42064
- drawingAnchors.push(buildShapeAnchorXml(drawing));
42038
+ }
42039
+ }
42040
+ for (let r = 0; r < rowTuples.length; r++) {
42041
+ const rowTuple = rowTuples[r];
42042
+ const gridRow = headerRows + r;
42043
+ for (let level = 0; level < numRowFields; level++) {
42044
+ cells[gridRow][level] = {
42045
+ kind: "rowHeader",
42046
+ depth: level,
42047
+ text: formatCellLabel(rowTuple[level])
42048
+ };
42049
+ }
42050
+ for (let c = 0; c < colTuples.length; c++) {
42051
+ const colTuple = colTuples[c];
42052
+ const groupRecords = groups.get(JSON.stringify([rowTuple, colTuple])) ?? [];
42053
+ for (let d = 0; d < table.dataFields.length; d++) {
42054
+ const df = table.dataFields[d];
42055
+ const values2 = groupRecords.map((rec) => rec[df.fieldIndex]);
42056
+ cells[gridRow][rowLabelCols + c * numDataFields + d] = {
42057
+ kind: "value",
42058
+ value: aggregate(values2, df.subtotal),
42059
+ numFmt: df.numFmt
42060
+ };
42065
42061
  }
42066
- entries[`xl/drawings/drawing${i2 + 1}.xml`] = strToU8(
42067
- `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42068
- <xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart">
42069
- ` + drawingAnchors.join("\n") + `
42070
- </xdr:wsDr>`
42062
+ }
42063
+ if (showColGrand) {
42064
+ const rowOnly = allRecords.filter(
42065
+ (rec) => sameTuple(tupleOf(rec, table.rowFieldIndices), rowTuple)
42071
42066
  );
42072
- extraContentTypes.push(`<Override PartName="/xl/drawings/drawing${i2 + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.drawing+xml"/>`);
42073
- if (drawingRels.length > 0) {
42074
- entries[`xl/drawings/_rels/drawing${i2 + 1}.xml.rels`] = strToU8(
42075
- `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42076
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42077
- ${drawingRels.join("\n")}
42078
- </Relationships>`
42079
- );
42067
+ for (let d = 0; d < table.dataFields.length; d++) {
42068
+ const df = table.dataFields[d];
42069
+ cells[gridRow][rowLabelCols + dataCols + d] = {
42070
+ kind: "rowTotal",
42071
+ value: aggregate(
42072
+ rowOnly.map((rec) => rec[df.fieldIndex]),
42073
+ df.subtotal
42074
+ )
42075
+ };
42080
42076
  }
42081
42077
  }
42082
- const tableRIds = [];
42083
- if (hasTables) {
42084
- for (const table of sheet.tables) {
42085
- const tableRId = `rId${nextRId++}`;
42086
- tableRIds.push(tableRId);
42087
- const tablePath = `xl/tables/table${globalTableIndex}.xml`;
42088
- entries[tablePath] = strToU8(buildTableXml(table, globalTableIndex));
42089
- extraContentTypes.push(`<Override PartName="/${tablePath}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"/>`);
42090
- sheetRels.push(`<Relationship Id="${tableRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" Target="../tables/table${globalTableIndex}.xml"/>`);
42091
- globalTableIndex++;
42078
+ }
42079
+ if (showRowGrand) {
42080
+ const gridRow = headerRows + rowTuples.length;
42081
+ cells[gridRow][0] = { kind: "totalLabel", text: TOTAL_LABEL };
42082
+ for (let c = 0; c < colTuples.length; c++) {
42083
+ const colTuple = colTuples[c];
42084
+ const colOnly = allRecords.filter(
42085
+ (rec) => sameTuple(tupleOf(rec, table.colFieldIndices), colTuple)
42086
+ );
42087
+ for (let d = 0; d < table.dataFields.length; d++) {
42088
+ const df = table.dataFields[d];
42089
+ cells[gridRow][rowLabelCols + c * numDataFields + d] = {
42090
+ kind: "colTotal",
42091
+ value: aggregate(
42092
+ colOnly.map((rec) => rec[df.fieldIndex]),
42093
+ df.subtotal
42094
+ )
42095
+ };
42092
42096
  }
42093
42097
  }
42094
- const pivotTargets = pivotInfo.pivotTablesBySheetIndex.get(i2);
42095
- if (pivotTargets && pivotTargets.length > 0) {
42096
- for (const target of pivotTargets) {
42097
- const rId = `rId${nextRId++}`;
42098
- sheetRels.push(
42099
- `<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable" Target="${escapeXml(target)}"/>`
42100
- );
42098
+ if (showColGrand) {
42099
+ for (let d = 0; d < table.dataFields.length; d++) {
42100
+ const df = table.dataFields[d];
42101
+ cells[gridRow][rowLabelCols + dataCols + d] = {
42102
+ kind: "grandTotal",
42103
+ value: aggregate(
42104
+ allRecords.map((rec) => rec[df.fieldIndex]),
42105
+ df.subtotal
42106
+ )
42107
+ };
42101
42108
  }
42102
42109
  }
42103
- if (sheetRels.length > 0) {
42104
- entries[`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`] = strToU8(
42105
- `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42106
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42107
- ${sheetRels.join("\n")}
42108
- </Relationships>`
42109
- );
42110
- }
42111
- entries[`xl/worksheets/sheet${i2 + 1}.xml`] = strToU8(
42112
- buildSheetXml(sheet, workbook.styles, sharedStrings.index, i2 === workbook.activeSheetIndex, stylesResult.xfMap, stylesResult.numFmtMap, stylesResult.dxfMap, drawingRId, tableRIds, hyperlinkRIds)
42113
- );
42114
42110
  }
42115
- entries["docProps/core.xml"] = strToU8(buildCoreProps());
42116
- entries["docProps/app.xml"] = strToU8(buildAppProps());
42117
- entries["[Content_Types].xml"] = strToU8(buildContentTypes(workbook.sheets.length, extraContentTypes));
42118
- entries["_rels/.rels"] = strToU8(buildRootRels());
42119
- return zipSync(entries, { level: 6 });
42111
+ void source;
42112
+ return {
42113
+ cells,
42114
+ headerRows,
42115
+ rowLabelCols,
42116
+ rows: totalRows,
42117
+ cols: totalCols
42118
+ };
42120
42119
  }
42121
- function buildSharedStrings(workbook) {
42122
- const strings = [];
42123
- const index = /* @__PURE__ */ new Map();
42124
- const richTextMap = /* @__PURE__ */ new Map();
42125
- let totalCount = 0;
42126
- for (const sheet of workbook.sheets) {
42127
- for (const cell of sheet.cells.values()) {
42128
- if (cell.error) continue;
42129
- if (cell.formula && typeof cell.value === "string") continue;
42130
- if (typeof cell.value === "string") {
42131
- totalCount++;
42132
- if (!index.has(cell.value)) {
42133
- index.set(cell.value, strings.length);
42134
- strings.push(cell.value);
42135
- if (cell.richText && cell.richText.length > 0) {
42136
- richTextMap.set(cell.value, cell.richText);
42137
- }
42138
- }
42139
- }
42120
+ function sameTuple(a, b) {
42121
+ if (a.length !== b.length) return false;
42122
+ for (let i2 = 0; i2 < a.length; i2++) {
42123
+ if (a[i2] !== b[i2]) {
42124
+ const an = a[i2] === void 0 || a[i2] === null || a[i2] === "";
42125
+ const bn = b[i2] === void 0 || b[i2] === null || b[i2] === "";
42126
+ if (!(an && bn)) return false;
42140
42127
  }
42141
42128
  }
42142
- const siEntries = strings.map((s) => {
42143
- const richText = richTextMap.get(s);
42144
- if (richText) {
42145
- return `<si>${richText.map((part) => buildRichTextRun(part)).join("")}</si>`;
42146
- }
42147
- const needsPreserve = s.length === 0 || s !== s.trim();
42148
- const spaceAttr = needsPreserve ? ' xml:space="preserve"' : "";
42149
- return `<si><t${spaceAttr}>${escapeXml(s)}</t></si>`;
42150
- });
42151
- const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42152
- <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${totalCount}" uniqueCount="${strings.length}">
42153
- ${siEntries.join("\n")}
42154
- </sst>`;
42155
- return { xml, index };
42129
+ return true;
42156
42130
  }
42157
- function buildRichTextRun(part) {
42158
- const needsPreserve = part.text.length === 0 || part.text !== part.text.trim();
42159
- const spaceAttr = needsPreserve ? ' xml:space="preserve"' : "";
42160
- if (!part.font) {
42161
- return `<r><t${spaceAttr}>${escapeXml(part.text)}</t></r>`;
42162
- }
42163
- return `<r>${buildRichTextRunProps(part.font)}<t${spaceAttr}>${escapeXml(part.text)}</t></r>`;
42131
+ function formatCellLabel(v) {
42132
+ if (v === void 0 || v === null || v === "") return "(blank)";
42133
+ if (typeof v === "boolean") return v ? "TRUE" : "FALSE";
42134
+ return String(v);
42164
42135
  }
42165
- function buildRichTextRunProps(font) {
42166
- let parts = "";
42167
- if (font.bold) parts += "<b/>";
42168
- if (font.italic) parts += "<i/>";
42169
- if (font.strike) parts += "<strike/>";
42170
- if (font.underline) parts += `<u val="${font.underline}"/>`;
42171
- if (font.vertAlign) parts += `<vertAlign val="${font.vertAlign}"/>`;
42172
- if (font.size) parts += `<sz val="${font.size}"/>`;
42173
- if (font.color) parts += `<color rgb="${hexToArgb(font.color)}"/>`;
42174
- if (font.name) parts += `<rFont val="${escapeXml(font.name)}"/>`;
42175
- return `<rPr>${parts}</rPr>`;
42176
- }
42177
- function buildStylesXml(workbook) {
42178
- const styles = [];
42179
- for (let i2 = 0; i2 < workbook.styles.size; i2++) {
42180
- styles.push(workbook.styles.get(i2));
42136
+
42137
+ // ../xlsx/src/pivot_model.ts
42138
+ var PivotTableModel = class {
42139
+ constructor(config, cache, authored = false) {
42140
+ this.config = config;
42141
+ this.cache = cache;
42142
+ this.authored = authored;
42181
42143
  }
42182
- const numFmtMap = /* @__PURE__ */ new Map();
42183
- let nextNumFmtId = 164;
42184
- for (const sheet of workbook.sheets) {
42185
- for (const cell of sheet.cells.values()) {
42186
- if (cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "") {
42187
- if (!numFmtMap.has(cell.numFmtCode)) {
42188
- numFmtMap.set(cell.numFmtCode, nextNumFmtId++);
42189
- }
42190
- }
42144
+ /**
42145
+ * Recompute the pivot result from the workbook's current source data.
42146
+ * Callers are responsible for triggering recomputation; the model does
42147
+ * not subscribe to workbook changes itself.
42148
+ */
42149
+ recompute(workbook) {
42150
+ const source = readSourceData(workbook, this.cache);
42151
+ if (!source) {
42152
+ this.result = void 0;
42153
+ return;
42191
42154
  }
42155
+ this.result = recomputePivot(this.config, this.cache, source);
42192
42156
  }
42193
- const cellNumFmtIds = /* @__PURE__ */ new Map();
42194
- for (let si = 0; si < workbook.sheets.length; si++) {
42195
- for (const [ref, cell] of workbook.sheets[si].cells) {
42196
- if (cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "") {
42197
- const id = numFmtMap.get(cell.numFmtCode);
42198
- if (id !== void 0) cellNumFmtIds.set(`${si}:${ref}`, id);
42199
- }
42200
- }
42157
+ };
42158
+ function readSourceData(workbook, cache) {
42159
+ if (cache.source.type !== "worksheet") return void 0;
42160
+ const source = cache.source;
42161
+ const sheet = workbook.sheets.find((s) => s.name === source.sheetName);
42162
+ if (!sheet) return void 0;
42163
+ const range = parseRange(source.ref);
42164
+ if (!range) return void 0;
42165
+ const header = [];
42166
+ for (let col = range.startCol; col <= range.endCol; col++) {
42167
+ const cell = sheet.getCell(rowColToRef(range.startRow, col));
42168
+ header.push(formatHeader(cell?.value));
42201
42169
  }
42202
- const fonts = /* @__PURE__ */ new Map();
42203
- const fontList = [];
42204
- fonts.set("default", 0);
42205
- fontList.push({});
42206
- for (const s of styles) {
42207
- const key = fontKey(s);
42208
- if (!fonts.has(key)) {
42209
- fonts.set(key, fontList.length);
42210
- fontList.push(s);
42170
+ const records = [];
42171
+ for (let row = range.startRow + 1; row <= range.endRow; row++) {
42172
+ const rec = [];
42173
+ for (let col = range.startCol; col <= range.endCol; col++) {
42174
+ const cell = sheet.getCell(rowColToRef(row, col));
42175
+ rec.push(coerceValue(cell?.value));
42211
42176
  }
42177
+ records.push(rec);
42212
42178
  }
42213
- const fillEntries = [];
42214
- const fillMap = /* @__PURE__ */ new Map();
42215
- fillEntries.push('<fill><patternFill patternType="none"/></fill>');
42216
- fillEntries.push('<fill><patternFill patternType="gray125"/></fill>');
42217
- fillMap.set("", 0);
42218
- for (const s of styles) {
42219
- const fk = fillKey(s);
42220
- if (fk === "" || fillMap.has(fk)) continue;
42221
- fillMap.set(fk, fillEntries.length);
42222
- fillEntries.push(buildFillXml(s));
42223
- }
42224
- const borderEntries = [];
42225
- const borderMap = /* @__PURE__ */ new Map();
42226
- borderEntries.push("<border><left/><right/><top/><bottom/><diagonal/></border>");
42227
- borderMap.set("", 0);
42228
- for (const s of styles) {
42229
- const bk = borderKey(s);
42230
- if (bk === "" || borderMap.has(bk)) continue;
42231
- borderMap.set(bk, borderEntries.length);
42232
- borderEntries.push(buildBorderXml(s));
42233
- }
42234
- const fontsXml = fontList.map((f) => buildFontXml(f)).join("\n");
42235
- const fillsXml = fillEntries.join("\n");
42236
- const bordersXml = borderEntries.join("\n");
42237
- let numFmtsXml = "";
42238
- if (numFmtMap.size > 0) {
42239
- const entries = Array.from(numFmtMap.entries()).map(([code, id]) => `<numFmt numFmtId="${id}" formatCode="${escapeXml(code)}"/>`).join("\n");
42240
- numFmtsXml = `<numFmts count="${numFmtMap.size}">
42241
- ${entries}
42242
- </numFmts>
42243
- `;
42244
- }
42245
- const xfEntries = [];
42246
- const xfMap = /* @__PURE__ */ new Map();
42247
- for (let styleIdx = 0; styleIdx < styles.length; styleIdx++) {
42248
- const s = styles[styleIdx];
42249
- const fontId = fonts.get(fontKey(s)) ?? 0;
42250
- const fillId = fillMap.get(fillKey(s)) ?? 0;
42251
- const borderId = borderMap.get(borderKey(s)) ?? 0;
42252
- const xfKey = `${styleIdx}:0`;
42253
- xfMap.set(xfKey, xfEntries.length);
42254
- xfEntries.push(buildXfXml(s, fontId, fillId, borderId, 0));
42179
+ return { header, records };
42180
+ }
42181
+ function formatHeader(v) {
42182
+ if (v === void 0 || v === null) return "";
42183
+ return String(v);
42184
+ }
42185
+ function coerceValue(v) {
42186
+ if (v === void 0 || v === null) return void 0;
42187
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
42188
+ return v;
42255
42189
  }
42256
- for (const [cellKey2, numFmtId] of cellNumFmtIds) {
42257
- const [siStr, ref] = cellKey2.split(":");
42258
- const cell = workbook.sheets[parseInt(siStr)].cells.get(ref);
42259
- if (!cell) continue;
42260
- const xfKey = `${cell.styleIndex}:${numFmtId}`;
42261
- if (xfMap.has(xfKey)) continue;
42262
- const s = styles[cell.styleIndex] ?? {};
42263
- const fontId = fonts.get(fontKey(s)) ?? 0;
42264
- const fillId = fillMap.get(fillKey(s)) ?? 0;
42265
- const borderId = borderMap.get(borderKey(s)) ?? 0;
42266
- xfMap.set(xfKey, xfEntries.length);
42267
- xfEntries.push(buildXfXml(s, fontId, fillId, borderId, numFmtId));
42190
+ return String(v);
42191
+ }
42192
+ function parseRange(ref) {
42193
+ const range = ref.includes("!") ? ref.split("!")[1] : ref;
42194
+ const cleaned = range.replace(/\$/g, "");
42195
+ const m = cleaned.match(/^([A-Z]+\d+)(?::([A-Z]+\d+))?$/);
42196
+ if (!m) return void 0;
42197
+ const start = refToRowCol(m[1]);
42198
+ if (!start) return void 0;
42199
+ const endRef = m[2] ?? m[1];
42200
+ const end = refToRowCol(endRef);
42201
+ if (!end) return void 0;
42202
+ return {
42203
+ startRow: start.row,
42204
+ startCol: start.col,
42205
+ endRow: end.row,
42206
+ endCol: end.col
42207
+ };
42208
+ }
42209
+
42210
+ // ../xlsx/src/pivot_writer.ts
42211
+ var MAIN_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
42212
+ var REL_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
42213
+ function sourceValueToItem(v) {
42214
+ if (v === void 0 || v === null || v === "") return { kind: "missing" };
42215
+ if (typeof v === "number") return { kind: "number", value: v };
42216
+ if (typeof v === "boolean") return { kind: "boolean", value: v };
42217
+ return { kind: "string", value: v };
42218
+ }
42219
+ function cacheItemKey(item) {
42220
+ switch (item.kind) {
42221
+ case "missing":
42222
+ return "m:";
42223
+ case "number":
42224
+ return `n:${item.value}`;
42225
+ case "boolean":
42226
+ return `b:${item.value}`;
42227
+ case "string":
42228
+ return `s:${item.value}`;
42229
+ case "date":
42230
+ return `d:${item.value}`;
42231
+ case "error":
42232
+ return `e:${item.value}`;
42268
42233
  }
42269
- const dxfEntries = [];
42270
- const dxfMap = /* @__PURE__ */ new Map();
42271
- for (const sheet of workbook.sheets) {
42272
- for (const cf of sheet.conditionalFormats) {
42273
- for (const rule of cf.rules) {
42274
- if (rule.ruleType === "style" && rule.style) {
42275
- const key = JSON.stringify(rule.style);
42276
- if (!dxfMap.has(key)) {
42277
- dxfMap.set(key, dxfEntries.length);
42278
- dxfEntries.push(buildDxfXml(rule.style));
42279
- }
42234
+ }
42235
+ function enumerateFlags(table, fieldCount) {
42236
+ const axis = /* @__PURE__ */ new Set([...table.rowFieldIndices, ...table.colFieldIndices, ...table.pageFieldIndices]);
42237
+ return Array.from({ length: fieldCount }, (_, i2) => axis.has(i2));
42238
+ }
42239
+ function buildPivotCacheRecordsXml(records, cache, enumerate) {
42240
+ const indexMaps = cache.fields.map((f, i2) => {
42241
+ if (!enumerate[i2]) return void 0;
42242
+ const m = /* @__PURE__ */ new Map();
42243
+ f.items.forEach((item, idx) => m.set(cacheItemKey(item), idx));
42244
+ return m;
42245
+ });
42246
+ const rows = records.map((rec) => {
42247
+ const cells = cache.fields.map((_f, i2) => {
42248
+ const item = sourceValueToItem(rec[i2]);
42249
+ const map2 = indexMaps[i2];
42250
+ if (map2) {
42251
+ const idx = map2.get(cacheItemKey(item));
42252
+ if (idx === void 0) {
42253
+ throw new Error(
42254
+ `buildPivotCacheRecordsXml: value ${JSON.stringify(rec[i2])} for field "${cache.fields[i2].name}" is missing from its cached shared items`
42255
+ );
42280
42256
  }
42257
+ return `<x v="${idx}"/>`;
42281
42258
  }
42282
- }
42283
- }
42284
- let dxfsXml = '<dxfs count="0"/>';
42285
- if (dxfEntries.length > 0) {
42286
- dxfsXml = `<dxfs count="${dxfEntries.length}">
42287
- ${dxfEntries.join("\n")}
42288
- </dxfs>`;
42289
- }
42290
- const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42291
- <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
42292
- ${numFmtsXml}<fonts count="${fontList.length}">
42293
- ${fontsXml}
42294
- </fonts>
42295
- <fills count="${fillEntries.length}">
42296
- ${fillsXml}
42297
- </fills>
42298
- <borders count="${borderEntries.length}">
42299
- ${bordersXml}
42300
- </borders>
42301
- <cellStyleXfs count="1">
42302
- <xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
42303
- </cellStyleXfs>
42304
- <cellXfs count="${xfEntries.length}">
42305
- ${xfEntries.join("\n")}
42306
- </cellXfs>
42307
- <cellStyles count="1">
42308
- <cellStyle name="Normal" xfId="0" builtinId="0"/>
42309
- </cellStyles>
42310
- ${dxfsXml}
42311
- </styleSheet>`;
42312
- return { xml, xfMap, numFmtMap, dxfMap };
42259
+ return inlineRecordCell(item);
42260
+ });
42261
+ return `<r>${cells.join("")}</r>`;
42262
+ });
42263
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42264
+ <pivotCacheRecords xmlns="${MAIN_NS}" xmlns:r="${REL_NS}" count="${records.length}">` + rows.join("") + `</pivotCacheRecords>`;
42313
42265
  }
42314
- function buildXfXml(s, fontId, fillId, borderId, numFmtId) {
42315
- let attrs = `numFmtId="${numFmtId}" fontId="${fontId}" fillId="${fillId}" borderId="${borderId}" xfId="0"`;
42316
- if (numFmtId > 0) attrs += ' applyNumberFormat="1"';
42317
- if (fontId > 0) attrs += ' applyFont="1"';
42318
- if (fillId > 0) attrs += ' applyFill="1"';
42319
- if (borderId > 0) attrs += ' applyBorder="1"';
42320
- if (s.horizontalAlign || s.verticalAlign || s.wrapText || s.indent || s.textRotation || s.shrinkToFit) {
42321
- const hAlign = s.horizontalAlign ? ` horizontal="${s.horizontalAlign}"` : "";
42322
- const vAlign = s.verticalAlign ? ` vertical="${s.verticalAlign}"` : "";
42323
- const wrap = s.wrapText ? ' wrapText="1"' : "";
42324
- const indent = s.indent ? ` indent="${s.indent}"` : "";
42325
- const rotation = s.textRotation !== void 0 ? ` textRotation="${s.textRotation === "vertical" ? 255 : s.textRotation}"` : "";
42326
- const shrink = s.shrinkToFit ? ' shrinkToFit="1"' : "";
42327
- return `<xf ${attrs} applyAlignment="1"><alignment${hAlign}${vAlign}${wrap}${indent}${rotation}${shrink}/></xf>`;
42266
+ function inlineRecordCell(item) {
42267
+ switch (item.kind) {
42268
+ case "missing":
42269
+ return "<m/>";
42270
+ case "number":
42271
+ return `<n v="${item.value}"/>`;
42272
+ case "boolean":
42273
+ return `<b v="${item.value ? 1 : 0}"/>`;
42274
+ case "date":
42275
+ return `<d v="${escapeXml(item.value)}"/>`;
42276
+ case "error":
42277
+ return `<e v="${escapeXml(item.value)}"/>`;
42278
+ case "string":
42279
+ return `<s v="${escapeXml(item.value)}"/>`;
42328
42280
  }
42329
- return `<xf ${attrs}/>`;
42330
- }
42331
- function fontKey(s) {
42332
- return `${s.fontName ?? ""}|${s.fontSize ?? 0}|${s.fontBold ? 1 : 0}|${s.fontItalic ? 1 : 0}|${s.fontColor ?? ""}|${s.fontUnderline ?? ""}|${s.fontStrike ? 1 : 0}`;
42333
42281
  }
42334
- function buildFontXml(s) {
42335
- let parts = "";
42336
- if (s.fontBold) parts += "<b/>";
42337
- if (s.fontItalic) parts += "<i/>";
42338
- if (s.fontStrike) parts += "<strike/>";
42339
- if (s.fontUnderline) parts += `<u val="${s.fontUnderline}"/>`;
42340
- parts += `<sz val="${s.fontSize ?? 11}"/>`;
42341
- if (s.fontColor) {
42342
- parts += `<color rgb="${hexToArgb(s.fontColor)}"/>`;
42343
- } else {
42344
- parts += '<color theme="1"/>';
42282
+ function buildPivotCacheDefinitionXml(cache, enumerate, recordCount, recordsRelId) {
42283
+ if (cache.source.type !== "worksheet") {
42284
+ throw new Error("buildPivotCacheDefinitionXml: only worksheet sources are supported");
42285
+ }
42286
+ const src = cache.source;
42287
+ const fields = cache.fields.map((f, i2) => cacheFieldXml(f, enumerate[i2])).join("");
42288
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42289
+ <pivotCacheDefinition xmlns="${MAIN_NS}" xmlns:r="${REL_NS}" r:id="${recordsRelId}" refreshOnLoad="1" refreshedBy="Lotics" createdVersion="6" refreshedVersion="6" minRefreshableVersion="3" recordCount="${recordCount}"><cacheSource type="worksheet"><worksheetSource ref="${escapeXml(src.ref)}" sheet="${escapeXml(src.sheetName)}"/></cacheSource><cacheFields count="${cache.fields.length}">${fields}</cacheFields></pivotCacheDefinition>`;
42290
+ }
42291
+ function cacheFieldXml(field, enumerate) {
42292
+ const name = `name="${escapeXml(field.name)}" numFmtId="0"`;
42293
+ if (!enumerate) {
42294
+ const flags = `containsBlank="${field.items.length === 0 ? 0 : 1}"` + (field.containsNumber ? ` containsString="0" containsNumber="1"` : "");
42295
+ return `<cacheField ${name}><sharedItems ${flags}/></cacheField>`;
42296
+ }
42297
+ const items = field.items.map(sharedItemXml).join("");
42298
+ const hasString = field.items.some((i2) => i2.kind === "string");
42299
+ const hasNumber = field.items.some((i2) => i2.kind === "number");
42300
+ const hasBlank = field.items.some((i2) => i2.kind === "missing");
42301
+ const attrs = `count="${field.items.length}"` + (hasBlank ? ` containsBlank="1"` : "") + (hasNumber && !hasString ? ` containsString="0" containsNumber="1"` : "");
42302
+ return `<cacheField ${name}><sharedItems ${attrs}>${items}</sharedItems></cacheField>`;
42303
+ }
42304
+ function sharedItemXml(item) {
42305
+ switch (item.kind) {
42306
+ case "missing":
42307
+ return `<m/>`;
42308
+ case "number":
42309
+ return `<n v="${item.value}"/>`;
42310
+ case "boolean":
42311
+ return `<b v="${item.value ? 1 : 0}"/>`;
42312
+ case "date":
42313
+ return `<d v="${escapeXml(item.value)}"/>`;
42314
+ case "error":
42315
+ return `<e v="${escapeXml(item.value)}"/>`;
42316
+ case "string":
42317
+ return `<s v="${escapeXml(item.value)}"/>`;
42345
42318
  }
42346
- parts += `<name val="${escapeXml(s.fontName ?? "Calibri")}"/>`;
42347
- return `<font>${parts}</font>`;
42348
42319
  }
42349
- function borderKey(s) {
42350
- const parts = [];
42351
- if (s.borderTop) parts.push(`t:${s.borderTop.style}:${s.borderTop.width}:${s.borderTop.color ?? ""}`);
42352
- if (s.borderRight) parts.push(`r:${s.borderRight.style}:${s.borderRight.width}:${s.borderRight.color ?? ""}`);
42353
- if (s.borderBottom) parts.push(`b:${s.borderBottom.style}:${s.borderBottom.width}:${s.borderBottom.color ?? ""}`);
42354
- if (s.borderLeft) parts.push(`l:${s.borderLeft.style}:${s.borderLeft.width}:${s.borderLeft.color ?? ""}`);
42355
- if (s.borderDiagonal) parts.push(`d:${s.borderDiagonal.style}:${s.borderDiagonal.width}:${s.borderDiagonal.color ?? ""}`);
42356
- if (s.diagonalUp) parts.push("du");
42357
- if (s.diagonalDown) parts.push("dd");
42358
- return parts.join("|");
42320
+ var SUBTOTAL_FN_TO_ENUM = {
42321
+ sum: "sum",
42322
+ count: "count",
42323
+ countNums: "countNums",
42324
+ average: "average",
42325
+ min: "min",
42326
+ max: "max",
42327
+ product: "product"
42328
+ };
42329
+ function buildPivotTableXml(table, cache) {
42330
+ const rowField = table.rowFieldIndices[0];
42331
+ const colField = table.colFieldIndices[0];
42332
+ if (rowField === void 0 || colField === void 0) {
42333
+ throw new Error("buildPivotTableXml: a row field and a column field are required");
42334
+ }
42335
+ const pageSet = new Set(table.pageFieldIndices);
42336
+ const pivotFields = cache.fields.map((f, i2) => {
42337
+ const onAxis = i2 === rowField ? "axisRow" : i2 === colField ? "axisCol" : pageSet.has(i2) ? "axisPage" : void 0;
42338
+ if (onAxis) return axisPivotFieldXml(onAxis, f.items.length);
42339
+ if (table.dataFields.some((d) => d.fieldIndex === i2)) {
42340
+ return `<pivotField dataField="1" showAll="0"/>`;
42341
+ }
42342
+ return `<pivotField showAll="0"/>`;
42343
+ }).join("");
42344
+ const rowCount = cache.fields[rowField].items.length;
42345
+ const colCount = cache.fields[colField].items.length;
42346
+ const rowItems = axisItemsXml("rowItems", rowCount, table.display.colGrandTotals);
42347
+ const colItems = axisItemsXml("colItems", colCount, table.display.rowGrandTotals);
42348
+ const pageFieldsXml = table.pageFieldIndices.length ? `<pageFields count="${table.pageFieldIndices.length}">` + table.pageFieldIndices.map((fld) => {
42349
+ const sel = table.fields[fld]?.selectedPageItem;
42350
+ const item = sel === null || sel === void 0 ? "" : ` item="${sel}"`;
42351
+ return `<pageField fld="${fld}"${item} hier="-1"/>`;
42352
+ }).join("") + `</pageFields>` : "";
42353
+ const dataFieldsXml = `<dataFields count="${table.dataFields.length}">` + table.dataFields.map((d) => {
42354
+ const fn = SUBTOTAL_FN_TO_ENUM[d.subtotal] ?? "sum";
42355
+ const sub = fn === "sum" ? "" : ` subtotal="${fn}"`;
42356
+ const numFmt = d.numFmt ? ` numFmtId="${escapeXml(d.numFmt)}"` : "";
42357
+ return `<dataField name="${escapeXml(d.name)}" fld="${d.fieldIndex}"${sub} baseField="0" baseItem="0"${numFmt}/>`;
42358
+ }).join("") + `</dataFields>`;
42359
+ const style = `<pivotTableStyleInfo name="${escapeXml(table.styleName ?? "PivotStyleLight16")}" showRowHeaders="1" showColHeaders="1" showRowStripes="${table.display.showRowStripes ? 1 : 0}" showColStripes="${table.display.showColStripes ? 1 : 0}" showLastColumn="1"/>`;
42360
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42361
+ <pivotTableDefinition xmlns="${MAIN_NS}" xmlns:r="${REL_NS}" name="${escapeXml(table.name)}" cacheId="${table.cacheId}" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Values" updatedVersion="6" minRefreshableVersion="3" useAutoFormatting="1" itemPrintTitles="1" createdVersion="6" indent="0" outline="1" outlineData="1" multipleFieldFilters="0" rowGrandTotals="${table.display.rowGrandTotals ? 1 : 0}" colGrandTotals="${table.display.colGrandTotals ? 1 : 0}"><location ref="${escapeXml(table.ref)}" firstHeaderRow="${table.firstHeaderRow}" firstDataRow="${table.firstDataRow}" firstDataCol="${table.firstDataCol}"/><pivotFields count="${cache.fields.length}">${pivotFields}</pivotFields><rowFields count="1"><field x="${rowField}"/></rowFields>` + rowItems + `<colFields count="1"><field x="${colField}"/></colFields>` + colItems + pageFieldsXml + dataFieldsXml + style + `</pivotTableDefinition>`;
42359
42362
  }
42360
- function toOoxmlBorderStyle(border2) {
42361
- const ooxmlStyles = [
42362
- "thin",
42363
- "medium",
42364
- "thick",
42365
- "dotted",
42366
- "dashed",
42367
- "double",
42368
- "hair",
42369
- "mediumDashed",
42370
- "dashDot",
42371
- "mediumDashDot",
42372
- "dashDotDot",
42373
- "mediumDashDotDot",
42374
- "slantDashDot"
42375
- ];
42376
- if (ooxmlStyles.includes(border2.style)) return border2.style;
42377
- if (border2.style === "solid") {
42378
- if (border2.width <= 1) return "thin";
42379
- if (border2.width <= 2) return "medium";
42380
- return "thick";
42381
- }
42382
- if (border2.style === "dashed") return "dashed";
42383
- if (border2.style === "dotted") return "dotted";
42384
- if (border2.style === "double") return "double";
42385
- return "thin";
42363
+ function axisPivotFieldXml(axis, itemCount) {
42364
+ const items = [];
42365
+ for (let i2 = 0; i2 < itemCount; i2++) items.push(`<item x="${i2}"/>`);
42366
+ items.push(`<item t="default"/>`);
42367
+ return `<pivotField axis="${axis}" showAll="0"><items count="${items.length}">${items.join("")}</items></pivotField>`;
42386
42368
  }
42387
- function buildBorderXml(s) {
42388
- let attrs = "";
42389
- if (s.diagonalUp) attrs += ' diagonalUp="1"';
42390
- if (s.diagonalDown) attrs += ' diagonalDown="1"';
42391
- const sides = [
42392
- { tag: "left", border: s.borderLeft },
42393
- { tag: "right", border: s.borderRight },
42394
- { tag: "top", border: s.borderTop },
42395
- { tag: "bottom", border: s.borderBottom },
42396
- { tag: "diagonal", border: s.borderDiagonal }
42397
- ];
42398
- const inner = sides.map(({ tag, border: border2 }) => {
42399
- if (!border2) return `<${tag}/>`;
42400
- const ooxmlStyle = toOoxmlBorderStyle(border2);
42401
- let colorXml = "";
42402
- if (border2.color) {
42403
- colorXml = `<color rgb="${hexToArgb(border2.color)}"/>`;
42404
- }
42405
- return `<${tag} style="${ooxmlStyle}">${colorXml}</${tag}>`;
42406
- }).join("");
42407
- return `<border${attrs}>${inner}</border>`;
42369
+ function axisItemsXml(element, itemCount, grandTotal) {
42370
+ const items = [];
42371
+ for (let i2 = 0; i2 < itemCount; i2++) items.push(`<i><x v="${i2}"/></i>`);
42372
+ if (grandTotal) items.push(`<i t="grand"><x/></i>`);
42373
+ return `<${element} count="${items.length}">${items.join("")}</${element}>`;
42408
42374
  }
42409
- function fillKey(s) {
42410
- if (s.gradientData) return `gradient:${JSON.stringify(s.gradientData)}`;
42411
- if (s.patternType && s.backgroundPattern) return `pattern:${s.patternType}|${s.backgroundPattern}`;
42412
- if (s.backgroundColor) return `solid:${s.backgroundColor}`;
42413
- return "";
42375
+
42376
+ // ../xlsx/src/xlsx_writer.ts
42377
+ function readWorkbookSheetOrder(originalZip) {
42378
+ const wbBytes = originalZip["xl/workbook.xml"];
42379
+ if (!wbBytes) return [];
42380
+ const xml = decode(wbBytes);
42381
+ const out = [];
42382
+ const re = /<sheet\b[^>]*?r:id="([^"]+)"/g;
42383
+ let m;
42384
+ while ((m = re.exec(xml)) !== null) {
42385
+ out.push(m[1]);
42386
+ }
42387
+ return out;
42414
42388
  }
42415
- function buildFillXml(s) {
42416
- if (s.gradientData) {
42417
- const g = s.gradientData;
42418
- const stops = g.stops.map((stop) => {
42419
- const hex = hexToArgb(stop.color);
42420
- return `<stop position="${stop.position}"><color rgb="${hex}"/></stop>`;
42421
- }).join("");
42422
- if (g.type === "radial") {
42423
- return `<fill><gradientFill type="path" left="0.5" right="0.5" top="0.5" bottom="0.5">${stops}</gradientFill></fill>`;
42389
+ function readWorkbookRels(originalZip) {
42390
+ const out = /* @__PURE__ */ new Map();
42391
+ const bytes = originalZip["xl/_rels/workbook.xml.rels"];
42392
+ if (!bytes) return out;
42393
+ const xml = decode(bytes);
42394
+ const re = /<Relationship\b([^/]*?)\/>/g;
42395
+ let m;
42396
+ while ((m = re.exec(xml)) !== null) {
42397
+ const attrs = m[1];
42398
+ const id = /\bId="([^"]+)"/.exec(attrs)?.[1];
42399
+ const type = /\bType="([^"]+)"/.exec(attrs)?.[1] ?? "";
42400
+ const target = /\bTarget="([^"]+)"/.exec(attrs)?.[1] ?? "";
42401
+ if (id) out.set(id, { type, target });
42402
+ }
42403
+ return out;
42404
+ }
42405
+ function readPivotCacheIdMap(originalZip) {
42406
+ const out = /* @__PURE__ */ new Map();
42407
+ const bytes = originalZip["xl/workbook.xml"];
42408
+ if (!bytes) return out;
42409
+ const xml = decode(bytes);
42410
+ const re = /<pivotCache\b([^/]*?)\/>/g;
42411
+ let m;
42412
+ while ((m = re.exec(xml)) !== null) {
42413
+ const attrs = m[1];
42414
+ const cacheIdMatch = /\bcacheId="(\d+)"/.exec(attrs);
42415
+ const ridMatch = /\br:id="([^"]+)"/.exec(attrs);
42416
+ if (cacheIdMatch && ridMatch) {
42417
+ out.set(parseInt(cacheIdMatch[1], 10), ridMatch[1]);
42424
42418
  }
42425
- return `<fill><gradientFill degree="${g.degree}">${stops}</gradientFill></fill>`;
42426
42419
  }
42427
- if (s.patternType && s.backgroundPattern) {
42428
- const colors = extractFillColors(s.backgroundPattern);
42429
- let colorAttrs = "";
42430
- if (colors.fg) colorAttrs += `<fgColor rgb="${hexToArgb(colors.fg)}"/>`;
42431
- if (colors.bg) colorAttrs += `<bgColor rgb="${hexToArgb(colors.bg)}"/>`;
42432
- return `<fill><patternFill patternType="${escapeXml(s.patternType)}">${colorAttrs}</patternFill></fill>`;
42420
+ return out;
42421
+ }
42422
+ function readSheetPivotPaths(originalZip, sheetTarget) {
42423
+ const sheetPath = `xl/${sheetTarget}`;
42424
+ const relsPath = sheetPath.replace(/([^/]+)$/, "_rels/$1.rels");
42425
+ const bytes = originalZip[relsPath];
42426
+ if (!bytes) return [];
42427
+ const xml = decode(bytes);
42428
+ const re = /<Relationship\b([^/]*?)\/>/g;
42429
+ const out = [];
42430
+ let m;
42431
+ while ((m = re.exec(xml)) !== null) {
42432
+ const attrs = m[1];
42433
+ const type = /\bType="([^"]+)"/.exec(attrs)?.[1] ?? "";
42434
+ if (!type.includes("/pivotTable")) continue;
42435
+ const target = /\bTarget="([^"]+)"/.exec(attrs)?.[1];
42436
+ if (target) out.push(target);
42433
42437
  }
42434
- return `<fill><patternFill patternType="solid"><fgColor rgb="${hexToArgb(s.backgroundColor)}"/></patternFill></fill>`;
42438
+ return out;
42435
42439
  }
42436
- function extractFillColors(css) {
42437
- const colorMatches = css.match(/rgba?\([^)]+\)/g);
42438
- if (colorMatches) {
42439
- return { fg: colorMatches[0], bg: colorMatches[1] };
42440
+ function extractPivotRoundTripInfo(originalZip) {
42441
+ const empty = {
42442
+ cachesByWorkbook: /* @__PURE__ */ new Map(),
42443
+ pivotTablesBySheetIndex: /* @__PURE__ */ new Map(),
42444
+ pivotXmlPaths: []
42445
+ };
42446
+ if (!originalZip) return empty;
42447
+ const sheetRIds = readWorkbookSheetOrder(originalZip);
42448
+ const wbRels = readWorkbookRels(originalZip);
42449
+ const cacheRIds = readPivotCacheIdMap(originalZip);
42450
+ const cachesByWorkbook = /* @__PURE__ */ new Map();
42451
+ for (const [cacheId, rid] of cacheRIds) {
42452
+ const rel = wbRels.get(rid);
42453
+ if (!rel) continue;
42454
+ cachesByWorkbook.set(cacheId, rel.target);
42440
42455
  }
42441
- const hexMatches = css.match(/#[0-9a-fA-F]{6}/g);
42442
- if (hexMatches) {
42443
- return { fg: hexMatches[0], bg: hexMatches[1] };
42456
+ const pivotTablesBySheetIndex = /* @__PURE__ */ new Map();
42457
+ for (let i2 = 0; i2 < sheetRIds.length; i2++) {
42458
+ const sheetTarget = wbRels.get(sheetRIds[i2])?.target;
42459
+ if (!sheetTarget) continue;
42460
+ const paths = readSheetPivotPaths(originalZip, sheetTarget);
42461
+ if (paths.length > 0) pivotTablesBySheetIndex.set(i2, paths);
42444
42462
  }
42445
- return { fg: void 0, bg: void 0 };
42446
- }
42447
- function buildSheetXml(sheet, styles, ssIndex, isActive, xfMap, numFmtMap, dxfMap, drawingRId, tableRIds, hyperlinkRIds) {
42448
- const rows = [];
42449
- const rowMap = /* @__PURE__ */ new Map();
42450
- for (const [ref, cell] of sheet.cells) {
42451
- const rc = refToRowCol(ref);
42452
- if (!rc) continue;
42453
- let arr = rowMap.get(rc.row);
42454
- if (!arr) {
42455
- arr = [];
42456
- rowMap.set(rc.row, arr);
42463
+ const pivotXmlPaths = [];
42464
+ for (const path7 of Object.keys(originalZip)) {
42465
+ if (path7.startsWith("xl/pivotTables/") && path7.endsWith(".xml")) {
42466
+ pivotXmlPaths.push(path7);
42467
+ }
42468
+ if (path7.startsWith("xl/pivotCache/") && path7.endsWith(".xml")) {
42469
+ pivotXmlPaths.push(path7);
42457
42470
  }
42458
- arr.push({ col: rc.col, cell });
42459
42471
  }
42460
- const sortedRows = Array.from(rowMap.keys()).sort((a, b) => a - b);
42461
- for (const rowNum of sortedRows) {
42462
- const cells = rowMap.get(rowNum);
42463
- cells.sort((a, b) => a.col - b.col);
42464
- const h = sheet.rowHeights.get(rowNum);
42465
- const rowAttrs = h ? ` ht="${h}" customHeight="1"` : "";
42466
- const hidden = sheet.hiddenRows.has(rowNum) ? ' hidden="1"' : "";
42467
- const cellsXml = cells.map(({ col, cell }) => {
42468
- const ref = rowColToRef(rowNum, col);
42469
- const type = getCellType(cell, ssIndex);
42470
- const value = getCellValue(cell, ssIndex);
42471
- let attrs = `r="${ref}"`;
42472
- let xfIndex = 0;
42473
- if (xfMap.size === 0 && cell.originalXfIndex !== void 0) {
42474
- xfIndex = cell.originalXfIndex;
42475
- } else {
42476
- const numFmtId = cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "" ? numFmtMap.get(cell.numFmtCode) ?? 0 : 0;
42477
- const xfKey = `${cell.styleIndex}:${numFmtId}`;
42478
- xfIndex = xfMap.get(xfKey) ?? 0;
42479
- }
42480
- if (xfIndex > 0) attrs += ` s="${xfIndex}"`;
42481
- if (type) attrs += ` t="${type}"`;
42482
- let inner = "";
42483
- if (cell.formula) {
42484
- if (cell.isArrayFormula && cell.arrayRange) {
42485
- inner += `<f t="array" ref="${cell.arrayRange}">${escapeXml(cell.formula)}</f>`;
42486
- } else {
42487
- inner += `<f>${escapeXml(cell.formula)}</f>`;
42488
- }
42489
- }
42490
- if (value !== void 0) inner += `<v>${escapeXml(String(value))}</v>`;
42491
- return `<c ${attrs}>${inner}</c>`;
42492
- }).join("");
42493
- rows.push(`<row r="${rowNum}"${rowAttrs}${hidden}>${cellsXml}</row>`);
42472
+ return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths };
42473
+ }
42474
+ function decode(bytes) {
42475
+ return new TextDecoder().decode(bytes);
42476
+ }
42477
+ function pivotContentTypeFor(path7) {
42478
+ if (path7.startsWith("xl/pivotTables/") && path7.endsWith(".xml")) {
42479
+ return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
42494
42480
  }
42495
- const cols = [];
42496
- const allCols = /* @__PURE__ */ new Set([...sheet.colWidths.keys(), ...sheet.hiddenCols]);
42497
- for (const c of Array.from(allCols).sort((a, b) => a - b)) {
42498
- const w = sheet.colWidths.get(c) ?? sheet.defaultColWidth;
42499
- const hidden = sheet.hiddenCols.has(c) ? ' hidden="1"' : "";
42500
- cols.push(`<col min="${c}" max="${c}" width="${w}" customWidth="1"${hidden}/>`);
42481
+ if (path7.includes("/pivotCacheDefinition") && path7.endsWith(".xml")) {
42482
+ return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
42501
42483
  }
42502
- let mergeXml = "";
42503
- if (sheet.mergedCells.length > 0) {
42504
- const merges = sheet.mergedCells.map((r) => `<mergeCell ref="${r}"/>`).join("");
42505
- mergeXml = `<mergeCells count="${sheet.mergedCells.length}">${merges}</mergeCells>`;
42484
+ if (path7.includes("/pivotCacheRecords") && path7.endsWith(".xml")) {
42485
+ return `<Override PartName="/${path7}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
42506
42486
  }
42507
- let paneXml = "";
42508
- let selectionXml = `<selection activeCell="A1" sqref="A1"/>`;
42509
- if (sheet.freeze) {
42510
- const activePane = sheet.freeze.col > 0 && sheet.freeze.row > 0 ? "bottomRight" : sheet.freeze.row > 0 ? "bottomLeft" : "topRight";
42511
- const topLeft = rowColToRef(sheet.freeze.row + 1, sheet.freeze.col + 1);
42512
- paneXml = `<pane xSplit="${sheet.freeze.col}" ySplit="${sheet.freeze.row}" topLeftCell="${topLeft}" activePane="${activePane}" state="frozen"/>`;
42513
- selectionXml = `<selection pane="${activePane}" activeCell="${topLeft}" sqref="${topLeft}"/>`;
42514
- }
42515
- const tabSelected = isActive ? ' tabSelected="1"' : "";
42516
- const sheetView = `<sheetView${tabSelected} workbookViewId="0"${!sheet.view.showGridLines ? ' showGridLines="0"' : ""}>${paneXml}${selectionXml}</sheetView>`;
42517
- let autoFilterXml = "";
42518
- if (sheet.autoFilter) {
42519
- let filterCols = "";
42520
- for (const col of sheet.autoFilter.columns) {
42521
- if (col.filterValues && col.filterValues.length > 0) {
42522
- const filters = col.filterValues.map((v) => `<filter val="${escapeXml(v)}"/>`).join("");
42523
- filterCols += `<filterColumn colId="${col.colIndex}"><filters>${filters}</filters></filterColumn>`;
42524
- }
42525
- }
42526
- autoFilterXml = `<autoFilter ref="${sheet.autoFilter.ref}">${filterCols}</autoFilter>`;
42527
- }
42528
- let dvXml = "";
42529
- if (sheet.dataValidations.length > 0) {
42530
- const dvEntries = sheet.dataValidations.map((dv) => {
42531
- let attrs = `sqref="${dv.ref}" type="${dv.type}"`;
42532
- if (dv.operator) attrs += ` operator="${dv.operator}"`;
42533
- if (!dv.showDropdown) attrs += ' showDropDown="1"';
42534
- if (dv.errorStyle) attrs += ` errorStyle="${dv.errorStyle}"`;
42535
- if (dv.errorTitle) attrs += ` errorTitle="${escapeXml(dv.errorTitle)}"`;
42536
- if (dv.errorMessage) attrs += ` error="${escapeXml(dv.errorMessage)}"`;
42537
- if (dv.promptTitle) attrs += ` promptTitle="${escapeXml(dv.promptTitle)}"`;
42538
- if (dv.promptMessage) attrs += ` prompt="${escapeXml(dv.promptMessage)}"`;
42539
- let inner = "";
42540
- if (dv.formula1) inner += `<formula1>${escapeXml(dv.formula1)}</formula1>`;
42541
- if (dv.formula2) inner += `<formula2>${escapeXml(dv.formula2)}</formula2>`;
42542
- return `<dataValidation ${attrs}>${inner}</dataValidation>`;
42543
- }).join("");
42544
- dvXml = `<dataValidations count="${sheet.dataValidations.length}">${dvEntries}</dataValidations>`;
42545
- }
42546
- let cfXml = "";
42547
- if (sheet.conditionalFormats.length > 0) {
42548
- cfXml = sheet.conditionalFormats.map((cf) => buildConditionalFormattingXml(cf, dxfMap)).join("");
42549
- }
42550
- let hyperlinksXml = "";
42551
- if (hyperlinkRIds && hyperlinkRIds.size > 0) {
42552
- const hlEntries = Array.from(hyperlinkRIds.entries()).map(([ref, rId]) => `<hyperlink ref="${ref}" r:id="${rId}"/>`).join("");
42553
- hyperlinksXml = `<hyperlinks>${hlEntries}</hyperlinks>`;
42554
- }
42555
- const drawingXml = drawingRId ? `<drawing r:id="${drawingRId}"/>` : "";
42556
- let tablePartsXml = "";
42557
- if (tableRIds && tableRIds.length > 0) {
42558
- const parts = tableRIds.map((rId) => `<tablePart r:id="${rId}"/>`).join("");
42559
- tablePartsXml = `<tableParts count="${tableRIds.length}">${parts}</tableParts>`;
42560
- }
42561
- const ps = sheet.pageSetup;
42562
- const hf = sheet.headerFooter;
42563
- const fitToPage = ps && (ps.fitToWidth !== void 0 || ps.fitToHeight !== void 0);
42564
- const sheetPrXml = fitToPage ? `<sheetPr><pageSetUpPr fitToPage="1"/></sheetPr>` : "";
42565
- const marginsXml = (() => {
42566
- const m = ps?.margins;
42567
- const left = m?.left ?? 0.7;
42568
- const right = m?.right ?? 0.7;
42569
- const top = m?.top ?? 0.75;
42570
- const bottom = m?.bottom ?? 0.75;
42571
- const header = m?.header ?? 0.3;
42572
- const footer = m?.footer ?? 0.3;
42573
- return `<pageMargins left="${left}" right="${right}" top="${top}" bottom="${bottom}" header="${header}" footer="${footer}"/>`;
42574
- })();
42575
- let pageSetupXml = "";
42576
- if (ps) {
42577
- const attrs = [];
42578
- if (ps.paperSize !== void 0) attrs.push(`paperSize="${ps.paperSize}"`);
42579
- if (ps.scale !== void 0) attrs.push(`scale="${ps.scale}"`);
42580
- if (ps.fitToWidth !== void 0) attrs.push(`fitToWidth="${ps.fitToWidth}"`);
42581
- if (ps.fitToHeight !== void 0) attrs.push(`fitToHeight="${ps.fitToHeight}"`);
42582
- if (ps.orientation) attrs.push(`orientation="${ps.orientation}"`);
42583
- if (attrs.length > 0) pageSetupXml = `<pageSetup ${attrs.join(" ")}/>`;
42584
- }
42585
- let headerFooterXml = "";
42586
- if (hf) {
42587
- const rootAttrs = [];
42588
- if (hf.differentOddEven) rootAttrs.push(`differentOddEven="1"`);
42589
- if (hf.differentFirst) rootAttrs.push(`differentFirst="1"`);
42590
- const inner = [];
42591
- if (hf.oddHeader) inner.push(`<oddHeader>${escapeXml(hf.oddHeader)}</oddHeader>`);
42592
- if (hf.oddFooter) inner.push(`<oddFooter>${escapeXml(hf.oddFooter)}</oddFooter>`);
42593
- if (hf.evenHeader) inner.push(`<evenHeader>${escapeXml(hf.evenHeader)}</evenHeader>`);
42594
- if (hf.evenFooter) inner.push(`<evenFooter>${escapeXml(hf.evenFooter)}</evenFooter>`);
42595
- if (hf.firstHeader) inner.push(`<firstHeader>${escapeXml(hf.firstHeader)}</firstHeader>`);
42596
- if (hf.firstFooter) inner.push(`<firstFooter>${escapeXml(hf.firstFooter)}</firstFooter>`);
42597
- if (inner.length > 0) {
42598
- const attrStr = rootAttrs.length > 0 ? ` ${rootAttrs.join(" ")}` : "";
42599
- headerFooterXml = `<headerFooter${attrStr}>${inner.join("")}</headerFooter>`;
42600
- }
42601
- }
42602
- let dimensionRef = "A1";
42603
- if (sortedRows.length > 0) {
42604
- let minCol = Infinity, maxCol = 0;
42605
- const minRow = sortedRows[0];
42606
- const maxRow = sortedRows[sortedRows.length - 1];
42607
- for (const rowNum of sortedRows) {
42608
- const cells = rowMap.get(rowNum);
42609
- for (const { col } of cells) {
42610
- if (col < minCol) minCol = col;
42611
- if (col > maxCol) maxCol = col;
42612
- }
42613
- }
42614
- dimensionRef = `${rowColToRef(minRow, minCol)}:${rowColToRef(maxRow, maxCol)}`;
42615
- }
42616
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42617
- <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
42618
- xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
42619
- ${sheetPrXml}<dimension ref="${dimensionRef}"/>
42620
- <sheetViews>${sheetView}</sheetViews>
42621
- <sheetFormatPr defaultRowHeight="${sheet.defaultRowHeight}" defaultColWidth="${sheet.defaultColWidth}"/>
42622
- ${cols.length > 0 ? `<cols>${cols.join("")}</cols>` : ""}
42623
- <sheetData>
42624
- ${rows.join("\n")}
42625
- </sheetData>
42626
- ${autoFilterXml}${mergeXml}${cfXml}${dvXml}${hyperlinksXml}${marginsXml}${pageSetupXml}${headerFooterXml}${drawingXml}${tablePartsXml}
42627
- </worksheet>`;
42628
- }
42629
- function getCellType(cell, ssIndex) {
42630
- if (cell.error) return "e";
42631
- if (cell.formula && typeof cell.value === "string") return "str";
42632
- if (typeof cell.value === "string" && ssIndex.has(cell.value)) return "s";
42633
- if (typeof cell.value === "boolean") return "b";
42634
42487
  return void 0;
42635
42488
  }
42636
- function getCellValue(cell, ssIndex) {
42637
- if (cell.value === null) return void 0;
42638
- if (cell.error) return cell.error;
42639
- if (cell.formula && typeof cell.value === "string") return cell.value;
42640
- if (typeof cell.value === "string") {
42641
- const idx = ssIndex.get(cell.value);
42642
- return idx !== void 0 ? idx : cell.value;
42643
- }
42644
- if (typeof cell.value === "boolean") return cell.value ? 1 : 0;
42645
- return cell.value;
42489
+ var REL_BASE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
42490
+ function relsXml(rels) {
42491
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42492
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42493
+ ` + rels.map((r) => `<Relationship Id="${r.id}" Type="${r.type}" Target="${escapeXml(r.target)}"/>`).join("\n") + `
42494
+ </Relationships>`;
42646
42495
  }
42647
- function quoteSheetName(name) {
42648
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? name : `'${name.replace(/'/g, "''")}'`;
42496
+ function emitAuthoredPivots(workbook, entries, startFileIndex) {
42497
+ const info = {
42498
+ cachesByWorkbook: /* @__PURE__ */ new Map(),
42499
+ pivotTablesBySheetIndex: /* @__PURE__ */ new Map(),
42500
+ pivotXmlPaths: []
42501
+ };
42502
+ let n = startFileIndex;
42503
+ for (let i2 = 0; i2 < workbook.sheets.length; i2++) {
42504
+ for (const model of workbook.sheets[i2].pivotTables) {
42505
+ if (!model.authored) continue;
42506
+ const idx = n++;
42507
+ const enumerate = enumerateFlags(model.config, model.cache.fields.length);
42508
+ const records = readSourceData(workbook, model.cache)?.records ?? [];
42509
+ const cacheDefPath = `xl/pivotCache/pivotCacheDefinition${idx}.xml`;
42510
+ const recordsPath = `xl/pivotCache/pivotCacheRecords${idx}.xml`;
42511
+ const tablePath = `xl/pivotTables/pivotTable${idx}.xml`;
42512
+ entries[cacheDefPath] = strToU8(buildPivotCacheDefinitionXml(model.cache, enumerate, records.length, "rId1"));
42513
+ entries[`xl/pivotCache/_rels/pivotCacheDefinition${idx}.xml.rels`] = strToU8(
42514
+ relsXml([{ id: "rId1", type: `${REL_BASE}/pivotCacheRecords`, target: `pivotCacheRecords${idx}.xml` }])
42515
+ );
42516
+ entries[recordsPath] = strToU8(buildPivotCacheRecordsXml(records, model.cache, enumerate));
42517
+ entries[tablePath] = strToU8(buildPivotTableXml(model.config, model.cache));
42518
+ entries[`xl/pivotTables/_rels/pivotTable${idx}.xml.rels`] = strToU8(
42519
+ relsXml([{ id: "rId1", type: `${REL_BASE}/pivotCacheDefinition`, target: `../pivotCache/pivotCacheDefinition${idx}.xml` }])
42520
+ );
42521
+ info.cachesByWorkbook.set(model.cache.id, `pivotCache/pivotCacheDefinition${idx}.xml`);
42522
+ const list = info.pivotTablesBySheetIndex.get(i2) ?? [];
42523
+ list.push(`../pivotTables/pivotTable${idx}.xml`);
42524
+ info.pivotTablesBySheetIndex.set(i2, list);
42525
+ info.pivotXmlPaths.push(tablePath, cacheDefPath, recordsPath);
42526
+ }
42527
+ }
42528
+ return info;
42649
42529
  }
42650
- function buildWorkbookXml(workbook, pivotInfo) {
42651
- const sheets = workbook.sheets.map(
42652
- (s, i2) => `<sheet name="${escapeXml(s.name)}" sheetId="${i2 + 1}" r:id="rId${i2 + 1}"/>`
42653
- ).join("\n");
42654
- const nameEntries = [];
42655
- for (const [name, value] of workbook.namedRanges) {
42656
- nameEntries.push(`<definedName name="${escapeXml(name)}">${escapeXml(value)}</definedName>`);
42530
+ function mergePivotInfo(a, b) {
42531
+ const cachesByWorkbook = new Map(a.cachesByWorkbook);
42532
+ for (const [k, v] of b.cachesByWorkbook) cachesByWorkbook.set(k, v);
42533
+ const pivotTablesBySheetIndex = /* @__PURE__ */ new Map();
42534
+ for (const [k, v] of a.pivotTablesBySheetIndex) pivotTablesBySheetIndex.set(k, [...v]);
42535
+ for (const [k, v] of b.pivotTablesBySheetIndex) {
42536
+ pivotTablesBySheetIndex.set(k, [...pivotTablesBySheetIndex.get(k) ?? [], ...v]);
42657
42537
  }
42658
- workbook.sheets.forEach((s, i2) => {
42659
- const pt = s.printTitles;
42660
- if (!pt || !pt.repeatRows && !pt.repeatCols) return;
42661
- const parts = [];
42662
- const sheetName = quoteSheetName(s.name);
42663
- if (pt.repeatCols) {
42664
- const [start, end] = pt.repeatCols;
42665
- parts.push(`${sheetName}!$${colNumToLetters(start)}:$${colNumToLetters(end)}`);
42538
+ return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths: [...a.pivotXmlPaths, ...b.pivotXmlPaths] };
42539
+ }
42540
+ function exportWorkbook(workbook, originalZip) {
42541
+ const entries = {};
42542
+ const stylesPassthrough = !!originalZip && !workbook.styles.dirty && !!originalZip["xl/styles.xml"];
42543
+ if (originalZip) {
42544
+ const regeneratedPaths = /* @__PURE__ */ new Set();
42545
+ regeneratedPaths.add("xl/sharedStrings.xml");
42546
+ if (!stylesPassthrough) regeneratedPaths.add("xl/styles.xml");
42547
+ regeneratedPaths.add("xl/workbook.xml");
42548
+ regeneratedPaths.add("xl/_rels/workbook.xml.rels");
42549
+ regeneratedPaths.add("[Content_Types].xml");
42550
+ regeneratedPaths.add("_rels/.rels");
42551
+ regeneratedPaths.add("docProps/core.xml");
42552
+ regeneratedPaths.add("docProps/app.xml");
42553
+ for (let i2 = 0; i2 < workbook.sheets.length + 10; i2++) {
42554
+ regeneratedPaths.add(`xl/worksheets/sheet${i2 + 1}.xml`);
42555
+ regeneratedPaths.add(`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`);
42666
42556
  }
42667
- if (pt.repeatRows) {
42668
- const [start, end] = pt.repeatRows;
42669
- parts.push(`${sheetName}!$${start}:$${end}`);
42557
+ for (const path7 of Object.keys(originalZip)) {
42558
+ if (path7.startsWith("xl/drawings/") || path7.startsWith("xl/charts/") || path7.startsWith("xl/tables/") || path7.startsWith("xl/media/")) {
42559
+ regeneratedPaths.add(path7);
42560
+ }
42561
+ }
42562
+ for (const [path7, data] of Object.entries(originalZip)) {
42563
+ if (!regeneratedPaths.has(path7)) entries[path7] = data;
42670
42564
  }
42671
- nameEntries.push(
42672
- `<definedName name="_xlnm.Print_Titles" localSheetId="${i2}">${escapeXml(parts.join(","))}</definedName>`
42673
- );
42674
- });
42675
- const definedNames = nameEntries.length > 0 ? `
42676
- <definedNames>
42677
- ${nameEntries.join("\n")}
42678
- </definedNames>` : "";
42679
- let pivotCachesBlock = "";
42680
- if (pivotInfo && pivotInfo.cachesByWorkbook.size > 0) {
42681
- const baseRId = workbook.sheets.length + 3;
42682
- const cacheIds = [...pivotInfo.cachesByWorkbook.keys()].sort((a, b) => a - b);
42683
- const items = cacheIds.map((cacheId, i2) => `<pivotCache cacheId="${cacheId}" r:id="rId${baseRId + i2}"/>`).join("\n");
42684
- pivotCachesBlock = `
42685
- <pivotCaches>
42686
- ${items}
42687
- </pivotCaches>`;
42688
42565
  }
42689
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42690
- <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
42691
- xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
42692
- <bookViews>
42693
- <workbookView activeTab="${workbook.activeSheetIndex}"/>
42694
- </bookViews>
42695
- <sheets>
42696
- ${sheets}
42697
- </sheets>${definedNames}${pivotCachesBlock}
42698
- <calcPr fullCalcOnLoad="1"/>
42699
- </workbook>`;
42700
- }
42701
- function buildWorkbookRels(workbook, pivotInfo) {
42702
- const rels = workbook.sheets.map(
42703
- (_, i2) => `<Relationship Id="rId${i2 + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet${i2 + 1}.xml"/>`
42566
+ const sharedStrings = buildSharedStrings(workbook);
42567
+ entries["xl/sharedStrings.xml"] = strToU8(sharedStrings.xml);
42568
+ const stylesResult = stylesPassthrough ? { xml: "", xfMap: /* @__PURE__ */ new Map(), numFmtMap: /* @__PURE__ */ new Map(), dxfMap: /* @__PURE__ */ new Map() } : buildStylesXml(workbook);
42569
+ if (!stylesPassthrough) entries["xl/styles.xml"] = strToU8(stylesResult.xml);
42570
+ const roundTripInfo = extractPivotRoundTripInfo(originalZip);
42571
+ const authoredStartIndex = roundTripInfo.pivotXmlPaths.filter((p) => p.startsWith("xl/pivotTables/")).length + 1;
42572
+ const pivotInfo = mergePivotInfo(roundTripInfo, emitAuthoredPivots(workbook, entries, authoredStartIndex));
42573
+ entries["xl/workbook.xml"] = strToU8(buildWorkbookXml(workbook, pivotInfo));
42574
+ entries["xl/_rels/workbook.xml.rels"] = strToU8(
42575
+ buildWorkbookRels(workbook, pivotInfo)
42704
42576
  );
42705
- rels.push(`<Relationship Id="rId${workbook.sheets.length + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>`);
42706
- rels.push(`<Relationship Id="rId${workbook.sheets.length + 2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>`);
42707
- if (pivotInfo && pivotInfo.cachesByWorkbook.size > 0) {
42708
- const baseRId = workbook.sheets.length + 3;
42709
- const cacheIds = [...pivotInfo.cachesByWorkbook.keys()].sort((a, b) => a - b);
42710
- cacheIds.forEach((cacheId, i2) => {
42711
- const target = pivotInfo.cachesByWorkbook.get(cacheId);
42712
- if (!target) return;
42713
- rels.push(
42714
- `<Relationship Id="rId${baseRId + i2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" Target="${escapeXml(target)}"/>`
42715
- );
42716
- });
42577
+ const extraContentTypes = [];
42578
+ for (const path7 of pivotInfo.pivotXmlPaths) {
42579
+ const ct = pivotContentTypeFor(path7);
42580
+ if (ct) extraContentTypes.push(ct);
42717
42581
  }
42718
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42719
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42720
- ${rels.join("\n")}
42721
- </Relationships>`;
42722
- }
42723
- function buildContentTypes(sheetCount, extraTypes = []) {
42724
- const sheetTypes = Array.from(
42725
- { length: sheetCount },
42726
- (_, i2) => `<Override PartName="/xl/worksheets/sheet${i2 + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`
42727
- ).join("\n");
42728
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42729
- <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
42730
- <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
42731
- <Default Extension="xml" ContentType="application/xml"/>
42732
- <Default Extension="png" ContentType="image/png"/>
42733
- <Default Extension="jpeg" ContentType="image/jpeg"/>
42734
- <Default Extension="jpg" ContentType="image/jpeg"/>
42735
- <Default Extension="gif" ContentType="image/gif"/>
42736
- <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
42737
- ${sheetTypes}
42738
- <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
42739
- <Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
42740
- <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
42741
- <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
42742
- ${extraTypes.join("\n")}
42743
- </Types>`;
42582
+ let globalChartIndex = 1;
42583
+ let globalImageIndex = 1;
42584
+ let globalTableIndex = 1;
42585
+ for (let i2 = 0; i2 < workbook.sheets.length; i2++) {
42586
+ const sheet = workbook.sheets[i2];
42587
+ const sheetRels = [];
42588
+ let nextRId = 1;
42589
+ const hasCharts = sheet.charts.length > 0;
42590
+ const hasImages = sheet.images.length > 0;
42591
+ const hasDrawings = sheet.drawings.length > 0;
42592
+ const hasTables = sheet.tables.length > 0;
42593
+ const hasHyperlinks = sheet.hyperlinks.size > 0;
42594
+ const needsDrawing = hasCharts || hasImages || hasDrawings;
42595
+ const hyperlinkRIds = /* @__PURE__ */ new Map();
42596
+ if (hasHyperlinks) {
42597
+ for (const [ref, url] of sheet.hyperlinks) {
42598
+ const rId = `rId${nextRId++}`;
42599
+ hyperlinkRIds.set(ref, rId);
42600
+ sheetRels.push(`<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="${escapeXml(url)}" TargetMode="External"/>`);
42601
+ }
42602
+ }
42603
+ let drawingRId = "";
42604
+ if (needsDrawing) {
42605
+ drawingRId = `rId${nextRId++}`;
42606
+ sheetRels.push(`<Relationship Id="${drawingRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" Target="../drawings/drawing${i2 + 1}.xml"/>`);
42607
+ const drawingRels = [];
42608
+ let drawingRelId = 1;
42609
+ const drawingAnchors = [];
42610
+ for (const chart of sheet.charts) {
42611
+ const chartRId = `rId${drawingRelId++}`;
42612
+ const chartPath = `xl/charts/chart${globalChartIndex}.xml`;
42613
+ entries[chartPath] = strToU8(buildChartXml(chart));
42614
+ extraContentTypes.push(`<Override PartName="/${chartPath}" ContentType="application/vnd.openxmlformats-officedocument.drawingml.chart+xml"/>`);
42615
+ drawingRels.push(`<Relationship Id="${chartRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart" Target="../charts/chart${globalChartIndex}.xml"/>`);
42616
+ drawingAnchors.push(buildChartAnchorXml(chart, chartRId));
42617
+ globalChartIndex++;
42618
+ }
42619
+ for (const image of sheet.images) {
42620
+ const imgRId = `rId${drawingRelId++}`;
42621
+ const ext = getImageExtension(image.dataUrl);
42622
+ const imgPath = `xl/media/image${globalImageIndex}.${ext}`;
42623
+ const imgBytes = dataUrlToBytes(image.dataUrl);
42624
+ if (imgBytes) {
42625
+ entries[imgPath] = imgBytes;
42626
+ drawingRels.push(`<Relationship Id="${imgRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image${globalImageIndex}.${ext}"/>`);
42627
+ drawingAnchors.push(buildImageAnchorXml(image, imgRId));
42628
+ globalImageIndex++;
42629
+ }
42630
+ }
42631
+ for (const drawing of sheet.drawings) {
42632
+ drawingAnchors.push(buildShapeAnchorXml(drawing));
42633
+ }
42634
+ entries[`xl/drawings/drawing${i2 + 1}.xml`] = strToU8(
42635
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42636
+ <xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart">
42637
+ ` + drawingAnchors.join("\n") + `
42638
+ </xdr:wsDr>`
42639
+ );
42640
+ extraContentTypes.push(`<Override PartName="/xl/drawings/drawing${i2 + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.drawing+xml"/>`);
42641
+ if (drawingRels.length > 0) {
42642
+ entries[`xl/drawings/_rels/drawing${i2 + 1}.xml.rels`] = strToU8(
42643
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42644
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42645
+ ${drawingRels.join("\n")}
42646
+ </Relationships>`
42647
+ );
42648
+ }
42649
+ }
42650
+ const tableRIds = [];
42651
+ if (hasTables) {
42652
+ for (const table of sheet.tables) {
42653
+ const tableRId = `rId${nextRId++}`;
42654
+ tableRIds.push(tableRId);
42655
+ const tablePath = `xl/tables/table${globalTableIndex}.xml`;
42656
+ entries[tablePath] = strToU8(buildTableXml(table, globalTableIndex));
42657
+ extraContentTypes.push(`<Override PartName="/${tablePath}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"/>`);
42658
+ sheetRels.push(`<Relationship Id="${tableRId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" Target="../tables/table${globalTableIndex}.xml"/>`);
42659
+ globalTableIndex++;
42660
+ }
42661
+ }
42662
+ const pivotTargets = pivotInfo.pivotTablesBySheetIndex.get(i2);
42663
+ if (pivotTargets && pivotTargets.length > 0) {
42664
+ for (const target of pivotTargets) {
42665
+ const rId = `rId${nextRId++}`;
42666
+ sheetRels.push(
42667
+ `<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable" Target="${escapeXml(target)}"/>`
42668
+ );
42669
+ }
42670
+ }
42671
+ if (sheetRels.length > 0) {
42672
+ entries[`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`] = strToU8(
42673
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42674
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42675
+ ${sheetRels.join("\n")}
42676
+ </Relationships>`
42677
+ );
42678
+ }
42679
+ entries[`xl/worksheets/sheet${i2 + 1}.xml`] = strToU8(
42680
+ buildSheetXml(sheet, workbook.styles, sharedStrings.index, i2 === workbook.activeSheetIndex, stylesResult.xfMap, stylesResult.numFmtMap, stylesResult.dxfMap, drawingRId, tableRIds, hyperlinkRIds)
42681
+ );
42682
+ }
42683
+ entries["docProps/core.xml"] = strToU8(buildCoreProps());
42684
+ entries["docProps/app.xml"] = strToU8(buildAppProps());
42685
+ entries["[Content_Types].xml"] = strToU8(buildContentTypes(workbook.sheets.length, extraContentTypes));
42686
+ entries["_rels/.rels"] = strToU8(buildRootRels());
42687
+ return zipSync(entries, { level: 6 });
42688
+ }
42689
+ function buildSharedStrings(workbook) {
42690
+ const strings = [];
42691
+ const index = /* @__PURE__ */ new Map();
42692
+ const richTextMap = /* @__PURE__ */ new Map();
42693
+ let totalCount = 0;
42694
+ for (const sheet of workbook.sheets) {
42695
+ for (const cell of sheet.cells.values()) {
42696
+ if (cell.error) continue;
42697
+ if (cell.formula && typeof cell.value === "string") continue;
42698
+ if (typeof cell.value === "string") {
42699
+ totalCount++;
42700
+ if (!index.has(cell.value)) {
42701
+ index.set(cell.value, strings.length);
42702
+ strings.push(cell.value);
42703
+ if (cell.richText && cell.richText.length > 0) {
42704
+ richTextMap.set(cell.value, cell.richText);
42705
+ }
42706
+ }
42707
+ }
42708
+ }
42709
+ }
42710
+ const siEntries = strings.map((s) => {
42711
+ const richText = richTextMap.get(s);
42712
+ if (richText) {
42713
+ return `<si>${richText.map((part) => buildRichTextRun(part)).join("")}</si>`;
42714
+ }
42715
+ const needsPreserve = s.length === 0 || s !== s.trim();
42716
+ const spaceAttr = needsPreserve ? ' xml:space="preserve"' : "";
42717
+ return `<si><t${spaceAttr}>${escapeXml(s)}</t></si>`;
42718
+ });
42719
+ const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42720
+ <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${totalCount}" uniqueCount="${strings.length}">
42721
+ ${siEntries.join("\n")}
42722
+ </sst>`;
42723
+ return { xml, index };
42724
+ }
42725
+ function buildRichTextRun(part) {
42726
+ const needsPreserve = part.text.length === 0 || part.text !== part.text.trim();
42727
+ const spaceAttr = needsPreserve ? ' xml:space="preserve"' : "";
42728
+ if (!part.font) {
42729
+ return `<r><t${spaceAttr}>${escapeXml(part.text)}</t></r>`;
42730
+ }
42731
+ return `<r>${buildRichTextRunProps(part.font)}<t${spaceAttr}>${escapeXml(part.text)}</t></r>`;
42732
+ }
42733
+ function buildRichTextRunProps(font) {
42734
+ let parts = "";
42735
+ if (font.bold) parts += "<b/>";
42736
+ if (font.italic) parts += "<i/>";
42737
+ if (font.strike) parts += "<strike/>";
42738
+ if (font.underline) parts += `<u val="${font.underline}"/>`;
42739
+ if (font.vertAlign) parts += `<vertAlign val="${font.vertAlign}"/>`;
42740
+ if (font.size) parts += `<sz val="${font.size}"/>`;
42741
+ if (font.color) parts += `<color rgb="${hexToArgb(font.color)}"/>`;
42742
+ if (font.name) parts += `<rFont val="${escapeXml(font.name)}"/>`;
42743
+ return `<rPr>${parts}</rPr>`;
42744
+ }
42745
+ function buildStylesXml(workbook) {
42746
+ const styles = [];
42747
+ for (let i2 = 0; i2 < workbook.styles.size; i2++) {
42748
+ styles.push(workbook.styles.get(i2));
42749
+ }
42750
+ const numFmtMap = /* @__PURE__ */ new Map();
42751
+ let nextNumFmtId = 164;
42752
+ for (const sheet of workbook.sheets) {
42753
+ for (const cell of sheet.cells.values()) {
42754
+ if (cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "") {
42755
+ if (!numFmtMap.has(cell.numFmtCode)) {
42756
+ numFmtMap.set(cell.numFmtCode, nextNumFmtId++);
42757
+ }
42758
+ }
42759
+ }
42760
+ }
42761
+ const cellNumFmtIds = /* @__PURE__ */ new Map();
42762
+ for (let si = 0; si < workbook.sheets.length; si++) {
42763
+ for (const [ref, cell] of workbook.sheets[si].cells) {
42764
+ if (cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "") {
42765
+ const id = numFmtMap.get(cell.numFmtCode);
42766
+ if (id !== void 0) cellNumFmtIds.set(`${si}:${ref}`, id);
42767
+ }
42768
+ }
42769
+ }
42770
+ const fonts = /* @__PURE__ */ new Map();
42771
+ const fontList = [];
42772
+ fonts.set("default", 0);
42773
+ fontList.push({});
42774
+ for (const s of styles) {
42775
+ const key = fontKey(s);
42776
+ if (!fonts.has(key)) {
42777
+ fonts.set(key, fontList.length);
42778
+ fontList.push(s);
42779
+ }
42780
+ }
42781
+ const fillEntries = [];
42782
+ const fillMap = /* @__PURE__ */ new Map();
42783
+ fillEntries.push('<fill><patternFill patternType="none"/></fill>');
42784
+ fillEntries.push('<fill><patternFill patternType="gray125"/></fill>');
42785
+ fillMap.set("", 0);
42786
+ for (const s of styles) {
42787
+ const fk = fillKey(s);
42788
+ if (fk === "" || fillMap.has(fk)) continue;
42789
+ fillMap.set(fk, fillEntries.length);
42790
+ fillEntries.push(buildFillXml(s));
42791
+ }
42792
+ const borderEntries = [];
42793
+ const borderMap = /* @__PURE__ */ new Map();
42794
+ borderEntries.push("<border><left/><right/><top/><bottom/><diagonal/></border>");
42795
+ borderMap.set("", 0);
42796
+ for (const s of styles) {
42797
+ const bk = borderKey(s);
42798
+ if (bk === "" || borderMap.has(bk)) continue;
42799
+ borderMap.set(bk, borderEntries.length);
42800
+ borderEntries.push(buildBorderXml(s));
42801
+ }
42802
+ const fontsXml = fontList.map((f) => buildFontXml(f)).join("\n");
42803
+ const fillsXml = fillEntries.join("\n");
42804
+ const bordersXml = borderEntries.join("\n");
42805
+ let numFmtsXml = "";
42806
+ if (numFmtMap.size > 0) {
42807
+ const entries = Array.from(numFmtMap.entries()).map(([code, id]) => `<numFmt numFmtId="${id}" formatCode="${escapeXml(code)}"/>`).join("\n");
42808
+ numFmtsXml = `<numFmts count="${numFmtMap.size}">
42809
+ ${entries}
42810
+ </numFmts>
42811
+ `;
42812
+ }
42813
+ const xfEntries = [];
42814
+ const xfMap = /* @__PURE__ */ new Map();
42815
+ for (let styleIdx = 0; styleIdx < styles.length; styleIdx++) {
42816
+ const s = styles[styleIdx];
42817
+ const fontId = fonts.get(fontKey(s)) ?? 0;
42818
+ const fillId = fillMap.get(fillKey(s)) ?? 0;
42819
+ const borderId = borderMap.get(borderKey(s)) ?? 0;
42820
+ const xfKey = `${styleIdx}:0`;
42821
+ xfMap.set(xfKey, xfEntries.length);
42822
+ xfEntries.push(buildXfXml(s, fontId, fillId, borderId, 0));
42823
+ }
42824
+ for (const [cellKey2, numFmtId] of cellNumFmtIds) {
42825
+ const [siStr, ref] = cellKey2.split(":");
42826
+ const cell = workbook.sheets[parseInt(siStr)].cells.get(ref);
42827
+ if (!cell) continue;
42828
+ const xfKey = `${cell.styleIndex}:${numFmtId}`;
42829
+ if (xfMap.has(xfKey)) continue;
42830
+ const s = styles[cell.styleIndex] ?? {};
42831
+ const fontId = fonts.get(fontKey(s)) ?? 0;
42832
+ const fillId = fillMap.get(fillKey(s)) ?? 0;
42833
+ const borderId = borderMap.get(borderKey(s)) ?? 0;
42834
+ xfMap.set(xfKey, xfEntries.length);
42835
+ xfEntries.push(buildXfXml(s, fontId, fillId, borderId, numFmtId));
42836
+ }
42837
+ const dxfEntries = [];
42838
+ const dxfMap = /* @__PURE__ */ new Map();
42839
+ for (const sheet of workbook.sheets) {
42840
+ for (const cf of sheet.conditionalFormats) {
42841
+ for (const rule of cf.rules) {
42842
+ if (rule.ruleType === "style" && rule.style) {
42843
+ const key = JSON.stringify(rule.style);
42844
+ if (!dxfMap.has(key)) {
42845
+ dxfMap.set(key, dxfEntries.length);
42846
+ dxfEntries.push(buildDxfXml(rule.style));
42847
+ }
42848
+ }
42849
+ }
42850
+ }
42851
+ }
42852
+ let dxfsXml = '<dxfs count="0"/>';
42853
+ if (dxfEntries.length > 0) {
42854
+ dxfsXml = `<dxfs count="${dxfEntries.length}">
42855
+ ${dxfEntries.join("\n")}
42856
+ </dxfs>`;
42857
+ }
42858
+ const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42859
+ <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
42860
+ ${numFmtsXml}<fonts count="${fontList.length}">
42861
+ ${fontsXml}
42862
+ </fonts>
42863
+ <fills count="${fillEntries.length}">
42864
+ ${fillsXml}
42865
+ </fills>
42866
+ <borders count="${borderEntries.length}">
42867
+ ${bordersXml}
42868
+ </borders>
42869
+ <cellStyleXfs count="1">
42870
+ <xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
42871
+ </cellStyleXfs>
42872
+ <cellXfs count="${xfEntries.length}">
42873
+ ${xfEntries.join("\n")}
42874
+ </cellXfs>
42875
+ <cellStyles count="1">
42876
+ <cellStyle name="Normal" xfId="0" builtinId="0"/>
42877
+ </cellStyles>
42878
+ ${dxfsXml}
42879
+ </styleSheet>`;
42880
+ return { xml, xfMap, numFmtMap, dxfMap };
42744
42881
  }
42745
- function buildRootRels() {
42746
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42747
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
42748
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
42749
- <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
42750
- <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
42751
- </Relationships>`;
42882
+ function buildXfXml(s, fontId, fillId, borderId, numFmtId) {
42883
+ let attrs = `numFmtId="${numFmtId}" fontId="${fontId}" fillId="${fillId}" borderId="${borderId}" xfId="0"`;
42884
+ if (numFmtId > 0) attrs += ' applyNumberFormat="1"';
42885
+ if (fontId > 0) attrs += ' applyFont="1"';
42886
+ if (fillId > 0) attrs += ' applyFill="1"';
42887
+ if (borderId > 0) attrs += ' applyBorder="1"';
42888
+ if (s.horizontalAlign || s.verticalAlign || s.wrapText || s.indent || s.textRotation || s.shrinkToFit) {
42889
+ const hAlign = s.horizontalAlign ? ` horizontal="${s.horizontalAlign}"` : "";
42890
+ const vAlign = s.verticalAlign ? ` vertical="${s.verticalAlign}"` : "";
42891
+ const wrap = s.wrapText ? ' wrapText="1"' : "";
42892
+ const indent = s.indent ? ` indent="${s.indent}"` : "";
42893
+ const rotation = s.textRotation !== void 0 ? ` textRotation="${s.textRotation === "vertical" ? 255 : s.textRotation}"` : "";
42894
+ const shrink = s.shrinkToFit ? ' shrinkToFit="1"' : "";
42895
+ return `<xf ${attrs} applyAlignment="1"><alignment${hAlign}${vAlign}${wrap}${indent}${rotation}${shrink}/></xf>`;
42896
+ }
42897
+ return `<xf ${attrs}/>`;
42752
42898
  }
42753
- function buildCoreProps() {
42754
- const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
42755
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42756
- <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
42757
- xmlns:dc="http://purl.org/dc/elements/1.1/"
42758
- xmlns:dcterms="http://purl.org/dc/terms/"
42759
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
42760
- <dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>
42761
- <dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>
42762
- </cp:coreProperties>`;
42899
+ function fontKey(s) {
42900
+ return `${s.fontName ?? ""}|${s.fontSize ?? 0}|${s.fontBold ? 1 : 0}|${s.fontItalic ? 1 : 0}|${s.fontColor ?? ""}|${s.fontUnderline ?? ""}|${s.fontStrike ? 1 : 0}`;
42763
42901
  }
42764
- function buildAppProps() {
42765
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42766
- <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">
42767
- <Application>Microsoft Excel</Application>
42768
- </Properties>`;
42902
+ function buildFontXml(s) {
42903
+ let parts = "";
42904
+ if (s.fontBold) parts += "<b/>";
42905
+ if (s.fontItalic) parts += "<i/>";
42906
+ if (s.fontStrike) parts += "<strike/>";
42907
+ if (s.fontUnderline) parts += `<u val="${s.fontUnderline}"/>`;
42908
+ parts += `<sz val="${s.fontSize ?? 11}"/>`;
42909
+ if (s.fontColor) {
42910
+ parts += `<color rgb="${hexToArgb(s.fontColor)}"/>`;
42911
+ } else {
42912
+ parts += '<color theme="1"/>';
42913
+ }
42914
+ parts += `<name val="${escapeXml(s.fontName ?? "Calibri")}"/>`;
42915
+ return `<font>${parts}</font>`;
42769
42916
  }
42770
- var CHART_TYPE_MAP2 = {
42771
- bar: "c:barChart",
42772
- col: "c:barChart",
42773
- line: "c:lineChart",
42774
- pie: "c:pieChart",
42775
- doughnut: "c:doughnutChart",
42776
- area: "c:areaChart",
42777
- scatter: "c:scatterChart",
42778
- bubble: "c:bubbleChart",
42779
- radar: "c:radarChart",
42780
- stock: "c:stockChart",
42781
- surface: "c:surfaceChart"
42782
- };
42783
- function buildSeriesXml(s, idx, chartType, categories) {
42784
- let nameXml = "";
42785
- if (s.name) nameXml = `<c:tx><c:strRef><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${escapeXml(s.name)}</c:v></c:pt></c:strCache></c:strRef></c:tx>`;
42786
- let colorXml = "";
42787
- if (s.color) colorXml = `<c:spPr><a:solidFill><a:srgbClr val="${hexToOoxmlRgb(s.color)}"/></a:solidFill></c:spPr>`;
42788
- const valTag = chartType === "scatter" || chartType === "bubble" ? "c:yVal" : "c:val";
42789
- const valPts = s.values.map((v, i2) => `<c:pt idx="${i2}"><c:v>${v}</c:v></c:pt>`).join("");
42790
- const valXml = `<${valTag}><c:numRef><c:numCache><c:ptCount val="${s.values.length}"/>${valPts}</c:numCache></c:numRef></${valTag}>`;
42791
- let catXml = "";
42792
- if (categories && categories.length > 0) {
42793
- const catTag = chartType === "scatter" || chartType === "bubble" ? "c:xVal" : "c:cat";
42794
- const catPts = categories.map((c, i2) => `<c:pt idx="${i2}"><c:v>${escapeXml(c)}</c:v></c:pt>`).join("");
42795
- catXml = `<${catTag}><c:strRef><c:strCache><c:ptCount val="${categories.length}"/>${catPts}</c:strCache></c:strRef></${catTag}>`;
42917
+ function borderKey(s) {
42918
+ const parts = [];
42919
+ if (s.borderTop) parts.push(`t:${s.borderTop.style}:${s.borderTop.width}:${s.borderTop.color ?? ""}`);
42920
+ if (s.borderRight) parts.push(`r:${s.borderRight.style}:${s.borderRight.width}:${s.borderRight.color ?? ""}`);
42921
+ if (s.borderBottom) parts.push(`b:${s.borderBottom.style}:${s.borderBottom.width}:${s.borderBottom.color ?? ""}`);
42922
+ if (s.borderLeft) parts.push(`l:${s.borderLeft.style}:${s.borderLeft.width}:${s.borderLeft.color ?? ""}`);
42923
+ if (s.borderDiagonal) parts.push(`d:${s.borderDiagonal.style}:${s.borderDiagonal.width}:${s.borderDiagonal.color ?? ""}`);
42924
+ if (s.diagonalUp) parts.push("du");
42925
+ if (s.diagonalDown) parts.push("dd");
42926
+ return parts.join("|");
42927
+ }
42928
+ function toOoxmlBorderStyle(border2) {
42929
+ const ooxmlStyles = [
42930
+ "thin",
42931
+ "medium",
42932
+ "thick",
42933
+ "dotted",
42934
+ "dashed",
42935
+ "double",
42936
+ "hair",
42937
+ "mediumDashed",
42938
+ "dashDot",
42939
+ "mediumDashDot",
42940
+ "dashDotDot",
42941
+ "mediumDashDotDot",
42942
+ "slantDashDot"
42943
+ ];
42944
+ if (ooxmlStyles.includes(border2.style)) return border2.style;
42945
+ if (border2.style === "solid") {
42946
+ if (border2.width <= 1) return "thin";
42947
+ if (border2.width <= 2) return "medium";
42948
+ return "thick";
42949
+ }
42950
+ if (border2.style === "dashed") return "dashed";
42951
+ if (border2.style === "dotted") return "dotted";
42952
+ if (border2.style === "double") return "double";
42953
+ return "thin";
42954
+ }
42955
+ function buildBorderXml(s) {
42956
+ let attrs = "";
42957
+ if (s.diagonalUp) attrs += ' diagonalUp="1"';
42958
+ if (s.diagonalDown) attrs += ' diagonalDown="1"';
42959
+ const sides = [
42960
+ { tag: "left", border: s.borderLeft },
42961
+ { tag: "right", border: s.borderRight },
42962
+ { tag: "top", border: s.borderTop },
42963
+ { tag: "bottom", border: s.borderBottom },
42964
+ { tag: "diagonal", border: s.borderDiagonal }
42965
+ ];
42966
+ const inner = sides.map(({ tag, border: border2 }) => {
42967
+ if (!border2) return `<${tag}/>`;
42968
+ const ooxmlStyle = toOoxmlBorderStyle(border2);
42969
+ let colorXml = "";
42970
+ if (border2.color) {
42971
+ colorXml = `<color rgb="${hexToArgb(border2.color)}"/>`;
42972
+ }
42973
+ return `<${tag} style="${ooxmlStyle}">${colorXml}</${tag}>`;
42974
+ }).join("");
42975
+ return `<border${attrs}>${inner}</border>`;
42976
+ }
42977
+ function fillKey(s) {
42978
+ if (s.gradientData) return `gradient:${JSON.stringify(s.gradientData)}`;
42979
+ if (s.patternType && s.backgroundPattern) return `pattern:${s.patternType}|${s.backgroundPattern}`;
42980
+ if (s.backgroundColor) return `solid:${s.backgroundColor}`;
42981
+ return "";
42982
+ }
42983
+ function buildFillXml(s) {
42984
+ if (s.gradientData) {
42985
+ const g = s.gradientData;
42986
+ const stops = g.stops.map((stop) => {
42987
+ const hex = hexToArgb(stop.color);
42988
+ return `<stop position="${stop.position}"><color rgb="${hex}"/></stop>`;
42989
+ }).join("");
42990
+ if (g.type === "radial") {
42991
+ return `<fill><gradientFill type="path" left="0.5" right="0.5" top="0.5" bottom="0.5">${stops}</gradientFill></fill>`;
42992
+ }
42993
+ return `<fill><gradientFill degree="${g.degree}">${stops}</gradientFill></fill>`;
42994
+ }
42995
+ if (s.patternType && s.backgroundPattern) {
42996
+ const colors = extractFillColors(s.backgroundPattern);
42997
+ let colorAttrs = "";
42998
+ if (colors.fg) colorAttrs += `<fgColor rgb="${hexToArgb(colors.fg)}"/>`;
42999
+ if (colors.bg) colorAttrs += `<bgColor rgb="${hexToArgb(colors.bg)}"/>`;
43000
+ return `<fill><patternFill patternType="${escapeXml(s.patternType)}">${colorAttrs}</patternFill></fill>`;
43001
+ }
43002
+ return `<fill><patternFill patternType="solid"><fgColor rgb="${hexToArgb(s.backgroundColor)}"/></patternFill></fill>`;
43003
+ }
43004
+ function extractFillColors(css) {
43005
+ const colorMatches = css.match(/rgba?\([^)]+\)/g);
43006
+ if (colorMatches) {
43007
+ return { fg: colorMatches[0], bg: colorMatches[1] };
43008
+ }
43009
+ const hexMatches = css.match(/#[0-9a-fA-F]{6}/g);
43010
+ if (hexMatches) {
43011
+ return { fg: hexMatches[0], bg: hexMatches[1] };
43012
+ }
43013
+ return { fg: void 0, bg: void 0 };
43014
+ }
43015
+ function buildSheetXml(sheet, styles, ssIndex, isActive, xfMap, numFmtMap, dxfMap, drawingRId, tableRIds, hyperlinkRIds) {
43016
+ const rows = [];
43017
+ const rowMap = /* @__PURE__ */ new Map();
43018
+ for (const [ref, cell] of sheet.cells) {
43019
+ const rc = refToRowCol(ref);
43020
+ if (!rc) continue;
43021
+ let arr = rowMap.get(rc.row);
43022
+ if (!arr) {
43023
+ arr = [];
43024
+ rowMap.set(rc.row, arr);
43025
+ }
43026
+ arr.push({ col: rc.col, cell });
43027
+ }
43028
+ const sortedRows = Array.from(rowMap.keys()).sort((a, b) => a - b);
43029
+ for (const rowNum of sortedRows) {
43030
+ const cells = rowMap.get(rowNum);
43031
+ cells.sort((a, b) => a.col - b.col);
43032
+ const h = sheet.rowHeights.get(rowNum);
43033
+ const rowAttrs = h ? ` ht="${h}" customHeight="1"` : "";
43034
+ const hidden = sheet.hiddenRows.has(rowNum) ? ' hidden="1"' : "";
43035
+ const cellsXml = cells.map(({ col, cell }) => {
43036
+ const ref = rowColToRef(rowNum, col);
43037
+ const type = getCellType(cell, ssIndex);
43038
+ const value = getCellValue(cell, ssIndex);
43039
+ let attrs = `r="${ref}"`;
43040
+ let xfIndex = 0;
43041
+ if (xfMap.size === 0 && cell.originalXfIndex !== void 0) {
43042
+ xfIndex = cell.originalXfIndex;
43043
+ } else {
43044
+ const numFmtId = cell.numFmtCode && cell.numFmtCode !== "General" && cell.numFmtCode !== "" ? numFmtMap.get(cell.numFmtCode) ?? 0 : 0;
43045
+ const xfKey = `${cell.styleIndex}:${numFmtId}`;
43046
+ xfIndex = xfMap.get(xfKey) ?? 0;
43047
+ }
43048
+ if (xfIndex > 0) attrs += ` s="${xfIndex}"`;
43049
+ if (type) attrs += ` t="${type}"`;
43050
+ let inner = "";
43051
+ if (cell.formula) {
43052
+ if (cell.isArrayFormula && cell.arrayRange) {
43053
+ inner += `<f t="array" ref="${cell.arrayRange}">${escapeXml(cell.formula)}</f>`;
43054
+ } else {
43055
+ inner += `<f>${escapeXml(cell.formula)}</f>`;
43056
+ }
43057
+ }
43058
+ if (value !== void 0) inner += `<v>${escapeXml(String(value))}</v>`;
43059
+ return `<c ${attrs}>${inner}</c>`;
43060
+ }).join("");
43061
+ rows.push(`<row r="${rowNum}"${rowAttrs}${hidden}>${cellsXml}</row>`);
42796
43062
  }
42797
- let bubbleXml = "";
42798
- if (s.bubbleSizes) {
42799
- const bPts = s.bubbleSizes.map((v, i2) => `<c:pt idx="${i2}"><c:v>${v}</c:v></c:pt>`).join("");
42800
- bubbleXml = `<c:bubbleSize><c:numRef><c:numCache><c:ptCount val="${s.bubbleSizes.length}"/>${bPts}</c:numCache></c:numRef></c:bubbleSize>`;
43063
+ const cols = [];
43064
+ const allCols = /* @__PURE__ */ new Set([...sheet.colWidths.keys(), ...sheet.hiddenCols]);
43065
+ for (const c of Array.from(allCols).sort((a, b) => a - b)) {
43066
+ const w = sheet.colWidths.get(c) ?? sheet.defaultColWidth;
43067
+ const hidden = sheet.hiddenCols.has(c) ? ' hidden="1"' : "";
43068
+ cols.push(`<col min="${c}" max="${c}" width="${w}" customWidth="1"${hidden}/>`);
42801
43069
  }
42802
- return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/>${nameXml}${colorXml}${catXml}${valXml}${bubbleXml}</c:ser>`;
42803
- }
42804
- function buildChartTypeElement(chartType, seriesXml, needsAxIds) {
42805
- const chartTag = CHART_TYPE_MAP2[chartType] ?? "c:barChart";
42806
- const isBar = chartType === "bar";
42807
- let barDir = "";
42808
- if (chartTag === "c:barChart") {
42809
- barDir = isBar ? '<c:barDir val="bar"/>' : '<c:barDir val="col"/>';
43070
+ let mergeXml = "";
43071
+ if (sheet.mergedCells.length > 0) {
43072
+ const merges = sheet.mergedCells.map((r) => `<mergeCell ref="${r}"/>`).join("");
43073
+ mergeXml = `<mergeCells count="${sheet.mergedCells.length}">${merges}</mergeCells>`;
42810
43074
  }
42811
- let grouping = "";
42812
- if (chartTag === "c:barChart") {
42813
- grouping = '<c:grouping val="clustered"/>';
42814
- } else if (chartTag === "c:lineChart" || chartTag === "c:areaChart") {
42815
- grouping = '<c:grouping val="clustered"/>';
43075
+ let paneXml = "";
43076
+ let selectionXml = `<selection activeCell="A1" sqref="A1"/>`;
43077
+ if (sheet.freeze) {
43078
+ const activePane = sheet.freeze.col > 0 && sheet.freeze.row > 0 ? "bottomRight" : sheet.freeze.row > 0 ? "bottomLeft" : "topRight";
43079
+ const topLeft = rowColToRef(sheet.freeze.row + 1, sheet.freeze.col + 1);
43080
+ paneXml = `<pane xSplit="${sheet.freeze.col}" ySplit="${sheet.freeze.row}" topLeftCell="${topLeft}" activePane="${activePane}" state="frozen"/>`;
43081
+ selectionXml = `<selection pane="${activePane}" activeCell="${topLeft}" sqref="${topLeft}"/>`;
42816
43082
  }
42817
- const axIds = needsAxIds ? '<c:axId val="1"/><c:axId val="2"/>' : "";
42818
- return `<${chartTag}>${barDir}${grouping}${seriesXml}${axIds}</${chartTag}>`;
42819
- }
42820
- function buildChartXml(chart) {
42821
- const needsAxIds = chart.chartType !== "pie" && chart.chartType !== "doughnut";
42822
- let plotArea;
42823
- if (chart.chartType === "combo") {
42824
- const groups = /* @__PURE__ */ new Map();
42825
- chart.series.forEach((s, idx) => {
42826
- const sType = s.seriesChartType ?? "col";
42827
- let group = groups.get(sType);
42828
- if (!group) {
42829
- group = [];
42830
- groups.set(sType, group);
43083
+ const tabSelected = isActive ? ' tabSelected="1"' : "";
43084
+ const sheetView = `<sheetView${tabSelected} workbookViewId="0"${!sheet.view.showGridLines ? ' showGridLines="0"' : ""}>${paneXml}${selectionXml}</sheetView>`;
43085
+ let autoFilterXml = "";
43086
+ if (sheet.autoFilter) {
43087
+ let filterCols = "";
43088
+ for (const col of sheet.autoFilter.columns) {
43089
+ if (col.filterValues && col.filterValues.length > 0) {
43090
+ const filters = col.filterValues.map((v) => `<filter val="${escapeXml(v)}"/>`).join("");
43091
+ filterCols += `<filterColumn colId="${col.colIndex}"><filters>${filters}</filters></filterColumn>`;
42831
43092
  }
42832
- group.push({ series: s, idx });
42833
- });
42834
- let chartElements = "";
42835
- for (const [groupType, groupSeries] of groups) {
42836
- const groupSeriesXml = groupSeries.map(
42837
- ({ series, idx }) => buildSeriesXml(series, idx, groupType, chart.categories)
42838
- ).join("");
42839
- chartElements += buildChartTypeElement(groupType, groupSeriesXml, true);
42840
43093
  }
42841
- plotArea = `<c:plotArea><c:layout/>${chartElements}`;
42842
- } else {
42843
- const seriesXml = chart.series.map(
42844
- (s, idx) => buildSeriesXml(s, idx, chart.chartType, chart.categories)
42845
- ).join("");
42846
- plotArea = `<c:plotArea><c:layout/>${buildChartTypeElement(chart.chartType, seriesXml, needsAxIds)}`;
43094
+ autoFilterXml = `<autoFilter ref="${sheet.autoFilter.ref}">${filterCols}</autoFilter>`;
42847
43095
  }
42848
- if (chart.chartType !== "pie" && chart.chartType !== "doughnut") {
42849
- const axes = chart.axes ?? [{ type: "category" }, { type: "value" }];
42850
- for (let i2 = 0; i2 < axes.length; i2++) {
42851
- const ax = axes[i2];
42852
- const axId = i2 + 1;
42853
- const crossId = i2 === 0 ? 2 : 1;
42854
- let axTag;
42855
- switch (ax.type) {
42856
- case "value":
42857
- axTag = "c:valAx";
42858
- break;
42859
- case "date":
42860
- axTag = "c:dateAx";
42861
- break;
42862
- case "series":
42863
- axTag = "c:serAx";
42864
- break;
42865
- default:
42866
- axTag = "c:catAx";
42867
- break;
42868
- }
42869
- let titleXml2 = "";
42870
- if (ax.title) titleXml2 = `<c:title><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(ax.title)}</a:t></a:r></a:p></c:rich></c:tx></c:title>`;
42871
- let scalingXml = '<c:scaling><c:orientation val="minMax"/>';
42872
- if (ax.min !== void 0) scalingXml += `<c:min val="${ax.min}"/>`;
42873
- if (ax.max !== void 0) scalingXml += `<c:max val="${ax.max}"/>`;
42874
- scalingXml += "</c:scaling>";
42875
- const numFmt = ax.numFmt ? `<c:numFmt formatCode="${escapeXml(ax.numFmt)}" sourceLinked="0"/>` : "";
42876
- plotArea += `<${axTag}><c:axId val="${axId}"/>${scalingXml}${titleXml2}${numFmt}<c:crossAx val="${crossId}"/></${axTag}>`;
42877
- }
43096
+ let dvXml = "";
43097
+ if (sheet.dataValidations.length > 0) {
43098
+ const dvEntries = sheet.dataValidations.map((dv) => {
43099
+ let attrs = `sqref="${dv.ref}" type="${dv.type}"`;
43100
+ if (dv.operator) attrs += ` operator="${dv.operator}"`;
43101
+ if (!dv.showDropdown) attrs += ' showDropDown="1"';
43102
+ if (dv.errorStyle) attrs += ` errorStyle="${dv.errorStyle}"`;
43103
+ if (dv.errorTitle) attrs += ` errorTitle="${escapeXml(dv.errorTitle)}"`;
43104
+ if (dv.errorMessage) attrs += ` error="${escapeXml(dv.errorMessage)}"`;
43105
+ if (dv.promptTitle) attrs += ` promptTitle="${escapeXml(dv.promptTitle)}"`;
43106
+ if (dv.promptMessage) attrs += ` prompt="${escapeXml(dv.promptMessage)}"`;
43107
+ let inner = "";
43108
+ if (dv.formula1) inner += `<formula1>${escapeXml(dv.formula1)}</formula1>`;
43109
+ if (dv.formula2) inner += `<formula2>${escapeXml(dv.formula2)}</formula2>`;
43110
+ return `<dataValidation ${attrs}>${inner}</dataValidation>`;
43111
+ }).join("");
43112
+ dvXml = `<dataValidations count="${sheet.dataValidations.length}">${dvEntries}</dataValidations>`;
42878
43113
  }
42879
- plotArea += "</c:plotArea>";
42880
- let titleXml = "";
42881
- if (chart.title) {
42882
- titleXml = `<c:title><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(chart.title)}</a:t></a:r></a:p></c:rich></c:tx></c:title>`;
43114
+ let cfXml = "";
43115
+ if (sheet.conditionalFormats.length > 0) {
43116
+ cfXml = sheet.conditionalFormats.map((cf) => buildConditionalFormattingXml(cf, dxfMap)).join("");
42883
43117
  }
42884
- let legendXml = "";
42885
- if (chart.legendPosition && chart.legendPosition !== "none") {
42886
- const posMap = { top: "t", bottom: "b", left: "l", right: "r" };
42887
- legendXml = `<c:legend><c:legendPos val="${posMap[chart.legendPosition] ?? "b"}"/></c:legend>`;
43118
+ let hyperlinksXml = "";
43119
+ if (hyperlinkRIds && hyperlinkRIds.size > 0) {
43120
+ const hlEntries = Array.from(hyperlinkRIds.entries()).map(([ref, rId]) => `<hyperlink ref="${ref}" r:id="${rId}"/>`).join("");
43121
+ hyperlinksXml = `<hyperlinks>${hlEntries}</hyperlinks>`;
42888
43122
  }
42889
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42890
- <c:chartSpace xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
42891
- <c:chart>${titleXml}${plotArea}${legendXml}</c:chart>
42892
- </c:chartSpace>`;
42893
- }
42894
- function buildAnchorPosition(pos) {
42895
- return `<xdr:col>${pos.col}</xdr:col><xdr:colOff>${pos.colOffset ?? 0}</xdr:colOff><xdr:row>${pos.row}</xdr:row><xdr:rowOff>${pos.rowOffset ?? 0}</xdr:rowOff>`;
42896
- }
42897
- function buildChartAnchorXml(chart, rId) {
42898
- return `<xdr:twoCellAnchor>
42899
- <xdr:from>${buildAnchorPosition(chart.anchor.from)}</xdr:from>
42900
- <xdr:to>${buildAnchorPosition(chart.anchor.to)}</xdr:to>
42901
- <xdr:graphicFrame macro="">
42902
- <xdr:nvGraphicFramePr><xdr:cNvPr id="0" name="Chart"/><xdr:cNvGraphicFramePr/></xdr:nvGraphicFramePr>
42903
- <xdr:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></xdr:xfrm>
42904
- <a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" r:id="${rId}"/></a:graphicData></a:graphic>
42905
- </xdr:graphicFrame>
42906
- <xdr:clientData/>
42907
- </xdr:twoCellAnchor>`;
42908
- }
42909
- function buildImageAnchorXml(image, rId) {
42910
- return `<xdr:twoCellAnchor editAs="oneCell">
42911
- <xdr:from>${buildAnchorPosition(image.tl)}</xdr:from>
42912
- <xdr:to>${buildAnchorPosition(image.br)}</xdr:to>
42913
- <xdr:pic>
42914
- <xdr:nvPicPr><xdr:cNvPr id="0" name="Image"/><xdr:cNvPicPr/></xdr:nvPicPr>
42915
- <xdr:blipFill><a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="${rId}"/><a:stretch><a:fillRect/></a:stretch></xdr:blipFill>
42916
- <xdr:spPr><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr>
42917
- </xdr:pic>
42918
- <xdr:clientData/>
42919
- </xdr:twoCellAnchor>`;
42920
- }
42921
- function buildShapeAnchorXml(drawing) {
42922
- let fillXml = "";
42923
- if (drawing.fillColor) fillXml = `<a:solidFill><a:srgbClr val="${hexToOoxmlRgb(drawing.fillColor)}"/></a:solidFill>`;
42924
- let outlineXml = "";
42925
- if (drawing.outlineColor) {
42926
- const w = Math.round((drawing.outlineWidth ?? 1) * 12700);
42927
- outlineXml = `<a:ln w="${w}"><a:solidFill><a:srgbClr val="${hexToOoxmlRgb(drawing.outlineColor)}"/></a:solidFill></a:ln>`;
43123
+ const drawingXml = drawingRId ? `<drawing r:id="${drawingRId}"/>` : "";
43124
+ let tablePartsXml = "";
43125
+ if (tableRIds && tableRIds.length > 0) {
43126
+ const parts = tableRIds.map((rId) => `<tablePart r:id="${rId}"/>`).join("");
43127
+ tablePartsXml = `<tableParts count="${tableRIds.length}">${parts}</tableParts>`;
42928
43128
  }
42929
- const geom = drawing.geometry ?? "rect";
42930
- let textXml = "";
42931
- if (drawing.text) textXml = `<xdr:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(drawing.text)}</a:t></a:r></a:p></xdr:txBody>`;
42932
- return `<xdr:twoCellAnchor>
42933
- <xdr:from>${buildAnchorPosition(drawing.anchor.from)}</xdr:from>
42934
- <xdr:to>${buildAnchorPosition(drawing.anchor.to)}</xdr:to>
42935
- <xdr:sp><xdr:nvSpPr><xdr:cNvPr id="0" name="Shape"/><xdr:cNvSpPr/></xdr:nvSpPr>
42936
- <xdr:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></a:xfrm><a:prstGeom prst="${geom}"><a:avLst/></a:prstGeom>${fillXml}${outlineXml}</xdr:spPr>
42937
- ${textXml}</xdr:sp>
42938
- <xdr:clientData/>
42939
- </xdr:twoCellAnchor>`;
42940
- }
42941
- function buildTableXml(table, tableId) {
42942
- const colsXml = table.columns.map((col) => {
42943
- let inner = "";
42944
- if (col.totalsFunction) inner += `<totalsRowFunction>${escapeXml(col.totalsFunction)}</totalsRowFunction>`;
42945
- if (col.totalsFormula) inner += `<totalsRowFormula>${escapeXml(col.totalsFormula)}</totalsRowFormula>`;
42946
- return `<tableColumn id="${col.id}" name="${escapeXml(col.name)}">${inner}</tableColumn>`;
42947
- }).join("");
42948
- const autoFilterXml = table.autoFilter ? `<autoFilter ref="${escapeXml(table.ref)}"/>` : "";
42949
- const styleName = table.styleName ?? "TableStyleMedium2";
42950
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
42951
- <table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="${tableId}" name="${escapeXml(table.name)}" displayName="${escapeXml(table.displayName)}" ref="${escapeXml(table.ref)}" totalsRowCount="${table.totalsRow ? 1 : 0}">
42952
- ${autoFilterXml}
42953
- <tableColumns count="${table.columns.length}">${colsXml}</tableColumns>
42954
- <tableStyleInfo name="${escapeXml(styleName)}" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/>
42955
- </table>`;
42956
- }
42957
- function buildConditionalFormattingXml(cf, dxfMap) {
42958
- const rules = cf.rules.map((rule) => {
42959
- switch (rule.ruleType) {
42960
- case "colorScale": {
42961
- const count = rule.colors.length;
42962
- const cfvos = count === 2 ? '<cfvo type="min"/><cfvo type="max"/>' : '<cfvo type="min"/><cfvo type="percentile" val="50"/><cfvo type="max"/>';
42963
- const colors = rule.colors.map((c) => `<color rgb="${hexToArgb(c)}"/>`).join("");
42964
- return `<cfRule type="colorScale" priority="${rule.priority}"><colorScale>${cfvos}${colors}</colorScale></cfRule>`;
42965
- }
42966
- case "dataBar": {
42967
- const showVal = rule.showValue ? "1" : "0";
42968
- return `<cfRule type="dataBar" priority="${rule.priority}"><dataBar minLength="${rule.minLength}" maxLength="${rule.maxLength}" showValue="${showVal}"><cfvo type="min"/><cfvo type="max"/><color rgb="${hexToArgb(rule.color)}"/></dataBar></cfRule>`;
42969
- }
42970
- case "iconSet": {
42971
- const thresholds = rule.thresholds.map((t) => {
42972
- if (t.type === "min" || t.type === "autoMin") return '<cfvo type="min"/>';
42973
- if (t.type === "max" || t.type === "autoMax") return '<cfvo type="max"/>';
42974
- return `<cfvo type="${t.type}" val="${t.value ?? 0}"/>`;
42975
- }).join("");
42976
- const showVal = rule.showValue ? "" : ' showValue="0"';
42977
- const reverse = rule.reverse ? ' reverse="1"' : "";
42978
- return `<cfRule type="iconSet" priority="${rule.priority}"><iconSet iconSet="${rule.iconSet}"${showVal}${reverse}>${thresholds}</iconSet></cfRule>`;
42979
- }
42980
- case "style": {
42981
- let attrs = `type="${rule.type}" priority="${rule.priority}"`;
42982
- if (rule.style) {
42983
- const dxfId = dxfMap.get(JSON.stringify(rule.style));
42984
- if (dxfId !== void 0) attrs += ` dxfId="${dxfId}"`;
42985
- }
42986
- if (rule.operator) attrs += ` operator="${rule.operator}"`;
42987
- if (rule.text) attrs += ` text="${escapeXml(rule.text)}"`;
42988
- if (rule.rank !== void 0) attrs += ` rank="${rule.rank}"`;
42989
- if (rule.percent) attrs += ' percent="1"';
42990
- if (rule.bottom) attrs += ' bottom="1"';
42991
- if (rule.aboveAverage === false) attrs += ' aboveAverage="0"';
42992
- if (rule.timePeriod) attrs += ` timePeriod="${rule.timePeriod}"`;
42993
- let inner = "";
42994
- if (rule.formulae) {
42995
- inner = rule.formulae.map((f) => `<formula>${escapeXml(String(f))}</formula>`).join("");
42996
- }
42997
- return `<cfRule ${attrs}>${inner}</cfRule>`;
42998
- }
43129
+ const ps = sheet.pageSetup;
43130
+ const hf = sheet.headerFooter;
43131
+ const fitToPage = ps && (ps.fitToWidth !== void 0 || ps.fitToHeight !== void 0);
43132
+ const sheetPrXml = fitToPage ? `<sheetPr><pageSetUpPr fitToPage="1"/></sheetPr>` : "";
43133
+ const marginsXml = (() => {
43134
+ const m = ps?.margins;
43135
+ const left = m?.left ?? 0.7;
43136
+ const right = m?.right ?? 0.7;
43137
+ const top = m?.top ?? 0.75;
43138
+ const bottom = m?.bottom ?? 0.75;
43139
+ const header = m?.header ?? 0.3;
43140
+ const footer = m?.footer ?? 0.3;
43141
+ return `<pageMargins left="${left}" right="${right}" top="${top}" bottom="${bottom}" header="${header}" footer="${footer}"/>`;
43142
+ })();
43143
+ let pageSetupXml = "";
43144
+ if (ps) {
43145
+ const attrs = [];
43146
+ if (ps.paperSize !== void 0) attrs.push(`paperSize="${ps.paperSize}"`);
43147
+ if (ps.scale !== void 0) attrs.push(`scale="${ps.scale}"`);
43148
+ if (ps.fitToWidth !== void 0) attrs.push(`fitToWidth="${ps.fitToWidth}"`);
43149
+ if (ps.fitToHeight !== void 0) attrs.push(`fitToHeight="${ps.fitToHeight}"`);
43150
+ if (ps.orientation) attrs.push(`orientation="${ps.orientation}"`);
43151
+ if (attrs.length > 0) pageSetupXml = `<pageSetup ${attrs.join(" ")}/>`;
43152
+ }
43153
+ let headerFooterXml = "";
43154
+ if (hf) {
43155
+ const rootAttrs = [];
43156
+ if (hf.differentOddEven) rootAttrs.push(`differentOddEven="1"`);
43157
+ if (hf.differentFirst) rootAttrs.push(`differentFirst="1"`);
43158
+ const inner = [];
43159
+ if (hf.oddHeader) inner.push(`<oddHeader>${escapeXml(hf.oddHeader)}</oddHeader>`);
43160
+ if (hf.oddFooter) inner.push(`<oddFooter>${escapeXml(hf.oddFooter)}</oddFooter>`);
43161
+ if (hf.evenHeader) inner.push(`<evenHeader>${escapeXml(hf.evenHeader)}</evenHeader>`);
43162
+ if (hf.evenFooter) inner.push(`<evenFooter>${escapeXml(hf.evenFooter)}</evenFooter>`);
43163
+ if (hf.firstHeader) inner.push(`<firstHeader>${escapeXml(hf.firstHeader)}</firstHeader>`);
43164
+ if (hf.firstFooter) inner.push(`<firstFooter>${escapeXml(hf.firstFooter)}</firstFooter>`);
43165
+ if (inner.length > 0) {
43166
+ const attrStr = rootAttrs.length > 0 ? ` ${rootAttrs.join(" ")}` : "";
43167
+ headerFooterXml = `<headerFooter${attrStr}>${inner.join("")}</headerFooter>`;
42999
43168
  }
43000
- }).join("");
43001
- return `<conditionalFormatting sqref="${cf.ref}">${rules}</conditionalFormatting>`;
43002
- }
43003
- function buildDxfXml(style) {
43004
- let inner = "";
43005
- if (style.fontBold || style.fontItalic || style.fontColor) {
43006
- let fontParts = "";
43007
- if (style.fontBold) fontParts += "<b/>";
43008
- if (style.fontItalic) fontParts += "<i/>";
43009
- if (style.fontColor) fontParts += `<color rgb="${hexToArgb(style.fontColor)}"/>`;
43010
- inner += `<font>${fontParts}</font>`;
43011
43169
  }
43012
- if (style.backgroundColor) {
43013
- inner += `<fill><patternFill><bgColor rgb="${hexToArgb(style.backgroundColor)}"/></patternFill></fill>`;
43170
+ let dimensionRef = "A1";
43171
+ if (sortedRows.length > 0) {
43172
+ let minCol = Infinity, maxCol = 0;
43173
+ const minRow = sortedRows[0];
43174
+ const maxRow = sortedRows[sortedRows.length - 1];
43175
+ for (const rowNum of sortedRows) {
43176
+ const cells = rowMap.get(rowNum);
43177
+ for (const { col } of cells) {
43178
+ if (col < minCol) minCol = col;
43179
+ if (col > maxCol) maxCol = col;
43180
+ }
43181
+ }
43182
+ dimensionRef = `${rowColToRef(minRow, minCol)}:${rowColToRef(maxRow, maxCol)}`;
43014
43183
  }
43015
- return `<dxf>${inner}</dxf>`;
43016
- }
43017
- function getImageExtension(dataUrl) {
43018
- if (dataUrl.startsWith("data:image/png")) return "png";
43019
- if (dataUrl.startsWith("data:image/jpeg") || dataUrl.startsWith("data:image/jpg")) return "jpeg";
43020
- if (dataUrl.startsWith("data:image/gif")) return "gif";
43021
- return "png";
43022
- }
43023
- function dataUrlToBytes(dataUrl) {
43024
- const match = dataUrl.match(/^data:[^;]+;base64,(.+)$/);
43025
- if (!match) return null;
43026
- const binary = atob(match[1]);
43027
- const bytes = new Uint8Array(binary.length);
43028
- for (let i2 = 0; i2 < binary.length; i2++) bytes[i2] = binary.charCodeAt(i2);
43029
- return bytes;
43184
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43185
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
43186
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
43187
+ ${sheetPrXml}<dimension ref="${dimensionRef}"/>
43188
+ <sheetViews>${sheetView}</sheetViews>
43189
+ <sheetFormatPr defaultRowHeight="${sheet.defaultRowHeight}" defaultColWidth="${sheet.defaultColWidth}"/>
43190
+ ${cols.length > 0 ? `<cols>${cols.join("")}</cols>` : ""}
43191
+ <sheetData>
43192
+ ${rows.join("\n")}
43193
+ </sheetData>
43194
+ ${autoFilterXml}${mergeXml}${cfXml}${dvXml}${hyperlinksXml}${marginsXml}${pageSetupXml}${headerFooterXml}${drawingXml}${tablePartsXml}
43195
+ </worksheet>`;
43030
43196
  }
43031
- function escapeXml(s) {
43032
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
43197
+ function getCellType(cell, ssIndex) {
43198
+ if (cell.error) return "e";
43199
+ if (cell.formula && typeof cell.value === "string") return "str";
43200
+ if (typeof cell.value === "string" && ssIndex.has(cell.value)) return "s";
43201
+ if (typeof cell.value === "boolean") return "b";
43202
+ return void 0;
43033
43203
  }
43034
-
43035
- // ../xlsx/src/style_helpers.ts
43036
- function border(style = "thin", color = "#000000") {
43037
- return { width: 1, style, color };
43204
+ function getCellValue(cell, ssIndex) {
43205
+ if (cell.value === null) return void 0;
43206
+ if (cell.error) return cell.error;
43207
+ if (cell.formula && typeof cell.value === "string") return cell.value;
43208
+ if (typeof cell.value === "string") {
43209
+ const idx = ssIndex.get(cell.value);
43210
+ return idx !== void 0 ? idx : cell.value;
43211
+ }
43212
+ if (typeof cell.value === "boolean") return cell.value ? 1 : 0;
43213
+ return cell.value;
43038
43214
  }
43039
- function allBorders(style = "thin", color = "#000000") {
43040
- const b = border(style, color);
43041
- return { borderTop: b, borderRight: b, borderBottom: b, borderLeft: b };
43215
+ function quoteSheetName(name) {
43216
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? name : `'${name.replace(/'/g, "''")}'`;
43042
43217
  }
43043
-
43044
- // ../xlsx/src/pivot_recompute.ts
43045
- var TOTAL_LABEL = "Grand Total";
43046
- function recomputePivot(table, cache, source) {
43047
- const records = filterByPageAxis(table, cache, source.records);
43048
- const rowTuples = distinctTuples(records, table.rowFieldIndices);
43049
- const colTuples = distinctTuples(records, table.colFieldIndices);
43050
- const groupKey = (rec) => JSON.stringify([
43051
- tupleOf(rec, table.rowFieldIndices),
43052
- tupleOf(rec, table.colFieldIndices)
43053
- ]);
43054
- const groups = /* @__PURE__ */ new Map();
43055
- for (const rec of records) {
43056
- const key = groupKey(rec);
43057
- let bucket = groups.get(key);
43058
- if (!bucket) {
43059
- bucket = [];
43060
- groups.set(key, bucket);
43218
+ function buildWorkbookXml(workbook, pivotInfo) {
43219
+ const sheets = workbook.sheets.map(
43220
+ (s, i2) => `<sheet name="${escapeXml(s.name)}" sheetId="${i2 + 1}" r:id="rId${i2 + 1}"/>`
43221
+ ).join("\n");
43222
+ const nameEntries = [];
43223
+ for (const [name, value] of workbook.namedRanges) {
43224
+ nameEntries.push(`<definedName name="${escapeXml(name)}">${escapeXml(value)}</definedName>`);
43225
+ }
43226
+ workbook.sheets.forEach((s, i2) => {
43227
+ const pt = s.printTitles;
43228
+ if (!pt || !pt.repeatRows && !pt.repeatCols) return;
43229
+ const parts = [];
43230
+ const sheetName = quoteSheetName(s.name);
43231
+ if (pt.repeatCols) {
43232
+ const [start, end] = pt.repeatCols;
43233
+ parts.push(`${sheetName}!$${colNumToLetters(start)}:$${colNumToLetters(end)}`);
43061
43234
  }
43062
- bucket.push(rec);
43235
+ if (pt.repeatRows) {
43236
+ const [start, end] = pt.repeatRows;
43237
+ parts.push(`${sheetName}!$${start}:$${end}`);
43238
+ }
43239
+ nameEntries.push(
43240
+ `<definedName name="_xlnm.Print_Titles" localSheetId="${i2}">${escapeXml(parts.join(","))}</definedName>`
43241
+ );
43242
+ });
43243
+ const definedNames = nameEntries.length > 0 ? `
43244
+ <definedNames>
43245
+ ${nameEntries.join("\n")}
43246
+ </definedNames>` : "";
43247
+ let pivotCachesBlock = "";
43248
+ if (pivotInfo && pivotInfo.cachesByWorkbook.size > 0) {
43249
+ const baseRId = workbook.sheets.length + 3;
43250
+ const cacheIds = [...pivotInfo.cachesByWorkbook.keys()].sort((a, b) => a - b);
43251
+ const items = cacheIds.map((cacheId, i2) => `<pivotCache cacheId="${cacheId}" r:id="rId${baseRId + i2}"/>`).join("\n");
43252
+ pivotCachesBlock = `
43253
+ <pivotCaches>
43254
+ ${items}
43255
+ </pivotCaches>`;
43063
43256
  }
43064
- return buildGrid(table, source, rowTuples, colTuples, groups, records);
43257
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43258
+ <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
43259
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
43260
+ <bookViews>
43261
+ <workbookView activeTab="${workbook.activeSheetIndex}"/>
43262
+ </bookViews>
43263
+ <sheets>
43264
+ ${sheets}
43265
+ </sheets>${definedNames}${pivotCachesBlock}
43266
+ <calcPr fullCalcOnLoad="1"/>
43267
+ </workbook>`;
43065
43268
  }
43066
- function filterByPageAxis(table, cache, records) {
43067
- const filters = [];
43068
- for (const fi of table.pageFieldIndices) {
43069
- const cfg = table.fields[fi];
43070
- if (cfg?.selectedPageItem == null) continue;
43071
- const cacheField = cache.fields[fi];
43072
- if (!cacheField) continue;
43073
- const allowed = cacheField.items[cfg.selectedPageItem];
43074
- if (allowed) filters.push({ fieldIndex: fi, allowed });
43075
- }
43076
- if (filters.length === 0) return records;
43077
- return records.filter(
43078
- (rec) => filters.every(
43079
- ({ fieldIndex, allowed }) => cellMatchesItem(rec[fieldIndex], allowed)
43080
- )
43269
+ function buildWorkbookRels(workbook, pivotInfo) {
43270
+ const rels = workbook.sheets.map(
43271
+ (_, i2) => `<Relationship Id="rId${i2 + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet${i2 + 1}.xml"/>`
43081
43272
  );
43082
- }
43083
- function cellMatchesItem(cell, item) {
43084
- switch (item.kind) {
43085
- case "string":
43086
- return typeof cell === "string" && cell === item.value;
43087
- case "number":
43088
- return typeof cell === "number" && cell === item.value;
43089
- case "boolean":
43090
- return typeof cell === "boolean" && cell === item.value;
43091
- case "date":
43092
- return typeof cell === "string" && cell === item.value;
43093
- case "missing":
43094
- return cell === void 0 || cell === null || cell === "";
43095
- case "error":
43096
- return typeof cell === "string" && cell === item.value;
43273
+ rels.push(`<Relationship Id="rId${workbook.sheets.length + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>`);
43274
+ rels.push(`<Relationship Id="rId${workbook.sheets.length + 2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>`);
43275
+ if (pivotInfo && pivotInfo.cachesByWorkbook.size > 0) {
43276
+ const baseRId = workbook.sheets.length + 3;
43277
+ const cacheIds = [...pivotInfo.cachesByWorkbook.keys()].sort((a, b) => a - b);
43278
+ cacheIds.forEach((cacheId, i2) => {
43279
+ const target = pivotInfo.cachesByWorkbook.get(cacheId);
43280
+ if (!target) return;
43281
+ rels.push(
43282
+ `<Relationship Id="rId${baseRId + i2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" Target="${escapeXml(target)}"/>`
43283
+ );
43284
+ });
43097
43285
  }
43286
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43287
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
43288
+ ${rels.join("\n")}
43289
+ </Relationships>`;
43290
+ }
43291
+ function buildContentTypes(sheetCount, extraTypes = []) {
43292
+ const sheetTypes = Array.from(
43293
+ { length: sheetCount },
43294
+ (_, i2) => `<Override PartName="/xl/worksheets/sheet${i2 + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`
43295
+ ).join("\n");
43296
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43297
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
43298
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
43299
+ <Default Extension="xml" ContentType="application/xml"/>
43300
+ <Default Extension="png" ContentType="image/png"/>
43301
+ <Default Extension="jpeg" ContentType="image/jpeg"/>
43302
+ <Default Extension="jpg" ContentType="image/jpeg"/>
43303
+ <Default Extension="gif" ContentType="image/gif"/>
43304
+ <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
43305
+ ${sheetTypes}
43306
+ <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
43307
+ <Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
43308
+ <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
43309
+ <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
43310
+ ${extraTypes.join("\n")}
43311
+ </Types>`;
43098
43312
  }
43099
- function tupleOf(rec, indices) {
43100
- return indices.map((i2) => rec[i2] ?? null);
43313
+ function buildRootRels() {
43314
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43315
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
43316
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
43317
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
43318
+ <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
43319
+ </Relationships>`;
43101
43320
  }
43102
- function distinctTuples(records, indices) {
43103
- const seen = /* @__PURE__ */ new Set();
43104
- const out = [];
43105
- for (const rec of records) {
43106
- const t = tupleOf(rec, indices);
43107
- const key = JSON.stringify(t);
43108
- if (seen.has(key)) continue;
43109
- seen.add(key);
43110
- out.push(t);
43111
- }
43112
- out.sort((a, b) => {
43113
- for (let i2 = 0; i2 < Math.max(a.length, b.length); i2++) {
43114
- const av = a[i2];
43115
- const bv = b[i2];
43116
- if (av === bv) continue;
43117
- const as = av === null || av === void 0 ? "" : String(av);
43118
- const bs = bv === null || bv === void 0 ? "" : String(bv);
43119
- if (as < bs) return -1;
43120
- if (as > bs) return 1;
43121
- }
43122
- return 0;
43123
- });
43124
- return out;
43321
+ function buildCoreProps() {
43322
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
43323
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43324
+ <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
43325
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
43326
+ xmlns:dcterms="http://purl.org/dc/terms/"
43327
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
43328
+ <dcterms:created xsi:type="dcterms:W3CDTF">${now}</dcterms:created>
43329
+ <dcterms:modified xsi:type="dcterms:W3CDTF">${now}</dcterms:modified>
43330
+ </cp:coreProperties>`;
43125
43331
  }
43126
- function aggregate(values2, fn) {
43127
- const numeric = values2.filter((v) => typeof v === "number");
43128
- switch (fn) {
43129
- case "count":
43130
- return values2.filter((v) => v !== null && v !== void 0 && v !== "").length;
43131
- case "countNums":
43132
- return numeric.length;
43133
- case "sum":
43134
- return numeric.reduce((a, b) => a + b, 0);
43135
- case "average":
43136
- if (numeric.length === 0) return null;
43137
- return numeric.reduce((a, b) => a + b, 0) / numeric.length;
43138
- case "min":
43139
- return numeric.length === 0 ? null : Math.min(...numeric);
43140
- case "max":
43141
- return numeric.length === 0 ? null : Math.max(...numeric);
43142
- case "product":
43143
- return numeric.length === 0 ? null : numeric.reduce((a, b) => a * b, 1);
43144
- }
43332
+ function buildAppProps() {
43333
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43334
+ <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">
43335
+ <Application>Microsoft Excel</Application>
43336
+ </Properties>`;
43145
43337
  }
43146
- function buildGrid(table, source, rowTuples, colTuples, groups, allRecords) {
43147
- const numRowFields = table.rowFieldIndices.length;
43148
- const numColFields = table.colFieldIndices.length;
43149
- const numDataFields = Math.max(table.dataFields.length, 1);
43150
- const showRowGrand = table.display.colGrandTotals;
43151
- const showColGrand = table.display.rowGrandTotals;
43152
- const rowLabelCols = Math.max(numRowFields, 1);
43153
- const colHeaderRows = numColFields + (numDataFields > 0 ? 1 : 0);
43154
- const headerRows = Math.max(colHeaderRows, 1);
43155
- const dataCols = colTuples.length * numDataFields;
43156
- const totalCols = rowLabelCols + dataCols + (showColGrand ? numDataFields : 0);
43157
- const totalRows = headerRows + rowTuples.length + (showRowGrand ? 1 : 0);
43158
- const cells = [];
43159
- for (let r = 0; r < totalRows; r++) {
43160
- cells.push(new Array(totalCols).fill({ kind: "blank" }));
43338
+ var CHART_TYPE_MAP2 = {
43339
+ bar: "c:barChart",
43340
+ col: "c:barChart",
43341
+ line: "c:lineChart",
43342
+ pie: "c:pieChart",
43343
+ doughnut: "c:doughnutChart",
43344
+ area: "c:areaChart",
43345
+ scatter: "c:scatterChart",
43346
+ bubble: "c:bubbleChart",
43347
+ radar: "c:radarChart",
43348
+ stock: "c:stockChart",
43349
+ surface: "c:surfaceChart"
43350
+ };
43351
+ function buildSeriesXml(s, idx, chartType, categories) {
43352
+ let nameXml = "";
43353
+ if (s.name) nameXml = `<c:tx><c:strRef><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${escapeXml(s.name)}</c:v></c:pt></c:strCache></c:strRef></c:tx>`;
43354
+ let colorXml = "";
43355
+ if (s.color) colorXml = `<c:spPr><a:solidFill><a:srgbClr val="${hexToOoxmlRgb(s.color)}"/></a:solidFill></c:spPr>`;
43356
+ const valTag = chartType === "scatter" || chartType === "bubble" ? "c:yVal" : "c:val";
43357
+ const valPts = s.values.map((v, i2) => `<c:pt idx="${i2}"><c:v>${v}</c:v></c:pt>`).join("");
43358
+ const valXml = `<${valTag}><c:numRef><c:numCache><c:ptCount val="${s.values.length}"/>${valPts}</c:numCache></c:numRef></${valTag}>`;
43359
+ let catXml = "";
43360
+ if (categories && categories.length > 0) {
43361
+ const catTag = chartType === "scatter" || chartType === "bubble" ? "c:xVal" : "c:cat";
43362
+ const catPts = categories.map((c, i2) => `<c:pt idx="${i2}"><c:v>${escapeXml(c)}</c:v></c:pt>`).join("");
43363
+ catXml = `<${catTag}><c:strRef><c:strCache><c:ptCount val="${categories.length}"/>${catPts}</c:strCache></c:strRef></${catTag}>`;
43161
43364
  }
43162
- for (let level = 0; level < numColFields; level++) {
43163
- let col = rowLabelCols;
43164
- for (const tuple of colTuples) {
43165
- const text = formatCellLabel(tuple[level]);
43166
- for (let i2 = 0; i2 < numDataFields; i2++) {
43167
- cells[level][col + i2] = { kind: "colHeader", depth: level, text };
43168
- }
43169
- col += numDataFields;
43170
- }
43365
+ let bubbleXml = "";
43366
+ if (s.bubbleSizes) {
43367
+ const bPts = s.bubbleSizes.map((v, i2) => `<c:pt idx="${i2}"><c:v>${v}</c:v></c:pt>`).join("");
43368
+ bubbleXml = `<c:bubbleSize><c:numRef><c:numCache><c:ptCount val="${s.bubbleSizes.length}"/>${bPts}</c:numCache></c:numRef></c:bubbleSize>`;
43171
43369
  }
43172
- if (numDataFields > 0) {
43173
- const labelRow = colHeaderRows - 1;
43174
- let col = rowLabelCols;
43175
- for (let _t = 0; _t < colTuples.length; _t++) {
43176
- for (let d = 0; d < table.dataFields.length; d++) {
43177
- cells[labelRow][col + d] = {
43178
- kind: "valueLabel",
43179
- text: table.dataFields[d].name
43180
- };
43181
- }
43182
- col += numDataFields;
43183
- }
43184
- if (showColGrand) {
43185
- for (let d = 0; d < table.dataFields.length; d++) {
43186
- cells[labelRow][rowLabelCols + dataCols + d] = {
43187
- kind: "valueLabel",
43188
- text: table.dataFields[d].name
43189
- };
43190
- }
43191
- }
43370
+ return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/>${nameXml}${colorXml}${catXml}${valXml}${bubbleXml}</c:ser>`;
43371
+ }
43372
+ function buildChartTypeElement(chartType, seriesXml, needsAxIds) {
43373
+ const chartTag = CHART_TYPE_MAP2[chartType] ?? "c:barChart";
43374
+ const isBar = chartType === "bar";
43375
+ let barDir = "";
43376
+ if (chartTag === "c:barChart") {
43377
+ barDir = isBar ? '<c:barDir val="bar"/>' : '<c:barDir val="col"/>';
43192
43378
  }
43193
- for (let r = 0; r < rowTuples.length; r++) {
43194
- const rowTuple = rowTuples[r];
43195
- const gridRow = headerRows + r;
43196
- for (let level = 0; level < numRowFields; level++) {
43197
- cells[gridRow][level] = {
43198
- kind: "rowHeader",
43199
- depth: level,
43200
- text: formatCellLabel(rowTuple[level])
43201
- };
43202
- }
43203
- for (let c = 0; c < colTuples.length; c++) {
43204
- const colTuple = colTuples[c];
43205
- const groupRecords = groups.get(JSON.stringify([rowTuple, colTuple])) ?? [];
43206
- for (let d = 0; d < table.dataFields.length; d++) {
43207
- const df = table.dataFields[d];
43208
- const values2 = groupRecords.map((rec) => rec[df.fieldIndex]);
43209
- cells[gridRow][rowLabelCols + c * numDataFields + d] = {
43210
- kind: "value",
43211
- value: aggregate(values2, df.subtotal),
43212
- numFmt: df.numFmt
43213
- };
43214
- }
43215
- }
43216
- if (showColGrand) {
43217
- const rowOnly = allRecords.filter(
43218
- (rec) => sameTuple(tupleOf(rec, table.rowFieldIndices), rowTuple)
43219
- );
43220
- for (let d = 0; d < table.dataFields.length; d++) {
43221
- const df = table.dataFields[d];
43222
- cells[gridRow][rowLabelCols + dataCols + d] = {
43223
- kind: "rowTotal",
43224
- value: aggregate(
43225
- rowOnly.map((rec) => rec[df.fieldIndex]),
43226
- df.subtotal
43227
- )
43228
- };
43229
- }
43230
- }
43379
+ let grouping = "";
43380
+ if (chartTag === "c:barChart") {
43381
+ grouping = '<c:grouping val="clustered"/>';
43382
+ } else if (chartTag === "c:lineChart" || chartTag === "c:areaChart") {
43383
+ grouping = '<c:grouping val="clustered"/>';
43231
43384
  }
43232
- if (showRowGrand) {
43233
- const gridRow = headerRows + rowTuples.length;
43234
- cells[gridRow][0] = { kind: "totalLabel", text: TOTAL_LABEL };
43235
- for (let c = 0; c < colTuples.length; c++) {
43236
- const colTuple = colTuples[c];
43237
- const colOnly = allRecords.filter(
43238
- (rec) => sameTuple(tupleOf(rec, table.colFieldIndices), colTuple)
43239
- );
43240
- for (let d = 0; d < table.dataFields.length; d++) {
43241
- const df = table.dataFields[d];
43242
- cells[gridRow][rowLabelCols + c * numDataFields + d] = {
43243
- kind: "colTotal",
43244
- value: aggregate(
43245
- colOnly.map((rec) => rec[df.fieldIndex]),
43246
- df.subtotal
43247
- )
43248
- };
43385
+ const axIds = needsAxIds ? '<c:axId val="1"/><c:axId val="2"/>' : "";
43386
+ return `<${chartTag}>${barDir}${grouping}${seriesXml}${axIds}</${chartTag}>`;
43387
+ }
43388
+ function buildChartXml(chart) {
43389
+ const needsAxIds = chart.chartType !== "pie" && chart.chartType !== "doughnut";
43390
+ let plotArea;
43391
+ if (chart.chartType === "combo") {
43392
+ const groups = /* @__PURE__ */ new Map();
43393
+ chart.series.forEach((s, idx) => {
43394
+ const sType = s.seriesChartType ?? "col";
43395
+ let group = groups.get(sType);
43396
+ if (!group) {
43397
+ group = [];
43398
+ groups.set(sType, group);
43249
43399
  }
43400
+ group.push({ series: s, idx });
43401
+ });
43402
+ let chartElements = "";
43403
+ for (const [groupType, groupSeries] of groups) {
43404
+ const groupSeriesXml = groupSeries.map(
43405
+ ({ series, idx }) => buildSeriesXml(series, idx, groupType, chart.categories)
43406
+ ).join("");
43407
+ chartElements += buildChartTypeElement(groupType, groupSeriesXml, true);
43250
43408
  }
43251
- if (showColGrand) {
43252
- for (let d = 0; d < table.dataFields.length; d++) {
43253
- const df = table.dataFields[d];
43254
- cells[gridRow][rowLabelCols + dataCols + d] = {
43255
- kind: "grandTotal",
43256
- value: aggregate(
43257
- allRecords.map((rec) => rec[df.fieldIndex]),
43258
- df.subtotal
43259
- )
43260
- };
43409
+ plotArea = `<c:plotArea><c:layout/>${chartElements}`;
43410
+ } else {
43411
+ const seriesXml = chart.series.map(
43412
+ (s, idx) => buildSeriesXml(s, idx, chart.chartType, chart.categories)
43413
+ ).join("");
43414
+ plotArea = `<c:plotArea><c:layout/>${buildChartTypeElement(chart.chartType, seriesXml, needsAxIds)}`;
43415
+ }
43416
+ if (chart.chartType !== "pie" && chart.chartType !== "doughnut") {
43417
+ const axes = chart.axes ?? [{ type: "category" }, { type: "value" }];
43418
+ for (let i2 = 0; i2 < axes.length; i2++) {
43419
+ const ax = axes[i2];
43420
+ const axId = i2 + 1;
43421
+ const crossId = i2 === 0 ? 2 : 1;
43422
+ let axTag;
43423
+ switch (ax.type) {
43424
+ case "value":
43425
+ axTag = "c:valAx";
43426
+ break;
43427
+ case "date":
43428
+ axTag = "c:dateAx";
43429
+ break;
43430
+ case "series":
43431
+ axTag = "c:serAx";
43432
+ break;
43433
+ default:
43434
+ axTag = "c:catAx";
43435
+ break;
43261
43436
  }
43437
+ let titleXml2 = "";
43438
+ if (ax.title) titleXml2 = `<c:title><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(ax.title)}</a:t></a:r></a:p></c:rich></c:tx></c:title>`;
43439
+ let scalingXml = '<c:scaling><c:orientation val="minMax"/>';
43440
+ if (ax.min !== void 0) scalingXml += `<c:min val="${ax.min}"/>`;
43441
+ if (ax.max !== void 0) scalingXml += `<c:max val="${ax.max}"/>`;
43442
+ scalingXml += "</c:scaling>";
43443
+ const numFmt = ax.numFmt ? `<c:numFmt formatCode="${escapeXml(ax.numFmt)}" sourceLinked="0"/>` : "";
43444
+ plotArea += `<${axTag}><c:axId val="${axId}"/>${scalingXml}${titleXml2}${numFmt}<c:crossAx val="${crossId}"/></${axTag}>`;
43262
43445
  }
43263
43446
  }
43264
- void source;
43265
- return {
43266
- cells,
43267
- headerRows,
43268
- rowLabelCols,
43269
- rows: totalRows,
43270
- cols: totalCols
43271
- };
43272
- }
43273
- function sameTuple(a, b) {
43274
- if (a.length !== b.length) return false;
43275
- for (let i2 = 0; i2 < a.length; i2++) {
43276
- if (a[i2] !== b[i2]) {
43277
- const an = a[i2] === void 0 || a[i2] === null || a[i2] === "";
43278
- const bn = b[i2] === void 0 || b[i2] === null || b[i2] === "";
43279
- if (!(an && bn)) return false;
43280
- }
43447
+ plotArea += "</c:plotArea>";
43448
+ let titleXml = "";
43449
+ if (chart.title) {
43450
+ titleXml = `<c:title><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(chart.title)}</a:t></a:r></a:p></c:rich></c:tx></c:title>`;
43281
43451
  }
43282
- return true;
43452
+ let legendXml = "";
43453
+ if (chart.legendPosition && chart.legendPosition !== "none") {
43454
+ const posMap = { top: "t", bottom: "b", left: "l", right: "r" };
43455
+ legendXml = `<c:legend><c:legendPos val="${posMap[chart.legendPosition] ?? "b"}"/></c:legend>`;
43456
+ }
43457
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43458
+ <c:chartSpace xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
43459
+ <c:chart>${titleXml}${plotArea}${legendXml}</c:chart>
43460
+ </c:chartSpace>`;
43283
43461
  }
43284
- function formatCellLabel(v) {
43285
- if (v === void 0 || v === null || v === "") return "(blank)";
43286
- if (typeof v === "boolean") return v ? "TRUE" : "FALSE";
43287
- return String(v);
43462
+ function buildAnchorPosition(pos) {
43463
+ return `<xdr:col>${pos.col}</xdr:col><xdr:colOff>${pos.colOffset ?? 0}</xdr:colOff><xdr:row>${pos.row}</xdr:row><xdr:rowOff>${pos.rowOffset ?? 0}</xdr:rowOff>`;
43288
43464
  }
43289
-
43290
- // ../xlsx/src/pivot_model.ts
43291
- var PivotTableModel = class {
43292
- constructor(config, cache) {
43293
- this.config = config;
43294
- this.cache = cache;
43465
+ function buildChartAnchorXml(chart, rId) {
43466
+ return `<xdr:twoCellAnchor>
43467
+ <xdr:from>${buildAnchorPosition(chart.anchor.from)}</xdr:from>
43468
+ <xdr:to>${buildAnchorPosition(chart.anchor.to)}</xdr:to>
43469
+ <xdr:graphicFrame macro="">
43470
+ <xdr:nvGraphicFramePr><xdr:cNvPr id="0" name="Chart"/><xdr:cNvGraphicFramePr/></xdr:nvGraphicFramePr>
43471
+ <xdr:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></xdr:xfrm>
43472
+ <a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart"><c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" r:id="${rId}"/></a:graphicData></a:graphic>
43473
+ </xdr:graphicFrame>
43474
+ <xdr:clientData/>
43475
+ </xdr:twoCellAnchor>`;
43476
+ }
43477
+ function buildImageAnchorXml(image, rId) {
43478
+ return `<xdr:twoCellAnchor editAs="oneCell">
43479
+ <xdr:from>${buildAnchorPosition(image.tl)}</xdr:from>
43480
+ <xdr:to>${buildAnchorPosition(image.br)}</xdr:to>
43481
+ <xdr:pic>
43482
+ <xdr:nvPicPr><xdr:cNvPr id="0" name="Image"/><xdr:cNvPicPr/></xdr:nvPicPr>
43483
+ <xdr:blipFill><a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="${rId}"/><a:stretch><a:fillRect/></a:stretch></xdr:blipFill>
43484
+ <xdr:spPr><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr>
43485
+ </xdr:pic>
43486
+ <xdr:clientData/>
43487
+ </xdr:twoCellAnchor>`;
43488
+ }
43489
+ function buildShapeAnchorXml(drawing) {
43490
+ let fillXml = "";
43491
+ if (drawing.fillColor) fillXml = `<a:solidFill><a:srgbClr val="${hexToOoxmlRgb(drawing.fillColor)}"/></a:solidFill>`;
43492
+ let outlineXml = "";
43493
+ if (drawing.outlineColor) {
43494
+ const w = Math.round((drawing.outlineWidth ?? 1) * 12700);
43495
+ outlineXml = `<a:ln w="${w}"><a:solidFill><a:srgbClr val="${hexToOoxmlRgb(drawing.outlineColor)}"/></a:solidFill></a:ln>`;
43295
43496
  }
43296
- /**
43297
- * Recompute the pivot result from the workbook's current source data.
43298
- * Callers are responsible for triggering recomputation; the model does
43299
- * not subscribe to workbook changes itself.
43300
- */
43301
- recompute(workbook) {
43302
- const source = readSourceData(workbook, this.cache);
43303
- if (!source) {
43304
- this.result = void 0;
43305
- return;
43497
+ const geom = drawing.geometry ?? "rect";
43498
+ let textXml = "";
43499
+ if (drawing.text) textXml = `<xdr:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:t>${escapeXml(drawing.text)}</a:t></a:r></a:p></xdr:txBody>`;
43500
+ return `<xdr:twoCellAnchor>
43501
+ <xdr:from>${buildAnchorPosition(drawing.anchor.from)}</xdr:from>
43502
+ <xdr:to>${buildAnchorPosition(drawing.anchor.to)}</xdr:to>
43503
+ <xdr:sp><xdr:nvSpPr><xdr:cNvPr id="0" name="Shape"/><xdr:cNvSpPr/></xdr:nvSpPr>
43504
+ <xdr:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/></a:xfrm><a:prstGeom prst="${geom}"><a:avLst/></a:prstGeom>${fillXml}${outlineXml}</xdr:spPr>
43505
+ ${textXml}</xdr:sp>
43506
+ <xdr:clientData/>
43507
+ </xdr:twoCellAnchor>`;
43508
+ }
43509
+ function buildTableXml(table, tableId) {
43510
+ const colsXml = table.columns.map((col) => {
43511
+ let inner = "";
43512
+ if (col.totalsFunction) inner += `<totalsRowFunction>${escapeXml(col.totalsFunction)}</totalsRowFunction>`;
43513
+ if (col.totalsFormula) inner += `<totalsRowFormula>${escapeXml(col.totalsFormula)}</totalsRowFormula>`;
43514
+ return `<tableColumn id="${col.id}" name="${escapeXml(col.name)}">${inner}</tableColumn>`;
43515
+ }).join("");
43516
+ const autoFilterXml = table.autoFilter ? `<autoFilter ref="${escapeXml(table.ref)}"/>` : "";
43517
+ const styleName = table.styleName ?? "TableStyleMedium2";
43518
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
43519
+ <table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="${tableId}" name="${escapeXml(table.name)}" displayName="${escapeXml(table.displayName)}" ref="${escapeXml(table.ref)}" totalsRowCount="${table.totalsRow ? 1 : 0}">
43520
+ ${autoFilterXml}
43521
+ <tableColumns count="${table.columns.length}">${colsXml}</tableColumns>
43522
+ <tableStyleInfo name="${escapeXml(styleName)}" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/>
43523
+ </table>`;
43524
+ }
43525
+ function buildConditionalFormattingXml(cf, dxfMap) {
43526
+ const rules = cf.rules.map((rule) => {
43527
+ switch (rule.ruleType) {
43528
+ case "colorScale": {
43529
+ const count = rule.colors.length;
43530
+ const cfvos = count === 2 ? '<cfvo type="min"/><cfvo type="max"/>' : '<cfvo type="min"/><cfvo type="percentile" val="50"/><cfvo type="max"/>';
43531
+ const colors = rule.colors.map((c) => `<color rgb="${hexToArgb(c)}"/>`).join("");
43532
+ return `<cfRule type="colorScale" priority="${rule.priority}"><colorScale>${cfvos}${colors}</colorScale></cfRule>`;
43533
+ }
43534
+ case "dataBar": {
43535
+ const showVal = rule.showValue ? "1" : "0";
43536
+ return `<cfRule type="dataBar" priority="${rule.priority}"><dataBar minLength="${rule.minLength}" maxLength="${rule.maxLength}" showValue="${showVal}"><cfvo type="min"/><cfvo type="max"/><color rgb="${hexToArgb(rule.color)}"/></dataBar></cfRule>`;
43537
+ }
43538
+ case "iconSet": {
43539
+ const thresholds = rule.thresholds.map((t) => {
43540
+ if (t.type === "min" || t.type === "autoMin") return '<cfvo type="min"/>';
43541
+ if (t.type === "max" || t.type === "autoMax") return '<cfvo type="max"/>';
43542
+ return `<cfvo type="${t.type}" val="${t.value ?? 0}"/>`;
43543
+ }).join("");
43544
+ const showVal = rule.showValue ? "" : ' showValue="0"';
43545
+ const reverse = rule.reverse ? ' reverse="1"' : "";
43546
+ return `<cfRule type="iconSet" priority="${rule.priority}"><iconSet iconSet="${rule.iconSet}"${showVal}${reverse}>${thresholds}</iconSet></cfRule>`;
43547
+ }
43548
+ case "style": {
43549
+ let attrs = `type="${rule.type}" priority="${rule.priority}"`;
43550
+ if (rule.style) {
43551
+ const dxfId = dxfMap.get(JSON.stringify(rule.style));
43552
+ if (dxfId !== void 0) attrs += ` dxfId="${dxfId}"`;
43553
+ }
43554
+ if (rule.operator) attrs += ` operator="${rule.operator}"`;
43555
+ if (rule.text) attrs += ` text="${escapeXml(rule.text)}"`;
43556
+ if (rule.rank !== void 0) attrs += ` rank="${rule.rank}"`;
43557
+ if (rule.percent) attrs += ' percent="1"';
43558
+ if (rule.bottom) attrs += ' bottom="1"';
43559
+ if (rule.aboveAverage === false) attrs += ' aboveAverage="0"';
43560
+ if (rule.timePeriod) attrs += ` timePeriod="${rule.timePeriod}"`;
43561
+ let inner = "";
43562
+ if (rule.formulae) {
43563
+ inner = rule.formulae.map((f) => `<formula>${escapeXml(String(f))}</formula>`).join("");
43564
+ }
43565
+ return `<cfRule ${attrs}>${inner}</cfRule>`;
43566
+ }
43306
43567
  }
43307
- this.result = recomputePivot(this.config, this.cache, source);
43308
- }
43309
- };
43310
- function readSourceData(workbook, cache) {
43311
- if (cache.source.type !== "worksheet") return void 0;
43312
- const source = cache.source;
43313
- const sheet = workbook.sheets.find((s) => s.name === source.sheetName);
43314
- if (!sheet) return void 0;
43315
- const range = parseRange(source.ref);
43316
- if (!range) return void 0;
43317
- const header = [];
43318
- for (let col = range.startCol; col <= range.endCol; col++) {
43319
- const cell = sheet.getCell(rowColToRef(range.startRow, col));
43320
- header.push(formatHeader(cell?.value));
43568
+ }).join("");
43569
+ return `<conditionalFormatting sqref="${cf.ref}">${rules}</conditionalFormatting>`;
43570
+ }
43571
+ function buildDxfXml(style) {
43572
+ let inner = "";
43573
+ if (style.fontBold || style.fontItalic || style.fontColor) {
43574
+ let fontParts = "";
43575
+ if (style.fontBold) fontParts += "<b/>";
43576
+ if (style.fontItalic) fontParts += "<i/>";
43577
+ if (style.fontColor) fontParts += `<color rgb="${hexToArgb(style.fontColor)}"/>`;
43578
+ inner += `<font>${fontParts}</font>`;
43321
43579
  }
43322
- const records = [];
43323
- for (let row = range.startRow + 1; row <= range.endRow; row++) {
43324
- const rec = [];
43325
- for (let col = range.startCol; col <= range.endCol; col++) {
43326
- const cell = sheet.getCell(rowColToRef(row, col));
43327
- rec.push(coerceValue(cell?.value));
43328
- }
43329
- records.push(rec);
43580
+ if (style.backgroundColor) {
43581
+ inner += `<fill><patternFill><bgColor rgb="${hexToArgb(style.backgroundColor)}"/></patternFill></fill>`;
43330
43582
  }
43331
- return { header, records };
43583
+ return `<dxf>${inner}</dxf>`;
43332
43584
  }
43333
- function formatHeader(v) {
43334
- if (v === void 0 || v === null) return "";
43335
- return String(v);
43585
+ function getImageExtension(dataUrl) {
43586
+ if (dataUrl.startsWith("data:image/png")) return "png";
43587
+ if (dataUrl.startsWith("data:image/jpeg") || dataUrl.startsWith("data:image/jpg")) return "jpeg";
43588
+ if (dataUrl.startsWith("data:image/gif")) return "gif";
43589
+ return "png";
43336
43590
  }
43337
- function coerceValue(v) {
43338
- if (v === void 0 || v === null) return void 0;
43339
- if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
43340
- return v;
43341
- }
43342
- return String(v);
43591
+ function dataUrlToBytes(dataUrl) {
43592
+ const match = dataUrl.match(/^data:[^;]+;base64,(.+)$/);
43593
+ if (!match) return null;
43594
+ const binary = atob(match[1]);
43595
+ const bytes = new Uint8Array(binary.length);
43596
+ for (let i2 = 0; i2 < binary.length; i2++) bytes[i2] = binary.charCodeAt(i2);
43597
+ return bytes;
43343
43598
  }
43344
- function parseRange(ref) {
43345
- const range = ref.includes("!") ? ref.split("!")[1] : ref;
43346
- const cleaned = range.replace(/\$/g, "");
43347
- const m = cleaned.match(/^([A-Z]+\d+)(?::([A-Z]+\d+))?$/);
43348
- if (!m) return void 0;
43349
- const start = refToRowCol(m[1]);
43350
- if (!start) return void 0;
43351
- const endRef = m[2] ?? m[1];
43352
- const end = refToRowCol(endRef);
43353
- if (!end) return void 0;
43354
- return {
43355
- startRow: start.row,
43356
- startCol: start.col,
43357
- endRow: end.row,
43358
- endCol: end.col
43359
- };
43599
+
43600
+ // ../xlsx/src/style_helpers.ts
43601
+ function border(style = "thin", color = "#000000") {
43602
+ return { width: 1, style, color };
43603
+ }
43604
+ function allBorders(style = "thin", color = "#000000") {
43605
+ const b = border(style, color);
43606
+ return { borderTop: b, borderRight: b, borderBottom: b, borderLeft: b };
43360
43607
  }
43361
43608
 
43362
43609
  // ../xlsx/src/workbook_model.ts