@odoo/o-spreadsheet 16.0.24 → 16.0.27
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.cjs.js +204 -144
- package/dist/o-spreadsheet.d.ts +23 -24
- package/dist/o-spreadsheet.esm.js +204 -144
- package/dist/o-spreadsheet.iife.js +204 -144
- package/dist/o-spreadsheet.iife.min.js +274 -274
- package/dist/o_spreadsheet.xml +6 -7
- package/package.json +1 -1
|
@@ -624,13 +624,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
|
|
|
624
624
|
}
|
|
625
625
|
|
|
626
626
|
//------------------------------------------------------------------------------
|
|
627
|
-
/**
|
|
628
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
629
|
-
* is ordered.
|
|
630
|
-
*/
|
|
631
|
-
function stringify(obj) {
|
|
632
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
633
|
-
}
|
|
634
627
|
/**
|
|
635
628
|
* Remove quotes from a quoted string
|
|
636
629
|
* ```js
|
|
@@ -932,7 +925,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
932
925
|
*/
|
|
933
926
|
function getItemId(item, itemsDic) {
|
|
934
927
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
935
|
-
if (
|
|
928
|
+
if (deepEquals(value, item)) {
|
|
936
929
|
return parseInt(key, 10);
|
|
937
930
|
}
|
|
938
931
|
}
|
|
@@ -1068,6 +1061,22 @@ function transpose2dArray(matrix) {
|
|
|
1068
1061
|
if (!matrix.length)
|
|
1069
1062
|
return matrix;
|
|
1070
1063
|
return matrix[0].map((_, i) => matrix.map((row) => row[i]));
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Creates a version of the function that's memoized on the value of its first
|
|
1067
|
+
* argument, if any.
|
|
1068
|
+
*/
|
|
1069
|
+
function memoize(func) {
|
|
1070
|
+
const cache = new Map();
|
|
1071
|
+
const funcName = func.name ? func.name + " (memoized)" : "memoized";
|
|
1072
|
+
return {
|
|
1073
|
+
[funcName](...args) {
|
|
1074
|
+
if (!cache.has(args[0])) {
|
|
1075
|
+
cache.set(args[0], func(...args));
|
|
1076
|
+
}
|
|
1077
|
+
return cache.get(args[0]);
|
|
1078
|
+
},
|
|
1079
|
+
}[funcName];
|
|
1071
1080
|
}
|
|
1072
1081
|
|
|
1073
1082
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -1347,8 +1356,10 @@ function isSameColor(color1, color2) {
|
|
|
1347
1356
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
1348
1357
|
// Same as above, but matches the exact string (nothing before or after)
|
|
1349
1358
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
1350
|
-
/** Reference of a column header (eg. A, AB) */
|
|
1351
|
-
const colHeader = new RegExp(
|
|
1359
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
1360
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
1361
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
1362
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
1352
1363
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
1353
1364
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
1354
1365
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -1378,6 +1389,9 @@ function isRowReference(xc) {
|
|
|
1378
1389
|
function isColHeader(str) {
|
|
1379
1390
|
return colHeader.test(str);
|
|
1380
1391
|
}
|
|
1392
|
+
function isRowHeader(str) {
|
|
1393
|
+
return rowHeader.test(str);
|
|
1394
|
+
}
|
|
1381
1395
|
/**
|
|
1382
1396
|
* Return true if the given xc is the reference of a single cell,
|
|
1383
1397
|
* without any specified sheet (e.g. A1)
|
|
@@ -2078,18 +2092,10 @@ class RangeImpl {
|
|
|
2078
2092
|
if (isFullCol) {
|
|
2079
2093
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2080
2094
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2081
|
-
if (zone.left === zone.right) {
|
|
2082
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2083
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2084
|
-
}
|
|
2085
2095
|
}
|
|
2086
2096
|
if (isFullRow) {
|
|
2087
2097
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2088
2098
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2089
|
-
if (zone.top === zone.bottom) {
|
|
2090
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2091
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2092
|
-
}
|
|
2093
2099
|
}
|
|
2094
2100
|
return parts;
|
|
2095
2101
|
}
|
|
@@ -3305,6 +3311,7 @@ exports.CommandResult = void 0;
|
|
|
3305
3311
|
CommandResult[CommandResult["ChartDoesNotExist"] = 84] = "ChartDoesNotExist";
|
|
3306
3312
|
CommandResult[CommandResult["InvalidHeaderIndex"] = 85] = "InvalidHeaderIndex";
|
|
3307
3313
|
CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
|
|
3314
|
+
CommandResult[CommandResult["NoChanges"] = 87] = "NoChanges";
|
|
3308
3315
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
3309
3316
|
|
|
3310
3317
|
function isMatrix(x) {
|
|
@@ -3880,6 +3887,7 @@ function getMenuDescription(node) {
|
|
|
3880
3887
|
return node.description ? node.description : "";
|
|
3881
3888
|
}
|
|
3882
3889
|
|
|
3890
|
+
const macRegex = /Mac/i;
|
|
3883
3891
|
/**
|
|
3884
3892
|
* Return true if the event was triggered from
|
|
3885
3893
|
* a child element.
|
|
@@ -3897,6 +3905,17 @@ function gridOverlayPosition() {
|
|
|
3897
3905
|
}
|
|
3898
3906
|
function getOpenedMenus() {
|
|
3899
3907
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
3908
|
+
}
|
|
3909
|
+
function isMacOS() {
|
|
3910
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
3914
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
3915
|
+
* On Mac, this is the "meta" or "command" key.
|
|
3916
|
+
*/
|
|
3917
|
+
function isCtrlKey(ev) {
|
|
3918
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
3900
3919
|
}
|
|
3901
3920
|
|
|
3902
3921
|
/**
|
|
@@ -10980,12 +10999,12 @@ function toString(value) {
|
|
|
10980
10999
|
}
|
|
10981
11000
|
}
|
|
10982
11001
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
10983
|
-
function normalizeString(str) {
|
|
11002
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
10984
11003
|
return str
|
|
10985
11004
|
.toLowerCase()
|
|
10986
11005
|
.normalize("NFD")
|
|
10987
11006
|
.replace(/[\u0300-\u036f]/g, "");
|
|
10988
|
-
}
|
|
11007
|
+
});
|
|
10989
11008
|
/**
|
|
10990
11009
|
* Normalize a value.
|
|
10991
11010
|
* If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
|
|
@@ -18560,7 +18579,7 @@ const machine = {
|
|
|
18560
18579
|
SPACE: goTo(State.RightRef),
|
|
18561
18580
|
NUMBER: goTo(State.Found),
|
|
18562
18581
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
18563
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
18582
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
18564
18583
|
},
|
|
18565
18584
|
[State.RightColumnRef]: {
|
|
18566
18585
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -18571,6 +18590,7 @@ const machine = {
|
|
|
18571
18590
|
SPACE: goTo(State.RightRowRef),
|
|
18572
18591
|
NUMBER: goTo(State.Found),
|
|
18573
18592
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
18593
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
18574
18594
|
},
|
|
18575
18595
|
[State.Found]: {},
|
|
18576
18596
|
};
|
|
@@ -19080,6 +19100,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
19080
19100
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
19081
19101
|
case "colrow":
|
|
19082
19102
|
indexOfNumber = xc.search(/[0-9]/);
|
|
19103
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
19104
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
19105
|
+
return "$" + xc;
|
|
19106
|
+
}
|
|
19083
19107
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
19084
19108
|
return "$" + xc;
|
|
19085
19109
|
case "none":
|
|
@@ -21461,7 +21485,10 @@ class GridOverlay extends owl.Component {
|
|
|
21461
21485
|
return;
|
|
21462
21486
|
}
|
|
21463
21487
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
21464
|
-
this.props.onCellClicked(col, row, {
|
|
21488
|
+
this.props.onCellClicked(col, row, {
|
|
21489
|
+
expandZone: ev.shiftKey,
|
|
21490
|
+
addZone: isCtrlKey(ev),
|
|
21491
|
+
});
|
|
21465
21492
|
}
|
|
21466
21493
|
onDoubleClick(ev) {
|
|
21467
21494
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -21533,6 +21560,7 @@ class AbstractResizer extends owl.Component {
|
|
|
21533
21560
|
draggerShadowThickness: 0,
|
|
21534
21561
|
delta: 0,
|
|
21535
21562
|
base: 0,
|
|
21563
|
+
position: "before",
|
|
21536
21564
|
});
|
|
21537
21565
|
}
|
|
21538
21566
|
_computeHandleDisplay(ev) {
|
|
@@ -21658,11 +21686,13 @@ class AbstractResizer extends owl.Component {
|
|
|
21658
21686
|
this.state.draggerLinePosition = dimensions.start;
|
|
21659
21687
|
this.state.draggerShadowPosition = dimensions.start;
|
|
21660
21688
|
this.state.base = elementIndex;
|
|
21689
|
+
this.state.position = "before";
|
|
21661
21690
|
}
|
|
21662
21691
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
21663
21692
|
this.state.draggerLinePosition = dimensions.end;
|
|
21664
21693
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
21665
|
-
this.state.base = elementIndex
|
|
21694
|
+
this.state.base = elementIndex;
|
|
21695
|
+
this.state.position = "after";
|
|
21666
21696
|
}
|
|
21667
21697
|
else {
|
|
21668
21698
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -21686,7 +21716,7 @@ class AbstractResizer extends owl.Component {
|
|
|
21686
21716
|
this._increaseSelection(index);
|
|
21687
21717
|
}
|
|
21688
21718
|
else {
|
|
21689
|
-
this._selectElement(index, ev
|
|
21719
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
21690
21720
|
}
|
|
21691
21721
|
this.lastSelectedElementIndex = index;
|
|
21692
21722
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -21699,7 +21729,7 @@ class AbstractResizer extends owl.Component {
|
|
|
21699
21729
|
const mouseUpSelect = () => {
|
|
21700
21730
|
this.state.isSelecting = false;
|
|
21701
21731
|
this.lastSelectedElementIndex = null;
|
|
21702
|
-
this.env.model.dispatch(ev
|
|
21732
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
21703
21733
|
this._computeGrabDisplay(ev);
|
|
21704
21734
|
};
|
|
21705
21735
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -21840,13 +21870,14 @@ class ColResizer extends AbstractResizer {
|
|
|
21840
21870
|
dimension: "COL",
|
|
21841
21871
|
base: this.state.base,
|
|
21842
21872
|
elements,
|
|
21873
|
+
position: this.state.position,
|
|
21843
21874
|
});
|
|
21844
21875
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
21845
21876
|
this.env.raiseError(MergeErrorMessage);
|
|
21846
21877
|
}
|
|
21847
21878
|
}
|
|
21848
|
-
_selectElement(index,
|
|
21849
|
-
this.env.model.selection.selectColumn(index,
|
|
21879
|
+
_selectElement(index, addDistinctHeader) {
|
|
21880
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
21850
21881
|
}
|
|
21851
21882
|
_increaseSelection(index) {
|
|
21852
21883
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -22009,13 +22040,14 @@ class RowResizer extends AbstractResizer {
|
|
|
22009
22040
|
dimension: "ROW",
|
|
22010
22041
|
base: this.state.base,
|
|
22011
22042
|
elements,
|
|
22043
|
+
position: this.state.position,
|
|
22012
22044
|
});
|
|
22013
22045
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22014
22046
|
this.env.raiseError(MergeErrorMessage);
|
|
22015
22047
|
}
|
|
22016
22048
|
}
|
|
22017
|
-
_selectElement(index,
|
|
22018
|
-
this.env.model.selection.selectRow(index,
|
|
22049
|
+
_selectElement(index, addDistinctHeader) {
|
|
22050
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22019
22051
|
}
|
|
22020
22052
|
_increaseSelection(index) {
|
|
22021
22053
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -22111,8 +22143,8 @@ function useWheelHandler(handler) {
|
|
|
22111
22143
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
22112
22144
|
}
|
|
22113
22145
|
const onMouseWheel = (ev) => {
|
|
22114
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
22115
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
22146
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
22147
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
22116
22148
|
handler(deltaX, deltaY);
|
|
22117
22149
|
};
|
|
22118
22150
|
return onMouseWheel;
|
|
@@ -22706,18 +22738,18 @@ class Grid extends owl.Component {
|
|
|
22706
22738
|
// ---------------------------------------------------------------------------
|
|
22707
22739
|
// Zone selection with mouse
|
|
22708
22740
|
// ---------------------------------------------------------------------------
|
|
22709
|
-
onCellClicked(col, row, {
|
|
22710
|
-
if (
|
|
22741
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
22742
|
+
if (addZone) {
|
|
22711
22743
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
22712
22744
|
}
|
|
22713
22745
|
this.closeOpenedPopover();
|
|
22714
22746
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
22715
22747
|
this.env.model.dispatch("STOP_EDITION");
|
|
22716
22748
|
}
|
|
22717
|
-
if (
|
|
22749
|
+
if (expandZone) {
|
|
22718
22750
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
22719
22751
|
}
|
|
22720
|
-
else if (
|
|
22752
|
+
else if (addZone) {
|
|
22721
22753
|
this.env.model.selection.addCellToSelection(col, row);
|
|
22722
22754
|
}
|
|
22723
22755
|
else {
|
|
@@ -22771,10 +22803,10 @@ class Grid extends owl.Component {
|
|
|
22771
22803
|
};
|
|
22772
22804
|
const direction = arrowMap[ev.key];
|
|
22773
22805
|
if (ev.shiftKey) {
|
|
22774
|
-
this.env.model.selection.resizeAnchorZone(direction, ev
|
|
22806
|
+
this.env.model.selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
22775
22807
|
}
|
|
22776
22808
|
else {
|
|
22777
|
-
this.env.model.selection.moveAnchorCell(direction, ev
|
|
22809
|
+
this.env.model.selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
22778
22810
|
}
|
|
22779
22811
|
if (this.env.model.getters.isPaintingFormat()) {
|
|
22780
22812
|
this.env.model.dispatch("PASTE", {
|
|
@@ -22788,9 +22820,7 @@ class Grid extends owl.Component {
|
|
|
22788
22820
|
return;
|
|
22789
22821
|
}
|
|
22790
22822
|
let keyDownString = "";
|
|
22791
|
-
if (ev
|
|
22792
|
-
keyDownString += "CTRL+";
|
|
22793
|
-
if (ev.metaKey)
|
|
22823
|
+
if (isCtrlKey(ev))
|
|
22794
22824
|
keyDownString += "CTRL+";
|
|
22795
22825
|
if (ev.altKey)
|
|
22796
22826
|
keyDownString += "ALT+";
|
|
@@ -27105,6 +27135,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
27105
27135
|
// ---------------------------------------------------------------------------
|
|
27106
27136
|
// Command Handling
|
|
27107
27137
|
// ---------------------------------------------------------------------------
|
|
27138
|
+
allowDispatch(cmd) {
|
|
27139
|
+
switch (cmd.type) {
|
|
27140
|
+
case "SET_BORDER":
|
|
27141
|
+
return this.checkBordersUnchanged(cmd);
|
|
27142
|
+
default:
|
|
27143
|
+
return 0 /* CommandResult.Success */;
|
|
27144
|
+
}
|
|
27145
|
+
}
|
|
27108
27146
|
handle(cmd) {
|
|
27109
27147
|
switch (cmd.type) {
|
|
27110
27148
|
case "ADD_MERGE":
|
|
@@ -27500,6 +27538,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
27500
27538
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
27501
27539
|
}
|
|
27502
27540
|
}
|
|
27541
|
+
checkBordersUnchanged(cmd) {
|
|
27542
|
+
var _a, _b, _c, _d;
|
|
27543
|
+
const currentBorder = this.getCellBorder(cmd.sheetId, cmd.col, cmd.row);
|
|
27544
|
+
const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
|
|
27545
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
27546
|
+
return 87 /* CommandResult.NoChanges */;
|
|
27547
|
+
}
|
|
27548
|
+
return 0 /* CommandResult.Success */;
|
|
27549
|
+
}
|
|
27503
27550
|
// ---------------------------------------------------------------------------
|
|
27504
27551
|
// Import/Export
|
|
27505
27552
|
// ---------------------------------------------------------------------------
|
|
@@ -27535,7 +27582,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
27535
27582
|
*/
|
|
27536
27583
|
function getBorderId(border) {
|
|
27537
27584
|
for (let [key, value] of Object.entries(borders)) {
|
|
27538
|
-
if (
|
|
27585
|
+
if (deepEquals(value, border)) {
|
|
27539
27586
|
return parseInt(key, 10);
|
|
27540
27587
|
}
|
|
27541
27588
|
}
|
|
@@ -27578,6 +27625,7 @@ const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
|
|
|
27578
27625
|
class CellPlugin extends CorePlugin {
|
|
27579
27626
|
constructor() {
|
|
27580
27627
|
super(...arguments);
|
|
27628
|
+
this.nextId = 1;
|
|
27581
27629
|
this.cells = {};
|
|
27582
27630
|
this.createCell = cellFactory(this.getters);
|
|
27583
27631
|
}
|
|
@@ -27603,8 +27651,9 @@ class CellPlugin extends CorePlugin {
|
|
|
27603
27651
|
allowDispatch(cmd) {
|
|
27604
27652
|
switch (cmd.type) {
|
|
27605
27653
|
case "UPDATE_CELL":
|
|
27654
|
+
return this.checkCellOutOfSheet(cmd);
|
|
27606
27655
|
case "CLEAR_CELL":
|
|
27607
|
-
return this.
|
|
27656
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
27608
27657
|
default:
|
|
27609
27658
|
return 0 /* CommandResult.Success */;
|
|
27610
27659
|
}
|
|
@@ -27745,7 +27794,7 @@ class CellPlugin extends CorePlugin {
|
|
|
27745
27794
|
importCell(sheetId, cellData, normalizedStyles, normalizedFormats) {
|
|
27746
27795
|
const style = (cellData.style && normalizedStyles[cellData.style]) || undefined;
|
|
27747
27796
|
const format = (cellData.format && normalizedFormats[cellData.format]) || undefined;
|
|
27748
|
-
const cellId = this.
|
|
27797
|
+
const cellId = this.getNextUid();
|
|
27749
27798
|
const properties = { format, style };
|
|
27750
27799
|
return this.createCell(cellId, (cellData === null || cellData === void 0 ? void 0 : cellData.content) || "", properties, sheetId);
|
|
27751
27800
|
}
|
|
@@ -27776,14 +27825,9 @@ class CellPlugin extends CorePlugin {
|
|
|
27776
27825
|
*/
|
|
27777
27826
|
getCellById(cellId) {
|
|
27778
27827
|
// this must be as fast as possible
|
|
27779
|
-
|
|
27780
|
-
|
|
27781
|
-
|
|
27782
|
-
if (cell) {
|
|
27783
|
-
return cell;
|
|
27784
|
-
}
|
|
27785
|
-
}
|
|
27786
|
-
return undefined;
|
|
27828
|
+
const position = this.getters.getCellPosition(cellId);
|
|
27829
|
+
const sheet = this.cells[position.sheetId];
|
|
27830
|
+
return sheet[cellId];
|
|
27787
27831
|
}
|
|
27788
27832
|
/*
|
|
27789
27833
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -27891,6 +27935,11 @@ class CellPlugin extends CorePlugin {
|
|
|
27891
27935
|
}
|
|
27892
27936
|
return format;
|
|
27893
27937
|
}
|
|
27938
|
+
getNextUid() {
|
|
27939
|
+
const id = this.nextId.toString();
|
|
27940
|
+
this.history.update("nextId", this.nextId + 1);
|
|
27941
|
+
return id;
|
|
27942
|
+
}
|
|
27894
27943
|
updateCell(sheetId, col, row, after) {
|
|
27895
27944
|
var _a;
|
|
27896
27945
|
const before = this.getters.getCell(sheetId, col, row);
|
|
@@ -27929,7 +27978,7 @@ class CellPlugin extends CorePlugin {
|
|
|
27929
27978
|
}
|
|
27930
27979
|
return;
|
|
27931
27980
|
}
|
|
27932
|
-
const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.
|
|
27981
|
+
const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.getNextUid();
|
|
27933
27982
|
const didContentChange = hasContent;
|
|
27934
27983
|
const properties = { format, style };
|
|
27935
27984
|
const cell = this.createCell(cellId, afterContent, properties, sheetId);
|
|
@@ -27943,13 +27992,23 @@ class CellPlugin extends CorePlugin {
|
|
|
27943
27992
|
this.history.update("cells", sheetId, cell.id, cell);
|
|
27944
27993
|
this.dispatch("UPDATE_CELL_POSITION", { cellId: cell.id, col, row, sheetId });
|
|
27945
27994
|
}
|
|
27946
|
-
checkCellOutOfSheet(
|
|
27995
|
+
checkCellOutOfSheet(cmd) {
|
|
27996
|
+
const { sheetId, col, row } = cmd;
|
|
27947
27997
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
27948
27998
|
if (!sheet)
|
|
27949
27999
|
return 27 /* CommandResult.InvalidSheetId */;
|
|
27950
28000
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
27951
28001
|
return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
|
|
27952
28002
|
}
|
|
28003
|
+
checkUselessClearCell(cmd) {
|
|
28004
|
+
const cell = this.getters.getCell(cmd.sheetId, cmd.col, cmd.row);
|
|
28005
|
+
if (!cell)
|
|
28006
|
+
return 87 /* CommandResult.NoChanges */;
|
|
28007
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
28008
|
+
return 87 /* CommandResult.NoChanges */;
|
|
28009
|
+
}
|
|
28010
|
+
return 0 /* CommandResult.Success */;
|
|
28011
|
+
}
|
|
27953
28012
|
}
|
|
27954
28013
|
CellPlugin.getters = [
|
|
27955
28014
|
"zoneToXC",
|
|
@@ -29901,7 +29960,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
29901
29960
|
const elements = cmd.dimension === "COL"
|
|
29902
29961
|
? this.getNumberCols(cmd.sheetId)
|
|
29903
29962
|
: this.getNumberRows(cmd.sheetId);
|
|
29904
|
-
if (cmd.base < 0 || cmd.base
|
|
29963
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
29905
29964
|
return 85 /* CommandResult.InvalidHeaderIndex */;
|
|
29906
29965
|
}
|
|
29907
29966
|
else if (cmd.quantity <= 0) {
|
|
@@ -30514,10 +30573,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
30514
30573
|
// begin with the end.
|
|
30515
30574
|
rows.sort((a, b) => b - a);
|
|
30516
30575
|
for (let group of groupConsecutive(rows)) {
|
|
30576
|
+
// indexes are sorted in the descending order
|
|
30577
|
+
const from = group[group.length - 1];
|
|
30578
|
+
const to = group[0];
|
|
30517
30579
|
// Move the cells.
|
|
30518
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
30519
|
-
// Effectively delete the
|
|
30520
|
-
|
|
30580
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
30581
|
+
// Effectively delete the rows
|
|
30582
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
30521
30583
|
}
|
|
30522
30584
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
30523
30585
|
if (count) {
|
|
@@ -30539,8 +30601,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
30539
30601
|
this.addEmptyRows(sheet, quantity);
|
|
30540
30602
|
// Move the cells.
|
|
30541
30603
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
30542
|
-
// Recompute the left-right/top-bottom.
|
|
30543
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
30544
30604
|
if (index < sheet.panes.ySplit) {
|
|
30545
30605
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
30546
30606
|
}
|
|
@@ -30641,35 +30701,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
30641
30701
|
}
|
|
30642
30702
|
}
|
|
30643
30703
|
}
|
|
30644
|
-
updateRowsStructureOnDeletion(
|
|
30704
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
30645
30705
|
const rows = [];
|
|
30646
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
30706
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
30647
30707
|
for (let i in sheet.rows) {
|
|
30648
|
-
|
|
30708
|
+
const row = Number(i);
|
|
30709
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
30649
30710
|
continue;
|
|
30650
30711
|
}
|
|
30651
30712
|
rows.push({
|
|
30652
|
-
cells: cellsQueue.
|
|
30713
|
+
cells: cellsQueue.pop(),
|
|
30653
30714
|
});
|
|
30654
30715
|
}
|
|
30655
30716
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
30656
30717
|
}
|
|
30657
|
-
/**
|
|
30658
|
-
* Update the rows of the sheet after an addition:
|
|
30659
|
-
* - Rename the rows
|
|
30660
|
-
*
|
|
30661
|
-
* @param sheet Sheet on which the deletion occurs
|
|
30662
|
-
* @param addedRow Index of the added row
|
|
30663
|
-
* @param rowsToAdd Number of the rows to add
|
|
30664
|
-
*/
|
|
30665
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
30666
|
-
const rows = [];
|
|
30667
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
30668
|
-
sheet.rows.forEach(() => rows.push({
|
|
30669
|
-
cells: cellsQueue.shift(),
|
|
30670
|
-
}));
|
|
30671
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
30672
|
-
}
|
|
30673
30718
|
/**
|
|
30674
30719
|
* Add empty rows at the end of the rows
|
|
30675
30720
|
*
|
|
@@ -32536,13 +32581,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32536
32581
|
// Getters
|
|
32537
32582
|
// ---------------------------------------------------------------------------
|
|
32538
32583
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
32539
|
-
|
|
32540
|
-
|
|
32541
|
-
|
|
32542
|
-
|
|
32543
|
-
|
|
32584
|
+
try {
|
|
32585
|
+
const compiledFormula = compile(formulaString);
|
|
32586
|
+
const params = this.getCompilationParameters(() => { });
|
|
32587
|
+
const ranges = [];
|
|
32588
|
+
for (let xc of compiledFormula.dependencies) {
|
|
32589
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
32590
|
+
}
|
|
32591
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
32592
|
+
}
|
|
32593
|
+
catch (error) {
|
|
32594
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
32544
32595
|
}
|
|
32545
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
32546
32596
|
}
|
|
32547
32597
|
/**
|
|
32548
32598
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -32658,6 +32708,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32658
32708
|
}
|
|
32659
32709
|
return cell.evaluated;
|
|
32660
32710
|
}
|
|
32711
|
+
const rangeCache = {};
|
|
32661
32712
|
/**
|
|
32662
32713
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
32663
32714
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -32674,21 +32725,26 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32674
32725
|
// Performance issue: Avoid fetching data on positions that are out of the spreadsheet
|
|
32675
32726
|
// e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
|
|
32676
32727
|
const sheetZone = getters.getSheetZone(sheetId);
|
|
32677
|
-
const result = [];
|
|
32678
32728
|
const zone = intersection(range.zone, sheetZone);
|
|
32679
32729
|
if (!zone) {
|
|
32680
|
-
|
|
32681
|
-
|
|
32730
|
+
return [[]];
|
|
32731
|
+
}
|
|
32732
|
+
const { top, left, bottom, right } = zone;
|
|
32733
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
32734
|
+
if (cacheKey in rangeCache) {
|
|
32735
|
+
return rangeCache[cacheKey];
|
|
32682
32736
|
}
|
|
32737
|
+
const result = new Array(right - left + 1);
|
|
32683
32738
|
// Performance issue: nested loop is faster than a map here
|
|
32684
|
-
for (let col =
|
|
32685
|
-
const rowValues =
|
|
32686
|
-
for (let row =
|
|
32739
|
+
for (let col = left; col <= right; col++) {
|
|
32740
|
+
const rowValues = new Array(bottom - top + 1);
|
|
32741
|
+
for (let row = top; row <= bottom; row++) {
|
|
32687
32742
|
const cell = evalContext.getters.getCell(range.sheetId, col, row);
|
|
32688
|
-
rowValues
|
|
32743
|
+
rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
|
|
32689
32744
|
}
|
|
32690
|
-
result
|
|
32745
|
+
result[col - left] = rowValues;
|
|
32691
32746
|
}
|
|
32747
|
+
rangeCache[cacheKey] = result;
|
|
32692
32748
|
return result;
|
|
32693
32749
|
}
|
|
32694
32750
|
/**
|
|
@@ -32938,39 +32994,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32938
32994
|
this.computedIcons[activeSheetId] = {};
|
|
32939
32995
|
const computedStyle = this.computedStyles[activeSheetId];
|
|
32940
32996
|
for (let cf of this.getters.getConditionalFormats(activeSheetId).reverse()) {
|
|
32941
|
-
|
|
32942
|
-
|
|
32943
|
-
|
|
32944
|
-
|
|
32945
|
-
|
|
32946
|
-
|
|
32947
|
-
|
|
32948
|
-
|
|
32949
|
-
|
|
32950
|
-
|
|
32951
|
-
|
|
32952
|
-
|
|
32953
|
-
|
|
32954
|
-
|
|
32955
|
-
|
|
32956
|
-
for (let
|
|
32957
|
-
|
|
32958
|
-
|
|
32959
|
-
|
|
32960
|
-
if (
|
|
32961
|
-
|
|
32962
|
-
|
|
32963
|
-
|
|
32964
|
-
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32965
|
-
}
|
|
32997
|
+
switch (cf.rule.type) {
|
|
32998
|
+
case "ColorScaleRule":
|
|
32999
|
+
for (let range of cf.ranges) {
|
|
33000
|
+
this.applyColorScale(range, cf.rule);
|
|
33001
|
+
}
|
|
33002
|
+
break;
|
|
33003
|
+
case "IconSetRule":
|
|
33004
|
+
for (let range of cf.ranges) {
|
|
33005
|
+
this.applyIcon(range, cf.rule);
|
|
33006
|
+
}
|
|
33007
|
+
break;
|
|
33008
|
+
default:
|
|
33009
|
+
for (let ref of cf.ranges) {
|
|
33010
|
+
const zone = this.getters.getRangeFromSheetXC(activeSheetId, ref).zone;
|
|
33011
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
33012
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
33013
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
33014
|
+
let cell = this.getters.getCell(activeSheetId, col, row);
|
|
33015
|
+
if (pr && pr(cell, cf.rule)) {
|
|
33016
|
+
if (!computedStyle[col])
|
|
33017
|
+
computedStyle[col] = [];
|
|
33018
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
33019
|
+
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32966
33020
|
}
|
|
32967
33021
|
}
|
|
32968
33022
|
}
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
}
|
|
32972
|
-
catch (_) {
|
|
32973
|
-
// we don't care about the errors within the evaluation of a rule
|
|
33023
|
+
}
|
|
33024
|
+
break;
|
|
32974
33025
|
}
|
|
32975
33026
|
}
|
|
32976
33027
|
}
|
|
@@ -32994,7 +33045,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32994
33045
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
32995
33046
|
case "formula":
|
|
32996
33047
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
32997
|
-
return
|
|
33048
|
+
return typeof value === "number" ? value : null;
|
|
32998
33049
|
default:
|
|
32999
33050
|
return null;
|
|
33000
33051
|
}
|
|
@@ -34942,7 +34993,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
34942
34993
|
sheetId: cmd.sheetId,
|
|
34943
34994
|
base: cmd.base,
|
|
34944
34995
|
quantity: thickness,
|
|
34945
|
-
position:
|
|
34996
|
+
position: cmd.position,
|
|
34946
34997
|
});
|
|
34947
34998
|
const isCol = cmd.dimension === "COL";
|
|
34948
34999
|
const start = cmd.elements[0];
|
|
@@ -34959,12 +35010,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
34959
35010
|
},
|
|
34960
35011
|
];
|
|
34961
35012
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
35013
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
34962
35014
|
const pasteTarget = [
|
|
34963
35015
|
{
|
|
34964
|
-
left: isCol ?
|
|
34965
|
-
right: isCol ?
|
|
34966
|
-
top: !isCol ?
|
|
34967
|
-
bottom: !isCol ?
|
|
35016
|
+
left: isCol ? base : 0,
|
|
35017
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
35018
|
+
top: !isCol ? base : 0,
|
|
35019
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
34968
35020
|
},
|
|
34969
35021
|
];
|
|
34970
35022
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -35001,6 +35053,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
35001
35053
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
35002
35054
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
35003
35055
|
}
|
|
35056
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
35057
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
35058
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
35059
|
+
return 85 /* CommandResult.InvalidHeaderIndex */;
|
|
35060
|
+
}
|
|
35004
35061
|
return 0 /* CommandResult.Success */;
|
|
35005
35062
|
}
|
|
35006
35063
|
//-------------------------------------------
|
|
@@ -39067,7 +39124,7 @@ class Spreadsheet extends owl.Component {
|
|
|
39067
39124
|
}
|
|
39068
39125
|
onKeydown(ev) {
|
|
39069
39126
|
let keyDownString = "";
|
|
39070
|
-
if (ev
|
|
39127
|
+
if (isCtrlKey(ev)) {
|
|
39071
39128
|
keyDownString += "CTRL+";
|
|
39072
39129
|
}
|
|
39073
39130
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -39911,9 +39968,9 @@ function revertChanges(revisions) {
|
|
|
39911
39968
|
* Apply the changes of the given HistoryChange to the state
|
|
39912
39969
|
*/
|
|
39913
39970
|
function applyChange(change, target) {
|
|
39914
|
-
let val = change.
|
|
39915
|
-
|
|
39916
|
-
for (let pathIndex =
|
|
39971
|
+
let val = change.path[0];
|
|
39972
|
+
const key = change.path[change.path.length - 1];
|
|
39973
|
+
for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
|
|
39917
39974
|
const p = change.path[pathIndex];
|
|
39918
39975
|
if (val[p] === undefined) {
|
|
39919
39976
|
const nextPath = change.path[pathIndex + 1];
|
|
@@ -41043,13 +41100,14 @@ class StateObserver {
|
|
|
41043
41100
|
}
|
|
41044
41101
|
addChange(...args) {
|
|
41045
41102
|
const val = args.pop();
|
|
41046
|
-
const
|
|
41103
|
+
const root = args[0];
|
|
41047
41104
|
let value = root;
|
|
41048
|
-
let key =
|
|
41049
|
-
|
|
41050
|
-
|
|
41105
|
+
let key = args[args.length - 1];
|
|
41106
|
+
const pathLength = args.length - 2;
|
|
41107
|
+
for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
|
|
41108
|
+
const p = args[pathIndex];
|
|
41051
41109
|
if (value[p] === undefined) {
|
|
41052
|
-
const nextPath =
|
|
41110
|
+
const nextPath = args[pathIndex + 1];
|
|
41053
41111
|
value[p] = createEmptyStructure(nextPath);
|
|
41054
41112
|
}
|
|
41055
41113
|
value = value[p];
|
|
@@ -41058,8 +41116,7 @@ class StateObserver {
|
|
|
41058
41116
|
return;
|
|
41059
41117
|
}
|
|
41060
41118
|
this.changes.push({
|
|
41061
|
-
|
|
41062
|
-
path,
|
|
41119
|
+
path: args,
|
|
41063
41120
|
before: value[key],
|
|
41064
41121
|
after: val,
|
|
41065
41122
|
});
|
|
@@ -42793,7 +42850,10 @@ class Model extends EventBus {
|
|
|
42793
42850
|
*/
|
|
42794
42851
|
checkDispatchAllowed(command) {
|
|
42795
42852
|
const results = this.handlers.map((handler) => handler.allowDispatch(command));
|
|
42796
|
-
|
|
42853
|
+
if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
|
|
42854
|
+
return new DispatchResult(results.flat());
|
|
42855
|
+
}
|
|
42856
|
+
return DispatchResult.Success;
|
|
42797
42857
|
}
|
|
42798
42858
|
finalize() {
|
|
42799
42859
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -43011,6 +43071,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
43011
43071
|
exports.tokenize = tokenize;
|
|
43012
43072
|
|
|
43013
43073
|
|
|
43014
|
-
__info__.version = '16.0.
|
|
43015
|
-
__info__.date = '
|
|
43016
|
-
__info__.hash = '
|
|
43074
|
+
__info__.version = '16.0.27';
|
|
43075
|
+
__info__.date = '2024-01-04T12:19:11.487Z';
|
|
43076
|
+
__info__.hash = '54006f6';
|