@odoo/o-spreadsheet 19.1.2 → 19.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,8 @@
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
5
  * @version 19.1.0-alpha.3
6
- * @date 2026-01-07T16:20:59.139Z
7
- * @hash febc3e9
6
+ * @date 2026-01-14T10:01:54.190Z
7
+ * @hash 52a3e52
8
8
  */
9
9
 
10
10
  class FunctionCodeBuilder {
@@ -15073,9 +15073,10 @@ function assertDomainLength(domain) {
15073
15073
  throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
15074
15074
  }
15075
15075
  }
15076
- function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
15076
+ function addPivotDependencies(evalContext, pivotId, forMeasures) {
15077
15077
  //TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
15078
15078
  const dependencies = [];
15079
+ const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
15079
15080
  if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
15080
15081
  const { sheetId, zone } = coreDefinition.dataSet;
15081
15082
  const xc = zoneToXc(zone);
@@ -15092,8 +15093,7 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
15092
15093
  }
15093
15094
  for (const measure of forMeasures) {
15094
15095
  if (measure.computedBy) {
15095
- const formula = evalContext.getters.getMeasureCompiledFormula(measure);
15096
- dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
15096
+ dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
15097
15097
  }
15098
15098
  }
15099
15099
  const originPosition = evalContext.__originCellPosition;
