@odoo/o-spreadsheet 17.0.2 → 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 +311 -228
- package/dist/o-spreadsheet.d.ts +21 -23
- package/dist/o-spreadsheet.esm.js +310 -229
- package/dist/o-spreadsheet.iife.js +311 -228
- package/dist/o-spreadsheet.iife.min.js +278 -278
- 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
|
(function (exports, owl) {
|
|
@@ -692,8 +692,7 @@
|
|
|
692
692
|
*
|
|
693
693
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
694
694
|
*/
|
|
695
|
-
const
|
|
696
|
-
" ",
|
|
695
|
+
const whiteSpaceSpecialCharacters = [
|
|
697
696
|
"\t",
|
|
698
697
|
"\f",
|
|
699
698
|
"\v",
|
|
@@ -708,8 +707,7 @@
|
|
|
708
707
|
String.fromCharCode(parseInt("3000", 16)),
|
|
709
708
|
String.fromCharCode(parseInt("feff", 16)),
|
|
710
709
|
];
|
|
711
|
-
const whiteSpaceRegexp = new RegExp(
|
|
712
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
710
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
713
711
|
/**
|
|
714
712
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
715
713
|
* different newlines types by \n.
|
|
@@ -717,9 +715,9 @@
|
|
|
717
715
|
function replaceSpecialSpaces(text) {
|
|
718
716
|
if (!text)
|
|
719
717
|
return "";
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
return text;
|
|
718
|
+
if (!whiteSpaceRegexp.test(text))
|
|
719
|
+
return text;
|
|
720
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
723
721
|
}
|
|
724
722
|
/**
|
|
725
723
|
* Determine if the numbers are consecutive.
|
|
@@ -2061,6 +2059,7 @@
|
|
|
2061
2059
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2062
2060
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2063
2061
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2062
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2064
2063
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
2065
2064
|
|
|
2066
2065
|
const DEFAULT_LOCALES = [
|
|
@@ -2190,12 +2189,12 @@
|
|
|
2190
2189
|
}
|
|
2191
2190
|
}
|
|
2192
2191
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2193
|
-
function normalizeString(str) {
|
|
2192
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2194
2193
|
return str
|
|
2195
2194
|
.toLowerCase()
|
|
2196
2195
|
.normalize("NFD")
|
|
2197
2196
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2198
|
-
}
|
|
2197
|
+
});
|
|
2199
2198
|
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);
|
|
2200
2199
|
function toBoolean(value) {
|
|
2201
2200
|
switch (typeof value) {
|
|
@@ -4541,14 +4540,14 @@
|
|
|
4541
4540
|
switch (context.textBaseline) {
|
|
4542
4541
|
case "top":
|
|
4543
4542
|
underlineY += boxHeight - 2 * strokeWidth;
|
|
4544
|
-
strikeY += boxHeight -
|
|
4543
|
+
strikeY += boxHeight / 2 - strokeWidth;
|
|
4545
4544
|
break;
|
|
4546
4545
|
case "middle":
|
|
4547
4546
|
underlineY += boxHeight / 2 - strokeWidth;
|
|
4548
4547
|
break;
|
|
4549
4548
|
case "alphabetic":
|
|
4550
4549
|
underlineY += 2 * strokeWidth;
|
|
4551
|
-
strikeY -=
|
|
4550
|
+
strikeY -= 3 * strokeWidth;
|
|
4552
4551
|
break;
|
|
4553
4552
|
case "bottom":
|
|
4554
4553
|
underlineY = y;
|
|
@@ -5967,7 +5966,7 @@
|
|
|
5967
5966
|
return { cellData: {} };
|
|
5968
5967
|
}
|
|
5969
5968
|
const sheetId = data.sheetId;
|
|
5970
|
-
const content = getters.getTranslatedCellFormula(sheetId, x, y, cell.compiledFormula
|
|
5969
|
+
const content = getters.getTranslatedCellFormula(sheetId, x, y, cell.compiledFormula);
|
|
5971
5970
|
return {
|
|
5972
5971
|
cellData: {
|
|
5973
5972
|
border: data.border,
|
|
@@ -7330,7 +7329,7 @@
|
|
|
7330
7329
|
return result;
|
|
7331
7330
|
}
|
|
7332
7331
|
function tokenizeDebugger(chars) {
|
|
7333
|
-
if (chars.current
|
|
7332
|
+
if (chars.current === "?") {
|
|
7334
7333
|
chars.shift();
|
|
7335
7334
|
return { type: "DEBUGGER", value: "?" };
|
|
7336
7335
|
}
|
|
@@ -7341,7 +7340,7 @@
|
|
|
7341
7340
|
")": "RIGHT_PAREN",
|
|
7342
7341
|
};
|
|
7343
7342
|
function tokenizeMisc(chars) {
|
|
7344
|
-
if (chars.current
|
|
7343
|
+
if (chars.current in misc$1) {
|
|
7345
7344
|
const value = chars.shift();
|
|
7346
7345
|
const type = misc$1[value];
|
|
7347
7346
|
return { type, value };
|
|
@@ -7349,7 +7348,7 @@
|
|
|
7349
7348
|
return null;
|
|
7350
7349
|
}
|
|
7351
7350
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7352
|
-
if (chars.current
|
|
7351
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7353
7352
|
const value = chars.shift();
|
|
7354
7353
|
const type = "ARG_SEPARATOR";
|
|
7355
7354
|
return { type, value };
|
|
@@ -7374,14 +7373,13 @@
|
|
|
7374
7373
|
return null;
|
|
7375
7374
|
}
|
|
7376
7375
|
function tokenizeString(chars) {
|
|
7377
|
-
if (chars.current
|
|
7376
|
+
if (chars.current === '"') {
|
|
7378
7377
|
const startChar = chars.shift();
|
|
7379
7378
|
let letters = startChar;
|
|
7380
|
-
while (chars.current()
|
|
7381
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7379
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7382
7380
|
letters += chars.shift();
|
|
7383
7381
|
}
|
|
7384
|
-
if (chars.current
|
|
7382
|
+
if (chars.current === '"') {
|
|
7385
7383
|
letters += chars.shift();
|
|
7386
7384
|
}
|
|
7387
7385
|
return {
|
|
@@ -7408,14 +7406,14 @@
|
|
|
7408
7406
|
let result = "";
|
|
7409
7407
|
// there are two main cases to manage: either something which starts with
|
|
7410
7408
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7411
|
-
if (chars.current
|
|
7409
|
+
if (chars.current === "'") {
|
|
7412
7410
|
let lastChar = chars.shift();
|
|
7413
7411
|
result += lastChar;
|
|
7414
|
-
while (chars.current
|
|
7412
|
+
while (chars.current) {
|
|
7415
7413
|
lastChar = chars.shift();
|
|
7416
7414
|
result += lastChar;
|
|
7417
7415
|
if (lastChar === "'") {
|
|
7418
|
-
if (chars.current
|
|
7416
|
+
if (chars.current && chars.current === "'") {
|
|
7419
7417
|
lastChar = chars.shift();
|
|
7420
7418
|
result += lastChar;
|
|
7421
7419
|
}
|
|
@@ -7431,7 +7429,7 @@
|
|
|
7431
7429
|
};
|
|
7432
7430
|
}
|
|
7433
7431
|
}
|
|
7434
|
-
while (chars.current
|
|
7432
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7435
7433
|
result += chars.shift();
|
|
7436
7434
|
}
|
|
7437
7435
|
if (result.length) {
|
|
@@ -7446,14 +7444,14 @@
|
|
|
7446
7444
|
}
|
|
7447
7445
|
function tokenizeSpace(chars) {
|
|
7448
7446
|
let length = 0;
|
|
7449
|
-
while (chars.current
|
|
7447
|
+
while (chars.current === NEWLINE) {
|
|
7450
7448
|
length++;
|
|
7451
7449
|
chars.shift();
|
|
7452
7450
|
}
|
|
7453
7451
|
if (length) {
|
|
7454
7452
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7455
7453
|
}
|
|
7456
|
-
while (chars.current
|
|
7454
|
+
while (chars.current === " ") {
|
|
7457
7455
|
length++;
|
|
7458
7456
|
chars.shift();
|
|
7459
7457
|
}
|
|
@@ -7472,17 +7470,20 @@
|
|
|
7472
7470
|
class TokenizingChars {
|
|
7473
7471
|
text;
|
|
7474
7472
|
currentIndex = 0;
|
|
7473
|
+
current;
|
|
7475
7474
|
constructor(text) {
|
|
7476
7475
|
this.text = text;
|
|
7477
|
-
|
|
7478
|
-
current() {
|
|
7479
|
-
return this.text[this.currentIndex];
|
|
7476
|
+
this.current = text[0];
|
|
7480
7477
|
}
|
|
7481
7478
|
shift() {
|
|
7482
|
-
|
|
7479
|
+
const current = this.current;
|
|
7480
|
+
const next = this.text[++this.currentIndex];
|
|
7481
|
+
this.current = next;
|
|
7482
|
+
return current;
|
|
7483
7483
|
}
|
|
7484
7484
|
advanceBy(length) {
|
|
7485
7485
|
this.currentIndex += length;
|
|
7486
|
+
this.current = this.text[this.currentIndex];
|
|
7486
7487
|
}
|
|
7487
7488
|
isOver() {
|
|
7488
7489
|
return this.currentIndex >= this.text.length;
|
|
@@ -10694,6 +10695,17 @@
|
|
|
10694
10695
|
const IS_ONLY_ONE_RANGE = (env) => {
|
|
10695
10696
|
return env.model.getters.getSelectedZones().length === 1;
|
|
10696
10697
|
};
|
|
10698
|
+
const CAN_INSERT_HEADER = (env, dimension) => {
|
|
10699
|
+
if (!IS_ONLY_ONE_RANGE(env)) {
|
|
10700
|
+
return false;
|
|
10701
|
+
}
|
|
10702
|
+
const activeHeaders = dimension === "COL" ? env.model.getters.getActiveCols() : env.model.getters.getActiveRows();
|
|
10703
|
+
const ortogonalActiveHeaders = dimension === "COL" ? env.model.getters.getActiveRows() : env.model.getters.getActiveCols();
|
|
10704
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
10705
|
+
const zone = env.model.getters.getSelectedZone();
|
|
10706
|
+
const allSheetSelected = isEqual(zone, env.model.getters.getSheetZone(sheetId));
|
|
10707
|
+
return isConsecutive(activeHeaders) && (ortogonalActiveHeaders.size === 0 || allSheetSelected);
|
|
10708
|
+
};
|
|
10697
10709
|
|
|
10698
10710
|
const undo = {
|
|
10699
10711
|
name: _t("Undo"),
|
|
@@ -19371,9 +19383,7 @@
|
|
|
19371
19383
|
const number = getRowsNumber(env);
|
|
19372
19384
|
return number === 1 ? _t("Insert row") : _t("Insert %s rows", number.toString());
|
|
19373
19385
|
},
|
|
19374
|
-
isVisible: (env) =>
|
|
19375
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19376
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19386
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19377
19387
|
icon: "o-spreadsheet-Icon.INSERT_ROW",
|
|
19378
19388
|
};
|
|
19379
19389
|
const rowInsertRowBefore = {
|
|
@@ -19382,9 +19392,7 @@
|
|
|
19382
19392
|
return number === 1 ? _t("Insert row above") : _t("Insert %s rows above", number.toString());
|
|
19383
19393
|
},
|
|
19384
19394
|
execute: INSERT_ROWS_BEFORE_ACTION,
|
|
19385
|
-
isVisible: (env) =>
|
|
19386
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19387
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19395
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19388
19396
|
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
19389
19397
|
};
|
|
19390
19398
|
const topBarInsertRowsBefore = {
|
|
@@ -19415,9 +19423,7 @@
|
|
|
19415
19423
|
const number = getRowsNumber(env);
|
|
19416
19424
|
return number === 1 ? _t("Insert row below") : _t("Insert %s rows below", number.toString());
|
|
19417
19425
|
},
|
|
19418
|
-
isVisible: (env) =>
|
|
19419
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19420
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19426
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19421
19427
|
icon: "o-spreadsheet-Icon.INSERT_ROW_AFTER",
|
|
19422
19428
|
};
|
|
19423
19429
|
const topBarInsertRowsAfter = {
|
|
@@ -19435,9 +19441,7 @@
|
|
|
19435
19441
|
const number = getColumnsNumber(env);
|
|
19436
19442
|
return number === 1 ? _t("Insert column") : _t("Insert %s columns", number.toString());
|
|
19437
19443
|
},
|
|
19438
|
-
isVisible: (env) =>
|
|
19439
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19440
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19444
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19441
19445
|
icon: "o-spreadsheet-Icon.INSERT_COL",
|
|
19442
19446
|
};
|
|
19443
19447
|
const colInsertColsBefore = {
|
|
@@ -19448,9 +19452,7 @@
|
|
|
19448
19452
|
: _t("Insert %s columns left", number.toString());
|
|
19449
19453
|
},
|
|
19450
19454
|
execute: INSERT_COLUMNS_BEFORE_ACTION,
|
|
19451
|
-
isVisible: (env) =>
|
|
19452
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19453
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19455
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19454
19456
|
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
19455
19457
|
};
|
|
19456
19458
|
const topBarInsertColsBefore = {
|
|
@@ -19483,9 +19485,7 @@
|
|
|
19483
19485
|
: _t("Insert %s columns right", number.toString());
|
|
19484
19486
|
},
|
|
19485
19487
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
19486
|
-
isVisible: (env) =>
|
|
19487
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19488
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19488
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19489
19489
|
icon: "o-spreadsheet-Icon.INSERT_COL_AFTER",
|
|
19490
19490
|
};
|
|
19491
19491
|
const topBarInsertColsAfter = {
|
|
@@ -23826,7 +23826,7 @@
|
|
|
23826
23826
|
}
|
|
23827
23827
|
.o-input-count {
|
|
23828
23828
|
width: fit-content;
|
|
23829
|
-
padding:
|
|
23829
|
+
padding: 4px 0 4px 4px;
|
|
23830
23830
|
}
|
|
23831
23831
|
}
|
|
23832
23832
|
}
|
|
@@ -29759,6 +29759,7 @@
|
|
|
29759
29759
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29760
29760
|
const target = this.env.model.getters.getSelectedZones();
|
|
29761
29761
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29762
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29762
29763
|
if (clipboardString === content) {
|
|
29763
29764
|
// the paste actually comes from o-spreadsheet itself
|
|
29764
29765
|
interactivePaste(this.env, target);
|
|
@@ -29766,7 +29767,7 @@
|
|
|
29766
29767
|
else {
|
|
29767
29768
|
interactivePasteFromOS(this.env, target, content);
|
|
29768
29769
|
}
|
|
29769
|
-
if (
|
|
29770
|
+
if (isCutOperation) {
|
|
29770
29771
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29771
29772
|
}
|
|
29772
29773
|
}
|
|
@@ -34060,6 +34061,14 @@
|
|
|
34060
34061
|
// ---------------------------------------------------------------------------
|
|
34061
34062
|
// Command Handling
|
|
34062
34063
|
// ---------------------------------------------------------------------------
|
|
34064
|
+
allowDispatch(cmd) {
|
|
34065
|
+
switch (cmd.type) {
|
|
34066
|
+
case "SET_BORDER":
|
|
34067
|
+
return this.checkBordersUnchanged(cmd);
|
|
34068
|
+
default:
|
|
34069
|
+
return "Success" /* CommandResult.Success */;
|
|
34070
|
+
}
|
|
34071
|
+
}
|
|
34063
34072
|
handle(cmd) {
|
|
34064
34073
|
switch (cmd.type) {
|
|
34065
34074
|
case "ADD_MERGE":
|
|
@@ -34479,6 +34488,14 @@
|
|
|
34479
34488
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34480
34489
|
}
|
|
34481
34490
|
}
|
|
34491
|
+
checkBordersUnchanged(cmd) {
|
|
34492
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34493
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34494
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34495
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34496
|
+
}
|
|
34497
|
+
return "Success" /* CommandResult.Success */;
|
|
34498
|
+
}
|
|
34482
34499
|
// ---------------------------------------------------------------------------
|
|
34483
34500
|
// Import/Export
|
|
34484
34501
|
// ---------------------------------------------------------------------------
|
|
@@ -34947,6 +34964,9 @@
|
|
|
34947
34964
|
// -----------------------------------------------------------------------------
|
|
34948
34965
|
function compile(formula) {
|
|
34949
34966
|
const tokens = rangeTokenize(formula);
|
|
34967
|
+
return compileTokens(tokens);
|
|
34968
|
+
}
|
|
34969
|
+
function compileTokens(tokens) {
|
|
34950
34970
|
const { dependencies, constantValues } = formulaArguments(tokens);
|
|
34951
34971
|
const cacheKey = compilationCacheKey(tokens, dependencies, constantValues);
|
|
34952
34972
|
if (!functionCache[cacheKey]) {
|
|
@@ -35313,11 +35333,11 @@
|
|
|
35313
35333
|
for (const sheet of Object.keys(this.cells)) {
|
|
35314
35334
|
for (const cell of Object.values(this.cells[sheet] || {})) {
|
|
35315
35335
|
if (cell.isFormula) {
|
|
35316
|
-
for (const range of cell.dependencies) {
|
|
35336
|
+
for (const range of cell.compiledFormula.dependencies) {
|
|
35317
35337
|
if (!sheetId || range.sheetId === sheetId) {
|
|
35318
35338
|
const change = applyChange(range);
|
|
35319
35339
|
if (change.changeType !== "NONE") {
|
|
35320
|
-
this.history.update("cells", sheet, cell.id, "dependencies", cell.dependencies.indexOf(range), change.range);
|
|
35340
|
+
this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
|
|
35321
35341
|
}
|
|
35322
35342
|
}
|
|
35323
35343
|
}
|
|
@@ -35331,8 +35351,9 @@
|
|
|
35331
35351
|
allowDispatch(cmd) {
|
|
35332
35352
|
switch (cmd.type) {
|
|
35333
35353
|
case "UPDATE_CELL":
|
|
35354
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35334
35355
|
case "CLEAR_CELL":
|
|
35335
|
-
return this.
|
|
35356
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35336
35357
|
default:
|
|
35337
35358
|
return "Success" /* CommandResult.Success */;
|
|
35338
35359
|
}
|
|
@@ -35501,22 +35522,17 @@
|
|
|
35501
35522
|
*/
|
|
35502
35523
|
getCellById(cellId) {
|
|
35503
35524
|
// this must be as fast as possible
|
|
35504
|
-
|
|
35505
|
-
|
|
35506
|
-
|
|
35507
|
-
if (cell) {
|
|
35508
|
-
return cell;
|
|
35509
|
-
}
|
|
35510
|
-
}
|
|
35511
|
-
return undefined;
|
|
35525
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35526
|
+
const sheet = this.cells[position.sheetId];
|
|
35527
|
+
return sheet[cellId];
|
|
35512
35528
|
}
|
|
35513
35529
|
/*
|
|
35514
35530
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
35515
35531
|
*/
|
|
35516
|
-
getFormulaCellContent(sheetId,
|
|
35517
|
-
const ranges = dependencies ||
|
|
35532
|
+
getFormulaCellContent(sheetId, compiledFormula, dependencies) {
|
|
35533
|
+
const ranges = dependencies || compiledFormula.dependencies;
|
|
35518
35534
|
let rangeIndex = 0;
|
|
35519
|
-
return concat(
|
|
35535
|
+
return concat(compiledFormula.tokens.map((token) => {
|
|
35520
35536
|
if (token.type === "REFERENCE") {
|
|
35521
35537
|
const range = ranges[rangeIndex++];
|
|
35522
35538
|
return this.getters.getRangeString(range, sheetId);
|
|
@@ -35527,12 +35543,9 @@
|
|
|
35527
35543
|
/*
|
|
35528
35544
|
* Constructs a formula string based on an initial formula and a translation vector
|
|
35529
35545
|
*/
|
|
35530
|
-
getTranslatedCellFormula(sheetId, offsetX, offsetY, compiledFormula
|
|
35531
|
-
const adaptedDependencies = this.getters.createAdaptedRanges(dependencies, offsetX, offsetY, sheetId);
|
|
35532
|
-
return this.getFormulaCellContent(sheetId,
|
|
35533
|
-
compiledFormula,
|
|
35534
|
-
dependencies: adaptedDependencies,
|
|
35535
|
-
});
|
|
35546
|
+
getTranslatedCellFormula(sheetId, offsetX, offsetY, compiledFormula) {
|
|
35547
|
+
const adaptedDependencies = this.getters.createAdaptedRanges(compiledFormula.dependencies, offsetX, offsetY, sheetId);
|
|
35548
|
+
return this.getFormulaCellContent(sheetId, compiledFormula, adaptedDependencies);
|
|
35536
35549
|
}
|
|
35537
35550
|
getCellStyle(position) {
|
|
35538
35551
|
return this.getters.getCell(position)?.style || {};
|
|
@@ -35712,8 +35725,10 @@
|
|
|
35712
35725
|
style,
|
|
35713
35726
|
format,
|
|
35714
35727
|
isFormula: true,
|
|
35715
|
-
compiledFormula
|
|
35716
|
-
|
|
35728
|
+
compiledFormula: {
|
|
35729
|
+
...compiledFormula,
|
|
35730
|
+
dependencies: [],
|
|
35731
|
+
},
|
|
35717
35732
|
};
|
|
35718
35733
|
}
|
|
35719
35734
|
/**
|
|
@@ -35722,7 +35737,7 @@
|
|
|
35722
35737
|
*/
|
|
35723
35738
|
createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
|
|
35724
35739
|
const dependencies = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
35725
|
-
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.
|
|
35740
|
+
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString.bind(this));
|
|
35726
35741
|
}
|
|
35727
35742
|
createErrorFormula(id, content, format, style, error) {
|
|
35728
35743
|
return {
|
|
@@ -35732,46 +35747,72 @@
|
|
|
35732
35747
|
format,
|
|
35733
35748
|
isFormula: true,
|
|
35734
35749
|
compiledFormula: {
|
|
35735
|
-
dependencies: [],
|
|
35736
35750
|
tokens: tokenize(content),
|
|
35751
|
+
dependencies: [],
|
|
35737
35752
|
execute: function () {
|
|
35738
35753
|
throw error;
|
|
35739
35754
|
},
|
|
35740
35755
|
},
|
|
35741
|
-
dependencies: [],
|
|
35742
35756
|
};
|
|
35743
35757
|
}
|
|
35744
|
-
checkCellOutOfSheet(
|
|
35758
|
+
checkCellOutOfSheet(cmd) {
|
|
35759
|
+
const { sheetId, col, row } = cmd;
|
|
35745
35760
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35746
35761
|
if (!sheet)
|
|
35747
35762
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35748
35763
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35749
35764
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35750
35765
|
}
|
|
35766
|
+
checkUselessClearCell(cmd) {
|
|
35767
|
+
const cell = this.getters.getCell(cmd);
|
|
35768
|
+
if (!cell)
|
|
35769
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35770
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35771
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35772
|
+
}
|
|
35773
|
+
return "Success" /* CommandResult.Success */;
|
|
35774
|
+
}
|
|
35751
35775
|
}
|
|
35752
35776
|
class FormulaCellWithDependencies {
|
|
35753
35777
|
id;
|
|
35754
|
-
compiledFormula;
|
|
35755
35778
|
format;
|
|
35756
35779
|
style;
|
|
35757
|
-
dependencies;
|
|
35758
35780
|
sheetId;
|
|
35759
|
-
|
|
35781
|
+
getRangeString;
|
|
35760
35782
|
isFormula = true;
|
|
35761
|
-
|
|
35783
|
+
compiledFormula;
|
|
35784
|
+
constructor(id, compiledFormula, format, style, dependencies, sheetId, getRangeString) {
|
|
35762
35785
|
this.id = id;
|
|
35763
|
-
this.compiledFormula = compiledFormula;
|
|
35764
35786
|
this.format = format;
|
|
35765
35787
|
this.style = style;
|
|
35766
|
-
this.dependencies = dependencies;
|
|
35767
35788
|
this.sheetId = sheetId;
|
|
35768
|
-
this.
|
|
35789
|
+
this.getRangeString = getRangeString;
|
|
35790
|
+
let rangeIndex = 0;
|
|
35791
|
+
const tokens = compiledFormula.tokens.map((token) => {
|
|
35792
|
+
if (token.type === "REFERENCE") {
|
|
35793
|
+
const index = rangeIndex++;
|
|
35794
|
+
return new RangeReferenceToken(() => this.getRangeString(dependencies[index], this.sheetId));
|
|
35795
|
+
}
|
|
35796
|
+
return token;
|
|
35797
|
+
});
|
|
35798
|
+
this.compiledFormula = {
|
|
35799
|
+
...compiledFormula,
|
|
35800
|
+
dependencies,
|
|
35801
|
+
tokens,
|
|
35802
|
+
};
|
|
35769
35803
|
}
|
|
35770
35804
|
get content() {
|
|
35771
|
-
return this.
|
|
35772
|
-
|
|
35773
|
-
|
|
35774
|
-
|
|
35805
|
+
return concat(this.compiledFormula.tokens.map((token) => token.value));
|
|
35806
|
+
}
|
|
35807
|
+
}
|
|
35808
|
+
class RangeReferenceToken {
|
|
35809
|
+
getValue;
|
|
35810
|
+
type = "REFERENCE";
|
|
35811
|
+
constructor(getValue) {
|
|
35812
|
+
this.getValue = getValue;
|
|
35813
|
+
}
|
|
35814
|
+
get value() {
|
|
35815
|
+
return this.getValue();
|
|
35775
35816
|
}
|
|
35776
35817
|
}
|
|
35777
35818
|
|
|
@@ -36420,6 +36461,9 @@
|
|
|
36420
36461
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36421
36462
|
}
|
|
36422
36463
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36464
|
+
if (!this.rules[sheetId]) {
|
|
36465
|
+
return undefined;
|
|
36466
|
+
}
|
|
36423
36467
|
for (const rule of this.rules[sheetId]) {
|
|
36424
36468
|
for (const range of rule.ranges) {
|
|
36425
36469
|
if (isInside(col, row, range.zone)) {
|
|
@@ -36916,6 +36960,13 @@
|
|
|
36916
36960
|
}
|
|
36917
36961
|
onDeleteColumnsRows(cmd) {
|
|
36918
36962
|
for (const table of this.getFilterTables(cmd.sheetId)) {
|
|
36963
|
+
// Remove the filter tables whose data filter headers are in the removed rows.
|
|
36964
|
+
if (cmd.dimension === "ROW" && cmd.elements.includes(table.zone.top)) {
|
|
36965
|
+
const tables = { ...this.tables[cmd.sheetId] };
|
|
36966
|
+
delete tables[table.id];
|
|
36967
|
+
this.history.update("tables", cmd.sheetId, tables);
|
|
36968
|
+
continue;
|
|
36969
|
+
}
|
|
36919
36970
|
const zone = reduceZoneOnDeletion(table.zone, cmd.dimension === "COL" ? "left" : "top", cmd.elements);
|
|
36920
36971
|
if (!zone) {
|
|
36921
36972
|
const tables = { ...this.tables[cmd.sheetId] };
|
|
@@ -39010,10 +39061,13 @@
|
|
|
39010
39061
|
// begin with the end.
|
|
39011
39062
|
rows.sort((a, b) => b - a);
|
|
39012
39063
|
for (let group of groupConsecutive(rows)) {
|
|
39064
|
+
// indexes are sorted in the descending order
|
|
39065
|
+
const from = group[group.length - 1];
|
|
39066
|
+
const to = group[0];
|
|
39013
39067
|
// Move the cells.
|
|
39014
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39015
|
-
// Effectively delete the
|
|
39016
|
-
|
|
39068
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39069
|
+
// Effectively delete the rows
|
|
39070
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39017
39071
|
}
|
|
39018
39072
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39019
39073
|
if (count) {
|
|
@@ -39035,8 +39089,6 @@
|
|
|
39035
39089
|
this.addEmptyRows(sheet, quantity);
|
|
39036
39090
|
// Move the cells.
|
|
39037
39091
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39038
|
-
// Recompute the left-right/top-bottom.
|
|
39039
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39040
39092
|
if (index < sheet.panes.ySplit) {
|
|
39041
39093
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39042
39094
|
}
|
|
@@ -39137,35 +39189,20 @@
|
|
|
39137
39189
|
}
|
|
39138
39190
|
}
|
|
39139
39191
|
}
|
|
39140
|
-
updateRowsStructureOnDeletion(
|
|
39192
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39141
39193
|
const rows = [];
|
|
39142
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39194
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39143
39195
|
for (let i in sheet.rows) {
|
|
39144
|
-
|
|
39196
|
+
const row = Number(i);
|
|
39197
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39145
39198
|
continue;
|
|
39146
39199
|
}
|
|
39147
39200
|
rows.push({
|
|
39148
|
-
cells: cellsQueue.
|
|
39201
|
+
cells: cellsQueue.pop(),
|
|
39149
39202
|
});
|
|
39150
39203
|
}
|
|
39151
39204
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39152
39205
|
}
|
|
39153
|
-
/**
|
|
39154
|
-
* Update the rows of the sheet after an addition:
|
|
39155
|
-
* - Rename the rows
|
|
39156
|
-
*
|
|
39157
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39158
|
-
* @param addedRow Index of the added row
|
|
39159
|
-
* @param rowsToAdd Number of the rows to add
|
|
39160
|
-
*/
|
|
39161
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39162
|
-
const rows = [];
|
|
39163
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39164
|
-
sheet.rows.forEach(() => rows.push({
|
|
39165
|
-
cells: cellsQueue.shift(),
|
|
39166
|
-
}));
|
|
39167
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39168
|
-
}
|
|
39169
39206
|
/**
|
|
39170
39207
|
* Add empty rows at the end of the rows
|
|
39171
39208
|
*
|
|
@@ -39692,6 +39729,7 @@
|
|
|
39692
39729
|
getters;
|
|
39693
39730
|
computeCell;
|
|
39694
39731
|
evalContext;
|
|
39732
|
+
rangeCache = {};
|
|
39695
39733
|
constructor(context, getters, computeCell) {
|
|
39696
39734
|
this.getters = getters;
|
|
39697
39735
|
this.computeCell = computeCell;
|
|
@@ -39777,17 +39815,24 @@
|
|
|
39777
39815
|
if (!_zone) {
|
|
39778
39816
|
return [[]];
|
|
39779
39817
|
}
|
|
39818
|
+
const { top, left, bottom, right } = zone;
|
|
39819
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
39820
|
+
if (cacheKey in this.rangeCache) {
|
|
39821
|
+
return this.rangeCache[cacheKey];
|
|
39822
|
+
}
|
|
39780
39823
|
const height = _zone.bottom - _zone.top + 1;
|
|
39781
39824
|
const width = _zone.right - _zone.left + 1;
|
|
39782
|
-
const matrix = Array
|
|
39825
|
+
const matrix = new Array(width);
|
|
39783
39826
|
// Performance issue: nested loop is faster than a map here
|
|
39784
39827
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
39828
|
+
const colIndex = col - _zone.left;
|
|
39829
|
+
matrix[colIndex] = new Array(height);
|
|
39785
39830
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39786
|
-
const colIndex = col - _zone.left;
|
|
39787
39831
|
const rowIndex = row - _zone.top;
|
|
39788
39832
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39789
39833
|
}
|
|
39790
39834
|
}
|
|
39835
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39791
39836
|
return matrix;
|
|
39792
39837
|
}
|
|
39793
39838
|
}
|
|
@@ -39964,6 +40009,13 @@
|
|
|
39964
40009
|
return (this.evaluatedCells.get(this.encodePosition(position)) ||
|
|
39965
40010
|
createEvaluatedCell("", { locale: this.getters.getLocale() }));
|
|
39966
40011
|
}
|
|
40012
|
+
getSpreadPositionsOf(position) {
|
|
40013
|
+
const positionId = this.encodePosition(position);
|
|
40014
|
+
if (!this.spreadingRelations.isArrayFormula(positionId)) {
|
|
40015
|
+
return [];
|
|
40016
|
+
}
|
|
40017
|
+
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map(this.decodePosition.bind(this));
|
|
40018
|
+
}
|
|
39967
40019
|
getArrayFormulaSpreadingOn(position) {
|
|
39968
40020
|
const positionId = this.encodePosition(position);
|
|
39969
40021
|
const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
|
|
@@ -39986,6 +40038,7 @@
|
|
|
39986
40038
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
39987
40039
|
}
|
|
39988
40040
|
updateCompilationParameters() {
|
|
40041
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
39989
40042
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
39990
40043
|
}
|
|
39991
40044
|
evaluateCells(positions) {
|
|
@@ -40029,6 +40082,16 @@
|
|
|
40029
40082
|
this.evaluatedCells = new Map();
|
|
40030
40083
|
this.evaluate(this.getAllCells());
|
|
40031
40084
|
}
|
|
40085
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40086
|
+
const compiledFormula = compile(formulaString);
|
|
40087
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40088
|
+
this.updateCompilationParameters();
|
|
40089
|
+
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40090
|
+
if (isMatrix(array)) {
|
|
40091
|
+
return matrixMap(array, (cell) => cell.value);
|
|
40092
|
+
}
|
|
40093
|
+
return array.value;
|
|
40094
|
+
}
|
|
40032
40095
|
getAllCells() {
|
|
40033
40096
|
const positionIds = new JetSet();
|
|
40034
40097
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40055,6 +40118,7 @@
|
|
|
40055
40118
|
this.nextPositionsToUpdate = cells;
|
|
40056
40119
|
let currentIteration = 0;
|
|
40057
40120
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40121
|
+
this.updateCompilationParameters();
|
|
40058
40122
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40059
40123
|
this.nextPositionsToUpdate.clear();
|
|
40060
40124
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40122,7 +40186,7 @@
|
|
|
40122
40186
|
const position = this.compilationParams[2].getters.getCellPosition(cellId);
|
|
40123
40187
|
return toXC(position.col, position.row);
|
|
40124
40188
|
};
|
|
40125
|
-
const formulaReturn = cellData.compiledFormula.execute(cellData.dependencies, ...this.compilationParams);
|
|
40189
|
+
const formulaReturn = cellData.compiledFormula.execute(cellData.compiledFormula.dependencies, ...this.compilationParams);
|
|
40126
40190
|
if (!isMatrix(formulaReturn)) {
|
|
40127
40191
|
return createEvaluatedCell(formulaReturn.value, {
|
|
40128
40192
|
format: cellData.format || formulaReturn.format,
|
|
@@ -40222,7 +40286,7 @@
|
|
|
40222
40286
|
return [];
|
|
40223
40287
|
}
|
|
40224
40288
|
const dependencies = [];
|
|
40225
|
-
for (const range of cell.dependencies) {
|
|
40289
|
+
for (const range of cell.compiledFormula.dependencies) {
|
|
40226
40290
|
if (range.invalidSheetName || range.invalidXc) {
|
|
40227
40291
|
continue;
|
|
40228
40292
|
}
|
|
@@ -40418,7 +40482,6 @@
|
|
|
40418
40482
|
// of other cells depending on it, at the next iteration.
|
|
40419
40483
|
//#endregion
|
|
40420
40484
|
class EvaluationPlugin extends UIPlugin {
|
|
40421
|
-
config;
|
|
40422
40485
|
static getters = [
|
|
40423
40486
|
"evaluateFormula",
|
|
40424
40487
|
"getCorrespondingFormulaCell",
|
|
@@ -40428,15 +40491,14 @@
|
|
|
40428
40491
|
"getEvaluatedCell",
|
|
40429
40492
|
"getEvaluatedCells",
|
|
40430
40493
|
"getEvaluatedCellsInZone",
|
|
40494
|
+
"getSpreadPositionsOf",
|
|
40495
|
+
"getArrayFormulaSpreadingOn",
|
|
40431
40496
|
];
|
|
40432
40497
|
shouldRebuildDependenciesGraph = true;
|
|
40433
40498
|
evaluator;
|
|
40434
|
-
compilationParams;
|
|
40435
40499
|
positionsToUpdate = [];
|
|
40436
40500
|
constructor(config) {
|
|
40437
40501
|
super(config);
|
|
40438
|
-
this.config = config;
|
|
40439
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40440
40502
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40441
40503
|
}
|
|
40442
40504
|
// ---------------------------------------------------------------------------
|
|
@@ -40461,10 +40523,6 @@
|
|
|
40461
40523
|
case "EVALUATE_CELLS":
|
|
40462
40524
|
this.evaluator.evaluateAllCells();
|
|
40463
40525
|
break;
|
|
40464
|
-
case "UPDATE_LOCALE":
|
|
40465
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40466
|
-
this.evaluator.updateCompilationParameters();
|
|
40467
|
-
break;
|
|
40468
40526
|
}
|
|
40469
40527
|
}
|
|
40470
40528
|
finalize() {
|
|
@@ -40482,16 +40540,7 @@
|
|
|
40482
40540
|
// Getters
|
|
40483
40541
|
// ---------------------------------------------------------------------------
|
|
40484
40542
|
evaluateFormula(sheetId, formulaString) {
|
|
40485
|
-
|
|
40486
|
-
const ranges = [];
|
|
40487
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40488
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40489
|
-
}
|
|
40490
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40491
|
-
if (isMatrix(array)) {
|
|
40492
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40493
|
-
}
|
|
40494
|
-
return array.value;
|
|
40543
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40495
40544
|
}
|
|
40496
40545
|
/**
|
|
40497
40546
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40537,6 +40586,12 @@
|
|
|
40537
40586
|
getEvaluatedCellsInZone(sheetId, zone) {
|
|
40538
40587
|
return positions(zone).map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId, col, row }));
|
|
40539
40588
|
}
|
|
40589
|
+
getSpreadPositionsOf(position) {
|
|
40590
|
+
return this.evaluator.getSpreadPositionsOf(position);
|
|
40591
|
+
}
|
|
40592
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40593
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40594
|
+
}
|
|
40540
40595
|
// ---------------------------------------------------------------------------
|
|
40541
40596
|
// Export
|
|
40542
40597
|
// ---------------------------------------------------------------------------
|
|
@@ -40574,13 +40629,13 @@
|
|
|
40574
40629
|
*/
|
|
40575
40630
|
getCorrespondingFormulaCell(position) {
|
|
40576
40631
|
const cell = this.getters.getCell(position);
|
|
40577
|
-
if (cell && cell.
|
|
40578
|
-
|
|
40579
|
-
|
|
40580
|
-
|
|
40632
|
+
if (cell && cell.isFormula) {
|
|
40633
|
+
return isBadExpression(cell.compiledFormula.tokens) ? undefined : cell;
|
|
40634
|
+
}
|
|
40635
|
+
else if (cell && cell.content) {
|
|
40581
40636
|
return undefined;
|
|
40582
40637
|
}
|
|
40583
|
-
const spreadingFormulaPosition = this.
|
|
40638
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40584
40639
|
if (spreadingFormulaPosition === undefined) {
|
|
40585
40640
|
return undefined;
|
|
40586
40641
|
}
|
|
@@ -40590,13 +40645,10 @@
|
|
|
40590
40645
|
}
|
|
40591
40646
|
return undefined;
|
|
40592
40647
|
}
|
|
40593
|
-
getCompilationParameters() {
|
|
40594
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40595
|
-
}
|
|
40596
40648
|
}
|
|
40597
|
-
function isBadExpression(
|
|
40649
|
+
function isBadExpression(tokens) {
|
|
40598
40650
|
try {
|
|
40599
|
-
|
|
40651
|
+
compileTokens(tokens);
|
|
40600
40652
|
return false;
|
|
40601
40653
|
}
|
|
40602
40654
|
catch (error) {
|
|
@@ -40765,22 +40817,20 @@
|
|
|
40765
40817
|
invalidateCFEvaluationCommands.has(cmd.type) ||
|
|
40766
40818
|
cmd.type === "EVALUATE_CELLS" ||
|
|
40767
40819
|
cmd.type === "UPDATE_CELL") {
|
|
40768
|
-
|
|
40769
|
-
|
|
40770
|
-
this.history.update("charts", chartId, undefined);
|
|
40771
|
-
}
|
|
40820
|
+
for (const chartId in this.charts) {
|
|
40821
|
+
this.charts[chartId] = undefined;
|
|
40772
40822
|
}
|
|
40773
40823
|
}
|
|
40774
40824
|
switch (cmd.type) {
|
|
40775
40825
|
case "UPDATE_CHART":
|
|
40776
40826
|
case "CREATE_CHART":
|
|
40777
40827
|
case "DELETE_FIGURE":
|
|
40778
|
-
this.
|
|
40828
|
+
this.charts[cmd.id] = undefined;
|
|
40779
40829
|
break;
|
|
40780
40830
|
case "DELETE_SHEET":
|
|
40781
40831
|
for (let chartId in this.charts) {
|
|
40782
40832
|
if (!this.getters.isChartDefined(chartId)) {
|
|
40783
|
-
this.
|
|
40833
|
+
this.charts[chartId] = undefined;
|
|
40784
40834
|
}
|
|
40785
40835
|
}
|
|
40786
40836
|
break;
|
|
@@ -40792,8 +40842,7 @@
|
|
|
40792
40842
|
if (!chart) {
|
|
40793
40843
|
throw new Error(`No chart for the given id: ${figureId}`);
|
|
40794
40844
|
}
|
|
40795
|
-
|
|
40796
|
-
this.history.update("charts", figureId, runtime);
|
|
40845
|
+
this.charts[figureId] = this.createRuntimeChart(chart);
|
|
40797
40846
|
}
|
|
40798
40847
|
return this.charts[figureId];
|
|
40799
40848
|
}
|
|
@@ -40945,7 +40994,10 @@
|
|
|
40945
40994
|
const values = cf.rule.values.map((value, i) => {
|
|
40946
40995
|
const compiledFormula = formulas[i];
|
|
40947
40996
|
if (compiledFormula) {
|
|
40948
|
-
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top,
|
|
40997
|
+
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top, {
|
|
40998
|
+
...compiledFormula,
|
|
40999
|
+
dependencies: compiledFormula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
41000
|
+
});
|
|
40949
41001
|
}
|
|
40950
41002
|
return value;
|
|
40951
41003
|
});
|
|
@@ -41317,7 +41369,10 @@
|
|
|
41317
41369
|
}
|
|
41318
41370
|
try {
|
|
41319
41371
|
const formula = compile(value);
|
|
41320
|
-
const translatedFormula = this.getters.getTranslatedCellFormula(sheetId, offset.col, offset.row,
|
|
41372
|
+
const translatedFormula = this.getters.getTranslatedCellFormula(sheetId, offset.col, offset.row, {
|
|
41373
|
+
...formula,
|
|
41374
|
+
dependencies: formula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
41375
|
+
});
|
|
41321
41376
|
const evaluated = this.getters.evaluateFormula(sheetId, translatedFormula);
|
|
41322
41377
|
return evaluated && !isMatrix(evaluated) ? evaluated.toString() : "";
|
|
41323
41378
|
}
|
|
@@ -43288,11 +43343,26 @@
|
|
|
43288
43343
|
let cellsInRow = [];
|
|
43289
43344
|
for (let col of columnsIndex) {
|
|
43290
43345
|
const position = { col, row, sheetId };
|
|
43346
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43347
|
+
let cell = getters.getCell(position);
|
|
43348
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43349
|
+
if (spreader) {
|
|
43350
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43351
|
+
const content = isSpreaderCopied
|
|
43352
|
+
? ""
|
|
43353
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43354
|
+
cell = {
|
|
43355
|
+
id: cell?.id || "",
|
|
43356
|
+
style: cell?.style,
|
|
43357
|
+
format: evaluatedCell.format,
|
|
43358
|
+
content,
|
|
43359
|
+
isFormula: false,
|
|
43360
|
+
};
|
|
43361
|
+
}
|
|
43291
43362
|
cellsInRow.push({
|
|
43292
|
-
cell
|
|
43293
|
-
style: getters.getCellComputedStyle(position),
|
|
43294
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43363
|
+
cell,
|
|
43295
43364
|
border: getters.getCellBorder(position) || undefined,
|
|
43365
|
+
evaluatedCell,
|
|
43296
43366
|
position,
|
|
43297
43367
|
});
|
|
43298
43368
|
}
|
|
@@ -43414,13 +43484,6 @@
|
|
|
43414
43484
|
});
|
|
43415
43485
|
}
|
|
43416
43486
|
this.pasteCopiedTables(target);
|
|
43417
|
-
this.cells.forEach((row) => {
|
|
43418
|
-
row.forEach((c) => {
|
|
43419
|
-
if (c.cell) {
|
|
43420
|
-
c.cell = undefined;
|
|
43421
|
-
}
|
|
43422
|
-
});
|
|
43423
|
-
});
|
|
43424
43487
|
}
|
|
43425
43488
|
/**
|
|
43426
43489
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43492,7 +43555,7 @@
|
|
|
43492
43555
|
clearClippedZones() {
|
|
43493
43556
|
for (const row of this.cells) {
|
|
43494
43557
|
for (const cell of row) {
|
|
43495
|
-
if (cell
|
|
43558
|
+
if (cell?.cell) {
|
|
43496
43559
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43497
43560
|
}
|
|
43498
43561
|
}
|
|
@@ -43518,6 +43581,9 @@
|
|
|
43518
43581
|
const rowCells = this.cells[r];
|
|
43519
43582
|
for (let c = 0; c < width; c++) {
|
|
43520
43583
|
const origin = rowCells[c];
|
|
43584
|
+
if (!origin) {
|
|
43585
|
+
continue;
|
|
43586
|
+
}
|
|
43521
43587
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43522
43588
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43523
43589
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43541,53 +43607,42 @@
|
|
|
43541
43607
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43542
43608
|
const { sheetId, col, row } = target;
|
|
43543
43609
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43544
|
-
if (clipboardOption?.pasteOption
|
|
43545
|
-
const
|
|
43546
|
-
const
|
|
43547
|
-
|
|
43548
|
-
|
|
43549
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43550
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43551
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43552
|
-
};
|
|
43553
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43610
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43611
|
+
const locale = this.getters.getLocale();
|
|
43612
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43613
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43614
|
+
return;
|
|
43554
43615
|
}
|
|
43555
|
-
|
|
43556
|
-
|
|
43557
|
-
|
|
43558
|
-
|
|
43559
|
-
|
|
43560
|
-
|
|
43561
|
-
|
|
43562
|
-
|
|
43563
|
-
|
|
43564
|
-
|
|
43565
|
-
|
|
43566
|
-
|
|
43567
|
-
|
|
43568
|
-
|
|
43569
|
-
}
|
|
43570
|
-
|
|
43571
|
-
|
|
43572
|
-
|
|
43573
|
-
|
|
43616
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43617
|
+
const originBorders = origin.border;
|
|
43618
|
+
const border = {
|
|
43619
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43620
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43621
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43622
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43623
|
+
};
|
|
43624
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43625
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43626
|
+
this.dispatch("UPDATE_CELL", {
|
|
43627
|
+
...target,
|
|
43628
|
+
style: origin.cell?.style ?? null,
|
|
43629
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43630
|
+
});
|
|
43631
|
+
return;
|
|
43632
|
+
}
|
|
43633
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43634
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43635
|
+
: origin.cell?.content;
|
|
43636
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43574
43637
|
this.dispatch("UPDATE_CELL", {
|
|
43575
43638
|
...target,
|
|
43576
43639
|
content,
|
|
43577
|
-
style: origin.cell
|
|
43578
|
-
format: origin.cell
|
|
43640
|
+
style: origin.cell?.style || null,
|
|
43641
|
+
format: origin.cell?.format,
|
|
43579
43642
|
});
|
|
43580
43643
|
}
|
|
43581
43644
|
else if (targetCell) {
|
|
43582
|
-
|
|
43583
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43584
|
-
}
|
|
43585
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43586
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43587
|
-
}
|
|
43588
|
-
else {
|
|
43589
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43590
|
-
}
|
|
43645
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43591
43646
|
}
|
|
43592
43647
|
}
|
|
43593
43648
|
/**
|
|
@@ -43649,22 +43704,28 @@
|
|
|
43649
43704
|
return (this.cells
|
|
43650
43705
|
.map((cells) => {
|
|
43651
43706
|
return cells
|
|
43652
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43707
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43653
43708
|
? c.cell?.content || ""
|
|
43654
|
-
: c
|
|
43709
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43655
43710
|
.join("\t");
|
|
43656
43711
|
})
|
|
43657
43712
|
.join("\n") || "\t");
|
|
43658
43713
|
}
|
|
43659
43714
|
getHTMLContent() {
|
|
43660
43715
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43716
|
+
if (!this.cells[0][0]) {
|
|
43717
|
+
return "";
|
|
43718
|
+
}
|
|
43661
43719
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43662
43720
|
}
|
|
43663
43721
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43664
43722
|
for (const row of this.cells) {
|
|
43665
43723
|
htmlTable += "<tr>";
|
|
43666
43724
|
for (const cell of row) {
|
|
43667
|
-
|
|
43725
|
+
if (!cell) {
|
|
43726
|
+
continue;
|
|
43727
|
+
}
|
|
43728
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43668
43729
|
const cellText = this.getters.getCellText(cell.position);
|
|
43669
43730
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43670
43731
|
}
|
|
@@ -44101,20 +44162,29 @@
|
|
|
44101
44162
|
const sheetId = this.getters.getActiveSheetId();
|
|
44102
44163
|
const cells = this.getters.getCells(sheetId);
|
|
44103
44164
|
const matches = [];
|
|
44104
|
-
if (this.toSearch) {
|
|
44165
|
+
if (this.toSearch && this.currentSearchRegex) {
|
|
44105
44166
|
for (const cell of Object.values(cells)) {
|
|
44106
44167
|
const { col, row } = this.getters.getCellPosition(cell.id);
|
|
44168
|
+
const cellPosition = { sheetId, col, row };
|
|
44107
44169
|
const isColHidden = this.getters.isColHidden(sheetId, col);
|
|
44108
44170
|
const isRowHidden = this.getters.isRowHidden(sheetId, row);
|
|
44109
44171
|
if (isColHidden || isRowHidden) {
|
|
44110
44172
|
continue;
|
|
44111
44173
|
}
|
|
44112
|
-
if (
|
|
44113
|
-
this.currentSearchRegex &&
|
|
44114
|
-
this.currentSearchRegex.test(this.getSearchableString({ sheetId, col, row }))) {
|
|
44174
|
+
if (this.currentSearchRegex.test(this.getSearchableString(cellPosition))) {
|
|
44115
44175
|
const match = { col, row, selected: false };
|
|
44116
44176
|
matches.push(match);
|
|
44117
44177
|
}
|
|
44178
|
+
for (const spreadPosition of this.getters.getSpreadPositionsOf(cellPosition)) {
|
|
44179
|
+
if (this.currentSearchRegex.test(this.getSearchableString(spreadPosition))) {
|
|
44180
|
+
const match = {
|
|
44181
|
+
col: spreadPosition.col,
|
|
44182
|
+
row: spreadPosition.row,
|
|
44183
|
+
selected: false,
|
|
44184
|
+
};
|
|
44185
|
+
matches.push(match);
|
|
44186
|
+
}
|
|
44187
|
+
}
|
|
44118
44188
|
}
|
|
44119
44189
|
}
|
|
44120
44190
|
return matches.sort(this.sortByRowThenColumn);
|
|
@@ -44173,16 +44243,19 @@
|
|
|
44173
44243
|
return;
|
|
44174
44244
|
}
|
|
44175
44245
|
const sheetId = this.getters.getActiveSheetId();
|
|
44176
|
-
const
|
|
44177
|
-
const
|
|
44246
|
+
const position = { sheetId, ...selectedMatch };
|
|
44247
|
+
const cell = this.getters.getCell(position);
|
|
44248
|
+
if (!cell?.content) {
|
|
44249
|
+
return;
|
|
44250
|
+
}
|
|
44178
44251
|
if (cell?.isFormula && !this.searchOptions.searchFormulas) {
|
|
44179
44252
|
return;
|
|
44180
44253
|
}
|
|
44181
44254
|
const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
|
|
44182
|
-
const toReplace = this.getSearchableString(
|
|
44255
|
+
const toReplace = this.getSearchableString(position);
|
|
44183
44256
|
const content = toReplace.replace(replaceRegex, replaceWith);
|
|
44184
44257
|
const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
|
|
44185
|
-
this.dispatch("UPDATE_CELL", {
|
|
44258
|
+
this.dispatch("UPDATE_CELL", { ...position, content: canonicalContent });
|
|
44186
44259
|
}
|
|
44187
44260
|
/**
|
|
44188
44261
|
* Replace the value of the currently selected match
|
|
@@ -45757,7 +45830,7 @@
|
|
|
45757
45830
|
if (cell.isFormula) {
|
|
45758
45831
|
const position = this.getters.getCellPosition(cell.id);
|
|
45759
45832
|
// we only have a vertical offset
|
|
45760
|
-
content = this.getters.getTranslatedCellFormula(sheetId, 0, newRow - position.row, cell.compiledFormula
|
|
45833
|
+
content = this.getters.getTranslatedCellFormula(sheetId, 0, newRow - position.row, cell.compiledFormula);
|
|
45761
45834
|
}
|
|
45762
45835
|
newCellValues.style = cell.style;
|
|
45763
45836
|
newCellValues.content = content;
|
|
@@ -46782,11 +46855,14 @@
|
|
|
46782
46855
|
}
|
|
46783
46856
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46784
46857
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
46858
|
+
if (this.state.operation === "CUT") {
|
|
46859
|
+
this.state = undefined;
|
|
46860
|
+
}
|
|
46785
46861
|
this.lastPasteState = this.state;
|
|
46786
46862
|
if (this.paintFormatStatus === "oneOff") {
|
|
46787
46863
|
this.paintFormatStatus = "inactive";
|
|
46788
|
-
this.status = "invisible";
|
|
46789
46864
|
}
|
|
46865
|
+
this.status = "invisible";
|
|
46790
46866
|
break;
|
|
46791
46867
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46792
46868
|
{
|
|
@@ -47820,6 +47896,8 @@
|
|
|
47820
47896
|
case "EVALUATE_CELLS":
|
|
47821
47897
|
case "ACTIVATE_SHEET":
|
|
47822
47898
|
case "REMOVE_FILTER_TABLE":
|
|
47899
|
+
case "ADD_COLUMNS_ROWS":
|
|
47900
|
+
case "REMOVE_COLUMNS_ROWS":
|
|
47823
47901
|
this.isEvaluationDirty = true;
|
|
47824
47902
|
break;
|
|
47825
47903
|
case "START":
|
|
@@ -55508,19 +55586,22 @@
|
|
|
55508
55586
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55509
55587
|
*/
|
|
55510
55588
|
checkDispatchAllowed(command) {
|
|
55511
|
-
|
|
55512
|
-
|
|
55589
|
+
const results = isCoreCommand(command)
|
|
55590
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55591
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55592
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55593
|
+
return new DispatchResult(results.flat());
|
|
55513
55594
|
}
|
|
55514
|
-
return
|
|
55595
|
+
return DispatchResult.Success;
|
|
55515
55596
|
}
|
|
55516
55597
|
checkDispatchAllowedCoreCommand(command) {
|
|
55517
55598
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55518
55599
|
results.push(this.range.allowDispatch(command));
|
|
55519
|
-
return
|
|
55600
|
+
return results;
|
|
55520
55601
|
}
|
|
55521
55602
|
checkDispatchAllowedLocalCommand(command) {
|
|
55522
55603
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55523
|
-
return
|
|
55604
|
+
return results;
|
|
55524
55605
|
}
|
|
55525
55606
|
finalize() {
|
|
55526
55607
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55843,6 +55924,7 @@
|
|
|
55843
55924
|
exports.addFunction = addFunction;
|
|
55844
55925
|
exports.astToFormula = astToFormula;
|
|
55845
55926
|
exports.compile = compile;
|
|
55927
|
+
exports.compileTokens = compileTokens;
|
|
55846
55928
|
exports.components = components;
|
|
55847
55929
|
exports.constants = constants;
|
|
55848
55930
|
exports.convertAstNodes = convertAstNodes;
|
|
@@ -55858,6 +55940,7 @@
|
|
|
55858
55940
|
exports.links = links;
|
|
55859
55941
|
exports.load = load;
|
|
55860
55942
|
exports.parse = parse;
|
|
55943
|
+
exports.parseTokens = parseTokens;
|
|
55861
55944
|
exports.readonlyAllowedCommands = readonlyAllowedCommands;
|
|
55862
55945
|
exports.registries = registries;
|
|
55863
55946
|
exports.setDefaultSheetViewSize = setDefaultSheetViewSize;
|
|
@@ -55865,9 +55948,9 @@
|
|
|
55865
55948
|
exports.tokenize = tokenize;
|
|
55866
55949
|
|
|
55867
55950
|
|
|
55868
|
-
__info__.version = "17.0.
|
|
55869
|
-
__info__.date = "2023-11-
|
|
55870
|
-
__info__.hash = "
|
|
55951
|
+
__info__.version = "17.0.4";
|
|
55952
|
+
__info__.date = "2023-11-24T13:13:42.575Z";
|
|
55953
|
+
__info__.hash = "7346d0a";
|
|
55871
55954
|
|
|
55872
55955
|
|
|
55873
55956
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|