@odoo/o-spreadsheet 17.0.3 → 17.0.4
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 +181 -152
- package/dist/o-spreadsheet.d.ts +9 -16
- package/dist/o-spreadsheet.esm.js +181 -152
- package/dist/o-spreadsheet.iife.js +181 -152
- package/dist/o-spreadsheet.iife.min.js +121 -121
- package/dist/o_spreadsheet.xml +6 -7
- 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 17.0.
|
|
6
|
-
* @date 2023-11-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.4
|
|
6
|
+
* @date 2023-11-24T13:13:42.575Z
|
|
7
|
+
* @hash 7346d0a
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -691,8 +691,7 @@ function removeFalsyAttributes(obj) {
|
|
|
691
691
|
*
|
|
692
692
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
693
693
|
*/
|
|
694
|
-
const
|
|
695
|
-
" ",
|
|
694
|
+
const whiteSpaceSpecialCharacters = [
|
|
696
695
|
"\t",
|
|
697
696
|
"\f",
|
|
698
697
|
"\v",
|
|
@@ -707,8 +706,7 @@ const whiteSpaceCharacters = [
|
|
|
707
706
|
String.fromCharCode(parseInt("3000", 16)),
|
|
708
707
|
String.fromCharCode(parseInt("feff", 16)),
|
|
709
708
|
];
|
|
710
|
-
const whiteSpaceRegexp = new RegExp(
|
|
711
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
709
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
712
710
|
/**
|
|
713
711
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
714
712
|
* different newlines types by \n.
|
|
@@ -716,9 +714,9 @@ const newLineRegex = /\r\n|\r|\n/g;
|
|
|
716
714
|
function replaceSpecialSpaces(text) {
|
|
717
715
|
if (!text)
|
|
718
716
|
return "";
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return text;
|
|
717
|
+
if (!whiteSpaceRegexp.test(text))
|
|
718
|
+
return text;
|
|
719
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
722
720
|
}
|
|
723
721
|
/**
|
|
724
722
|
* Determine if the numbers are consecutive.
|
|
@@ -2060,6 +2058,7 @@ var CommandResult;
|
|
|
2060
2058
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2061
2059
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2062
2060
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2061
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2063
2062
|
})(CommandResult || (CommandResult = {}));
|
|
2064
2063
|
|
|
2065
2064
|
const DEFAULT_LOCALES = [
|
|
@@ -2189,12 +2188,12 @@ function toString(value) {
|
|
|
2189
2188
|
}
|
|
2190
2189
|
}
|
|
2191
2190
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2192
|
-
function normalizeString(str) {
|
|
2191
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2193
2192
|
return str
|
|
2194
2193
|
.toLowerCase()
|
|
2195
2194
|
.normalize("NFD")
|
|
2196
2195
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2197
|
-
}
|
|
2196
|
+
});
|
|
2198
2197
|
const expectBooleanValueError = (value) => _t("The function [[FUNCTION_NAME]] expects a boolean value, but '%s' is a text, and cannot be coerced to a number.", value);
|
|
2199
2198
|
function toBoolean(value) {
|
|
2200
2199
|
switch (typeof value) {
|
|
@@ -7329,7 +7328,7 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
|
7329
7328
|
return result;
|
|
7330
7329
|
}
|
|
7331
7330
|
function tokenizeDebugger(chars) {
|
|
7332
|
-
if (chars.current
|
|
7331
|
+
if (chars.current === "?") {
|
|
7333
7332
|
chars.shift();
|
|
7334
7333
|
return { type: "DEBUGGER", value: "?" };
|
|
7335
7334
|
}
|
|
@@ -7340,7 +7339,7 @@ const misc$1 = {
|
|
|
7340
7339
|
")": "RIGHT_PAREN",
|
|
7341
7340
|
};
|
|
7342
7341
|
function tokenizeMisc(chars) {
|
|
7343
|
-
if (chars.current
|
|
7342
|
+
if (chars.current in misc$1) {
|
|
7344
7343
|
const value = chars.shift();
|
|
7345
7344
|
const type = misc$1[value];
|
|
7346
7345
|
return { type, value };
|
|
@@ -7348,7 +7347,7 @@ function tokenizeMisc(chars) {
|
|
|
7348
7347
|
return null;
|
|
7349
7348
|
}
|
|
7350
7349
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7351
|
-
if (chars.current
|
|
7350
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7352
7351
|
const value = chars.shift();
|
|
7353
7352
|
const type = "ARG_SEPARATOR";
|
|
7354
7353
|
return { type, value };
|
|
@@ -7373,14 +7372,13 @@ function tokenizeNumber(chars, locale) {
|
|
|
7373
7372
|
return null;
|
|
7374
7373
|
}
|
|
7375
7374
|
function tokenizeString(chars) {
|
|
7376
|
-
if (chars.current
|
|
7375
|
+
if (chars.current === '"') {
|
|
7377
7376
|
const startChar = chars.shift();
|
|
7378
7377
|
let letters = startChar;
|
|
7379
|
-
while (chars.current()
|
|
7380
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7378
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7381
7379
|
letters += chars.shift();
|
|
7382
7380
|
}
|
|
7383
|
-
if (chars.current
|
|
7381
|
+
if (chars.current === '"') {
|
|
7384
7382
|
letters += chars.shift();
|
|
7385
7383
|
}
|
|
7386
7384
|
return {
|
|
@@ -7407,14 +7405,14 @@ function tokenizeSymbol(chars) {
|
|
|
7407
7405
|
let result = "";
|
|
7408
7406
|
// there are two main cases to manage: either something which starts with
|
|
7409
7407
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7410
|
-
if (chars.current
|
|
7408
|
+
if (chars.current === "'") {
|
|
7411
7409
|
let lastChar = chars.shift();
|
|
7412
7410
|
result += lastChar;
|
|
7413
|
-
while (chars.current
|
|
7411
|
+
while (chars.current) {
|
|
7414
7412
|
lastChar = chars.shift();
|
|
7415
7413
|
result += lastChar;
|
|
7416
7414
|
if (lastChar === "'") {
|
|
7417
|
-
if (chars.current
|
|
7415
|
+
if (chars.current && chars.current === "'") {
|
|
7418
7416
|
lastChar = chars.shift();
|
|
7419
7417
|
result += lastChar;
|
|
7420
7418
|
}
|
|
@@ -7430,7 +7428,7 @@ function tokenizeSymbol(chars) {
|
|
|
7430
7428
|
};
|
|
7431
7429
|
}
|
|
7432
7430
|
}
|
|
7433
|
-
while (chars.current
|
|
7431
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7434
7432
|
result += chars.shift();
|
|
7435
7433
|
}
|
|
7436
7434
|
if (result.length) {
|
|
@@ -7445,14 +7443,14 @@ function tokenizeSymbol(chars) {
|
|
|
7445
7443
|
}
|
|
7446
7444
|
function tokenizeSpace(chars) {
|
|
7447
7445
|
let length = 0;
|
|
7448
|
-
while (chars.current
|
|
7446
|
+
while (chars.current === NEWLINE) {
|
|
7449
7447
|
length++;
|
|
7450
7448
|
chars.shift();
|
|
7451
7449
|
}
|
|
7452
7450
|
if (length) {
|
|
7453
7451
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7454
7452
|
}
|
|
7455
|
-
while (chars.current
|
|
7453
|
+
while (chars.current === " ") {
|
|
7456
7454
|
length++;
|
|
7457
7455
|
chars.shift();
|
|
7458
7456
|
}
|
|
@@ -7471,17 +7469,20 @@ function tokenizeInvalidRange(chars) {
|
|
|
7471
7469
|
class TokenizingChars {
|
|
7472
7470
|
text;
|
|
7473
7471
|
currentIndex = 0;
|
|
7472
|
+
current;
|
|
7474
7473
|
constructor(text) {
|
|
7475
7474
|
this.text = text;
|
|
7476
|
-
|
|
7477
|
-
current() {
|
|
7478
|
-
return this.text[this.currentIndex];
|
|
7475
|
+
this.current = text[0];
|
|
7479
7476
|
}
|
|
7480
7477
|
shift() {
|
|
7481
|
-
|
|
7478
|
+
const current = this.current;
|
|
7479
|
+
const next = this.text[++this.currentIndex];
|
|
7480
|
+
this.current = next;
|
|
7481
|
+
return current;
|
|
7482
7482
|
}
|
|
7483
7483
|
advanceBy(length) {
|
|
7484
7484
|
this.currentIndex += length;
|
|
7485
|
+
this.current = this.text[this.currentIndex];
|
|
7485
7486
|
}
|
|
7486
7487
|
isOver() {
|
|
7487
7488
|
return this.currentIndex >= this.text.length;
|
|
@@ -29757,6 +29758,7 @@ class Grid extends Component {
|
|
|
29757
29758
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29758
29759
|
const target = this.env.model.getters.getSelectedZones();
|
|
29759
29760
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29761
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29760
29762
|
if (clipboardString === content) {
|
|
29761
29763
|
// the paste actually comes from o-spreadsheet itself
|
|
29762
29764
|
interactivePaste(this.env, target);
|
|
@@ -29764,7 +29766,7 @@ class Grid extends Component {
|
|
|
29764
29766
|
else {
|
|
29765
29767
|
interactivePasteFromOS(this.env, target, content);
|
|
29766
29768
|
}
|
|
29767
|
-
if (
|
|
29769
|
+
if (isCutOperation) {
|
|
29768
29770
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29769
29771
|
}
|
|
29770
29772
|
}
|
|
@@ -34058,6 +34060,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34058
34060
|
// ---------------------------------------------------------------------------
|
|
34059
34061
|
// Command Handling
|
|
34060
34062
|
// ---------------------------------------------------------------------------
|
|
34063
|
+
allowDispatch(cmd) {
|
|
34064
|
+
switch (cmd.type) {
|
|
34065
|
+
case "SET_BORDER":
|
|
34066
|
+
return this.checkBordersUnchanged(cmd);
|
|
34067
|
+
default:
|
|
34068
|
+
return "Success" /* CommandResult.Success */;
|
|
34069
|
+
}
|
|
34070
|
+
}
|
|
34061
34071
|
handle(cmd) {
|
|
34062
34072
|
switch (cmd.type) {
|
|
34063
34073
|
case "ADD_MERGE":
|
|
@@ -34477,6 +34487,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34477
34487
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34478
34488
|
}
|
|
34479
34489
|
}
|
|
34490
|
+
checkBordersUnchanged(cmd) {
|
|
34491
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34492
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34493
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34494
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34495
|
+
}
|
|
34496
|
+
return "Success" /* CommandResult.Success */;
|
|
34497
|
+
}
|
|
34480
34498
|
// ---------------------------------------------------------------------------
|
|
34481
34499
|
// Import/Export
|
|
34482
34500
|
// ---------------------------------------------------------------------------
|
|
@@ -35332,8 +35350,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35332
35350
|
allowDispatch(cmd) {
|
|
35333
35351
|
switch (cmd.type) {
|
|
35334
35352
|
case "UPDATE_CELL":
|
|
35353
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35335
35354
|
case "CLEAR_CELL":
|
|
35336
|
-
return this.
|
|
35355
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35337
35356
|
default:
|
|
35338
35357
|
return "Success" /* CommandResult.Success */;
|
|
35339
35358
|
}
|
|
@@ -35502,14 +35521,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35502
35521
|
*/
|
|
35503
35522
|
getCellById(cellId) {
|
|
35504
35523
|
// this must be as fast as possible
|
|
35505
|
-
|
|
35506
|
-
|
|
35507
|
-
|
|
35508
|
-
if (cell) {
|
|
35509
|
-
return cell;
|
|
35510
|
-
}
|
|
35511
|
-
}
|
|
35512
|
-
return undefined;
|
|
35524
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35525
|
+
const sheet = this.cells[position.sheetId];
|
|
35526
|
+
return sheet[cellId];
|
|
35513
35527
|
}
|
|
35514
35528
|
/*
|
|
35515
35529
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -35740,13 +35754,23 @@ class CellPlugin extends CorePlugin {
|
|
|
35740
35754
|
},
|
|
35741
35755
|
};
|
|
35742
35756
|
}
|
|
35743
|
-
checkCellOutOfSheet(
|
|
35757
|
+
checkCellOutOfSheet(cmd) {
|
|
35758
|
+
const { sheetId, col, row } = cmd;
|
|
35744
35759
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35745
35760
|
if (!sheet)
|
|
35746
35761
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35747
35762
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35748
35763
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35749
35764
|
}
|
|
35765
|
+
checkUselessClearCell(cmd) {
|
|
35766
|
+
const cell = this.getters.getCell(cmd);
|
|
35767
|
+
if (!cell)
|
|
35768
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35769
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35770
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35771
|
+
}
|
|
35772
|
+
return "Success" /* CommandResult.Success */;
|
|
35773
|
+
}
|
|
35750
35774
|
}
|
|
35751
35775
|
class FormulaCellWithDependencies {
|
|
35752
35776
|
id;
|
|
@@ -36436,6 +36460,9 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
36436
36460
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36437
36461
|
}
|
|
36438
36462
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36463
|
+
if (!this.rules[sheetId]) {
|
|
36464
|
+
return undefined;
|
|
36465
|
+
}
|
|
36439
36466
|
for (const rule of this.rules[sheetId]) {
|
|
36440
36467
|
for (const range of rule.ranges) {
|
|
36441
36468
|
if (isInside(col, row, range.zone)) {
|
|
@@ -39033,10 +39060,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
39033
39060
|
// begin with the end.
|
|
39034
39061
|
rows.sort((a, b) => b - a);
|
|
39035
39062
|
for (let group of groupConsecutive(rows)) {
|
|
39063
|
+
// indexes are sorted in the descending order
|
|
39064
|
+
const from = group[group.length - 1];
|
|
39065
|
+
const to = group[0];
|
|
39036
39066
|
// Move the cells.
|
|
39037
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39038
|
-
// Effectively delete the
|
|
39039
|
-
|
|
39067
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39068
|
+
// Effectively delete the rows
|
|
39069
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39040
39070
|
}
|
|
39041
39071
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39042
39072
|
if (count) {
|
|
@@ -39058,8 +39088,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
39058
39088
|
this.addEmptyRows(sheet, quantity);
|
|
39059
39089
|
// Move the cells.
|
|
39060
39090
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39061
|
-
// Recompute the left-right/top-bottom.
|
|
39062
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39063
39091
|
if (index < sheet.panes.ySplit) {
|
|
39064
39092
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39065
39093
|
}
|
|
@@ -39160,35 +39188,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
39160
39188
|
}
|
|
39161
39189
|
}
|
|
39162
39190
|
}
|
|
39163
|
-
updateRowsStructureOnDeletion(
|
|
39191
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39164
39192
|
const rows = [];
|
|
39165
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39193
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39166
39194
|
for (let i in sheet.rows) {
|
|
39167
|
-
|
|
39195
|
+
const row = Number(i);
|
|
39196
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39168
39197
|
continue;
|
|
39169
39198
|
}
|
|
39170
39199
|
rows.push({
|
|
39171
|
-
cells: cellsQueue.
|
|
39200
|
+
cells: cellsQueue.pop(),
|
|
39172
39201
|
});
|
|
39173
39202
|
}
|
|
39174
39203
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39175
39204
|
}
|
|
39176
|
-
/**
|
|
39177
|
-
* Update the rows of the sheet after an addition:
|
|
39178
|
-
* - Rename the rows
|
|
39179
|
-
*
|
|
39180
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39181
|
-
* @param addedRow Index of the added row
|
|
39182
|
-
* @param rowsToAdd Number of the rows to add
|
|
39183
|
-
*/
|
|
39184
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39185
|
-
const rows = [];
|
|
39186
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39187
|
-
sheet.rows.forEach(() => rows.push({
|
|
39188
|
-
cells: cellsQueue.shift(),
|
|
39189
|
-
}));
|
|
39190
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39191
|
-
}
|
|
39192
39205
|
/**
|
|
39193
39206
|
* Add empty rows at the end of the rows
|
|
39194
39207
|
*
|
|
@@ -39715,6 +39728,7 @@ class CompilationParametersBuilder {
|
|
|
39715
39728
|
getters;
|
|
39716
39729
|
computeCell;
|
|
39717
39730
|
evalContext;
|
|
39731
|
+
rangeCache = {};
|
|
39718
39732
|
constructor(context, getters, computeCell) {
|
|
39719
39733
|
this.getters = getters;
|
|
39720
39734
|
this.computeCell = computeCell;
|
|
@@ -39800,17 +39814,24 @@ class CompilationParametersBuilder {
|
|
|
39800
39814
|
if (!_zone) {
|
|
39801
39815
|
return [[]];
|
|
39802
39816
|
}
|
|
39817
|
+
const { top, left, bottom, right } = zone;
|
|
39818
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
39819
|
+
if (cacheKey in this.rangeCache) {
|
|
39820
|
+
return this.rangeCache[cacheKey];
|
|
39821
|
+
}
|
|
39803
39822
|
const height = _zone.bottom - _zone.top + 1;
|
|
39804
39823
|
const width = _zone.right - _zone.left + 1;
|
|
39805
|
-
const matrix = Array
|
|
39824
|
+
const matrix = new Array(width);
|
|
39806
39825
|
// Performance issue: nested loop is faster than a map here
|
|
39807
39826
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
39827
|
+
const colIndex = col - _zone.left;
|
|
39828
|
+
matrix[colIndex] = new Array(height);
|
|
39808
39829
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39809
|
-
const colIndex = col - _zone.left;
|
|
39810
39830
|
const rowIndex = row - _zone.top;
|
|
39811
39831
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39812
39832
|
}
|
|
39813
39833
|
}
|
|
39834
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39814
39835
|
return matrix;
|
|
39815
39836
|
}
|
|
39816
39837
|
}
|
|
@@ -40016,6 +40037,7 @@ class Evaluator {
|
|
|
40016
40037
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
40017
40038
|
}
|
|
40018
40039
|
updateCompilationParameters() {
|
|
40040
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
40019
40041
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40020
40042
|
}
|
|
40021
40043
|
evaluateCells(positions) {
|
|
@@ -40059,6 +40081,16 @@ class Evaluator {
|
|
|
40059
40081
|
this.evaluatedCells = new Map();
|
|
40060
40082
|
this.evaluate(this.getAllCells());
|
|
40061
40083
|
}
|
|
40084
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40085
|
+
const compiledFormula = compile(formulaString);
|
|
40086
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40087
|
+
this.updateCompilationParameters();
|
|
40088
|
+
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40089
|
+
if (isMatrix(array)) {
|
|
40090
|
+
return matrixMap(array, (cell) => cell.value);
|
|
40091
|
+
}
|
|
40092
|
+
return array.value;
|
|
40093
|
+
}
|
|
40062
40094
|
getAllCells() {
|
|
40063
40095
|
const positionIds = new JetSet();
|
|
40064
40096
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40085,6 +40117,7 @@ class Evaluator {
|
|
|
40085
40117
|
this.nextPositionsToUpdate = cells;
|
|
40086
40118
|
let currentIteration = 0;
|
|
40087
40119
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40120
|
+
this.updateCompilationParameters();
|
|
40088
40121
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40089
40122
|
this.nextPositionsToUpdate.clear();
|
|
40090
40123
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40448,7 +40481,6 @@ class PositionBitsEncoder {
|
|
|
40448
40481
|
// of other cells depending on it, at the next iteration.
|
|
40449
40482
|
//#endregion
|
|
40450
40483
|
class EvaluationPlugin extends UIPlugin {
|
|
40451
|
-
config;
|
|
40452
40484
|
static getters = [
|
|
40453
40485
|
"evaluateFormula",
|
|
40454
40486
|
"getCorrespondingFormulaCell",
|
|
@@ -40459,15 +40491,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40459
40491
|
"getEvaluatedCells",
|
|
40460
40492
|
"getEvaluatedCellsInZone",
|
|
40461
40493
|
"getSpreadPositionsOf",
|
|
40494
|
+
"getArrayFormulaSpreadingOn",
|
|
40462
40495
|
];
|
|
40463
40496
|
shouldRebuildDependenciesGraph = true;
|
|
40464
40497
|
evaluator;
|
|
40465
|
-
compilationParams;
|
|
40466
40498
|
positionsToUpdate = [];
|
|
40467
40499
|
constructor(config) {
|
|
40468
40500
|
super(config);
|
|
40469
|
-
this.config = config;
|
|
40470
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40471
40501
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40472
40502
|
}
|
|
40473
40503
|
// ---------------------------------------------------------------------------
|
|
@@ -40492,10 +40522,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40492
40522
|
case "EVALUATE_CELLS":
|
|
40493
40523
|
this.evaluator.evaluateAllCells();
|
|
40494
40524
|
break;
|
|
40495
|
-
case "UPDATE_LOCALE":
|
|
40496
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40497
|
-
this.evaluator.updateCompilationParameters();
|
|
40498
|
-
break;
|
|
40499
40525
|
}
|
|
40500
40526
|
}
|
|
40501
40527
|
finalize() {
|
|
@@ -40513,16 +40539,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40513
40539
|
// Getters
|
|
40514
40540
|
// ---------------------------------------------------------------------------
|
|
40515
40541
|
evaluateFormula(sheetId, formulaString) {
|
|
40516
|
-
|
|
40517
|
-
const ranges = [];
|
|
40518
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40519
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40520
|
-
}
|
|
40521
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40522
|
-
if (isMatrix(array)) {
|
|
40523
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40524
|
-
}
|
|
40525
|
-
return array.value;
|
|
40542
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40526
40543
|
}
|
|
40527
40544
|
/**
|
|
40528
40545
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40571,6 +40588,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40571
40588
|
getSpreadPositionsOf(position) {
|
|
40572
40589
|
return this.evaluator.getSpreadPositionsOf(position);
|
|
40573
40590
|
}
|
|
40591
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40592
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40593
|
+
}
|
|
40574
40594
|
// ---------------------------------------------------------------------------
|
|
40575
40595
|
// Export
|
|
40576
40596
|
// ---------------------------------------------------------------------------
|
|
@@ -40614,7 +40634,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40614
40634
|
else if (cell && cell.content) {
|
|
40615
40635
|
return undefined;
|
|
40616
40636
|
}
|
|
40617
|
-
const spreadingFormulaPosition = this.
|
|
40637
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40618
40638
|
if (spreadingFormulaPosition === undefined) {
|
|
40619
40639
|
return undefined;
|
|
40620
40640
|
}
|
|
@@ -40624,9 +40644,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40624
40644
|
}
|
|
40625
40645
|
return undefined;
|
|
40626
40646
|
}
|
|
40627
|
-
getCompilationParameters() {
|
|
40628
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40629
|
-
}
|
|
40630
40647
|
}
|
|
40631
40648
|
function isBadExpression(tokens) {
|
|
40632
40649
|
try {
|
|
@@ -43325,11 +43342,26 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43325
43342
|
let cellsInRow = [];
|
|
43326
43343
|
for (let col of columnsIndex) {
|
|
43327
43344
|
const position = { col, row, sheetId };
|
|
43345
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43346
|
+
let cell = getters.getCell(position);
|
|
43347
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43348
|
+
if (spreader) {
|
|
43349
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43350
|
+
const content = isSpreaderCopied
|
|
43351
|
+
? ""
|
|
43352
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43353
|
+
cell = {
|
|
43354
|
+
id: cell?.id || "",
|
|
43355
|
+
style: cell?.style,
|
|
43356
|
+
format: evaluatedCell.format,
|
|
43357
|
+
content,
|
|
43358
|
+
isFormula: false,
|
|
43359
|
+
};
|
|
43360
|
+
}
|
|
43328
43361
|
cellsInRow.push({
|
|
43329
|
-
cell
|
|
43330
|
-
style: getters.getCellComputedStyle(position),
|
|
43331
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43362
|
+
cell,
|
|
43332
43363
|
border: getters.getCellBorder(position) || undefined,
|
|
43364
|
+
evaluatedCell,
|
|
43333
43365
|
position,
|
|
43334
43366
|
});
|
|
43335
43367
|
}
|
|
@@ -43451,13 +43483,6 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43451
43483
|
});
|
|
43452
43484
|
}
|
|
43453
43485
|
this.pasteCopiedTables(target);
|
|
43454
|
-
this.cells.forEach((row) => {
|
|
43455
|
-
row.forEach((c) => {
|
|
43456
|
-
if (c.cell) {
|
|
43457
|
-
c.cell = undefined;
|
|
43458
|
-
}
|
|
43459
|
-
});
|
|
43460
|
-
});
|
|
43461
43486
|
}
|
|
43462
43487
|
/**
|
|
43463
43488
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43529,7 +43554,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43529
43554
|
clearClippedZones() {
|
|
43530
43555
|
for (const row of this.cells) {
|
|
43531
43556
|
for (const cell of row) {
|
|
43532
|
-
if (cell
|
|
43557
|
+
if (cell?.cell) {
|
|
43533
43558
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43534
43559
|
}
|
|
43535
43560
|
}
|
|
@@ -43555,6 +43580,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43555
43580
|
const rowCells = this.cells[r];
|
|
43556
43581
|
for (let c = 0; c < width; c++) {
|
|
43557
43582
|
const origin = rowCells[c];
|
|
43583
|
+
if (!origin) {
|
|
43584
|
+
continue;
|
|
43585
|
+
}
|
|
43558
43586
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43559
43587
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43560
43588
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43578,53 +43606,42 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43578
43606
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43579
43607
|
const { sheetId, col, row } = target;
|
|
43580
43608
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43581
|
-
if (clipboardOption?.pasteOption
|
|
43582
|
-
const
|
|
43583
|
-
const
|
|
43584
|
-
|
|
43585
|
-
|
|
43586
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43587
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43588
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43589
|
-
};
|
|
43590
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43609
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43610
|
+
const locale = this.getters.getLocale();
|
|
43611
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43612
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43613
|
+
return;
|
|
43591
43614
|
}
|
|
43592
|
-
|
|
43593
|
-
|
|
43594
|
-
|
|
43595
|
-
|
|
43596
|
-
|
|
43597
|
-
|
|
43598
|
-
|
|
43599
|
-
|
|
43600
|
-
|
|
43601
|
-
|
|
43602
|
-
|
|
43603
|
-
|
|
43604
|
-
|
|
43605
|
-
|
|
43606
|
-
}
|
|
43607
|
-
|
|
43608
|
-
|
|
43609
|
-
|
|
43610
|
-
|
|
43615
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43616
|
+
const originBorders = origin.border;
|
|
43617
|
+
const border = {
|
|
43618
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43619
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43620
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43621
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43622
|
+
};
|
|
43623
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43624
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43625
|
+
this.dispatch("UPDATE_CELL", {
|
|
43626
|
+
...target,
|
|
43627
|
+
style: origin.cell?.style ?? null,
|
|
43628
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43629
|
+
});
|
|
43630
|
+
return;
|
|
43631
|
+
}
|
|
43632
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43633
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43634
|
+
: origin.cell?.content;
|
|
43635
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43611
43636
|
this.dispatch("UPDATE_CELL", {
|
|
43612
43637
|
...target,
|
|
43613
43638
|
content,
|
|
43614
|
-
style: origin.cell
|
|
43615
|
-
format: origin.cell
|
|
43639
|
+
style: origin.cell?.style || null,
|
|
43640
|
+
format: origin.cell?.format,
|
|
43616
43641
|
});
|
|
43617
43642
|
}
|
|
43618
43643
|
else if (targetCell) {
|
|
43619
|
-
|
|
43620
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43621
|
-
}
|
|
43622
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43623
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43624
|
-
}
|
|
43625
|
-
else {
|
|
43626
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43627
|
-
}
|
|
43644
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43628
43645
|
}
|
|
43629
43646
|
}
|
|
43630
43647
|
/**
|
|
@@ -43686,22 +43703,28 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43686
43703
|
return (this.cells
|
|
43687
43704
|
.map((cells) => {
|
|
43688
43705
|
return cells
|
|
43689
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43706
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43690
43707
|
? c.cell?.content || ""
|
|
43691
|
-
: c
|
|
43708
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43692
43709
|
.join("\t");
|
|
43693
43710
|
})
|
|
43694
43711
|
.join("\n") || "\t");
|
|
43695
43712
|
}
|
|
43696
43713
|
getHTMLContent() {
|
|
43697
43714
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43715
|
+
if (!this.cells[0][0]) {
|
|
43716
|
+
return "";
|
|
43717
|
+
}
|
|
43698
43718
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43699
43719
|
}
|
|
43700
43720
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43701
43721
|
for (const row of this.cells) {
|
|
43702
43722
|
htmlTable += "<tr>";
|
|
43703
43723
|
for (const cell of row) {
|
|
43704
|
-
|
|
43724
|
+
if (!cell) {
|
|
43725
|
+
continue;
|
|
43726
|
+
}
|
|
43727
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43705
43728
|
const cellText = this.getters.getCellText(cell.position);
|
|
43706
43729
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43707
43730
|
}
|
|
@@ -46831,11 +46854,14 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
46831
46854
|
}
|
|
46832
46855
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46833
46856
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
46857
|
+
if (this.state.operation === "CUT") {
|
|
46858
|
+
this.state = undefined;
|
|
46859
|
+
}
|
|
46834
46860
|
this.lastPasteState = this.state;
|
|
46835
46861
|
if (this.paintFormatStatus === "oneOff") {
|
|
46836
46862
|
this.paintFormatStatus = "inactive";
|
|
46837
|
-
this.status = "invisible";
|
|
46838
46863
|
}
|
|
46864
|
+
this.status = "invisible";
|
|
46839
46865
|
break;
|
|
46840
46866
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46841
46867
|
{
|
|
@@ -55559,19 +55585,22 @@ class Model extends EventBus {
|
|
|
55559
55585
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55560
55586
|
*/
|
|
55561
55587
|
checkDispatchAllowed(command) {
|
|
55562
|
-
|
|
55563
|
-
|
|
55588
|
+
const results = isCoreCommand(command)
|
|
55589
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55590
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55591
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55592
|
+
return new DispatchResult(results.flat());
|
|
55564
55593
|
}
|
|
55565
|
-
return
|
|
55594
|
+
return DispatchResult.Success;
|
|
55566
55595
|
}
|
|
55567
55596
|
checkDispatchAllowedCoreCommand(command) {
|
|
55568
55597
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55569
55598
|
results.push(this.range.allowDispatch(command));
|
|
55570
|
-
return
|
|
55599
|
+
return results;
|
|
55571
55600
|
}
|
|
55572
55601
|
checkDispatchAllowedLocalCommand(command) {
|
|
55573
55602
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55574
|
-
return
|
|
55603
|
+
return results;
|
|
55575
55604
|
}
|
|
55576
55605
|
finalize() {
|
|
55577
55606
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55883,6 +55912,6 @@ const constants = {
|
|
|
55883
55912
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
55884
55913
|
|
|
55885
55914
|
|
|
55886
|
-
__info__.version = "17.0.
|
|
55887
|
-
__info__.date = "2023-11-
|
|
55888
|
-
__info__.hash = "
|
|
55915
|
+
__info__.version = "17.0.4";
|
|
55916
|
+
__info__.date = "2023-11-24T13:13:42.575Z";
|
|
55917
|
+
__info__.hash = "7346d0a";
|