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