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