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