@@ -15590,7 +15590,7 @@ const PIVOT_VALUE = {
15590
15590
  assertDomainLength(domainArgs);
15591
15591
  const pivot = this.getters.getPivot(pivotId);
15592
15592
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
15593
- addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
15593
+ addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
15594
15594
  pivot.init({ reload: pivot.needsReevaluation });
15595
15595
  const error = pivot.assertIsValid({ throwOnError: false });
15596
15596
  if (error) {
@@ -15623,8 +15623,7 @@ const PIVOT_HEADER = {
15623
15623
  const _pivotId = getPivotId(_pivotFormulaId, this.getters);
15624
15624
  assertDomainLength(domainArgs);
15625
15625
  const pivot = this.getters.getPivot(_pivotId);
15626
- const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
15627
- addPivotDependencies(this, coreDefinition, []);
15626
+ addPivotDependencies(this, _pivotId, []);
15628
15627
  pivot.init({ reload: pivot.needsReevaluation });
15629
15628
  const error = pivot.assertIsValid({ throwOnError: false });
15630
15629
  if (error) {
@@ -15676,7 +15675,7 @@ const PIVOT = {
15676
15675
  if (pivotStyle.numberOfColumns < 0) {
15677
15676
  return new EvaluationError(_t("The number of columns must be positive."));
15678
15677
  }
15679
- addPivotDependencies(this, coreDefinition, coreDefinition.measures);
15678
+ addPivotDependencies(this, pivotId, coreDefinition.measures);
15680
15679
  pivot.init({ reload: pivot.needsReevaluation });
15681
15680
  const error = pivot.assertIsValid({ throwOnError: false });
15682
15681
  if (error) {
@@ -22782,6 +22781,403 @@ function hexaToInt(hex) {
22782
22781
  */
22783
22782
  const DEFAULT_SYSTEM_COLOR = "FF000000";
22784
22783
 
22784
+ const globalReverseLookup$1 = new WeakMap();
22785
+ const globalIdCounter = new WeakMap();
22786
+ /**
22787
+ * Get the id of the given item (its key in the given dictionary).
22788
+ * If the given item does not exist in the dictionary, it creates one with a new id.
22789
+ */
22790
+ function getItemId(item, itemsDic) {
22791
+ if (!globalReverseLookup$1.has(itemsDic)) {
22792
+ globalReverseLookup$1.set(itemsDic, new Map());
22793
+ globalIdCounter.set(itemsDic, 0);
22794
+ }
22795
+ const reverseLookup = globalReverseLookup$1.get(itemsDic);
22796
+ const canonical = getCanonicalRepresentation(item);
22797
+ if (reverseLookup.has(canonical)) {
22798
+ const id = reverseLookup.get(canonical);
22799
+ itemsDic[id] = item;
22800
+ return id;
22801
+ }
22802
+ // Generate new Id if the item didn't exist in the dictionary
22803
+ const newId = globalIdCounter.get(itemsDic) + 1;
22804
+ reverseLookup.set(canonical, newId);
22805
+ globalIdCounter.set(itemsDic, newId);
22806
+ itemsDic[newId] = item;
22807
+ return newId;
22808
+ }
22809
+ function groupItemIdsByZones(positionsByItemId) {
22810
+ const result = {};
22811
+ for (const itemId in positionsByItemId) {
22812
+ const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
22813
+ for (const zone of zones) {
22814
+ result[zoneToXc(zone)] = Number(itemId);
22815
+ }
22816
+ }
22817
+ return result;
22818
+ }
22819
+ function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
22820
+ for (const zoneXc in itemIdsByZones) {
22821
+ const zone = toZone(zoneXc);
22822
+ const itemId = itemIdsByZones[zoneXc];
22823
+ for (let row = zone.top; row <= zone.bottom; row++) {
22824
+ for (let col = zone.left; col <= zone.right; col++) {
22825
+ const position = { sheetId, col, row };
22826
+ yield [position, itemId];
22827
+ }
22828
+ }
22829
+ }
22830
+ }
22831
+ function getCanonicalRepresentation(item) {
22832
+ if (item === null)
22833
+ return "null";
22834
+ if (item === undefined)
22835
+ return "undefined";
22836
+ if (typeof item !== "object")
22837
+ return String(item);
22838
+ if (Array.isArray(item)) {
22839
+ const len = item.length;
22840
+ let result = "[";
22841
+ for (let i = 0; i < len; i++) {
22842
+ if (i > 0)
22843
+ result += ",";
22844
+ result += getCanonicalRepresentation(item[i]);
22845
+ }
22846
+ return result + "]";
22847
+ }
22848
+ const keys = Object.keys(item).sort();
22849
+ let repr = "{";
22850
+ for (const key of keys) {
22851
+ if (item[key] !== undefined) {
22852
+ repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
22853
+ }
22854
+ }
22855
+ repr += "}";
22856
+ return repr;
22857
+ }
22858
+
22859
+ // -------------------------------------
22860
+ // CF HELPERS
22861
+ // -------------------------------------
22862
+ /**
22863
+ * Convert the conditional formatting o-spreadsheet operator to
22864
+ * the corresponding excel operator.
22865
+ * */
22866
+ function convertOperator(operator) {
22867
+ switch (operator) {
22868
+ case "isNotEmpty":
22869
+ return "notContainsBlanks";
22870
+ case "isEmpty":
22871
+ return "containsBlanks";
22872
+ case "notContainsText":
22873
+ return "notContainsBlanks";
22874
+ case "containsText":
22875
+ return "containsText";
22876
+ case "beginsWithText":
22877
+ return "beginsWith";
22878
+ case "endsWithText":
22879
+ return "endsWith";
22880
+ case "isGreaterThan":
22881
+ return "greaterThan";
22882
+ case "isGreaterOrEqualTo":
22883
+ return "greaterThanOrEqual";
22884
+ case "isLessThan":
22885
+ return "lessThan";
22886
+ case "isLessOrEqualTo":
22887
+ return "lessThanOrEqual";
22888
+ case "isBetween":
22889
+ return "between";
22890
+ case "isNotBetween":
22891
+ return "notBetween";
22892
+ case "isEqual":
22893
+ return "equal";
22894
+ case "isNotEqual":
22895
+ return "notEqual";
22896
+ case "customFormula":
22897
+ return "";
22898
+ case "dateIs":
22899
+ return "";
22900
+ case "dateIsBefore":
22901
+ return "lessThan";
22902
+ case "dateIsAfter":
22903
+ return "greaterThan";
22904
+ case "dateIsOnOrAfter":
22905
+ return "greaterThanOrEqual";
22906
+ case "dateIsOnOrBefore":
22907
+ return "lessThanOrEqual";
22908
+ }
22909
+ }
22910
+ // -------------------------------------
22911
+ // WORKSHEET HELPERS
22912
+ // -------------------------------------
22913
+ function getCellType(value) {
22914
+ switch (typeof value) {
22915
+ case "boolean":
22916
+ return "b";
22917
+ case "string":
22918
+ return "str";
22919
+ case "number":
22920
+ return "n";
22921
+ default:
22922
+ return undefined;
22923
+ }
22924
+ }
22925
+ function convertHeightToExcel(height) {
22926
+ return Math.round(HEIGHT_FACTOR * height * 100) / 100;
22927
+ }
22928
+ function convertWidthToExcel(width) {
22929
+ return Math.round(WIDTH_FACTOR * width * 100) / 100;
22930
+ }
22931
+ function convertHeightFromExcel(height) {
22932
+ if (!height)
22933
+ return height;
22934
+ return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
22935
+ }
22936
+ function convertWidthFromExcel(width) {
22937
+ if (!width)
22938
+ return width;
22939
+ return Math.round((width / WIDTH_FACTOR) * 100) / 100;
22940
+ }
22941
+ function extractStyle(data, content, styleId, formatId, borderId) {
22942
+ const style = styleId ? data.styles[styleId] : {};
22943
+ const format = formatId ? data.formats[formatId] : undefined;
22944
+ const styles = {
22945
+ font: {
22946
+ size: style?.fontSize || DEFAULT_FONT_SIZE,
22947
+ color: { rgb: style?.textColor ? style.textColor : "000000" },
22948
+ family: 2,
22949
+ name: "Arial",
22950
+ },
22951
+ fill: style?.fillColor
22952
+ ? {
22953
+ fgColor: { rgb: style.fillColor },
22954
+ }
22955
+ : { reservedAttribute: "none" },
22956
+ numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
22957
+ border: borderId || 0,
22958
+ alignment: {
22959
+ horizontal: style.align,
22960
+ vertical: style.verticalAlign
22961
+ ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
22962
+ : undefined,
22963
+ wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
22964
+ textRotation: style.rotation ? rotationToXLSX(style.rotation) : undefined,
22965
+ },
22966
+ };
22967
+ styles.font["strike"] = !!style?.strikethrough || undefined;
22968
+ styles.font["underline"] = !!style?.underline || undefined;
22969
+ styles.font["bold"] = !!style?.bold || undefined;
22970
+ styles.font["italic"] = !!style?.italic || undefined;
22971
+ return styles;
22972
+ }
22973
+ function rotationToXLSX(rad) {
22974
+ let deg = Math.round((-rad / Math.PI) * 180) % 180;
22975
+ if (deg > 90) {
22976
+ deg -= 180;
22977
+ }
22978
+ else if (deg < -90) {
22979
+ deg += 180;
22980
+ }
22981
+ if (deg >= 0) {
22982
+ return deg;
22983
+ }
22984
+ else {
22985
+ return 90 - deg;
22986
+ }
22987
+ }
22988
+ function rotationFromXLSX(deg) {
22989
+ if (deg <= 90) {
22990
+ return -(deg / 180) * Math.PI;
22991
+ }
22992
+ else {
22993
+ return (-(90 - deg) / 180) * Math.PI;
22994
+ }
22995
+ }
22996
+ function normalizeStyle(construct, styles) {
22997
+ // Normalize this
22998
+ const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
22999
+ const style = {
23000
+ fontId: pushElement(styles.font, construct.fonts),
23001
+ fillId: pushElement(styles.fill, construct.fills),
23002
+ borderId: styles.border,
23003
+ numFmtId,
23004
+ alignment: {
23005
+ vertical: styles.alignment.vertical,
23006
+ horizontal: styles.alignment.horizontal,
23007
+ wrapText: styles.alignment.wrapText,
23008
+ textRotation: styles.alignment.textRotation,
23009
+ },
23010
+ };
23011
+ return pushElement(style, construct.styles);
23012
+ }
23013
+ function convertFormat(format, numFmtStructure) {
23014
+ if (!format) {
23015
+ return 0;
23016
+ }
23017
+ let formatId = XLSX_FORMAT_MAP[format.format];
23018
+ if (!formatId) {
23019
+ formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23020
+ }
23021
+ return formatId;
23022
+ }
23023
+ /**
23024
+ * Add a relation to the given file and return its id.
23025
+ */
23026
+ function addRelsToFile(relsFiles, path, rel) {
23027
+ const relsFile = relsFiles.find((file) => file.path === path);
23028
+ // the id is a one-based int casted as string
23029
+ let id;
23030
+ if (!relsFile) {
23031
+ id = "rId1";
23032
+ relsFiles.push({ path, rels: [{ ...rel, id }] });
23033
+ }
23034
+ else {
23035
+ id = `rId${(relsFile.rels.length + 1).toString()}`;
23036
+ relsFile.rels.push({
23037
+ ...rel,
23038
+ id,
23039
+ });
23040
+ }
23041
+ return id;
23042
+ }
23043
+ const globalReverseLookup = new WeakMap();
23044
+ function pushElement(property, propertyList) {
23045
+ let reverseLookup = globalReverseLookup.get(propertyList);
23046
+ if (!reverseLookup) {
23047
+ reverseLookup = new Map();
23048
+ for (let i = 0; i < propertyList.length; i++) {
23049
+ const canonical = getCanonicalRepresentation(propertyList[i]);
23050
+ reverseLookup.set(canonical, i);
23051
+ }
23052
+ globalReverseLookup.set(propertyList, reverseLookup);
23053
+ }
23054
+ const canonical = getCanonicalRepresentation(property);
23055
+ if (reverseLookup.has(canonical)) {
23056
+ return reverseLookup.get(canonical);
23057
+ }
23058
+ const maxId = propertyList.length;
23059
+ propertyList.push(property);
23060
+ reverseLookup.set(canonical, maxId);
23061
+ return maxId;
23062
+ }
23063
+ /**
23064
+ * Convert a chart o-spreadsheet id to a xlsx id which
23065
+ * are unsigned integers (starting from 1).
23066
+ */
23067
+ function convertChartId(chartId, construct) {
23068
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23069
+ if (xlsxId === -1) {
23070
+ construct.chartIds.push(chartId);
23071
+ return construct.chartIds.length;
23072
+ }
23073
+ return xlsxId + 1;
23074
+ }
23075
+ const imageIds = [];
23076
+ /**
23077
+ * Convert a image o-spreadsheet id to a xlsx id which
23078
+ * are unsigned integers (starting from 1).
23079
+ */
23080
+ function convertImageId(imageId) {
23081
+ const xlsxId = imageIds.findIndex((id) => id === imageId);
23082
+ if (xlsxId === -1) {
23083
+ imageIds.push(imageId);
23084
+ return imageIds.length;
23085
+ }
23086
+ return xlsxId + 1;
23087
+ }
23088
+ /**
23089
+ * Convert a value expressed in dot to EMU.
23090
+ * EMU = English Metrical Unit
23091
+ * There are 914400 EMU per inch.
23092
+ *
23093
+ * /!\ A value expressed in EMU cannot be fractional.
23094
+ * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23095
+ */
23096
+ function convertDotValueToEMU(value) {
23097
+ const DPI = 96;
23098
+ return Math.round((value * 914400) / DPI);
23099
+ }
23100
+ function getRangeSize(reference, defaultSheetIndex, data) {
23101
+ let xc = reference;
23102
+ let sheetName = undefined;
23103
+ ({ xc, sheetName } = splitReference(reference));
23104
+ let rangeSheetIndex;
23105
+ if (sheetName) {
23106
+ const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23107
+ if (index < 0) {
23108
+ throw new Error("Unable to find a sheet with the name " + sheetName);
23109
+ }
23110
+ rangeSheetIndex = index;
23111
+ }
23112
+ else {
23113
+ rangeSheetIndex = Number(defaultSheetIndex);
23114
+ }
23115
+ const zone = toUnboundedZone(xc);
23116
+ if (zone.right === undefined) {
23117
+ zone.right = data.sheets[rangeSheetIndex].colNumber;
23118
+ }
23119
+ if (zone.bottom === undefined) {
23120
+ zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23121
+ }
23122
+ return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23123
+ }
23124
+ function convertEMUToDotValue(value) {
23125
+ const DPI = 96;
23126
+ return Math.round((value * DPI) / 914400);
23127
+ }
23128
+ /**
23129
+ * Get the position of the start of a column in Excel (in px).
23130
+ */
23131
+ function getColPosition(colIndex, sheetData) {
23132
+ let position = 0;
23133
+ for (let i = 0; i < colIndex; i++) {
23134
+ const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23135
+ if (colAtIndex?.width) {
23136
+ position += colAtIndex.width;
23137
+ }
23138
+ else if (sheetData.sheetFormat?.defaultColWidth) {
23139
+ position += sheetData.sheetFormat.defaultColWidth;
23140
+ }
23141
+ else {
23142
+ position += EXCEL_DEFAULT_COL_WIDTH;
23143
+ }
23144
+ }
23145
+ return position / WIDTH_FACTOR;
23146
+ }
23147
+ /**
23148
+ * Get the position of the start of a row in Excel (in px).
23149
+ */
23150
+ function getRowPosition(rowIndex, sheetData) {
23151
+ let position = 0;
23152
+ for (let i = 0; i < rowIndex; i++) {
23153
+ const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23154
+ if (rowAtIndex?.height) {
23155
+ position += rowAtIndex.height;
23156
+ }
23157
+ else if (sheetData.sheetFormat?.defaultRowHeight) {
23158
+ position += sheetData.sheetFormat.defaultRowHeight;
23159
+ }
23160
+ else {
23161
+ position += EXCEL_DEFAULT_ROW_HEIGHT;
23162
+ }
23163
+ }
23164
+ return position / HEIGHT_FACTOR;
23165
+ }
23166
+ /**
23167
+ * Convert the o-spreadsheet data validation decimal
23168
+ * criterion type to the corresponding excel operator.
23169
+ */
23170
+ function convertDecimalCriterionTypeToExcelOperator(operator) {
23171
+ return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23172
+ }
23173
+ /**
23174
+ * Convert the o-spreadsheet data validation date
23175
+ * criterion type to the corresponding excel operator.
23176
+ */
23177
+ function convertDateCriterionTypeToExcelOperator(operator) {
23178
+ return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23179
+ }
23180
+
22785
23181
  const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
22786
23182
  /**
22787
23183
  * Convert excel format to o_spreadsheet format
@@ -22881,6 +23277,9 @@ function convertStyle(styleStruct, warningManager) {
22881
23277
  align: styleStruct.alignment?.horizontal
22882
23278
  ? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
22883
23279
  : undefined,
23280
+ rotation: styleStruct.alignment?.textRotation
23281
+ ? rotationFromXLSX(styleStruct.alignment.textRotation)
23282
+ : undefined,
22884
23283
  // In xlsx fills, bgColor is the color of the fill, and fgColor is the color of the pattern above the background, except in solid fills
22885
23284
  fillColor: styleStruct.fillStyle?.patternType === "solid"
22886
23285
  ? convertColor(styleStruct.fillStyle?.fgColor)
@@ -23180,378 +23579,6 @@ function addCfConversionWarnings(cf, dxfs, warningManager) {
23180
23579
  }
23181
23580
  }
23182
23581
 
23183
- const globalReverseLookup$1 = new WeakMap();
23184
- const globalIdCounter = new WeakMap();
23185
- /**
23186
- * Get the id of the given item (its key in the given dictionary).
23187
- * If the given item does not exist in the dictionary, it creates one with a new id.
23188
- */
23189
- function getItemId(item, itemsDic) {
23190
- if (!globalReverseLookup$1.has(itemsDic)) {
23191
- globalReverseLookup$1.set(itemsDic, new Map());
23192
- globalIdCounter.set(itemsDic, 0);
23193
- }
23194
- const reverseLookup = globalReverseLookup$1.get(itemsDic);
23195
- const canonical = getCanonicalRepresentation(item);
23196
- if (reverseLookup.has(canonical)) {
23197
- const id = reverseLookup.get(canonical);
23198
- itemsDic[id] = item;
23199
- return id;
23200
- }
23201
- // Generate new Id if the item didn't exist in the dictionary
23202
- const newId = globalIdCounter.get(itemsDic) + 1;
23203
- reverseLookup.set(canonical, newId);
23204
- globalIdCounter.set(itemsDic, newId);
23205
- itemsDic[newId] = item;
23206
- return newId;
23207
- }
23208
- function groupItemIdsByZones(positionsByItemId) {
23209
- const result = {};
23210
- for (const itemId in positionsByItemId) {
23211
- const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
23212
- for (const zone of zones) {
23213
- result[zoneToXc(zone)] = Number(itemId);
23214
- }
23215
- }
23216
- return result;
23217
- }
23218
- function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
23219
- for (const zoneXc in itemIdsByZones) {
23220
- const zone = toZone(zoneXc);
23221
- const itemId = itemIdsByZones[zoneXc];
23222
- for (let row = zone.top; row <= zone.bottom; row++) {
23223
- for (let col = zone.left; col <= zone.right; col++) {
23224
- const position = { sheetId, col, row };
23225
- yield [position, itemId];
23226
- }
23227
- }
23228
- }
23229
- }
23230
- function getCanonicalRepresentation(item) {
23231
- if (item === null)
23232
- return "null";
23233
- if (item === undefined)
23234
- return "undefined";
23235
- if (typeof item !== "object")
23236
- return String(item);
23237
- if (Array.isArray(item)) {
23238
- const len = item.length;
23239
- let result = "[";
23240
- for (let i = 0; i < len; i++) {
23241
- if (i > 0)
23242
- result += ",";
23243
- result += getCanonicalRepresentation(item[i]);
23244
- }
23245
- return result + "]";
23246
- }
23247
- const keys = Object.keys(item).sort();
23248
- let repr = "{";
23249
- for (const key of keys) {
23250
- if (item[key] !== undefined) {
23251
- repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
23252
- }
23253
- }
23254
- repr += "}";
23255
- return repr;
23256
- }
23257
-
23258
- // -------------------------------------
23259
- // CF HELPERS
23260
- // -------------------------------------
23261
- /**
23262
- * Convert the conditional formatting o-spreadsheet operator to
23263
- * the corresponding excel operator.
23264
- * */
23265
- function convertOperator(operator) {
23266
- switch (operator) {
23267
- case "isNotEmpty":
23268
- return "notContainsBlanks";
23269
- case "isEmpty":
23270
- return "containsBlanks";
23271
- case "notContainsText":
23272
- return "notContainsBlanks";
23273
- case "containsText":
23274
- return "containsText";
23275
- case "beginsWithText":
23276
- return "beginsWith";
23277
- case "endsWithText":
23278
- return "endsWith";
23279
- case "isGreaterThan":
23280
- return "greaterThan";
23281
- case "isGreaterOrEqualTo":
23282
- return "greaterThanOrEqual";
23283
- case "isLessThan":
23284
- return "lessThan";
23285
- case "isLessOrEqualTo":
23286
- return "lessThanOrEqual";
23287
- case "isBetween":
23288
- return "between";
23289
- case "isNotBetween":
23290
- return "notBetween";
23291
- case "isEqual":
23292
- return "equal";
23293
- case "isNotEqual":
23294
- return "notEqual";
23295
- case "customFormula":
23296
- return "";
23297
- case "dateIs":
23298
- return "";
23299
- case "dateIsBefore":
23300
- return "lessThan";
23301
- case "dateIsAfter":
23302
- return "greaterThan";
23303
- case "dateIsOnOrAfter":
23304
- return "greaterThanOrEqual";
23305
- case "dateIsOnOrBefore":
23306
- return "lessThanOrEqual";
23307
- }
23308
- }
23309
- // -------------------------------------
23310
- // WORKSHEET HELPERS
23311
- // -------------------------------------
23312
- function getCellType(value) {
23313
- switch (typeof value) {
23314
- case "boolean":
23315
- return "b";
23316
- case "string":
23317
- return "str";
23318
- case "number":
23319
- return "n";
23320
- default:
23321
- return undefined;
23322
- }
23323
- }
23324
- function convertHeightToExcel(height) {
23325
- return Math.round(HEIGHT_FACTOR * height * 100) / 100;
23326
- }
23327
- function convertWidthToExcel(width) {
23328
- return Math.round(WIDTH_FACTOR * width * 100) / 100;
23329
- }
23330
- function convertHeightFromExcel(height) {
23331
- if (!height)
23332
- return height;
23333
- return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
23334
- }
23335
- function convertWidthFromExcel(width) {
23336
- if (!width)
23337
- return width;
23338
- return Math.round((width / WIDTH_FACTOR) * 100) / 100;
23339
- }
23340
- function extractStyle(data, content, styleId, formatId, borderId) {
23341
- const style = styleId ? data.styles[styleId] : {};
23342
- const format = formatId ? data.formats[formatId] : undefined;
23343
- const styles = {
23344
- font: {
23345
- size: style?.fontSize || DEFAULT_FONT_SIZE,
23346
- color: { rgb: style?.textColor ? style.textColor : "000000" },
23347
- family: 2,
23348
- name: "Arial",
23349
- },
23350
- fill: style?.fillColor
23351
- ? {
23352
- fgColor: { rgb: style.fillColor },
23353
- }
23354
- : { reservedAttribute: "none" },
23355
- numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
23356
- border: borderId || 0,
23357
- alignment: {
23358
- horizontal: style.align,
23359
- vertical: style.verticalAlign
23360
- ? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
23361
- : undefined,
23362
- wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
23363
- },
23364
- };
23365
- styles.font["strike"] = !!style?.strikethrough || undefined;
23366
- styles.font["underline"] = !!style?.underline || undefined;
23367
- styles.font["bold"] = !!style?.bold || undefined;
23368
- styles.font["italic"] = !!style?.italic || undefined;
23369
- return styles;
23370
- }
23371
- function normalizeStyle(construct, styles) {
23372
- // Normalize this
23373
- const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
23374
- const style = {
23375
- fontId: pushElement(styles.font, construct.fonts),
23376
- fillId: pushElement(styles.fill, construct.fills),
23377
- borderId: styles.border,
23378
- numFmtId,
23379
- alignment: {
23380
- vertical: styles.alignment.vertical,
23381
- horizontal: styles.alignment.horizontal,
23382
- wrapText: styles.alignment.wrapText,
23383
- },
23384
- };
23385
- return pushElement(style, construct.styles);
23386
- }
23387
- function convertFormat(format, numFmtStructure) {
23388
- if (!format) {
23389
- return 0;
23390
- }
23391
- let formatId = XLSX_FORMAT_MAP[format.format];
23392
- if (!formatId) {
23393
- formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
23394
- }
23395
- return formatId;
23396
- }
23397
- /**
23398
- * Add a relation to the given file and return its id.
23399
- */
23400
- function addRelsToFile(relsFiles, path, rel) {
23401
- const relsFile = relsFiles.find((file) => file.path === path);
23402
- // the id is a one-based int casted as string
23403
- let id;
23404
- if (!relsFile) {
23405
- id = "rId1";
23406
- relsFiles.push({ path, rels: [{ ...rel, id }] });
23407
- }
23408
- else {
23409
- id = `rId${(relsFile.rels.length + 1).toString()}`;
23410
- relsFile.rels.push({
23411
- ...rel,
23412
- id,
23413
- });
23414
- }
23415
- return id;
23416
- }
23417
- const globalReverseLookup = new WeakMap();
23418
- function pushElement(property, propertyList) {
23419
- let reverseLookup = globalReverseLookup.get(propertyList);
23420
- if (!reverseLookup) {
23421
- reverseLookup = new Map();
23422
- for (let i = 0; i < propertyList.length; i++) {
23423
- const canonical = getCanonicalRepresentation(propertyList[i]);
23424
- reverseLookup.set(canonical, i);
23425
- }
23426
- globalReverseLookup.set(propertyList, reverseLookup);
23427
- }
23428
- const canonical = getCanonicalRepresentation(property);
23429
- if (reverseLookup.has(canonical)) {
23430
- return reverseLookup.get(canonical);
23431
- }
23432
- const maxId = propertyList.length;
23433
- propertyList.push(property);
23434
- reverseLookup.set(canonical, maxId);
23435
- return maxId;
23436
- }
23437
- /**
23438
- * Convert a chart o-spreadsheet id to a xlsx id which
23439
- * are unsigned integers (starting from 1).
23440
- */
23441
- function convertChartId(chartId, construct) {
23442
- const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
23443
- if (xlsxId === -1) {
23444
- construct.chartIds.push(chartId);
23445
- return construct.chartIds.length;
23446
- }
23447
- return xlsxId + 1;
23448
- }
23449
- const imageIds = [];
23450
- /**
23451
- * Convert a image o-spreadsheet id to a xlsx id which
23452
- * are unsigned integers (starting from 1).
23453
- */
23454
- function convertImageId(imageId) {
23455
- const xlsxId = imageIds.findIndex((id) => id === imageId);
23456
- if (xlsxId === -1) {
23457
- imageIds.push(imageId);
23458
- return imageIds.length;
23459
- }
23460
- return xlsxId + 1;
23461
- }
23462
- /**
23463
- * Convert a value expressed in dot to EMU.
23464
- * EMU = English Metrical Unit
23465
- * There are 914400 EMU per inch.
23466
- *
23467
- * /!\ A value expressed in EMU cannot be fractional.
23468
- * See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
23469
- */
23470
- function convertDotValueToEMU(value) {
23471
- const DPI = 96;
23472
- return Math.round((value * 914400) / DPI);
23473
- }
23474
- function getRangeSize(reference, defaultSheetIndex, data) {
23475
- let xc = reference;
23476
- let sheetName = undefined;
23477
- ({ xc, sheetName } = splitReference(reference));
23478
- let rangeSheetIndex;
23479
- if (sheetName) {
23480
- const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
23481
- if (index < 0) {
23482
- throw new Error("Unable to find a sheet with the name " + sheetName);
23483
- }
23484
- rangeSheetIndex = index;
23485
- }
23486
- else {
23487
- rangeSheetIndex = Number(defaultSheetIndex);
23488
- }
23489
- const zone = toUnboundedZone(xc);
23490
- if (zone.right === undefined) {
23491
- zone.right = data.sheets[rangeSheetIndex].colNumber;
23492
- }
23493
- if (zone.bottom === undefined) {
23494
- zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
23495
- }
23496
- return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
23497
- }
23498
- function convertEMUToDotValue(value) {
23499
- const DPI = 96;
23500
- return Math.round((value * DPI) / 914400);
23501
- }
23502
- /**
23503
- * Get the position of the start of a column in Excel (in px).
23504
- */
23505
- function getColPosition(colIndex, sheetData) {
23506
- let position = 0;
23507
- for (let i = 0; i < colIndex; i++) {
23508
- const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
23509
- if (colAtIndex?.width) {
23510
- position += colAtIndex.width;
23511
- }
23512
- else if (sheetData.sheetFormat?.defaultColWidth) {
23513
- position += sheetData.sheetFormat.defaultColWidth;
23514
- }
23515
- else {
23516
- position += EXCEL_DEFAULT_COL_WIDTH;
23517
- }
23518
- }
23519
- return position / WIDTH_FACTOR;
23520
- }
23521
- /**
23522
- * Get the position of the start of a row in Excel (in px).
23523
- */
23524
- function getRowPosition(rowIndex, sheetData) {
23525
- let position = 0;
23526
- for (let i = 0; i < rowIndex; i++) {
23527
- const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
23528
- if (rowAtIndex?.height) {
23529
- position += rowAtIndex.height;
23530
- }
23531
- else if (sheetData.sheetFormat?.defaultRowHeight) {
23532
- position += sheetData.sheetFormat.defaultRowHeight;
23533
- }
23534
- else {
23535
- position += EXCEL_DEFAULT_ROW_HEIGHT;
23536
- }
23537
- }
23538
- return position / HEIGHT_FACTOR;
23539
- }
23540
- /**
23541
- * Convert the o-spreadsheet data validation decimal
23542
- * criterion type to the corresponding excel operator.
23543
- */
23544
- function convertDecimalCriterionTypeToExcelOperator(operator) {
23545
- return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
23546
- }
23547
- /**
23548
- * Convert the o-spreadsheet data validation date
23549
- * criterion type to the corresponding excel operator.
23550
- */
23551
- function convertDateCriterionTypeToExcelOperator(operator) {
23552
- return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
23553
- }
23554
-
23555
23582
  function convertFigures(sheetData) {
23556
23583
  let id = 1;
23557
23584
  return sheetData.figures
@@ -33409,6 +33436,7 @@ class PivotCorePlugin extends CorePlugin {
33409
33436
  "getMeasureCompiledFormula",
33410
33437
  "getPivotName",
33411
33438
  "isExistingPivot",
33439
+ "getMeasureFullDependencies",
33412
33440
  ];
33413
33441
  nextFormulaId = 1;
33414
33442
  pivots = {};
@@ -33494,7 +33522,7 @@ class PivotCorePlugin extends CorePlugin {
33494
33522
  }
33495
33523
  case "UPDATE_PIVOT": {
33496
33524
  this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
33497
- this.compileCalculatedMeasures(cmd.pivot.measures);
33525
+ this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
33498
33526
  break;
33499
33527
  }
33500
33528
  }
@@ -33512,9 +33540,14 @@ class PivotCorePlugin extends CorePlugin {
33512
33540
  this.history.update("pivots", pivotId, "definition", newDefinition);
33513
33541
  }
33514
33542
  }
33515
- for (const sheetId in this.compiledMeasureFormulas) {
33516
- for (const formulaString in this.compiledMeasureFormulas[sheetId]) {
33517
- const compiledFormula = this.compiledMeasureFormulas[sheetId][formulaString];
33543
+ for (const pivotId in this.compiledMeasureFormulas) {
33544
+ for (const measureId in this.compiledMeasureFormulas[pivotId]) {
33545
+ const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
33546
+ if (!measure || !measure.computedBy) {
33547
+ continue;
33548
+ }
33549
+ const sheetId = measure.computedBy.sheetId;
33550
+ const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
33518
33551
  const newDependencies = [];
33519
33552
  for (const range of compiledFormula.dependencies) {
33520
33553
  const change = applyChange(range);
@@ -33526,8 +33559,9 @@ class PivotCorePlugin extends CorePlugin {
33526
33559
  }
33527
33560
  }
33528
33561
  const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
33529
- if (newFormulaString !== formulaString) {
33530
- this.replaceMeasureFormula(sheetId, formulaString, newFormulaString);
33562
+ const oldFormulaString = measure.computedBy.formula;
33563
+ if (newFormulaString !== oldFormulaString) {
33564
+ this.replaceMeasureFormula(pivotId, measure, newFormulaString);
33531
33565
  }
33532
33566
  }
33533
33567
  }
@@ -33565,30 +33599,59 @@ class PivotCorePlugin extends CorePlugin {
33565
33599
  isExistingPivot(pivotId) {
33566
33600
  return pivotId in this.pivots;
33567
33601
  }
33568
- getMeasureCompiledFormula(measure) {
33602
+ getMeasureCompiledFormula(pivotId, measure) {
33603
+ if (!measure.computedBy) {
33604
+ throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33605
+ }
33606
+ return this.compiledMeasureFormulas[pivotId][measure.id].formula;
33607
+ }
33608
+ getMeasureFullDependencies(pivotId, measure) {
33569
33609
  if (!measure.computedBy) {
33570
33610
  throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
33571
33611
  }
33572
- const sheetId = measure.computedBy.sheetId;
33573
- return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
33612
+ return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
33574
33613
  }
33575
33614
  // -------------------------------------------------------------------------
33576
33615
  // Private
33577
33616
  // -------------------------------------------------------------------------
33578
33617
  addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
33579
33618
  this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
33580
- this.compileCalculatedMeasures(pivot.measures);
33619
+ this.compileCalculatedMeasures(pivotId, pivot.measures);
33581
33620
  this.history.update("formulaIds", formulaId, pivotId);
33582
33621
  this.history.update("nextFormulaId", this.nextFormulaId + 1);
33583
33622
  }
33584
- compileCalculatedMeasures(measures) {
33623
+ compileCalculatedMeasures(pivotId, measures) {
33585
33624
  for (const measure of measures) {
33586
33625
  if (measure.computedBy) {
33587
- const sheetId = measure.computedBy.sheetId;
33588
33626
  const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
33589
- this.history.update("compiledMeasureFormulas", sheetId, measure.computedBy.formula, compiledFormula);
33627
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
33590
33628
  }
33591
33629
  }
33630
+ for (const measure of measures) {
33631
+ if (measure.computedBy) {
33632
+ const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
33633
+ this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
33634
+ }
33635
+ }
33636
+ }
33637
+ computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
33638
+ const rangeDependencies = [];
33639
+ const definition = this.getPivotCoreDefinition(pivotId);
33640
+ const formula = this.getMeasureCompiledFormula(pivotId, measure);
33641
+ exploredMeasures.add(measure.id);
33642
+ for (const token of formula.tokens) {
33643
+ if (token.type !== "SYMBOL") {
33644
+ continue;
33645
+ }
33646
+ const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
33647
+ measure.id !== measureCandidate.id);
33648
+ if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
33649
+ continue;
33650
+ }
33651
+ rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
33652
+ }
33653
+ rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
33654
+ return rangeDependencies;
33592
33655
  }
33593
33656
  insertPivot(position, formulaId, table) {
33594
33657
  this.resizeSheet(position.sheetId, position, table);
@@ -33648,21 +33711,17 @@ class PivotCorePlugin extends CorePlugin {
33648
33711
  dependencies: rangeDependencies,
33649
33712
  };
33650
33713
  }
33651
- replaceMeasureFormula(sheetId, formulaString, newFormulaString) {
33652
- this.history.update("compiledMeasureFormulas", sheetId, formulaString, undefined);
33653
- this.history.update("compiledMeasureFormulas", sheetId, newFormulaString, this.compileMeasureFormula(sheetId, newFormulaString));
33654
- for (const pivotId in this.pivots) {
33655
- const pivot = this.pivots[pivotId];
33656
- if (!pivot) {
33657
- continue;
33658
- }
33659
- for (const measure of pivot.definition.measures) {
33660
- if (measure.computedBy?.formula === formulaString) {
33661
- const measureIndex = pivot.definition.measures.indexOf(measure);
33662
- this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
33663
- }
33664
- }
33714
+ replaceMeasureFormula(pivotId, measure, newFormulaString) {
33715
+ const pivot = this.pivots[pivotId];
33716
+ if (!pivot) {
33717
+ return;
33665
33718
  }
33719
+ const measureIndex = pivot.definition.measures.indexOf(measure);
33720
+ this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
33721
+ formula: newFormulaString,
33722
+ sheetId: measure.computedBy.sheetId,
33723
+ });
33724
+ this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
33666
33725
  }
33667
33726
  checkSortedColumnInMeasures(definition) {
33668
33727
  const measures = definition.measures.map((measure) => measure.id);
@@ -34723,7 +34782,7 @@ class StylePlugin extends CorePlugin {
34723
34782
  case "UPDATE_CELL":
34724
34783
  if (cmd.style !== undefined) {
34725
34784
  if (cmd.style !== null) {
34726
- this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style);
34785
+ this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style, { force: true });
34727
34786
  }
34728
34787
  else {
34729
34788
  this.clearStyle(cmd.sheetId, [positionToZone(cmd)]);
@@ -34791,16 +34850,22 @@ class StylePlugin extends CorePlugin {
34791
34850
  }
34792
34851
  }
34793
34852
  styleIsDefault(style) {
34794
- return deepEquals(this.removeDefaultStyleValues(style), {});
34853
+ for (const key in style) {
34854
+ if (DEFAULT_STYLE_NO_ALIGN[key] !== style[key]) {
34855
+ return false;
34856
+ }
34857
+ }
34858
+ return true;
34795
34859
  }
34796
34860
  removeDefaultStyleValues(style) {
34797
34861
  const cleanedStyle = { ...style };
34798
- for (const property in DEFAULT_STYLE_NO_ALIGN) {
34799
- if (cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34862
+ for (const property in style) {
34863
+ if (cleanedStyle[property] === undefined ||
34864
+ cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
34800
34865
  delete cleanedStyle[property];
34801
34866
  }
34802
34867
  }
34803
- return cleanedStyle;
34868
+ return Object.keys(cleanedStyle).length > 0 ? cleanedStyle : undefined;
34804
34869
  }
34805
34870
  onMerge(sheetId, zone) {
34806
34871
  this.setStyle(sheetId, zone, this.getCellStyle({ sheetId, col: zone.left, row: zone.top }), {
@@ -34836,13 +34901,13 @@ class StylePlugin extends CorePlugin {
34836
34901
  }
34837
34902
  editingZone = recomputeZones(editingZone, [inter]);
34838
34903
  }
34904
+ style = this.removeDefaultStyleValues(style);
34839
34905
  if (style) {
34840
- const newStyle = this.removeDefaultStyleValues(style);
34841
34906
  styles.push(...editingZone.map((zone) => {
34842
- return { zone, style: newStyle };
34907
+ return { zone, style };
34843
34908
  }));
34844
34909
  }
34845
- this.history.update("styles", sheetId, styles.filter((zoneStyle) => !this.styleIsDefault(zoneStyle.style)));
34910
+ this.history.update("styles", sheetId, styles);
34846
34911
  }
34847
34912
  clearStyle(sheetId, zones) {
34848
34913
  this.setStyles(sheetId, zones, undefined, { force: true });
@@ -40484,14 +40549,16 @@ const PERCENT_FORMAT = "0.00%";
40484
40549
  function withPivotPresentationLayer (PivotClass) {
40485
40550
  class PivotPresentationLayer extends PivotClass {
40486
40551
  getters;
40552
+ pivotId;
40487
40553
  cache = {};
40488
40554
  rankAsc = {};
40489
40555
  rankDesc = {};
40490
40556
  runningTotal = {};
40491
40557
  runningTotalInPercent = {};
40492
- constructor(custom, params) {
40558
+ constructor(pivotId, custom, params) {
40493
40559
  super(custom, params);
40494
40560
  this.getters = params.getters;
40561
+ this.pivotId = pivotId;
40495
40562
  }
40496
40563
  markAsDirtyForEvaluation() {
40497
40564
  this.cache = {};
@@ -40541,7 +40608,7 @@ function withPivotPresentationLayer (PivotClass) {
40541
40608
  return handleError(error, measure.aggregator.toUpperCase());
40542
40609
  }
40543
40610
  }
40544
- const formula = this.getters.getMeasureCompiledFormula(measure);
40611
+ const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
40545
40612
  const getSymbolValue = (symbolName) => {
40546
40613
  const { columns, rows } = this.definition;
40547
40614
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
@@ -41288,7 +41355,7 @@ class PivotUIPlugin extends CoreViewPlugin {
41288
41355
  const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
41289
41356
  if (!(pivotId in this.pivots)) {
41290
41357
  const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
41291
- this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
41358
+ this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
41292
41359
  }
41293
41360
  else if (recreate) {
41294
41361
  this.pivots[pivotId].onDefinitionChange(definition);
@@ -50280,6 +50347,9 @@ function addStyles(styles) {
50280
50347
  if (style.alignment && style.alignment.wrapText) {
50281
50348
  alignAttrs.push(["wrapText", "1"]);
50282
50349
  }
50350
+ if (style.alignment && style.alignment.textRotation) {
50351
+ alignAttrs.push(["textRotation", style.alignment.textRotation]);
50352
+ }
50283
50353
  if (alignAttrs.length > 0) {
50284
50354
  attributes.push(["applyAlignment", "1"]); // for Libre Office
50285
50355
  styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
@@ -51560,5 +51630,5 @@ export { BadExpressionError, BasePlugin, CellErrorType, CircularDependencyError,
51560
51630
 
51561
51631
 
51562
51632
  __info__.version = "19.1.0-alpha.3";
51563
- __info__.date = "2026-01-07T16:20:59.139Z";
51564
- __info__.hash = "febc3e9";
51633
+ __info__.date = "2026-01-14T10:01:54.190Z";
51634
+ __info__.hash = "52a3e52";