@odoo/o-spreadsheet 19.1.2 → 19.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet-engine.d.ts +10 -4
- package/dist/o-spreadsheet-engine.esm.js +491 -421
- package/dist/o-spreadsheet-engine.iife.js +491 -421
- package/dist/o-spreadsheet-engine.min.iife.js +305 -305
- package/dist/o-spreadsheet.d.ts +10 -4
- package/dist/o_spreadsheet.css +3 -3
- package/dist/o_spreadsheet.esm.js +477 -375
- package/dist/o_spreadsheet.iife.js +477 -375
- package/dist/o_spreadsheet.min.iife.js +311 -311
- package/dist/o_spreadsheet.xml +6 -4
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
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
|
-
* @version 19.1.
|
|
6
|
-
* @date 2026-01-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.1.3
|
|
6
|
+
* @date 2026-01-14T10:02:32.431Z
|
|
7
|
+
* @hash 52a3e52
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -179,6 +179,7 @@
|
|
|
179
179
|
textColor: "",
|
|
180
180
|
rotation: 0,
|
|
181
181
|
};
|
|
182
|
+
const ROTATION_EPSILON = 0.001;
|
|
182
183
|
const DEFAULT_VERTICAL_ALIGN = DEFAULT_STYLE.verticalAlign;
|
|
183
184
|
const DEFAULT_WRAPPING_MODE = DEFAULT_STYLE.wrapping;
|
|
184
185
|
// Fonts
|
|
@@ -15492,9 +15493,10 @@
|
|
|
15492
15493
|
throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
|
|
15493
15494
|
}
|
|
15494
15495
|
}
|
|
15495
|
-
function addPivotDependencies(evalContext,
|
|
15496
|
+
function addPivotDependencies(evalContext, pivotId, forMeasures) {
|
|
15496
15497
|
//TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
|
|
15497
15498
|
const dependencies = [];
|
|
15499
|
+
const coreDefinition = evalContext.getters.getPivotCoreDefinition(pivotId);
|
|
15498
15500
|
if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
|
|
15499
15501
|
const { sheetId, zone } = coreDefinition.dataSet;
|
|
15500
15502
|
const xc = zoneToXc(zone);
|
|
@@ -15511,8 +15513,7 @@
|
|
|
15511
15513
|
}
|
|
15512
15514
|
for (const measure of forMeasures) {
|
|
15513
15515
|
if (measure.computedBy) {
|
|
15514
|
-
|
|
15515
|
-
dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
15516
|
+
dependencies.push(...evalContext.getters.getMeasureFullDependencies(pivotId, measure));
|
|
15516
15517
|
}
|
|
15517
15518
|
}
|
|
15518
15519
|
const originPosition = evalContext.__originCellPosition;
|
|
@@ -16009,7 +16010,7 @@
|
|
|
16009
16010
|
assertDomainLength(domainArgs);
|
|
16010
16011
|
const pivot = this.getters.getPivot(pivotId);
|
|
16011
16012
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
16012
|
-
addPivotDependencies(this,
|
|
16013
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures.filter((m) => m.id === _measure));
|
|
16013
16014
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
16014
16015
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
16015
16016
|
if (error) {
|
|
@@ -16042,8 +16043,7 @@
|
|
|
16042
16043
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
16043
16044
|
assertDomainLength(domainArgs);
|
|
16044
16045
|
const pivot = this.getters.getPivot(_pivotId);
|
|
16045
|
-
|
|
16046
|
-
addPivotDependencies(this, coreDefinition, []);
|
|
16046
|
+
addPivotDependencies(this, _pivotId, []);
|
|
16047
16047
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
16048
16048
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
16049
16049
|
if (error) {
|
|
@@ -16095,7 +16095,7 @@
|
|
|
16095
16095
|
if (pivotStyle.numberOfColumns < 0) {
|
|
16096
16096
|
return new EvaluationError(_t("The number of columns must be positive."));
|
|
16097
16097
|
}
|
|
16098
|
-
addPivotDependencies(this,
|
|
16098
|
+
addPivotDependencies(this, pivotId, coreDefinition.measures);
|
|
16099
16099
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
16100
16100
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
16101
16101
|
if (error) {
|
|
@@ -20554,7 +20554,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20554
20554
|
let { x, y } = rect; // top-left when align=left and top-right when align=right, top-center when align=center
|
|
20555
20555
|
const cos = Math.cos(-style.rotation);
|
|
20556
20556
|
const sin = Math.sin(-style.rotation);
|
|
20557
|
-
const width = rect.textWidth - MIN_CELL_TEXT_MARGIN;
|
|
20557
|
+
const width = rect.textWidth - 2 * MIN_CELL_TEXT_MARGIN;
|
|
20558
20558
|
const height = rect.textHeight;
|
|
20559
20559
|
const center = style.align === "center";
|
|
20560
20560
|
const rotateTowardCellCenter = (style.align === "left") === sin < 0;
|
|
@@ -20588,6 +20588,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20588
20588
|
else {
|
|
20589
20589
|
if (center) {
|
|
20590
20590
|
x -= sh / 2;
|
|
20591
|
+
y -= height / 2;
|
|
20592
|
+
if (rotateTowardCellCenter) {
|
|
20593
|
+
y += sh;
|
|
20594
|
+
}
|
|
20595
|
+
else {
|
|
20596
|
+
y -= sh;
|
|
20597
|
+
}
|
|
20591
20598
|
}
|
|
20592
20599
|
else if (rotateTowardCellCenter) {
|
|
20593
20600
|
x -= sh;
|
|
@@ -34400,6 +34407,328 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34400
34407
|
*/
|
|
34401
34408
|
const DEFAULT_SYSTEM_COLOR = "FF000000";
|
|
34402
34409
|
|
|
34410
|
+
// -------------------------------------
|
|
34411
|
+
// CF HELPERS
|
|
34412
|
+
// -------------------------------------
|
|
34413
|
+
/**
|
|
34414
|
+
* Convert the conditional formatting o-spreadsheet operator to
|
|
34415
|
+
* the corresponding excel operator.
|
|
34416
|
+
* */
|
|
34417
|
+
function convertOperator(operator) {
|
|
34418
|
+
switch (operator) {
|
|
34419
|
+
case "isNotEmpty":
|
|
34420
|
+
return "notContainsBlanks";
|
|
34421
|
+
case "isEmpty":
|
|
34422
|
+
return "containsBlanks";
|
|
34423
|
+
case "notContainsText":
|
|
34424
|
+
return "notContainsBlanks";
|
|
34425
|
+
case "containsText":
|
|
34426
|
+
return "containsText";
|
|
34427
|
+
case "beginsWithText":
|
|
34428
|
+
return "beginsWith";
|
|
34429
|
+
case "endsWithText":
|
|
34430
|
+
return "endsWith";
|
|
34431
|
+
case "isGreaterThan":
|
|
34432
|
+
return "greaterThan";
|
|
34433
|
+
case "isGreaterOrEqualTo":
|
|
34434
|
+
return "greaterThanOrEqual";
|
|
34435
|
+
case "isLessThan":
|
|
34436
|
+
return "lessThan";
|
|
34437
|
+
case "isLessOrEqualTo":
|
|
34438
|
+
return "lessThanOrEqual";
|
|
34439
|
+
case "isBetween":
|
|
34440
|
+
return "between";
|
|
34441
|
+
case "isNotBetween":
|
|
34442
|
+
return "notBetween";
|
|
34443
|
+
case "isEqual":
|
|
34444
|
+
return "equal";
|
|
34445
|
+
case "isNotEqual":
|
|
34446
|
+
return "notEqual";
|
|
34447
|
+
case "customFormula":
|
|
34448
|
+
return "";
|
|
34449
|
+
case "dateIs":
|
|
34450
|
+
return "";
|
|
34451
|
+
case "dateIsBefore":
|
|
34452
|
+
return "lessThan";
|
|
34453
|
+
case "dateIsAfter":
|
|
34454
|
+
return "greaterThan";
|
|
34455
|
+
case "dateIsOnOrAfter":
|
|
34456
|
+
return "greaterThanOrEqual";
|
|
34457
|
+
case "dateIsOnOrBefore":
|
|
34458
|
+
return "lessThanOrEqual";
|
|
34459
|
+
}
|
|
34460
|
+
}
|
|
34461
|
+
// -------------------------------------
|
|
34462
|
+
// WORKSHEET HELPERS
|
|
34463
|
+
// -------------------------------------
|
|
34464
|
+
function getCellType(value) {
|
|
34465
|
+
switch (typeof value) {
|
|
34466
|
+
case "boolean":
|
|
34467
|
+
return "b";
|
|
34468
|
+
case "string":
|
|
34469
|
+
return "str";
|
|
34470
|
+
case "number":
|
|
34471
|
+
return "n";
|
|
34472
|
+
default:
|
|
34473
|
+
return undefined;
|
|
34474
|
+
}
|
|
34475
|
+
}
|
|
34476
|
+
function convertHeightToExcel(height) {
|
|
34477
|
+
return Math.round(HEIGHT_FACTOR * height * 100) / 100;
|
|
34478
|
+
}
|
|
34479
|
+
function convertWidthToExcel(width) {
|
|
34480
|
+
return Math.round(WIDTH_FACTOR * width * 100) / 100;
|
|
34481
|
+
}
|
|
34482
|
+
function convertHeightFromExcel(height) {
|
|
34483
|
+
if (!height)
|
|
34484
|
+
return height;
|
|
34485
|
+
return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
|
|
34486
|
+
}
|
|
34487
|
+
function convertWidthFromExcel(width) {
|
|
34488
|
+
if (!width)
|
|
34489
|
+
return width;
|
|
34490
|
+
return Math.round((width / WIDTH_FACTOR) * 100) / 100;
|
|
34491
|
+
}
|
|
34492
|
+
function extractStyle(data, content, styleId, formatId, borderId) {
|
|
34493
|
+
const style = styleId ? data.styles[styleId] : {};
|
|
34494
|
+
const format = formatId ? data.formats[formatId] : undefined;
|
|
34495
|
+
const styles = {
|
|
34496
|
+
font: {
|
|
34497
|
+
size: style?.fontSize || DEFAULT_FONT_SIZE,
|
|
34498
|
+
color: { rgb: style?.textColor ? style.textColor : "000000" },
|
|
34499
|
+
family: 2,
|
|
34500
|
+
name: "Arial",
|
|
34501
|
+
},
|
|
34502
|
+
fill: style?.fillColor
|
|
34503
|
+
? {
|
|
34504
|
+
fgColor: { rgb: style.fillColor },
|
|
34505
|
+
}
|
|
34506
|
+
: { reservedAttribute: "none" },
|
|
34507
|
+
numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
|
|
34508
|
+
border: borderId || 0,
|
|
34509
|
+
alignment: {
|
|
34510
|
+
horizontal: style.align,
|
|
34511
|
+
vertical: style.verticalAlign
|
|
34512
|
+
? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
|
|
34513
|
+
: undefined,
|
|
34514
|
+
wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
|
|
34515
|
+
textRotation: style.rotation ? rotationToXLSX(style.rotation) : undefined,
|
|
34516
|
+
},
|
|
34517
|
+
};
|
|
34518
|
+
styles.font["strike"] = !!style?.strikethrough || undefined;
|
|
34519
|
+
styles.font["underline"] = !!style?.underline || undefined;
|
|
34520
|
+
styles.font["bold"] = !!style?.bold || undefined;
|
|
34521
|
+
styles.font["italic"] = !!style?.italic || undefined;
|
|
34522
|
+
return styles;
|
|
34523
|
+
}
|
|
34524
|
+
function rotationToXLSX(rad) {
|
|
34525
|
+
let deg = Math.round((-rad / Math.PI) * 180) % 180;
|
|
34526
|
+
if (deg > 90) {
|
|
34527
|
+
deg -= 180;
|
|
34528
|
+
}
|
|
34529
|
+
else if (deg < -90) {
|
|
34530
|
+
deg += 180;
|
|
34531
|
+
}
|
|
34532
|
+
if (deg >= 0) {
|
|
34533
|
+
return deg;
|
|
34534
|
+
}
|
|
34535
|
+
else {
|
|
34536
|
+
return 90 - deg;
|
|
34537
|
+
}
|
|
34538
|
+
}
|
|
34539
|
+
function rotationFromXLSX(deg) {
|
|
34540
|
+
if (deg <= 90) {
|
|
34541
|
+
return -(deg / 180) * Math.PI;
|
|
34542
|
+
}
|
|
34543
|
+
else {
|
|
34544
|
+
return (-(90 - deg) / 180) * Math.PI;
|
|
34545
|
+
}
|
|
34546
|
+
}
|
|
34547
|
+
function normalizeStyle(construct, styles) {
|
|
34548
|
+
// Normalize this
|
|
34549
|
+
const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
|
|
34550
|
+
const style = {
|
|
34551
|
+
fontId: pushElement(styles.font, construct.fonts),
|
|
34552
|
+
fillId: pushElement(styles.fill, construct.fills),
|
|
34553
|
+
borderId: styles.border,
|
|
34554
|
+
numFmtId,
|
|
34555
|
+
alignment: {
|
|
34556
|
+
vertical: styles.alignment.vertical,
|
|
34557
|
+
horizontal: styles.alignment.horizontal,
|
|
34558
|
+
wrapText: styles.alignment.wrapText,
|
|
34559
|
+
textRotation: styles.alignment.textRotation,
|
|
34560
|
+
},
|
|
34561
|
+
};
|
|
34562
|
+
return pushElement(style, construct.styles);
|
|
34563
|
+
}
|
|
34564
|
+
function convertFormat(format, numFmtStructure) {
|
|
34565
|
+
if (!format) {
|
|
34566
|
+
return 0;
|
|
34567
|
+
}
|
|
34568
|
+
let formatId = XLSX_FORMAT_MAP[format.format];
|
|
34569
|
+
if (!formatId) {
|
|
34570
|
+
formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
|
|
34571
|
+
}
|
|
34572
|
+
return formatId;
|
|
34573
|
+
}
|
|
34574
|
+
/**
|
|
34575
|
+
* Add a relation to the given file and return its id.
|
|
34576
|
+
*/
|
|
34577
|
+
function addRelsToFile(relsFiles, path, rel) {
|
|
34578
|
+
const relsFile = relsFiles.find((file) => file.path === path);
|
|
34579
|
+
// the id is a one-based int casted as string
|
|
34580
|
+
let id;
|
|
34581
|
+
if (!relsFile) {
|
|
34582
|
+
id = "rId1";
|
|
34583
|
+
relsFiles.push({ path, rels: [{ ...rel, id }] });
|
|
34584
|
+
}
|
|
34585
|
+
else {
|
|
34586
|
+
id = `rId${(relsFile.rels.length + 1).toString()}`;
|
|
34587
|
+
relsFile.rels.push({
|
|
34588
|
+
...rel,
|
|
34589
|
+
id,
|
|
34590
|
+
});
|
|
34591
|
+
}
|
|
34592
|
+
return id;
|
|
34593
|
+
}
|
|
34594
|
+
const globalReverseLookup = new WeakMap();
|
|
34595
|
+
function pushElement(property, propertyList) {
|
|
34596
|
+
let reverseLookup = globalReverseLookup.get(propertyList);
|
|
34597
|
+
if (!reverseLookup) {
|
|
34598
|
+
reverseLookup = new Map();
|
|
34599
|
+
for (let i = 0; i < propertyList.length; i++) {
|
|
34600
|
+
const canonical = getCanonicalRepresentation(propertyList[i]);
|
|
34601
|
+
reverseLookup.set(canonical, i);
|
|
34602
|
+
}
|
|
34603
|
+
globalReverseLookup.set(propertyList, reverseLookup);
|
|
34604
|
+
}
|
|
34605
|
+
const canonical = getCanonicalRepresentation(property);
|
|
34606
|
+
if (reverseLookup.has(canonical)) {
|
|
34607
|
+
return reverseLookup.get(canonical);
|
|
34608
|
+
}
|
|
34609
|
+
const maxId = propertyList.length;
|
|
34610
|
+
propertyList.push(property);
|
|
34611
|
+
reverseLookup.set(canonical, maxId);
|
|
34612
|
+
return maxId;
|
|
34613
|
+
}
|
|
34614
|
+
/**
|
|
34615
|
+
* Convert a chart o-spreadsheet id to a xlsx id which
|
|
34616
|
+
* are unsigned integers (starting from 1).
|
|
34617
|
+
*/
|
|
34618
|
+
function convertChartId(chartId, construct) {
|
|
34619
|
+
const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
|
|
34620
|
+
if (xlsxId === -1) {
|
|
34621
|
+
construct.chartIds.push(chartId);
|
|
34622
|
+
return construct.chartIds.length;
|
|
34623
|
+
}
|
|
34624
|
+
return xlsxId + 1;
|
|
34625
|
+
}
|
|
34626
|
+
const imageIds = [];
|
|
34627
|
+
/**
|
|
34628
|
+
* Convert a image o-spreadsheet id to a xlsx id which
|
|
34629
|
+
* are unsigned integers (starting from 1).
|
|
34630
|
+
*/
|
|
34631
|
+
function convertImageId(imageId) {
|
|
34632
|
+
const xlsxId = imageIds.findIndex((id) => id === imageId);
|
|
34633
|
+
if (xlsxId === -1) {
|
|
34634
|
+
imageIds.push(imageId);
|
|
34635
|
+
return imageIds.length;
|
|
34636
|
+
}
|
|
34637
|
+
return xlsxId + 1;
|
|
34638
|
+
}
|
|
34639
|
+
/**
|
|
34640
|
+
* Convert a value expressed in dot to EMU.
|
|
34641
|
+
* EMU = English Metrical Unit
|
|
34642
|
+
* There are 914400 EMU per inch.
|
|
34643
|
+
*
|
|
34644
|
+
* /!\ A value expressed in EMU cannot be fractional.
|
|
34645
|
+
* See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
|
|
34646
|
+
*/
|
|
34647
|
+
function convertDotValueToEMU(value) {
|
|
34648
|
+
const DPI = 96;
|
|
34649
|
+
return Math.round((value * 914400) / DPI);
|
|
34650
|
+
}
|
|
34651
|
+
function getRangeSize(reference, defaultSheetIndex, data) {
|
|
34652
|
+
let xc = reference;
|
|
34653
|
+
let sheetName = undefined;
|
|
34654
|
+
({ xc, sheetName } = splitReference(reference));
|
|
34655
|
+
let rangeSheetIndex;
|
|
34656
|
+
if (sheetName) {
|
|
34657
|
+
const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
|
|
34658
|
+
if (index < 0) {
|
|
34659
|
+
throw new Error("Unable to find a sheet with the name " + sheetName);
|
|
34660
|
+
}
|
|
34661
|
+
rangeSheetIndex = index;
|
|
34662
|
+
}
|
|
34663
|
+
else {
|
|
34664
|
+
rangeSheetIndex = Number(defaultSheetIndex);
|
|
34665
|
+
}
|
|
34666
|
+
const zone = toUnboundedZone(xc);
|
|
34667
|
+
if (zone.right === undefined) {
|
|
34668
|
+
zone.right = data.sheets[rangeSheetIndex].colNumber;
|
|
34669
|
+
}
|
|
34670
|
+
if (zone.bottom === undefined) {
|
|
34671
|
+
zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
|
|
34672
|
+
}
|
|
34673
|
+
return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
|
|
34674
|
+
}
|
|
34675
|
+
function convertEMUToDotValue(value) {
|
|
34676
|
+
const DPI = 96;
|
|
34677
|
+
return Math.round((value * DPI) / 914400);
|
|
34678
|
+
}
|
|
34679
|
+
/**
|
|
34680
|
+
* Get the position of the start of a column in Excel (in px).
|
|
34681
|
+
*/
|
|
34682
|
+
function getColPosition(colIndex, sheetData) {
|
|
34683
|
+
let position = 0;
|
|
34684
|
+
for (let i = 0; i < colIndex; i++) {
|
|
34685
|
+
const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
|
|
34686
|
+
if (colAtIndex?.width) {
|
|
34687
|
+
position += colAtIndex.width;
|
|
34688
|
+
}
|
|
34689
|
+
else if (sheetData.sheetFormat?.defaultColWidth) {
|
|
34690
|
+
position += sheetData.sheetFormat.defaultColWidth;
|
|
34691
|
+
}
|
|
34692
|
+
else {
|
|
34693
|
+
position += EXCEL_DEFAULT_COL_WIDTH;
|
|
34694
|
+
}
|
|
34695
|
+
}
|
|
34696
|
+
return position / WIDTH_FACTOR;
|
|
34697
|
+
}
|
|
34698
|
+
/**
|
|
34699
|
+
* Get the position of the start of a row in Excel (in px).
|
|
34700
|
+
*/
|
|
34701
|
+
function getRowPosition(rowIndex, sheetData) {
|
|
34702
|
+
let position = 0;
|
|
34703
|
+
for (let i = 0; i < rowIndex; i++) {
|
|
34704
|
+
const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
|
|
34705
|
+
if (rowAtIndex?.height) {
|
|
34706
|
+
position += rowAtIndex.height;
|
|
34707
|
+
}
|
|
34708
|
+
else if (sheetData.sheetFormat?.defaultRowHeight) {
|
|
34709
|
+
position += sheetData.sheetFormat.defaultRowHeight;
|
|
34710
|
+
}
|
|
34711
|
+
else {
|
|
34712
|
+
position += EXCEL_DEFAULT_ROW_HEIGHT;
|
|
34713
|
+
}
|
|
34714
|
+
}
|
|
34715
|
+
return position / HEIGHT_FACTOR;
|
|
34716
|
+
}
|
|
34717
|
+
/**
|
|
34718
|
+
* Convert the o-spreadsheet data validation decimal
|
|
34719
|
+
* criterion type to the corresponding excel operator.
|
|
34720
|
+
*/
|
|
34721
|
+
function convertDecimalCriterionTypeToExcelOperator(operator) {
|
|
34722
|
+
return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
|
|
34723
|
+
}
|
|
34724
|
+
/**
|
|
34725
|
+
* Convert the o-spreadsheet data validation date
|
|
34726
|
+
* criterion type to the corresponding excel operator.
|
|
34727
|
+
*/
|
|
34728
|
+
function convertDateCriterionTypeToExcelOperator(operator) {
|
|
34729
|
+
return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
|
|
34730
|
+
}
|
|
34731
|
+
|
|
34403
34732
|
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;
|
|
34404
34733
|
/**
|
|
34405
34734
|
* Convert excel format to o_spreadsheet format
|
|
@@ -34499,6 +34828,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34499
34828
|
align: styleStruct.alignment?.horizontal
|
|
34500
34829
|
? H_ALIGNMENT_CONVERSION_MAP[styleStruct.alignment.horizontal]
|
|
34501
34830
|
: undefined,
|
|
34831
|
+
rotation: styleStruct.alignment?.textRotation
|
|
34832
|
+
? rotationFromXLSX(styleStruct.alignment.textRotation)
|
|
34833
|
+
: undefined,
|
|
34502
34834
|
// 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
|
|
34503
34835
|
fillColor: styleStruct.fillStyle?.patternType === "solid"
|
|
34504
34836
|
? convertColor(styleStruct.fillStyle?.fgColor)
|
|
@@ -34798,303 +35130,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34798
35130
|
}
|
|
34799
35131
|
}
|
|
34800
35132
|
|
|
34801
|
-
// -------------------------------------
|
|
34802
|
-
// CF HELPERS
|
|
34803
|
-
// -------------------------------------
|
|
34804
|
-
/**
|
|
34805
|
-
* Convert the conditional formatting o-spreadsheet operator to
|
|
34806
|
-
* the corresponding excel operator.
|
|
34807
|
-
* */
|
|
34808
|
-
function convertOperator(operator) {
|
|
34809
|
-
switch (operator) {
|
|
34810
|
-
case "isNotEmpty":
|
|
34811
|
-
return "notContainsBlanks";
|
|
34812
|
-
case "isEmpty":
|
|
34813
|
-
return "containsBlanks";
|
|
34814
|
-
case "notContainsText":
|
|
34815
|
-
return "notContainsBlanks";
|
|
34816
|
-
case "containsText":
|
|
34817
|
-
return "containsText";
|
|
34818
|
-
case "beginsWithText":
|
|
34819
|
-
return "beginsWith";
|
|
34820
|
-
case "endsWithText":
|
|
34821
|
-
return "endsWith";
|
|
34822
|
-
case "isGreaterThan":
|
|
34823
|
-
return "greaterThan";
|
|
34824
|
-
case "isGreaterOrEqualTo":
|
|
34825
|
-
return "greaterThanOrEqual";
|
|
34826
|
-
case "isLessThan":
|
|
34827
|
-
return "lessThan";
|
|
34828
|
-
case "isLessOrEqualTo":
|
|
34829
|
-
return "lessThanOrEqual";
|
|
34830
|
-
case "isBetween":
|
|
34831
|
-
return "between";
|
|
34832
|
-
case "isNotBetween":
|
|
34833
|
-
return "notBetween";
|
|
34834
|
-
case "isEqual":
|
|
34835
|
-
return "equal";
|
|
34836
|
-
case "isNotEqual":
|
|
34837
|
-
return "notEqual";
|
|
34838
|
-
case "customFormula":
|
|
34839
|
-
return "";
|
|
34840
|
-
case "dateIs":
|
|
34841
|
-
return "";
|
|
34842
|
-
case "dateIsBefore":
|
|
34843
|
-
return "lessThan";
|
|
34844
|
-
case "dateIsAfter":
|
|
34845
|
-
return "greaterThan";
|
|
34846
|
-
case "dateIsOnOrAfter":
|
|
34847
|
-
return "greaterThanOrEqual";
|
|
34848
|
-
case "dateIsOnOrBefore":
|
|
34849
|
-
return "lessThanOrEqual";
|
|
34850
|
-
}
|
|
34851
|
-
}
|
|
34852
|
-
// -------------------------------------
|
|
34853
|
-
// WORKSHEET HELPERS
|
|
34854
|
-
// -------------------------------------
|
|
34855
|
-
function getCellType(value) {
|
|
34856
|
-
switch (typeof value) {
|
|
34857
|
-
case "boolean":
|
|
34858
|
-
return "b";
|
|
34859
|
-
case "string":
|
|
34860
|
-
return "str";
|
|
34861
|
-
case "number":
|
|
34862
|
-
return "n";
|
|
34863
|
-
default:
|
|
34864
|
-
return undefined;
|
|
34865
|
-
}
|
|
34866
|
-
}
|
|
34867
|
-
function convertHeightToExcel(height) {
|
|
34868
|
-
return Math.round(HEIGHT_FACTOR * height * 100) / 100;
|
|
34869
|
-
}
|
|
34870
|
-
function convertWidthToExcel(width) {
|
|
34871
|
-
return Math.round(WIDTH_FACTOR * width * 100) / 100;
|
|
34872
|
-
}
|
|
34873
|
-
function convertHeightFromExcel(height) {
|
|
34874
|
-
if (!height)
|
|
34875
|
-
return height;
|
|
34876
|
-
return Math.round((height / HEIGHT_FACTOR) * 100) / 100;
|
|
34877
|
-
}
|
|
34878
|
-
function convertWidthFromExcel(width) {
|
|
34879
|
-
if (!width)
|
|
34880
|
-
return width;
|
|
34881
|
-
return Math.round((width / WIDTH_FACTOR) * 100) / 100;
|
|
34882
|
-
}
|
|
34883
|
-
function extractStyle(data, content, styleId, formatId, borderId) {
|
|
34884
|
-
const style = styleId ? data.styles[styleId] : {};
|
|
34885
|
-
const format = formatId ? data.formats[formatId] : undefined;
|
|
34886
|
-
const styles = {
|
|
34887
|
-
font: {
|
|
34888
|
-
size: style?.fontSize || DEFAULT_FONT_SIZE,
|
|
34889
|
-
color: { rgb: style?.textColor ? style.textColor : "000000" },
|
|
34890
|
-
family: 2,
|
|
34891
|
-
name: "Arial",
|
|
34892
|
-
},
|
|
34893
|
-
fill: style?.fillColor
|
|
34894
|
-
? {
|
|
34895
|
-
fgColor: { rgb: style.fillColor },
|
|
34896
|
-
}
|
|
34897
|
-
: { reservedAttribute: "none" },
|
|
34898
|
-
numFmt: format ? { format: format, id: 0 /* id not used for export */ } : undefined,
|
|
34899
|
-
border: borderId || 0,
|
|
34900
|
-
alignment: {
|
|
34901
|
-
horizontal: style.align,
|
|
34902
|
-
vertical: style.verticalAlign
|
|
34903
|
-
? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
|
|
34904
|
-
: undefined,
|
|
34905
|
-
wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
|
|
34906
|
-
},
|
|
34907
|
-
};
|
|
34908
|
-
styles.font["strike"] = !!style?.strikethrough || undefined;
|
|
34909
|
-
styles.font["underline"] = !!style?.underline || undefined;
|
|
34910
|
-
styles.font["bold"] = !!style?.bold || undefined;
|
|
34911
|
-
styles.font["italic"] = !!style?.italic || undefined;
|
|
34912
|
-
return styles;
|
|
34913
|
-
}
|
|
34914
|
-
function normalizeStyle(construct, styles) {
|
|
34915
|
-
// Normalize this
|
|
34916
|
-
const numFmtId = convertFormat(styles["numFmt"], construct.numFmts);
|
|
34917
|
-
const style = {
|
|
34918
|
-
fontId: pushElement(styles.font, construct.fonts),
|
|
34919
|
-
fillId: pushElement(styles.fill, construct.fills),
|
|
34920
|
-
borderId: styles.border,
|
|
34921
|
-
numFmtId,
|
|
34922
|
-
alignment: {
|
|
34923
|
-
vertical: styles.alignment.vertical,
|
|
34924
|
-
horizontal: styles.alignment.horizontal,
|
|
34925
|
-
wrapText: styles.alignment.wrapText,
|
|
34926
|
-
},
|
|
34927
|
-
};
|
|
34928
|
-
return pushElement(style, construct.styles);
|
|
34929
|
-
}
|
|
34930
|
-
function convertFormat(format, numFmtStructure) {
|
|
34931
|
-
if (!format) {
|
|
34932
|
-
return 0;
|
|
34933
|
-
}
|
|
34934
|
-
let formatId = XLSX_FORMAT_MAP[format.format];
|
|
34935
|
-
if (!formatId) {
|
|
34936
|
-
formatId = pushElement(format, numFmtStructure) + FIRST_NUMFMT_ID;
|
|
34937
|
-
}
|
|
34938
|
-
return formatId;
|
|
34939
|
-
}
|
|
34940
|
-
/**
|
|
34941
|
-
* Add a relation to the given file and return its id.
|
|
34942
|
-
*/
|
|
34943
|
-
function addRelsToFile(relsFiles, path, rel) {
|
|
34944
|
-
const relsFile = relsFiles.find((file) => file.path === path);
|
|
34945
|
-
// the id is a one-based int casted as string
|
|
34946
|
-
let id;
|
|
34947
|
-
if (!relsFile) {
|
|
34948
|
-
id = "rId1";
|
|
34949
|
-
relsFiles.push({ path, rels: [{ ...rel, id }] });
|
|
34950
|
-
}
|
|
34951
|
-
else {
|
|
34952
|
-
id = `rId${(relsFile.rels.length + 1).toString()}`;
|
|
34953
|
-
relsFile.rels.push({
|
|
34954
|
-
...rel,
|
|
34955
|
-
id,
|
|
34956
|
-
});
|
|
34957
|
-
}
|
|
34958
|
-
return id;
|
|
34959
|
-
}
|
|
34960
|
-
const globalReverseLookup = new WeakMap();
|
|
34961
|
-
function pushElement(property, propertyList) {
|
|
34962
|
-
let reverseLookup = globalReverseLookup.get(propertyList);
|
|
34963
|
-
if (!reverseLookup) {
|
|
34964
|
-
reverseLookup = new Map();
|
|
34965
|
-
for (let i = 0; i < propertyList.length; i++) {
|
|
34966
|
-
const canonical = getCanonicalRepresentation(propertyList[i]);
|
|
34967
|
-
reverseLookup.set(canonical, i);
|
|
34968
|
-
}
|
|
34969
|
-
globalReverseLookup.set(propertyList, reverseLookup);
|
|
34970
|
-
}
|
|
34971
|
-
const canonical = getCanonicalRepresentation(property);
|
|
34972
|
-
if (reverseLookup.has(canonical)) {
|
|
34973
|
-
return reverseLookup.get(canonical);
|
|
34974
|
-
}
|
|
34975
|
-
const maxId = propertyList.length;
|
|
34976
|
-
propertyList.push(property);
|
|
34977
|
-
reverseLookup.set(canonical, maxId);
|
|
34978
|
-
return maxId;
|
|
34979
|
-
}
|
|
34980
|
-
/**
|
|
34981
|
-
* Convert a chart o-spreadsheet id to a xlsx id which
|
|
34982
|
-
* are unsigned integers (starting from 1).
|
|
34983
|
-
*/
|
|
34984
|
-
function convertChartId(chartId, construct) {
|
|
34985
|
-
const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
|
|
34986
|
-
if (xlsxId === -1) {
|
|
34987
|
-
construct.chartIds.push(chartId);
|
|
34988
|
-
return construct.chartIds.length;
|
|
34989
|
-
}
|
|
34990
|
-
return xlsxId + 1;
|
|
34991
|
-
}
|
|
34992
|
-
const imageIds = [];
|
|
34993
|
-
/**
|
|
34994
|
-
* Convert a image o-spreadsheet id to a xlsx id which
|
|
34995
|
-
* are unsigned integers (starting from 1).
|
|
34996
|
-
*/
|
|
34997
|
-
function convertImageId(imageId) {
|
|
34998
|
-
const xlsxId = imageIds.findIndex((id) => id === imageId);
|
|
34999
|
-
if (xlsxId === -1) {
|
|
35000
|
-
imageIds.push(imageId);
|
|
35001
|
-
return imageIds.length;
|
|
35002
|
-
}
|
|
35003
|
-
return xlsxId + 1;
|
|
35004
|
-
}
|
|
35005
|
-
/**
|
|
35006
|
-
* Convert a value expressed in dot to EMU.
|
|
35007
|
-
* EMU = English Metrical Unit
|
|
35008
|
-
* There are 914400 EMU per inch.
|
|
35009
|
-
*
|
|
35010
|
-
* /!\ A value expressed in EMU cannot be fractional.
|
|
35011
|
-
* See https://docs.microsoft.com/en-us/windows/win32/vml/msdn-online-vml-units#other-units-of-measurement
|
|
35012
|
-
*/
|
|
35013
|
-
function convertDotValueToEMU(value) {
|
|
35014
|
-
const DPI = 96;
|
|
35015
|
-
return Math.round((value * 914400) / DPI);
|
|
35016
|
-
}
|
|
35017
|
-
function getRangeSize(reference, defaultSheetIndex, data) {
|
|
35018
|
-
let xc = reference;
|
|
35019
|
-
let sheetName = undefined;
|
|
35020
|
-
({ xc, sheetName } = splitReference(reference));
|
|
35021
|
-
let rangeSheetIndex;
|
|
35022
|
-
if (sheetName) {
|
|
35023
|
-
const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
|
|
35024
|
-
if (index < 0) {
|
|
35025
|
-
throw new Error("Unable to find a sheet with the name " + sheetName);
|
|
35026
|
-
}
|
|
35027
|
-
rangeSheetIndex = index;
|
|
35028
|
-
}
|
|
35029
|
-
else {
|
|
35030
|
-
rangeSheetIndex = Number(defaultSheetIndex);
|
|
35031
|
-
}
|
|
35032
|
-
const zone = toUnboundedZone(xc);
|
|
35033
|
-
if (zone.right === undefined) {
|
|
35034
|
-
zone.right = data.sheets[rangeSheetIndex].colNumber;
|
|
35035
|
-
}
|
|
35036
|
-
if (zone.bottom === undefined) {
|
|
35037
|
-
zone.bottom = data.sheets[rangeSheetIndex].rowNumber;
|
|
35038
|
-
}
|
|
35039
|
-
return (zone.right - zone.left + 1) * (zone.bottom - zone.top + 1);
|
|
35040
|
-
}
|
|
35041
|
-
function convertEMUToDotValue(value) {
|
|
35042
|
-
const DPI = 96;
|
|
35043
|
-
return Math.round((value * DPI) / 914400);
|
|
35044
|
-
}
|
|
35045
|
-
/**
|
|
35046
|
-
* Get the position of the start of a column in Excel (in px).
|
|
35047
|
-
*/
|
|
35048
|
-
function getColPosition(colIndex, sheetData) {
|
|
35049
|
-
let position = 0;
|
|
35050
|
-
for (let i = 0; i < colIndex; i++) {
|
|
35051
|
-
const colAtIndex = sheetData.cols.find((col) => i >= col.min && i <= col.max);
|
|
35052
|
-
if (colAtIndex?.width) {
|
|
35053
|
-
position += colAtIndex.width;
|
|
35054
|
-
}
|
|
35055
|
-
else if (sheetData.sheetFormat?.defaultColWidth) {
|
|
35056
|
-
position += sheetData.sheetFormat.defaultColWidth;
|
|
35057
|
-
}
|
|
35058
|
-
else {
|
|
35059
|
-
position += EXCEL_DEFAULT_COL_WIDTH;
|
|
35060
|
-
}
|
|
35061
|
-
}
|
|
35062
|
-
return position / WIDTH_FACTOR;
|
|
35063
|
-
}
|
|
35064
|
-
/**
|
|
35065
|
-
* Get the position of the start of a row in Excel (in px).
|
|
35066
|
-
*/
|
|
35067
|
-
function getRowPosition(rowIndex, sheetData) {
|
|
35068
|
-
let position = 0;
|
|
35069
|
-
for (let i = 0; i < rowIndex; i++) {
|
|
35070
|
-
const rowAtIndex = sheetData.rows.find((row) => row.index - 1 === i);
|
|
35071
|
-
if (rowAtIndex?.height) {
|
|
35072
|
-
position += rowAtIndex.height;
|
|
35073
|
-
}
|
|
35074
|
-
else if (sheetData.sheetFormat?.defaultRowHeight) {
|
|
35075
|
-
position += sheetData.sheetFormat.defaultRowHeight;
|
|
35076
|
-
}
|
|
35077
|
-
else {
|
|
35078
|
-
position += EXCEL_DEFAULT_ROW_HEIGHT;
|
|
35079
|
-
}
|
|
35080
|
-
}
|
|
35081
|
-
return position / HEIGHT_FACTOR;
|
|
35082
|
-
}
|
|
35083
|
-
/**
|
|
35084
|
-
* Convert the o-spreadsheet data validation decimal
|
|
35085
|
-
* criterion type to the corresponding excel operator.
|
|
35086
|
-
*/
|
|
35087
|
-
function convertDecimalCriterionTypeToExcelOperator(operator) {
|
|
35088
|
-
return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
|
|
35089
|
-
}
|
|
35090
|
-
/**
|
|
35091
|
-
* Convert the o-spreadsheet data validation date
|
|
35092
|
-
* criterion type to the corresponding excel operator.
|
|
35093
|
-
*/
|
|
35094
|
-
function convertDateCriterionTypeToExcelOperator(operator) {
|
|
35095
|
-
return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
|
|
35096
|
-
}
|
|
35097
|
-
|
|
35098
35133
|
function convertFigures(sheetData) {
|
|
35099
35134
|
let id = 1;
|
|
35100
35135
|
return sheetData.figures
|
|
@@ -44675,6 +44710,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44675
44710
|
"getMeasureCompiledFormula",
|
|
44676
44711
|
"getPivotName",
|
|
44677
44712
|
"isExistingPivot",
|
|
44713
|
+
"getMeasureFullDependencies",
|
|
44678
44714
|
];
|
|
44679
44715
|
nextFormulaId = 1;
|
|
44680
44716
|
pivots = {};
|
|
@@ -44760,7 +44796,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44760
44796
|
}
|
|
44761
44797
|
case "UPDATE_PIVOT": {
|
|
44762
44798
|
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
44763
|
-
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
44799
|
+
this.compileCalculatedMeasures(cmd.pivotId, cmd.pivot.measures);
|
|
44764
44800
|
break;
|
|
44765
44801
|
}
|
|
44766
44802
|
}
|
|
@@ -44778,9 +44814,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44778
44814
|
this.history.update("pivots", pivotId, "definition", newDefinition);
|
|
44779
44815
|
}
|
|
44780
44816
|
}
|
|
44781
|
-
for (const
|
|
44782
|
-
for (const
|
|
44783
|
-
const
|
|
44817
|
+
for (const pivotId in this.compiledMeasureFormulas) {
|
|
44818
|
+
for (const measureId in this.compiledMeasureFormulas[pivotId]) {
|
|
44819
|
+
const measure = this.pivots[pivotId]?.definition.measures.find((m) => m.id === measureId);
|
|
44820
|
+
if (!measure || !measure.computedBy) {
|
|
44821
|
+
continue;
|
|
44822
|
+
}
|
|
44823
|
+
const sheetId = measure.computedBy.sheetId;
|
|
44824
|
+
const compiledFormula = this.compiledMeasureFormulas[pivotId][measureId].formula;
|
|
44784
44825
|
const newDependencies = [];
|
|
44785
44826
|
for (const range of compiledFormula.dependencies) {
|
|
44786
44827
|
const change = applyChange(range);
|
|
@@ -44792,8 +44833,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44792
44833
|
}
|
|
44793
44834
|
}
|
|
44794
44835
|
const newFormulaString = this.getters.getFormulaString(sheetId, compiledFormula.tokens, newDependencies);
|
|
44795
|
-
|
|
44796
|
-
|
|
44836
|
+
const oldFormulaString = measure.computedBy.formula;
|
|
44837
|
+
if (newFormulaString !== oldFormulaString) {
|
|
44838
|
+
this.replaceMeasureFormula(pivotId, measure, newFormulaString);
|
|
44797
44839
|
}
|
|
44798
44840
|
}
|
|
44799
44841
|
}
|
|
@@ -44831,30 +44873,59 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44831
44873
|
isExistingPivot(pivotId) {
|
|
44832
44874
|
return pivotId in this.pivots;
|
|
44833
44875
|
}
|
|
44834
|
-
getMeasureCompiledFormula(measure) {
|
|
44876
|
+
getMeasureCompiledFormula(pivotId, measure) {
|
|
44877
|
+
if (!measure.computedBy) {
|
|
44878
|
+
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
44879
|
+
}
|
|
44880
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].formula;
|
|
44881
|
+
}
|
|
44882
|
+
getMeasureFullDependencies(pivotId, measure) {
|
|
44835
44883
|
if (!measure.computedBy) {
|
|
44836
44884
|
throw new Error(`Measure ${measure.fieldName} is not computed by formula`);
|
|
44837
44885
|
}
|
|
44838
|
-
|
|
44839
|
-
return this.compiledMeasureFormulas[sheetId][measure.computedBy.formula];
|
|
44886
|
+
return this.compiledMeasureFormulas[pivotId][measure.id].dependencies;
|
|
44840
44887
|
}
|
|
44841
44888
|
// -------------------------------------------------------------------------
|
|
44842
44889
|
// Private
|
|
44843
44890
|
// -------------------------------------------------------------------------
|
|
44844
44891
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
44845
44892
|
this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
|
|
44846
|
-
this.compileCalculatedMeasures(pivot.measures);
|
|
44893
|
+
this.compileCalculatedMeasures(pivotId, pivot.measures);
|
|
44847
44894
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
44848
44895
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
44849
44896
|
}
|
|
44850
|
-
compileCalculatedMeasures(measures) {
|
|
44897
|
+
compileCalculatedMeasures(pivotId, measures) {
|
|
44851
44898
|
for (const measure of measures) {
|
|
44852
44899
|
if (measure.computedBy) {
|
|
44853
|
-
const sheetId = measure.computedBy.sheetId;
|
|
44854
44900
|
const compiledFormula = this.compileMeasureFormula(measure.computedBy.sheetId, measure.computedBy.formula);
|
|
44855
|
-
this.history.update("compiledMeasureFormulas",
|
|
44901
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "formula", compiledFormula);
|
|
44902
|
+
}
|
|
44903
|
+
}
|
|
44904
|
+
for (const measure of measures) {
|
|
44905
|
+
if (measure.computedBy) {
|
|
44906
|
+
const dependencies = this.computeMeasureFullDependencies(pivotId, measure);
|
|
44907
|
+
this.history.update("compiledMeasureFormulas", pivotId, measure.id, "dependencies", dependencies);
|
|
44908
|
+
}
|
|
44909
|
+
}
|
|
44910
|
+
}
|
|
44911
|
+
computeMeasureFullDependencies(pivotId, measure, exploredMeasures = new Set()) {
|
|
44912
|
+
const rangeDependencies = [];
|
|
44913
|
+
const definition = this.getPivotCoreDefinition(pivotId);
|
|
44914
|
+
const formula = this.getMeasureCompiledFormula(pivotId, measure);
|
|
44915
|
+
exploredMeasures.add(measure.id);
|
|
44916
|
+
for (const token of formula.tokens) {
|
|
44917
|
+
if (token.type !== "SYMBOL") {
|
|
44918
|
+
continue;
|
|
44919
|
+
}
|
|
44920
|
+
const otherMeasure = definition.measures.find((measureCandidate) => getCanonicalSymbolName(measureCandidate.id) === token.value &&
|
|
44921
|
+
measure.id !== measureCandidate.id);
|
|
44922
|
+
if (!otherMeasure || exploredMeasures.has(otherMeasure.id) || !otherMeasure.computedBy) {
|
|
44923
|
+
continue;
|
|
44856
44924
|
}
|
|
44925
|
+
rangeDependencies.push(...this.computeMeasureFullDependencies(pivotId, otherMeasure, exploredMeasures));
|
|
44857
44926
|
}
|
|
44927
|
+
rangeDependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
44928
|
+
return rangeDependencies;
|
|
44858
44929
|
}
|
|
44859
44930
|
insertPivot(position, formulaId, table) {
|
|
44860
44931
|
this.resizeSheet(position.sheetId, position, table);
|
|
@@ -44914,21 +44985,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44914
44985
|
dependencies: rangeDependencies,
|
|
44915
44986
|
};
|
|
44916
44987
|
}
|
|
44917
|
-
replaceMeasureFormula(
|
|
44918
|
-
|
|
44919
|
-
|
|
44920
|
-
|
|
44921
|
-
const pivot = this.pivots[pivotId];
|
|
44922
|
-
if (!pivot) {
|
|
44923
|
-
continue;
|
|
44924
|
-
}
|
|
44925
|
-
for (const measure of pivot.definition.measures) {
|
|
44926
|
-
if (measure.computedBy?.formula === formulaString) {
|
|
44927
|
-
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
44928
|
-
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", { formula: newFormulaString, sheetId });
|
|
44929
|
-
}
|
|
44930
|
-
}
|
|
44988
|
+
replaceMeasureFormula(pivotId, measure, newFormulaString) {
|
|
44989
|
+
const pivot = this.pivots[pivotId];
|
|
44990
|
+
if (!pivot) {
|
|
44991
|
+
return;
|
|
44931
44992
|
}
|
|
44993
|
+
const measureIndex = pivot.definition.measures.indexOf(measure);
|
|
44994
|
+
this.history.update("pivots", pivotId, "definition", "measures", measureIndex, "computedBy", {
|
|
44995
|
+
formula: newFormulaString,
|
|
44996
|
+
sheetId: measure.computedBy.sheetId,
|
|
44997
|
+
});
|
|
44998
|
+
this.compileCalculatedMeasures(pivotId, pivot.definition.measures);
|
|
44932
44999
|
}
|
|
44933
45000
|
checkSortedColumnInMeasures(definition) {
|
|
44934
45001
|
const measures = definition.measures.map((measure) => measure.id);
|
|
@@ -45989,7 +46056,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45989
46056
|
case "UPDATE_CELL":
|
|
45990
46057
|
if (cmd.style !== undefined) {
|
|
45991
46058
|
if (cmd.style !== null) {
|
|
45992
|
-
this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style);
|
|
46059
|
+
this.setStyles(cmd.sheetId, [positionToZone(cmd)], cmd.style, { force: true });
|
|
45993
46060
|
}
|
|
45994
46061
|
else {
|
|
45995
46062
|
this.clearStyle(cmd.sheetId, [positionToZone(cmd)]);
|
|
@@ -46057,16 +46124,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46057
46124
|
}
|
|
46058
46125
|
}
|
|
46059
46126
|
styleIsDefault(style) {
|
|
46060
|
-
|
|
46127
|
+
for (const key in style) {
|
|
46128
|
+
if (DEFAULT_STYLE_NO_ALIGN[key] !== style[key]) {
|
|
46129
|
+
return false;
|
|
46130
|
+
}
|
|
46131
|
+
}
|
|
46132
|
+
return true;
|
|
46061
46133
|
}
|
|
46062
46134
|
removeDefaultStyleValues(style) {
|
|
46063
46135
|
const cleanedStyle = { ...style };
|
|
46064
|
-
for (const property in
|
|
46065
|
-
if (cleanedStyle[property] ===
|
|
46136
|
+
for (const property in style) {
|
|
46137
|
+
if (cleanedStyle[property] === undefined ||
|
|
46138
|
+
cleanedStyle[property] === DEFAULT_STYLE_NO_ALIGN[property]) {
|
|
46066
46139
|
delete cleanedStyle[property];
|
|
46067
46140
|
}
|
|
46068
46141
|
}
|
|
46069
|
-
return cleanedStyle;
|
|
46142
|
+
return Object.keys(cleanedStyle).length > 0 ? cleanedStyle : undefined;
|
|
46070
46143
|
}
|
|
46071
46144
|
onMerge(sheetId, zone) {
|
|
46072
46145
|
this.setStyle(sheetId, zone, this.getCellStyle({ sheetId, col: zone.left, row: zone.top }), {
|
|
@@ -46102,13 +46175,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46102
46175
|
}
|
|
46103
46176
|
editingZone = recomputeZones(editingZone, [inter]);
|
|
46104
46177
|
}
|
|
46178
|
+
style = this.removeDefaultStyleValues(style);
|
|
46105
46179
|
if (style) {
|
|
46106
|
-
const newStyle = this.removeDefaultStyleValues(style);
|
|
46107
46180
|
styles.push(...editingZone.map((zone) => {
|
|
46108
|
-
return { zone, style
|
|
46181
|
+
return { zone, style };
|
|
46109
46182
|
}));
|
|
46110
46183
|
}
|
|
46111
|
-
this.history.update("styles", sheetId, styles
|
|
46184
|
+
this.history.update("styles", sheetId, styles);
|
|
46112
46185
|
}
|
|
46113
46186
|
clearStyle(sheetId, zones) {
|
|
46114
46187
|
this.setStyles(sheetId, zones, undefined, { force: true });
|
|
@@ -52037,14 +52110,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52037
52110
|
function withPivotPresentationLayer (PivotClass) {
|
|
52038
52111
|
class PivotPresentationLayer extends PivotClass {
|
|
52039
52112
|
getters;
|
|
52113
|
+
pivotId;
|
|
52040
52114
|
cache = {};
|
|
52041
52115
|
rankAsc = {};
|
|
52042
52116
|
rankDesc = {};
|
|
52043
52117
|
runningTotal = {};
|
|
52044
52118
|
runningTotalInPercent = {};
|
|
52045
|
-
constructor(custom, params) {
|
|
52119
|
+
constructor(pivotId, custom, params) {
|
|
52046
52120
|
super(custom, params);
|
|
52047
52121
|
this.getters = params.getters;
|
|
52122
|
+
this.pivotId = pivotId;
|
|
52048
52123
|
}
|
|
52049
52124
|
markAsDirtyForEvaluation() {
|
|
52050
52125
|
this.cache = {};
|
|
@@ -52094,7 +52169,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52094
52169
|
return handleError(error, measure.aggregator.toUpperCase());
|
|
52095
52170
|
}
|
|
52096
52171
|
}
|
|
52097
|
-
const formula = this.getters.getMeasureCompiledFormula(measure);
|
|
52172
|
+
const formula = this.getters.getMeasureCompiledFormula(this.pivotId, measure);
|
|
52098
52173
|
const getSymbolValue = (symbolName) => {
|
|
52099
52174
|
const { columns, rows } = this.definition;
|
|
52100
52175
|
if (columns.find((col) => col.nameWithGranularity === symbolName)) {
|
|
@@ -52841,7 +52916,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52841
52916
|
const definition = deepCopy(this.getters.getPivotCoreDefinition(pivotId));
|
|
52842
52917
|
if (!(pivotId in this.pivots)) {
|
|
52843
52918
|
const Pivot = withPivotPresentationLayer(pivotRegistry.get(definition.type).ui);
|
|
52844
|
-
this.pivots[pivotId] = new Pivot(this.custom, { definition, getters: this.getters });
|
|
52919
|
+
this.pivots[pivotId] = new Pivot(pivotId, this.custom, { definition, getters: this.getters });
|
|
52845
52920
|
}
|
|
52846
52921
|
else if (recreate) {
|
|
52847
52922
|
this.pivots[pivotId].onDefinitionChange(definition);
|
|
@@ -61939,6 +62014,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61939
62014
|
if (style.alignment && style.alignment.wrapText) {
|
|
61940
62015
|
alignAttrs.push(["wrapText", "1"]);
|
|
61941
62016
|
}
|
|
62017
|
+
if (style.alignment && style.alignment.textRotation) {
|
|
62018
|
+
alignAttrs.push(["textRotation", style.alignment.textRotation]);
|
|
62019
|
+
}
|
|
61942
62020
|
if (alignAttrs.length > 0) {
|
|
61943
62021
|
attributes.push(["applyAlignment", "1"]); // for Libre Office
|
|
61944
62022
|
styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
|
|
@@ -72239,7 +72317,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72239
72317
|
}
|
|
72240
72318
|
captureSelection(zone, col, row) {
|
|
72241
72319
|
this.model.selection.capture(this, {
|
|
72242
|
-
cell: { col: col ?? zone.left, row: row ?? zone.
|
|
72320
|
+
cell: { col: col ?? zone.left, row: row ?? zone.top },
|
|
72243
72321
|
zone,
|
|
72244
72322
|
}, {
|
|
72245
72323
|
handleEvent: this.handleEvent.bind(this),
|
|
@@ -77962,35 +78040,46 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77962
78040
|
name: _t("Rotation"),
|
|
77963
78041
|
icon: (env) => getRotationIcon(env),
|
|
77964
78042
|
};
|
|
78043
|
+
function setRotation(env, rotation) {
|
|
78044
|
+
rotation = Math.trunc(rotation / ROTATION_EPSILON) * ROTATION_EPSILON;
|
|
78045
|
+
setStyle(env, { rotation });
|
|
78046
|
+
}
|
|
78047
|
+
function currentRotationEqual(env, rotation) {
|
|
78048
|
+
const current = env.model.getters.getCurrentStyle().rotation;
|
|
78049
|
+
if (current === undefined) {
|
|
78050
|
+
return rotation === 0;
|
|
78051
|
+
}
|
|
78052
|
+
return Math.abs(current - rotation) < ROTATION_EPSILON;
|
|
78053
|
+
}
|
|
77965
78054
|
const formatNoRotation = {
|
|
77966
78055
|
name: _t("No rotation"),
|
|
77967
78056
|
execute: (env) => setStyle(env, { rotation: 0 }),
|
|
77968
78057
|
icon: "o-spreadsheet-Icon.ROTATION-0",
|
|
77969
|
-
isActive: (env) => env
|
|
78058
|
+
isActive: (env) => currentRotationEqual(env, 0),
|
|
77970
78059
|
};
|
|
77971
78060
|
const formatRotation45 = {
|
|
77972
78061
|
name: _t("45° rotation"),
|
|
77973
|
-
execute: (env) =>
|
|
78062
|
+
execute: (env) => setRotation(env, Math.PI / 4),
|
|
77974
78063
|
icon: "o-spreadsheet-Icon.ROTATION-45",
|
|
77975
|
-
isActive: (env) => env
|
|
78064
|
+
isActive: (env) => currentRotationEqual(env, Math.PI / 4),
|
|
77976
78065
|
};
|
|
77977
78066
|
const formatRotation90 = {
|
|
77978
78067
|
name: _t("90° rotation"),
|
|
77979
|
-
execute: (env) =>
|
|
78068
|
+
execute: (env) => setRotation(env, Math.PI / 2),
|
|
77980
78069
|
icon: "o-spreadsheet-Icon.ROTATION-90",
|
|
77981
|
-
isActive: (env) => env
|
|
78070
|
+
isActive: (env) => currentRotationEqual(env, Math.PI / 2),
|
|
77982
78071
|
};
|
|
77983
78072
|
const formatRotation270 = {
|
|
77984
78073
|
name: _t("-90° rotation"),
|
|
77985
|
-
execute: (env) =>
|
|
78074
|
+
execute: (env) => setRotation(env, -Math.PI / 2),
|
|
77986
78075
|
icon: "o-spreadsheet-Icon.ROTATION-270",
|
|
77987
|
-
isActive: (env) => env
|
|
78076
|
+
isActive: (env) => currentRotationEqual(env, -Math.PI / 2),
|
|
77988
78077
|
};
|
|
77989
78078
|
const formatRotation315 = {
|
|
77990
78079
|
name: _t("-45° rotation"),
|
|
77991
|
-
execute: (env) =>
|
|
78080
|
+
execute: (env) => setRotation(env, -Math.PI / 4),
|
|
77992
78081
|
icon: "o-spreadsheet-Icon.ROTATION-315",
|
|
77993
|
-
isActive: (env) => env
|
|
78082
|
+
isActive: (env) => currentRotationEqual(env, -Math.PI / 4),
|
|
77994
78083
|
};
|
|
77995
78084
|
const formatStrikethrough = {
|
|
77996
78085
|
name: _t("Strikethrough"),
|
|
@@ -78156,10 +78245,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78156
78245
|
}
|
|
78157
78246
|
return DEFAULT_WRAPPING_MODE;
|
|
78158
78247
|
}
|
|
78159
|
-
function getRotation(env) {
|
|
78160
|
-
const style = env.model.getters.getCurrentStyle();
|
|
78161
|
-
return style.rotation ?? 0;
|
|
78162
|
-
}
|
|
78163
78248
|
function getHorizontalAlignmentIcon(env) {
|
|
78164
78249
|
const horizontalAlign = getHorizontalAlign(env);
|
|
78165
78250
|
switch (horizontalAlign) {
|
|
@@ -78194,19 +78279,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78194
78279
|
}
|
|
78195
78280
|
}
|
|
78196
78281
|
function getRotationIcon(env) {
|
|
78197
|
-
|
|
78198
|
-
|
|
78199
|
-
|
|
78200
|
-
|
|
78201
|
-
|
|
78202
|
-
|
|
78203
|
-
|
|
78204
|
-
|
|
78205
|
-
case -Math.PI / 4:
|
|
78206
|
-
return "o-spreadsheet-Icon.ROTATION-315";
|
|
78207
|
-
default:
|
|
78208
|
-
return "o-spreadsheet-Icon.ROTATION-0";
|
|
78282
|
+
if (currentRotationEqual(env, Math.PI / 2)) {
|
|
78283
|
+
return "o-spreadsheet-Icon.ROTATION-90";
|
|
78284
|
+
}
|
|
78285
|
+
else if (currentRotationEqual(env, -Math.PI / 2)) {
|
|
78286
|
+
return "o-spreadsheet-Icon.ROTATION-270";
|
|
78287
|
+
}
|
|
78288
|
+
else if (currentRotationEqual(env, Math.PI / 4)) {
|
|
78289
|
+
return "o-spreadsheet-Icon.ROTATION-45";
|
|
78209
78290
|
}
|
|
78291
|
+
else if (currentRotationEqual(env, -Math.PI / 4)) {
|
|
78292
|
+
return "o-spreadsheet-Icon.ROTATION-315";
|
|
78293
|
+
}
|
|
78294
|
+
return "o-spreadsheet-Icon.ROTATION-0";
|
|
78210
78295
|
}
|
|
78211
78296
|
|
|
78212
78297
|
const colMenuRegistry = new MenuItemRegistry();
|
|
@@ -86418,6 +86503,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
86418
86503
|
case "ACTIVATE_SHEET":
|
|
86419
86504
|
this.isSearchDirty = true;
|
|
86420
86505
|
this.shouldFinalizeUpdateSelection = true;
|
|
86506
|
+
if (this.searchOptions.specificRange) {
|
|
86507
|
+
this.searchOptions.specificRange = {
|
|
86508
|
+
...this.searchOptions.specificRange,
|
|
86509
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
86510
|
+
};
|
|
86511
|
+
}
|
|
86421
86512
|
break;
|
|
86422
86513
|
case "REPLACE_SEARCH":
|
|
86423
86514
|
for (const match of cmd.matches) {
|
|
@@ -86804,9 +86895,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
86804
86895
|
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
|
|
86805
86896
|
this.store.updateSearchOptions({ specificRange });
|
|
86806
86897
|
}
|
|
86898
|
+
get specificRange() {
|
|
86899
|
+
const range = this.store.searchOptions.specificRange;
|
|
86900
|
+
return range ? this.env.model.getters.getRangeString(range, "forceSheetReference") : "";
|
|
86901
|
+
}
|
|
86807
86902
|
get pendingSearch() {
|
|
86808
86903
|
return this.updateSearchContent.isDebouncePending();
|
|
86809
86904
|
}
|
|
86905
|
+
get selectionInputKey() {
|
|
86906
|
+
// Selections input are made to work with objects linked to a sheet id. They store the active sheet id at their creation,
|
|
86907
|
+
// and have specific behaviour linked to it (eg. go back to the initial sheet after confirmation).
|
|
86908
|
+
// We don't want all those behaviors here, so we force the recreation of the component when the active sheet changes.
|
|
86909
|
+
// The only drawback is that the input loses focus when changing sheet.
|
|
86910
|
+
return this.env.model.getters.getActiveSheetId();
|
|
86911
|
+
}
|
|
86810
86912
|
}
|
|
86811
86913
|
|
|
86812
86914
|
/**
|
|
@@ -97985,9 +98087,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
97985
98087
|
exports.tokenize = tokenize;
|
|
97986
98088
|
|
|
97987
98089
|
|
|
97988
|
-
__info__.version = "19.1.
|
|
97989
|
-
__info__.date = "2026-01-
|
|
97990
|
-
__info__.hash = "
|
|
98090
|
+
__info__.version = "19.1.3";
|
|
98091
|
+
__info__.date = "2026-01-14T10:02:32.431Z";
|
|
98092
|
+
__info__.hash = "52a3e52";
|
|
97991
98093
|
|
|
97992
98094
|
|
|
97993
98095
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|