@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
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
|
33516
|
-
for (const
|
|
33517
|
-
const
|
|
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
|
-
|
|
33530
|
-
|
|
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
|
-
|
|
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",
|
|
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(
|
|
33652
|
-
|
|
33653
|
-
|
|
33654
|
-
|
|
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
|
-
|
|
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
|
|
34799
|
-
if (cleanedStyle[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
|
|
34907
|
+
return { zone, style };
|
|
34843
34908
|
}));
|
|
34844
34909
|
}
|
|
34845
|
-
this.history.update("styles", sheetId, styles
|
|
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-
|
|
51564
|
-
__info__.hash = "
|
|
51633
|
+
__info__.date = "2026-01-14T10:01:54.190Z";
|
|
51634
|
+
__info__.hash = "52a3e52";
|