@odoo/o-spreadsheet 19.1.1 → 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 +11 -4
- package/dist/o-spreadsheet-engine.esm.js +544 -437
- package/dist/o-spreadsheet-engine.iife.js +544 -437
- package/dist/o-spreadsheet-engine.min.iife.js +304 -304
- package/dist/o-spreadsheet.d.ts +16 -12
- package/dist/o_spreadsheet.css +3 -3
- package/dist/o_spreadsheet.esm.js +545 -408
- package/dist/o_spreadsheet.iife.js +545 -408
- package/dist/o_spreadsheet.min.iife.js +311 -311
- package/dist/o_spreadsheet.xml +7 -7
- 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
|
|
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) {
|
|
@@ -18115,7 +18114,7 @@
|
|
|
18115
18114
|
if (message.type === "CLIENT_JOINED" ||
|
|
18116
18115
|
message.type === "CLIENT_LEFT" ||
|
|
18117
18116
|
message.type === "CLIENT_MOVED") {
|
|
18118
|
-
this.transportService.sendMessage(message);
|
|
18117
|
+
await this.transportService.sendMessage(message);
|
|
18119
18118
|
}
|
|
18120
18119
|
// ignore all other messages
|
|
18121
18120
|
}
|
|
@@ -20734,7 +20733,7 @@
|
|
|
20734
20733
|
}
|
|
20735
20734
|
delete this.clients[this.clientId];
|
|
20736
20735
|
this.transportService.leave(this.clientId);
|
|
20737
|
-
this.
|
|
20736
|
+
this.sendToTransport({
|
|
20738
20737
|
type: "CLIENT_LEFT",
|
|
20739
20738
|
clientId: this.clientId,
|
|
20740
20739
|
version: MESSAGE_VERSION,
|
|
@@ -20748,7 +20747,7 @@
|
|
|
20748
20747
|
return;
|
|
20749
20748
|
}
|
|
20750
20749
|
const snapshotId = this.uuidGenerator.uuidv4();
|
|
20751
|
-
await this.
|
|
20750
|
+
await this.sendToTransport({
|
|
20752
20751
|
type: "SNAPSHOT",
|
|
20753
20752
|
nextRevisionId: snapshotId,
|
|
20754
20753
|
serverRevisionId: this.serverRevisionId,
|
|
@@ -20796,10 +20795,14 @@
|
|
|
20796
20795
|
const type = currentPosition ? "CLIENT_MOVED" : "CLIENT_JOINED";
|
|
20797
20796
|
const client = this.getCurrentClient();
|
|
20798
20797
|
this.clients[this.clientId] = { ...client, position };
|
|
20799
|
-
this.
|
|
20798
|
+
this.sendToTransport({
|
|
20800
20799
|
type,
|
|
20801
20800
|
version: MESSAGE_VERSION,
|
|
20802
20801
|
client: { ...client, position },
|
|
20802
|
+
}).then(() => {
|
|
20803
|
+
if (this.pendingMessages.length > 0 && !this.waitingAck) {
|
|
20804
|
+
this.sendPendingMessage();
|
|
20805
|
+
}
|
|
20803
20806
|
});
|
|
20804
20807
|
}
|
|
20805
20808
|
/**
|
|
@@ -20880,7 +20883,7 @@
|
|
|
20880
20883
|
if (client) {
|
|
20881
20884
|
const { position } = client;
|
|
20882
20885
|
if (position) {
|
|
20883
|
-
this.
|
|
20886
|
+
this.sendToTransport({
|
|
20884
20887
|
type: "CLIENT_MOVED",
|
|
20885
20888
|
version: MESSAGE_VERSION,
|
|
20886
20889
|
client: { ...client, position },
|
|
@@ -20901,6 +20904,10 @@
|
|
|
20901
20904
|
}
|
|
20902
20905
|
this.sendPendingMessage();
|
|
20903
20906
|
}
|
|
20907
|
+
async sendToTransport(message) {
|
|
20908
|
+
// wrap in an async function to ensure it returns a promise
|
|
20909
|
+
return this.transportService.sendMessage(message);
|
|
20910
|
+
}
|
|
20904
20911
|
/**
|
|
20905
20912
|
* Send the next pending message
|
|
20906
20913
|
*/
|
|
@@ -20929,9 +20936,14 @@
|
|
|
20929
20936
|
${JSON.stringify(message)}`);
|
|
20930
20937
|
}
|
|
20931
20938
|
this.waitingAck = true;
|
|
20932
|
-
this.
|
|
20939
|
+
this.sendToTransport({
|
|
20933
20940
|
...message,
|
|
20934
20941
|
serverRevisionId: this.serverRevisionId,
|
|
20942
|
+
}).catch((e) => {
|
|
20943
|
+
if (!(e instanceof ClientDisconnectedError)) {
|
|
20944
|
+
throw e.cause || e;
|
|
20945
|
+
}
|
|
20946
|
+
this.waitingAck = false;
|
|
20935
20947
|
});
|
|
20936
20948
|
}
|
|
20937
20949
|
acknowledge(message) {
|
|
@@ -22772,6 +22784,403 @@
|
|
|
22772
22784
|
*/
|
|
22773
22785
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
22774
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
|
+
|
|
22775
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;
|
|
22776
23185
|
/**
|
|
22777
23186
|
* Convert excel format to o_spreadsheet format
|
|
@@ -22871,6 +23280,9 @@
|
|
|
22871
23280
|
align: styleStruct.alignment?.horizontal
|
|
22872
23281
|
? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
|
|
22873
23282
|
: undefined,
|
|
23283
|
+
rotation: styleStruct.alignment?.textRotation
|
|
23284
|
+
? rotationFromXLSX(styleStruct.alignment.textRotation)
|
|
23285
|
+
: undefined,
|
|
22874
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
|
|
22875
23287
|
fillColor: styleStruct.fillStyle?.patternType === "solid"
|
|
22876
23288
|
? convertColor(styleStruct.fillStyle?.fgColor)
|
|
@@ -23170,378 +23582,6 @@
|
|
|
23170
23582
|
}
|
|
23171
23583
|
}
|
|
23172
23584
|
|
|
23173
|
-
const globalReverseLookup$1 = new WeakMap();
|
|
23174
|
-
const globalIdCounter = new WeakMap();
|
|
23175
|
-
/**
|
|
23176
|
-
* Get the id of the given item (its key in the given dictionary).
|
|
23177
|
-
* If the given item does not exist in the dictionary, it creates one with a new id.
|
|
23178
|
-
*/
|
|
23179
|
-
function getItemId(item, itemsDic) {
|
|
23180
|
-
if (!globalReverseLookup$1.has(itemsDic)) {
|
|
23181
|
-
globalReverseLookup$1.set(itemsDic, new Map());
|
|
23182
|
-
globalIdCounter.set(itemsDic, 0);
|
|
23183
|
-
}
|
|
23184
|
-
const reverseLookup = globalReverseLookup$1.get(itemsDic);
|
|
23185
|
-
const canonical = getCanonicalRepresentation(item);
|
|
23186
|
-
if (reverseLookup.has(canonical)) {
|
|
23187
|
-
const id = reverseLookup.get(canonical);
|
|
23188
|
-
itemsDic[id] = item;
|
|
23189
|
-
return id;
|
|
23190
|
-
}
|
|
23191
|
-
// Generate new Id if the item didn't exist in the dictionary
|
|
23192
|
-
const newId = globalIdCounter.get(itemsDic) + 1;
|
|
23193
|
-
reverseLookup.set(canonical, newId);
|
|
23194
|
-
globalIdCounter.set(itemsDic, newId);
|
|
23195
|
-
itemsDic[newId] = item;
|
|
23196
|
-
return newId;
|
|
23197
|
-
}
|
|
23198
|
-
function groupItemIdsByZones(positionsByItemId) {
|
|
23199
|
-
const result = {};
|
|
23200
|
-
for (const itemId in positionsByItemId) {
|
|
23201
|
-
const zones = recomputeZones(positionsByItemId[itemId].map(positionToZone));
|
|
23202
|
-
for (const zone of zones) {
|
|
23203
|
-
result[zoneToXc(zone)] = Number(itemId);
|
|
23204
|
-
}
|
|
23205
|
-
}
|
|
23206
|
-
return result;
|
|
23207
|
-
}
|
|
23208
|
-
function* iterateItemIdsPositions(sheetId, itemIdsByZones) {
|
|
23209
|
-
for (const zoneXc in itemIdsByZones) {
|
|
23210
|
-
const zone = toZone(zoneXc);
|
|
23211
|
-
const itemId = itemIdsByZones[zoneXc];
|
|
23212
|
-
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
23213
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
23214
|
-
const position = { sheetId, col, row };
|
|
23215
|
-
yield [position, itemId];
|
|
23216
|
-
}
|
|
23217
|
-
}
|
|
23218
|
-
}
|
|
23219
|
-
}
|
|
23220
|
-
function getCanonicalRepresentation(item) {
|
|
23221
|
-
if (item === null)
|
|
23222
|
-
return "null";
|
|
23223
|
-
if (item === undefined)
|
|
23224
|
-
return "undefined";
|
|
23225
|
-
if (typeof item !== "object")
|
|
23226
|
-
return String(item);
|
|
23227
|
-
if (Array.isArray(item)) {
|
|
23228
|
-
const len = item.length;
|
|
23229
|
-
let result = "[";
|
|
23230
|
-
for (let i = 0; i < len; i++) {
|
|
23231
|
-
if (i > 0)
|
|
23232
|
-
result += ",";
|
|
23233
|
-
result += getCanonicalRepresentation(item[i]);
|
|
23234
|
-
}
|
|
23235
|
-
return result + "]";
|
|
23236
|
-
}
|
|
23237
|
-
const keys = Object.keys(item).sort();
|
|
23238
|
-
let repr = "{";
|
|
23239
|
-
for (const key of keys) {
|
|
23240
|
-
if (item[key] !== undefined) {
|
|
23241
|
-
repr += `"${key}":${getCanonicalRepresentation(item[key])},`;
|
|
23242
|
-
}
|
|
23243
|
-
}
|
|
23244
|
-
repr += "}";
|
|
23245
|
-
return repr;
|
|
23246
|
-
}
|
|
23247
|
-
|
|
23248
|
-
// -------------------------------------
|
|
23249
|
-
// CF HELPERS
|
|
23250
|
-
// -------------------------------------
|
|
23251
|
-
/**
|
|
23252
|
-
* Convert the conditional formatting o-spreadsheet operator to
|
|
23253
|
-
* the corresponding excel operator.
|
|
23254
|
-
* */
|
|
23255
|
-
function convertOperator(operator) {
|
|
23256
|
-
switch (operator) {
|
|
23257
|
-
case "isNotEmpty":
|
|
23258
|
-
return "notContainsBlanks";
|
|
23259
|
-
case "isEmpty":
|
|
23260
|
-
return "containsBlanks";
|
|
23261
|
-
case "notContainsText":
|
|
23262
|
-
return "notContainsBlanks";
|
|
23263
|
-
case "containsText":
|
|
23264
|
-
return "containsText";
|
|
23265
|
-
case "beginsWithText":
|
|
23266
|
-
return "beginsWith";
|
|
23267
|
-
case "endsWithText":
|
|
23268
|
-
return "endsWith";
|
|
23269
|
-
case "isGreaterThan":
|
|
23270
|
-
return "greaterThan";
|
|
23271
|
-
case "isGreaterOrEqualTo":
|
|
23272
|
-
return "greaterThanOrEqual";
|
|
23273
|
-
case "isLessThan":
|
|
23274
|
-
return "lessThan";
|
|
23275
|
-
case "isLessOrEqualTo":
|
|
23276
|
-
return "lessThanOrEqual";
|
|
23277
|
-
case "isBetween":
|
|
23278
|
-
return "between";
|
|
23279
|
-
case "isNotBetween":
|
|
23280
|
-
return "notBetween";
|
|
23281
|
-
case "isEqual":
|
|
23282
|
-
return "equal";
|
|
23283
|
-
case "isNotEqual":
|
|
23284
|
-
return "notEqual";
|
|
23285
|
-
case "customFormula":
|
|
23286
|
-
return "";
|
|
23287
|
-
case "dateIs":
|
|
23288
|
-
return "";
|
|
23289
|
-
case "dateIsBefore":
|
|
23290
|
-
return "lessThan";
|
|
23291
|
-
case "dateIsAfter":
|
|
23292
|
-
return "greaterThan";
|
|
23293
|
-
case "dateIsOnOrAfter":
|
|
23294
|
-
return "greaterThanOrEqual";
|
|
23295
|
-
case "dateIsOnOrBefore":
|
|
23296
|
-
return "lessThanOrEqual";
|
|
23297
|
-
}
|
|
23298
|
-
}
|
|
23299
|
-
// -------------------------------------
|
|
23300
|
-
// WORKSHEET HELPERS
|
|
23301
|
-
// -------------------------------------
|
|
23302
|
-
function getCellType(value) {
|
|
23303
|
-
switch (typeof value) {
|
|
23304
|
-
case "boolean":
|
|
23305
|
-
return "b";
|
|
23306
|
-
case "string":
|
|
23307
|
-
return "str";
|
|
23308
|
-
case "number":
|
|
23309
|
-
return "n";
|
|
23310
|
-
default:
|
|
23311
|
-
return undefined;
|
|
23312
|
-
}
|
|
23313
|
-
}
|
|
23314
|
-
function convertHeightToExcel(height) {
|
|
23315
|
-
return Math.round(HEIGHT_FACTOR * height * 100) / 100;
|
|
23316
|
-
}
|
|
23317
|
-
function convertWidthToExcel(width) {
|
|
23318
|
-
return Math.round(WIDTH_FACTOR * width * 100) / 100;
|
|
23319
|
-
}
|
|
23320
|
-
function convertHeightFromExcel(height) {
|
|
23321
|
-
if (!height)
|
|
23322
|
-
return height;
|
|
23323
|
-
return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
|
|
23324
|
-
}
|
|
23325
|
-
function convertWidthFromExcel(width) {
|
|
23326
|
-
if (!width)
|
|
23327
|
-
return width;
|
|
23328
|
-
return Math.round((width / WIDTH_FACTOR) * 100) / 100;
|
|
23329
|
-
}
|
|
23330
|
-
function extractStyle(data, content, styleId, formatId, borderId) {
|
|
23331
|
-
const style = styleId ? data.styles[styleId] : {};
|
|
23332
|
-
const format = formatId ? data.formats[formatId] : undefined;
|
|
23333
|
-
const styles = {
|
|
23334
|
-
font: {
|
|
23335
|
-
size: style?.fontSize || DEFAULT_FONT_SIZE,
|
|
23336
|
-
color: { rgb: style?.textColor ? style.textColor : "000000" },
|
|
23337
|
-
family: 2,
|
|
23338
|
-
name: "Arial",
|
|
23339
|
-
},
|
|
23340
|
-
fill: style?.fillColor
|
|
23341
|
-
? {
|
|
23342
|
-
fgColor: { rgb: style.fillColor },
|
|
23343
|
-
}
|
|
23344
|
-
: { reservedAttribute: "none" },
|
|
23345
|
-
numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
|
|
23346
|
-
border: borderId || 0,
|
|
23347
|
-
alignment: {
|
|
23348
|
-
horizontal: style.align,
|
|
23349
|
-
vertical: style.verticalAlign
|
|
23350
|
-
? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
|
|
23351
|
-
: undefined,
|
|
23352
|
-
wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
|
|
23353
|
-
},
|
|
23354
|
-
};
|
|
23355
|
-
styles.font["strike"] = !!style?.strikethrough || undefined;
|
|
23356
|
-
styles.font["underline"] = !!style?.underline || undefined;
|
|
23357
|
-
styles.font["bold"] = !!style?.bold || undefined;
|
|
23358
|
-
styles.font["italic"] = !!style?.italic || undefined;
|
|
23359
|
-
return styles;
|
|
23360
|
-
}
|
|
23361
|
-
function normalizeStyle(construct, styles) {
|
|
23362
|
-
// Normalize this
|
|
23363
|
-
const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
|
|
23364
|
-
const style = {
|
|
23365
|
-
fontId: pushElement(styles.font, construct.fonts),
|
|
23366
|
-
fillId: pushElement(styles.fill, construct.fills),
|
|
23367
|
-
borderId: styles.border,
|
|
23368
|
-
numFmtId,
|
|
23369
|
-
alignment: {
|
|
23370
|
-
vertical: styles.alignment.vertical,
|
|
23371
|
-
horizontal: styles.alignment.horizontal,
|
|
23372
|
-
wrapText: styles.alignment.wrapText,
|
|
23373
|
-
},
|
|
23374
|
-
};
|
|
23375
|
-
return pushElement(style, construct.styles);
|
|
23376
|
-
}
|
|
23377
|
-
function convertFormat(format, numFmtStructure) {
|
|
23378
|
-
if (!format) {
|
|
23379
|
-
return 0;
|
|
23380
|
-
}
|
|
23381
|
-
let formatId = XLSX_FORMAT_MAP[format.format];
|
|
23382
|
-
if (!formatId) {
|
|
23383
|
-
formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
|
|
23384
|
-
}
|
|
23385
|
-
return formatId;
|
|
23386
|
-
}
|
|
23387
|
-
/**
|
|
23388
|
-
* Add a relation to the given file and return its id.
|
|
23389
|
-
*/
|
|
23390
|
-
function addRelsToFile(relsFiles, path, rel) {
|
|
23391
|
-
const relsFile = relsFiles.find((file) => file.path === path);
|
|
23392
|
-
// the id is a one-based int casted as string
|
|
23393
|
-
let id;
|
|
23394
|
-
if (!relsFile) {
|
|
23395
|
-
id = "rId1";
|
|
23396
|
-
relsFiles.push({ path, rels: [{ ...rel, id }] });
|
|
23397
|
-
}
|
|
23398
|
-
else {
|
|
23399
|
-
id = `rId${(relsFile.rels.length + 1).toString()}`;
|
|
23400
|
-
relsFile.rels.push({
|
|
23401
|
-
...rel,
|
|
23402
|
-
id,
|
|
23403
|
-
});
|
|
23404
|
-
}
|
|
23405
|
-
return id;
|
|
23406
|
-
}
|
|
23407
|
-
const globalReverseLookup = new WeakMap();
|
|
23408
|
-
function pushElement(property, propertyList) {
|
|
23409
|
-
let reverseLookup = globalReverseLookup.get(propertyList);
|
|
23410
|
-
if (!reverseLookup) {
|
|
23411
|
-
reverseLookup = new Map();
|
|
23412
|
-
for (let i = 0; i < propertyList.length; i++) {
|
|
23413
|
-
const canonical = getCanonicalRepresentation(propertyList[i]);
|
|
23414
|
-
reverseLookup.set(canonical, i);
|
|
23415
|
-
}
|
|
23416
|
-
globalReverseLookup.set(propertyList, reverseLookup);
|
|
23417
|
-
}
|
|
23418
|
-
const canonical = getCanonicalRepresentation(property);
|
|
23419
|
-
if (reverseLookup.has(canonical)) {
|
|
23420
|
-
return reverseLookup.get(canonical);
|
|
23421
|
-
}
|
|
23422
|
-
const maxId = propertyList.length;
|
|
23423
|
-
propertyList.push(property);
|
|
23424
|
-
reverseLookup.set(canonical, maxId);
|
|
23425
|
-
return maxId;
|
|
23426
|
-
}
|
|
23427
|
-
/**
|
|
23428
|
-
* Convert a chart o-spreadsheet id to a xlsx id which
|
|
23429
|
-
* are unsigned integers (starting from 1).
|
|
23430
|
-
*/
|
|
23431
|
-
function convertChartId(chartId, construct) {
|
|
23432
|
-
const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
|
|
23433
|
-
if (xlsxId === -1) {
|
|
23434
|
-
construct.chartIds.push(chartId);
|
|
23435
|
-
return construct.chartIds.length;
|
|
23436
|
-
}
|
|
23437
|
-
return xlsxId + 1;
|
|
23438
|
-
}
|
|
23439
|
-
const imageIds = [];
|
|
23440
|
-
/**
|
|
23441
|
-
* Convert a image o-spreadsheet id to a xlsx id which
|
|
23442
|
-
* are unsigned integers (starting from 1).
|
|
23443
|
-
*/
|
|
23444
|
-
function convertImageId(imageId) {
|
|
23445
|
-
const xlsxId = imageIds.findIndex((id) => id === imageId);
|
|
23446
|
-
if (xlsxId === -1) {
|
|
23447
|
-
imageIds.push(imageId);
|
|
23448
|
-
return imageIds.length;
|
|
23449
|
-
}
|
|
23450
|
-
return xlsxId + 1;
|
|
23451
|
-
}
|
|
23452
|
-
/**
|
|
23453
|
-
* Convert a value expressed in dot to EMU.
|
|
23454
|
-
* EMU = English Metrical Unit
|
|
23455
|
-
* There are 914400 EMU per inch.
|
|
23456
|
-
*
|
|
23457
|
-
* /!\ A value expressed in EMU cannot be fractional.
|
|
23458
|
-
* See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
|
|
23459
|
-
*/
|
|
23460
|
-
function convertDotValueToEMU(value) {
|
|
23461
|
-
const DPI = 96;
|
|
23462
|
-
return Math.round((value * 914400) / DPI);
|
|
23463
|
-
}
|
|
23464
|
-
function getRangeSize(reference, defaultSheetIndex, data) {
|
|
23465
|
-
let xc = reference;
|
|
23466
|
-
let sheetName = undefined;
|
|
23467
|
-
({ xc, sheetName } = splitReference(reference));
|
|
23468
|
-
let rangeSheetIndex;
|
|
23469
|
-
if (sheetName) {
|
|
23470
|
-
const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
|
|
23471
|
-
if (index < 0) {
|
|
23472
|
-
throw new Error("Unable to find a sheet with the name " + sheetName);
|
|
23473
|
-
}
|
|
23474
|
-
rangeSheetIndex = index;
|
|
23475
|
-
}
|
|
23476
|
-
else {
|
|
23477
|
-
rangeSheetIndex = Number(defaultSheetIndex);
|
|
23478
|
-
}
|
|
23479
|
-
const zone = toUnboundedZone(xc);
|
|
23480
|
-
if (zone.right === undefined) {
|
|
23481
|
-
zone.right = data.sheets[rangeSheetIndex].colNumber;
|
|
23482
|
-
}
|
|
23483
|
-
if (zone.bottom === undefined) {
|
|
23484
|
-
zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
|
|
23485
|
-
}
|
|
23486
|
-
return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
|
|
23487
|
-
}
|
|
23488
|
-
function convertEMUToDotValue(value) {
|
|
23489
|
-
const DPI = 96;
|
|
23490
|
-
return Math.round((value * DPI) / 914400);
|
|
23491
|
-
}
|
|
23492
|
-
/**
|
|
23493
|
-
* Get the position of the start of a column in Excel (in px).
|
|
23494
|
-
*/
|
|
23495
|
-
function getColPosition(colIndex, sheetData) {
|
|
23496
|
-
let position = 0;
|
|
23497
|
-
for (let i = 0; i < colIndex; i++) {
|
|
23498
|
-
const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
|
|
23499
|
-
if (colAtIndex?.width) {
|
|
23500
|
-
position += colAtIndex.width;
|
|
23501
|
-
}
|
|
23502
|
-
else if (sheetData.sheetFormat?.defaultColWidth) {
|
|
23503
|
-
position += sheetData.sheetFormat.defaultColWidth;
|
|
23504
|
-
}
|
|
23505
|
-
else {
|
|
23506
|
-
position += EXCEL_DEFAULT_COL_WIDTH;
|
|
23507
|
-
}
|
|
23508
|
-
}
|
|
23509
|
-
return position / WIDTH_FACTOR;
|
|
23510
|
-
}
|
|
23511
|
-
/**
|
|
23512
|
-
* Get the position of the start of a row in Excel (in px).
|
|
23513
|
-
*/
|
|
23514
|
-
function getRowPosition(rowIndex, sheetData) {
|
|
23515
|
-
let position = 0;
|
|
23516
|
-
for (let i = 0; i < rowIndex; i++) {
|
|
23517
|
-
const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
|
|
23518
|
-
if (rowAtIndex?.height) {
|
|
23519
|
-
position += rowAtIndex.height;
|
|
23520
|
-
}
|
|
23521
|
-
else if (sheetData.sheetFormat?.defaultRowHeight) {
|
|
23522
|
-
position += sheetData.sheetFormat.defaultRowHeight;
|
|
23523
|
-
}
|
|
23524
|
-
else {
|
|
23525
|
-
position += EXCEL_DEFAULT_ROW_HEIGHT;
|
|
23526
|
-
}
|
|
23527
|
-
}
|
|
23528
|
-
return position / HEIGHT_FACTOR;
|
|
23529
|
-
}
|
|
23530
|
-
/**
|
|
23531
|
-
* Convert the o-spreadsheet data validation decimal
|
|
23532
|
-
* criterion type to the corresponding excel operator.
|
|
23533
|
-
*/
|
|
23534
|
-
function convertDecimalCriterionTypeToExcelOperator(operator) {
|
|
23535
|
-
return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
|
|
23536
|
-
}
|
|
23537
|
-
/**
|
|
23538
|
-
* Convert the o-spreadsheet data validation date
|
|
23539
|
-
* criterion type to the corresponding excel operator.
|
|
23540
|
-
*/
|
|
23541
|
-
function convertDateCriterionTypeToExcelOperator(operator) {
|
|
23542
|
-
return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
|
|
23543
|
-
}
|
|
23544
|
-
|
|
23545
23585
|
function convertFigures(sheetData) {
|
|
23546
23586
|
let id = 1;
|
|
23547
23587
|
return sheetData.figures
|
|
@@ -23913,17 +23953,41 @@
|
|
|
23913
23953
|
const today = DateTime.now();
|
|
23914
23954
|
switch (dateValue) {
|
|
23915
23955
|
case "today":
|
|
23916
|
-
return jsDateToNumber(today);
|
|
23917
|
-
case "yesterday":
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
|
|
23956
|
+
return Math.floor(jsDateToNumber(today));
|
|
23957
|
+
case "yesterday": {
|
|
23958
|
+
today.setDate(today.getDate() - 1);
|
|
23959
|
+
return Math.floor(jsDateToNumber(today));
|
|
23960
|
+
}
|
|
23961
|
+
case "tomorrow": {
|
|
23962
|
+
today.setDate(today.getDate() + 1);
|
|
23963
|
+
return Math.floor(jsDateToNumber(today));
|
|
23964
|
+
}
|
|
23921
23965
|
case "lastWeek":
|
|
23922
|
-
|
|
23923
|
-
|
|
23924
|
-
|
|
23966
|
+
today.setDate(today.getDate() - 6);
|
|
23967
|
+
return Math.floor(jsDateToNumber(today));
|
|
23968
|
+
case "lastMonth": {
|
|
23969
|
+
const lastMonth = today.getMonth() === 0 ? 11 : today.getMonth() - 1;
|
|
23970
|
+
const dateInLastMonth = new DateTime(today.getFullYear(), lastMonth, 1);
|
|
23971
|
+
if (today.getDate() > getDaysInMonth(dateInLastMonth)) {
|
|
23972
|
+
today.setDate(1);
|
|
23973
|
+
}
|
|
23974
|
+
else {
|
|
23975
|
+
today.setDate(today.getDate() + 1);
|
|
23976
|
+
today.setMonth(today.getMonth() - 1);
|
|
23977
|
+
}
|
|
23978
|
+
return Math.floor(jsDateToNumber(today));
|
|
23979
|
+
}
|
|
23925
23980
|
case "lastYear":
|
|
23926
|
-
|
|
23981
|
+
// Handle leap year case
|
|
23982
|
+
if (today.getMonth() === 1 && today.getDate() === 29) {
|
|
23983
|
+
today.setDate(28);
|
|
23984
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
23985
|
+
}
|
|
23986
|
+
else {
|
|
23987
|
+
today.setDate(today.getDate() + 1);
|
|
23988
|
+
today.setFullYear(today.getFullYear() - 1);
|
|
23989
|
+
}
|
|
23990
|
+
return Math.floor(jsDateToNumber(today));
|
|
23927
23991
|
}
|
|
23928
23992
|
}
|
|
23929
23993
|
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
@@ -28948,7 +29012,7 @@
|
|
|
28948
29012
|
return false;
|
|
28949
29013
|
}
|
|
28950
29014
|
if (["lastWeek", "lastMonth", "lastYear"].includes(criterion.dateValue)) {
|
|
28951
|
-
const today =
|
|
29015
|
+
const today = Math.floor(jsDateToNumber(DateTime.now()));
|
|
28952
29016
|
return isDateBetween(dateValue, today, criterionValue);
|
|
28953
29017
|
}
|
|
28954
29018
|
return areDatesSameDay(dateValue, criterionValue);
|
|
@@ -33375,6 +33439,7 @@
|
|
|
33375
33439
|
"getMeasureCompiledFormula",
|
|
33376
33440
|
"getPivotName",
|
|
33377
33441
|
"isExistingPivot",
|
|
33442
|
+
"getMeasureFullDependencies",
|
|
33378
33443
|
];
|
|
33379
33444
|
nextFormulaId = 1;
|
|
33380
33445
|
pivots = {};
|
|
@@ -33460,7 +33525,7 @@
|
|
|
33460
33525
|
}
|
|
33461
33526
|
case "UPDATE_PIVOT": {
|
|
33462
33527
|
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
33463
|
-
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
33528
|
+
this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
|
|
33464
33529
|
break;
|
|
33465
33530
|
}
|
|
33466
33531
|
}
|
|
@@ -33478,9 +33543,14 @@
|
|
|
33478
33543
|
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
33479
33544
|
}
|
|
33480
33545
|
}
|
|
33481
|
-
for (const
|
|
33482
|
-
for (const
|
|
33483
|
-
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;
|
|
33484
33554
|
const newDependencies = [];
|
|
33485
33555
|
for (const range of compiledFormula.dependencies) {
|
|
33486
33556
|
const change = applyChange(range);
|
|
@@ -33492,8 +33562,9 @@
|
|
|
33492
33562
|
}
|
|
33493
33563
|
}
|
|
33494
33564
|
const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
|
|
33495
|
-
|
|
33496
|
-
|
|
33565
|
+
const oldFormulaString = measure.computedBy.formula;
|
|
33566
|
+
if (newFormulaString !== oldFormulaString) {
|
|
33567
|
+
this.replaceMeasureFormula(pivotId, measure, newFormulaString);
|
|
33497
33568
|
}
|
|
33498
33569
|
}
|
|
33499
33570
|
}
|
|
@@ -33531,31 +33602,60 @@
|
|
|
33531
33602
|
isExistingPivot(pivotId) {
|
|
33532
33603
|
return pivotId in this.pivots;
|
|
33533
33604
|
}
|
|
33534
|
-
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) {
|
|
33535
33612
|
if (!measure.computedBy) {
|
|
33536
33613
|
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
33537
33614
|
}
|
|
33538
|
-
|
|
33539
|
-
return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
|
|
33615
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
|
|
33540
33616
|
}
|
|
33541
33617
|
// -------------------------------------------------------------------------
|
|
33542
33618
|
// Private
|
|
33543
33619
|
// -------------------------------------------------------------------------
|
|
33544
33620
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
33545
33621
|
this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
|
|
33546
|
-
this.compileCalculatedMeasures(pivot.measures);
|
|
33622
|
+
this.compileCalculatedMeasures(pivotId, pivot.measures);
|
|
33547
33623
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
33548
33624
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
33549
33625
|
}
|
|
33550
|
-
compileCalculatedMeasures(measures) {
|
|
33626
|
+
compileCalculatedMeasures(pivotId, measures) {
|
|
33551
33627
|
for (const measure of measures) {
|
|
33552
33628
|
if (measure.computedBy) {
|
|
33553
|
-
const sheetId = measure.computedBy.sheetId;
|
|
33554
33629
|
const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
|
|
33555
|
-
this.history.update("compiledMeasureFormulas",
|
|
33630
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
|
|
33631
|
+
}
|
|
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);
|
|
33556
33637
|
}
|
|
33557
33638
|
}
|
|
33558
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;
|
|
33658
|
+
}
|
|
33559
33659
|
insertPivot(position, formulaId, table) {
|
|
33560
33660
|
this.resizeSheet(position.sheetId, position, table);
|
|
33561
33661
|
const pivotCells = table.getPivotCells();
|
|
@@ -33614,21 +33714,17 @@
|
|
|
33614
33714
|
dependencies: rangeDependencies,
|
|
33615
33715
|
};
|
|
33616
33716
|
}
|
|
33617
|
-
replaceMeasureFormula(
|
|
33618
|
-
|
|
33619
|
-
|
|
33620
|
-
|
|
33621
|
-
const pivot = this.pivots[pivotId];
|
|
33622
|
-
if (!pivot) {
|
|
33623
|
-
continue;
|
|
33624
|
-
}
|
|
33625
|
-
for (const measure of pivot.definition.measures) {
|
|
33626
|
-
if (measure.computedBy?.formula === formulaString) {
|
|
33627
|
-
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
33628
|
-
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
|
|
33629
|
-
}
|
|
33630
|
-
}
|
|
33717
|
+
replaceMeasureFormula(pivotId, measure, newFormulaString) {
|
|
33718
|
+
const pivot = this.pivots[pivotId];
|
|
33719
|
+
if (!pivot) {
|
|
33720
|
+
return;
|
|
33631
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);
|
|
33632
33728
|
}
|
|
33633
33729
|
checkSortedColumnInMeasures(definition) {
|
|
33634
33730
|
const measures = definition.measures.map((measure) => measure.id);
|
|
@@ -34689,7 +34785,7 @@
|
|
|
34689
34785
|
case "UPDATE_CELL":
|
|
34690
34786
|
if (cmd.style !== undefined) {
|
|
34691
34787
|
if (cmd.style !== null) {
|
|
34692
|
-
this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style);
|
|
34788
|
+
this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style, { force: true });
|
|
34693
34789
|
}
|
|
34694
34790
|
else {
|
|
34695
34791
|
this.clearStyle(cmd.sheetId, [positionToZone(cmd)]);
|
|
@@ -34757,16 +34853,22 @@
|
|
|
34757
34853
|
}
|
|
34758
34854
|
}
|
|
34759
34855
|
styleIsDefault(style) {
|
|
34760
|
-
|
|
34856
|
+
for (const key in style) {
|
|
34857
|
+
if (DEFAULT_STYLE_NO_ALIGN[key] !== style[key]) {
|
|
34858
|
+
return false;
|
|
34859
|
+
}
|
|
34860
|
+
}
|
|
34861
|
+
return true;
|
|
34761
34862
|
}
|
|
34762
34863
|
removeDefaultStyleValues(style) {
|
|
34763
34864
|
const cleanedStyle = { ...style };
|
|
34764
|
-
for (const property in
|
|
34765
|
-
if (cleanedStyle[property] ===
|
|
34865
|
+
for (const property in style) {
|
|
34866
|
+
if (cleanedStyle[property] === undefined ||
|
|
34867
|
+
cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
|
|
34766
34868
|
delete cleanedStyle[property];
|
|
34767
34869
|
}
|
|
34768
34870
|
}
|
|
34769
|
-
return cleanedStyle;
|
|
34871
|
+
return Object.keys(cleanedStyle).length > 0 ? cleanedStyle : undefined;
|
|
34770
34872
|
}
|
|
34771
34873
|
onMerge(sheetId, zone) {
|
|
34772
34874
|
this.setStyle(sheetId, zone, this.getCellStyle({ sheetId, col: zone.left, row: zone.top }), {
|
|
@@ -34802,13 +34904,13 @@
|
|
|
34802
34904
|
}
|
|
34803
34905
|
editingZone = recomputeZones(editingZone, [inter]);
|
|
34804
34906
|
}
|
|
34907
|
+
style = this.removeDefaultStyleValues(style);
|
|
34805
34908
|
if (style) {
|
|
34806
|
-
const newStyle = this.removeDefaultStyleValues(style);
|
|
34807
34909
|
styles.push(...editingZone.map((zone) => {
|
|
34808
|
-
return { zone, style
|
|
34910
|
+
return { zone, style };
|
|
34809
34911
|
}));
|
|
34810
34912
|
}
|
|
34811
|
-
this.history.update("styles", sheetId, styles
|
|
34913
|
+
this.history.update("styles", sheetId, styles);
|
|
34812
34914
|
}
|
|
34813
34915
|
clearStyle(sheetId, zones) {
|
|
34814
34916
|
this.setStyles(sheetId, zones, undefined, { force: true });
|
|
@@ -40450,14 +40552,16 @@
|
|
|
40450
40552
|
function withPivotPresentationLayer (PivotClass) {
|
|
40451
40553
|
class PivotPresentationLayer extends PivotClass {
|
|
40452
40554
|
getters;
|
|
40555
|
+
pivotId;
|
|
40453
40556
|
cache = {};
|
|
40454
40557
|
rankAsc = {};
|
|
40455
40558
|
rankDesc = {};
|
|
40456
40559
|
runningTotal = {};
|
|
40457
40560
|
runningTotalInPercent = {};
|
|
40458
|
-
constructor(custom, params) {
|
|
40561
|
+
constructor(pivotId, custom, params) {
|
|
40459
40562
|
super(custom, params);
|
|
40460
40563
|
this.getters = params.getters;
|
|
40564
|
+
this.pivotId = pivotId;
|
|
40461
40565
|
}
|
|
40462
40566
|
markAsDirtyForEvaluation() {
|
|
40463
40567
|
this.cache = {};
|
|
@@ -40507,7 +40611,7 @@
|
|
|
40507
40611
|
return handleError(error, measure.aggregator.toUpperCase());
|
|
40508
40612
|
}
|
|
40509
40613
|
}
|
|
40510
|
-
const formula = this.getters.getMeasureCompiledFormula(measure);
|
|
40614
|
+
const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
|
|
40511
40615
|
const getSymbolValue = (symbolName) => {
|
|
40512
40616
|
const { columns, rows } = this.definition;
|
|
40513
40617
|
if (columns.find((col) => col.nameWithGranularity === symbolName)) {
|
|
@@ -41254,7 +41358,7 @@
|
|
|
41254
41358
|
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
41255
41359
|
if (!(pivotId in this.pivots)) {
|
|
41256
41360
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
41257
|
-
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
41361
|
+
this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
|
|
41258
41362
|
}
|
|
41259
41363
|
else if (recreate) {
|
|
41260
41364
|
this.pivots[pivotId].onDefinitionChange(definition);
|
|
@@ -50246,6 +50350,9 @@
|
|
|
50246
50350
|
if (style.alignment && style.alignment.wrapText) {
|
|
50247
50351
|
alignAttrs.push(["wrapText", "1"]);
|
|
50248
50352
|
}
|
|
50353
|
+
if (style.alignment && style.alignment.textRotation) {
|
|
50354
|
+
alignAttrs.push(["textRotation", style.alignment.textRotation]);
|
|
50355
|
+
}
|
|
50249
50356
|
if (alignAttrs.length > 0) {
|
|
50250
50357
|
attributes.push(["applyAlignment", "1"]); // for Libre Office
|
|
50251
50358
|
styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
|
|
@@ -51635,8 +51742,8 @@
|
|
|
51635
51742
|
|
|
51636
51743
|
|
|
51637
51744
|
__info__.version = "19.1.0-alpha.3";
|
|
51638
|
-
__info__.date = "
|
|
51639
|
-
__info__.hash = "
|
|
51745
|
+
__info__.date = "2026-01-14T10:01:54.190Z";
|
|
51746
|
+
__info__.hash = "52a3e52";
|
|
51640
51747
|
|
|
51641
51748
|
|
|
51642
51749
|
})(this.o_spreadsheet_engine = this.o_spreadsheet_engine || {});
|