@odoo/o-spreadsheet 16.3.17 → 16.3.22
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 +318 -196
- package/dist/o-spreadsheet.d.ts +49 -25
- package/dist/o-spreadsheet.esm.js +318 -196
- package/dist/o-spreadsheet.iife.js +318 -196
- package/dist/o-spreadsheet.iife.min.js +256 -256
- package/dist/o_spreadsheet.xml +6 -7
- package/package.json +1 -1
|
@@ -298,15 +298,80 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
298
298
|
// -----------------------------------------------------------------------------
|
|
299
299
|
// Date Type
|
|
300
300
|
// -----------------------------------------------------------------------------
|
|
301
|
+
/**
|
|
302
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
303
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
304
|
+
* and it is timezone-agnostic.
|
|
305
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
306
|
+
*/
|
|
307
|
+
class DateTime {
|
|
308
|
+
jsDate;
|
|
309
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
310
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
311
|
+
}
|
|
312
|
+
static fromTimestamp(timestamp) {
|
|
313
|
+
const date = new Date(timestamp);
|
|
314
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
315
|
+
}
|
|
316
|
+
static now() {
|
|
317
|
+
const now = new Date();
|
|
318
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
319
|
+
}
|
|
320
|
+
toString() {
|
|
321
|
+
return this.jsDate.toString();
|
|
322
|
+
}
|
|
323
|
+
toLocaleDateString() {
|
|
324
|
+
return this.jsDate.toLocaleDateString();
|
|
325
|
+
}
|
|
326
|
+
getTime() {
|
|
327
|
+
return this.jsDate.getTime();
|
|
328
|
+
}
|
|
329
|
+
getFullYear() {
|
|
330
|
+
return this.jsDate.getUTCFullYear();
|
|
331
|
+
}
|
|
332
|
+
getMonth() {
|
|
333
|
+
return this.jsDate.getUTCMonth();
|
|
334
|
+
}
|
|
335
|
+
getDate() {
|
|
336
|
+
return this.jsDate.getUTCDate();
|
|
337
|
+
}
|
|
338
|
+
getDay() {
|
|
339
|
+
return this.jsDate.getUTCDay();
|
|
340
|
+
}
|
|
341
|
+
getHours() {
|
|
342
|
+
return this.jsDate.getUTCHours();
|
|
343
|
+
}
|
|
344
|
+
getMinutes() {
|
|
345
|
+
return this.jsDate.getUTCMinutes();
|
|
346
|
+
}
|
|
347
|
+
getSeconds() {
|
|
348
|
+
return this.jsDate.getUTCSeconds();
|
|
349
|
+
}
|
|
350
|
+
setFullYear(year) {
|
|
351
|
+
this.jsDate.setFullYear(year);
|
|
352
|
+
}
|
|
353
|
+
setDate(date) {
|
|
354
|
+
this.jsDate.setUTCDate(date);
|
|
355
|
+
}
|
|
356
|
+
setHours(hours) {
|
|
357
|
+
this.jsDate.setUTCHours(hours);
|
|
358
|
+
}
|
|
359
|
+
setMinutes(minutes) {
|
|
360
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
361
|
+
}
|
|
362
|
+
setSeconds(seconds) {
|
|
363
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
301
366
|
// -----------------------------------------------------------------------------
|
|
302
367
|
// Parsing
|
|
303
368
|
// -----------------------------------------------------------------------------
|
|
304
|
-
const INITIAL_1900_DAY = new
|
|
369
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
305
370
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
306
371
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
307
|
-
const CURRENT_YEAR =
|
|
308
|
-
const INITIAL_JS_DAY =
|
|
309
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
372
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
373
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
374
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
310
375
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
311
376
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
312
377
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -355,7 +420,7 @@ function _parseDateTime(str) {
|
|
|
355
420
|
return {
|
|
356
421
|
value: date.value + time.value,
|
|
357
422
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
358
|
-
jsDate: new
|
|
423
|
+
jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
|
|
359
424
|
};
|
|
360
425
|
}
|
|
361
426
|
return date || time;
|
|
@@ -372,13 +437,13 @@ function parseDate(str, dateFormat) {
|
|
|
372
437
|
const day = Number(parts[dayIndex]);
|
|
373
438
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
374
439
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
375
|
-
const jsDate = new
|
|
440
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
376
441
|
const sep = str.match(/\/|-|\s/)[0];
|
|
377
442
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
378
443
|
// invalid date
|
|
379
444
|
return null;
|
|
380
445
|
}
|
|
381
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
446
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
382
447
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
383
448
|
if (parts[yearIndex]) {
|
|
384
449
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -438,7 +503,7 @@ function parseTime(str) {
|
|
|
438
503
|
if (hours >= 24) {
|
|
439
504
|
format = "hhhh:mm:ss";
|
|
440
505
|
}
|
|
441
|
-
const jsDate = new
|
|
506
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
442
507
|
return {
|
|
443
508
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
444
509
|
format: format,
|
|
@@ -452,7 +517,7 @@ function parseTime(str) {
|
|
|
452
517
|
// -----------------------------------------------------------------------------
|
|
453
518
|
function numberToJsDate(value) {
|
|
454
519
|
const truncValue = Math.trunc(value);
|
|
455
|
-
let date =
|
|
520
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
456
521
|
let time = value - truncValue;
|
|
457
522
|
time = time < 0 ? 1 + time : time;
|
|
458
523
|
const hours = Math.round(time * 24);
|
|
@@ -469,7 +534,7 @@ function jsDateToRoundNumber(date) {
|
|
|
469
534
|
}
|
|
470
535
|
/** Return the number of days in the current month of the given date */
|
|
471
536
|
function getDaysInMonth(date) {
|
|
472
|
-
return new
|
|
537
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
473
538
|
}
|
|
474
539
|
function isLastDayOfMonth(date) {
|
|
475
540
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -487,7 +552,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
487
552
|
const yStart = date.getFullYear();
|
|
488
553
|
const mStart = date.getMonth();
|
|
489
554
|
const dStart = date.getDate();
|
|
490
|
-
const jsDate = new
|
|
555
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
491
556
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
492
557
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
493
558
|
}
|
|
@@ -647,13 +712,6 @@ function areTwoDatesWithinOneYear(startDate, endDate) {
|
|
|
647
712
|
}
|
|
648
713
|
|
|
649
714
|
//------------------------------------------------------------------------------
|
|
650
|
-
/**
|
|
651
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
652
|
-
* is ordered.
|
|
653
|
-
*/
|
|
654
|
-
function stringify(obj) {
|
|
655
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
656
|
-
}
|
|
657
715
|
/**
|
|
658
716
|
* Remove quotes from a quoted string
|
|
659
717
|
* ```js
|
|
@@ -883,7 +941,7 @@ function isBoolean(str) {
|
|
|
883
941
|
function isDateTime(str) {
|
|
884
942
|
return parseDateTime(str) !== null;
|
|
885
943
|
}
|
|
886
|
-
const MARKDOWN_LINK_REGEX = /^\[(
|
|
944
|
+
const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
|
|
887
945
|
//link must start with http or https
|
|
888
946
|
//https://stackoverflow.com/a/3809435/4760614
|
|
889
947
|
const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
|
|
@@ -952,7 +1010,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
952
1010
|
*/
|
|
953
1011
|
function getItemId(item, itemsDic) {
|
|
954
1012
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
955
|
-
if (
|
|
1013
|
+
if (deepEquals(value, item)) {
|
|
956
1014
|
return parseInt(key, 10);
|
|
957
1015
|
}
|
|
958
1016
|
}
|
|
@@ -1018,6 +1076,22 @@ function lazy(fn) {
|
|
|
1018
1076
|
lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
|
|
1019
1077
|
return lazyValue;
|
|
1020
1078
|
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Creates a version of the function that's memoized on the value of its first
|
|
1081
|
+
* argument, if any.
|
|
1082
|
+
*/
|
|
1083
|
+
function memoize(func) {
|
|
1084
|
+
const cache = new Map();
|
|
1085
|
+
const funcName = func.name ? func.name + " (memoized)" : "memoized";
|
|
1086
|
+
return {
|
|
1087
|
+
[funcName](...args) {
|
|
1088
|
+
if (!cache.has(args[0])) {
|
|
1089
|
+
cache.set(args[0], func(...args));
|
|
1090
|
+
}
|
|
1091
|
+
return cache.get(args[0]);
|
|
1092
|
+
},
|
|
1093
|
+
}[funcName];
|
|
1094
|
+
}
|
|
1021
1095
|
/**
|
|
1022
1096
|
* Find the next defined value after the given index in an array of strings. If there is no defined value
|
|
1023
1097
|
* after the index, return the closest defined value before the index. Return an empty string if no
|
|
@@ -1936,7 +2010,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1936
2010
|
.map((p) => {
|
|
1937
2011
|
switch (p) {
|
|
1938
2012
|
case "hhhh":
|
|
1939
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
2013
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1940
2014
|
return helapsedHours.toString();
|
|
1941
2015
|
case "hh":
|
|
1942
2016
|
return hours.toString().padStart(2, "0");
|
|
@@ -2183,8 +2257,10 @@ function convertInternalFormatToFormat(internalFormat) {
|
|
|
2183
2257
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
2184
2258
|
// Same as above, but matches the exact string (nothing before or after)
|
|
2185
2259
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
2186
|
-
/** Reference of a column header (eg. A, AB) */
|
|
2187
|
-
const colHeader = new RegExp(
|
|
2260
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
2261
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
2262
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
2263
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
2188
2264
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
2189
2265
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
2190
2266
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -2214,6 +2290,9 @@ function isRowReference(xc) {
|
|
|
2214
2290
|
function isColHeader(str) {
|
|
2215
2291
|
return colHeader.test(str);
|
|
2216
2292
|
}
|
|
2293
|
+
function isRowHeader(str) {
|
|
2294
|
+
return rowHeader.test(str);
|
|
2295
|
+
}
|
|
2217
2296
|
/**
|
|
2218
2297
|
* Return true if the given xc is the reference of a single cell,
|
|
2219
2298
|
* without any specified sheet (e.g. A1)
|
|
@@ -2280,18 +2359,10 @@ class RangeImpl {
|
|
|
2280
2359
|
if (isFullCol) {
|
|
2281
2360
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2282
2361
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2283
|
-
if (zone.left === zone.right) {
|
|
2284
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2285
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2286
|
-
}
|
|
2287
2362
|
}
|
|
2288
2363
|
if (isFullRow) {
|
|
2289
2364
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2290
2365
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2291
|
-
if (zone.top === zone.bottom) {
|
|
2292
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2293
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2294
|
-
}
|
|
2295
2366
|
}
|
|
2296
2367
|
return parts;
|
|
2297
2368
|
}
|
|
@@ -3690,12 +3761,12 @@ function toString(value) {
|
|
|
3690
3761
|
}
|
|
3691
3762
|
}
|
|
3692
3763
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
3693
|
-
function normalizeString(str) {
|
|
3764
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
3694
3765
|
return str
|
|
3695
3766
|
.toLowerCase()
|
|
3696
3767
|
.normalize("NFD")
|
|
3697
3768
|
.replace(/[\u0300-\u036f]/g, "");
|
|
3698
|
-
}
|
|
3769
|
+
});
|
|
3699
3770
|
/**
|
|
3700
3771
|
* Normalize a value.
|
|
3701
3772
|
* If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
|
|
@@ -4426,6 +4497,7 @@ var CommandResult;
|
|
|
4426
4497
|
CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
|
|
4427
4498
|
CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
|
|
4428
4499
|
CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
|
|
4500
|
+
CommandResult[CommandResult["NoChanges"] = 93] = "NoChanges";
|
|
4429
4501
|
})(CommandResult || (CommandResult = {}));
|
|
4430
4502
|
|
|
4431
4503
|
const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
@@ -5150,6 +5222,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
5150
5222
|
},
|
|
5151
5223
|
};
|
|
5152
5224
|
|
|
5225
|
+
const macRegex = /Mac/i;
|
|
5153
5226
|
/**
|
|
5154
5227
|
* Return true if the event was triggered from
|
|
5155
5228
|
* a child element.
|
|
@@ -5195,6 +5268,17 @@ function setElementScrollTop(el, scroll) {
|
|
|
5195
5268
|
}
|
|
5196
5269
|
function getOpenedMenus() {
|
|
5197
5270
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5271
|
+
}
|
|
5272
|
+
function isMacOS() {
|
|
5273
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5274
|
+
}
|
|
5275
|
+
/**
|
|
5276
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5277
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5278
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5279
|
+
*/
|
|
5280
|
+
function isCtrlKey(ev) {
|
|
5281
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5198
5282
|
}
|
|
5199
5283
|
|
|
5200
5284
|
/**
|
|
@@ -9581,6 +9665,9 @@ function arg(definition, description = "") {
|
|
|
9581
9665
|
function makeArg(str, description) {
|
|
9582
9666
|
let parts = str.match(ARG_REGEXP);
|
|
9583
9667
|
let name = parts[1].trim();
|
|
9668
|
+
if (!name) {
|
|
9669
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
9670
|
+
}
|
|
9584
9671
|
let types = [];
|
|
9585
9672
|
let isOptional = false;
|
|
9586
9673
|
let isRepeating = false;
|
|
@@ -12034,7 +12121,7 @@ const DATE = {
|
|
|
12034
12121
|
if (_year < 1900) {
|
|
12035
12122
|
_year += 1900;
|
|
12036
12123
|
}
|
|
12037
|
-
const jsDate = new
|
|
12124
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
12038
12125
|
const result = jsDateToRoundNumber(jsDate);
|
|
12039
12126
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
12040
12127
|
return result;
|
|
@@ -12077,7 +12164,7 @@ const DATEDIF = {
|
|
|
12077
12164
|
// See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
|
|
12078
12165
|
let days = jsEndDate.getDate() - jsStartDate.getDate();
|
|
12079
12166
|
if (days < 0) {
|
|
12080
|
-
const monthBeforeEndMonth = new
|
|
12167
|
+
const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
|
|
12081
12168
|
const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
|
|
12082
12169
|
days = daysInMonthBeforeEndMonth - Math.abs(days);
|
|
12083
12170
|
}
|
|
@@ -12086,7 +12173,7 @@ const DATEDIF = {
|
|
|
12086
12173
|
if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
|
|
12087
12174
|
return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
|
|
12088
12175
|
}
|
|
12089
|
-
const endDateWithinOneYear = new
|
|
12176
|
+
const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
|
|
12090
12177
|
let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
|
|
12091
12178
|
if (days < 0) {
|
|
12092
12179
|
endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
|
|
@@ -12199,7 +12286,7 @@ const EOMONTH = {
|
|
|
12199
12286
|
const _months = Math.trunc(toNumber(months));
|
|
12200
12287
|
const yStart = _startDate.getFullYear();
|
|
12201
12288
|
const mStart = _startDate.getMonth();
|
|
12202
|
-
const jsDate = new
|
|
12289
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
12203
12290
|
return jsDateToRoundNumber(jsDate);
|
|
12204
12291
|
},
|
|
12205
12292
|
isExported: true,
|
|
@@ -12236,17 +12323,17 @@ const ISOWEEKNUM = {
|
|
|
12236
12323
|
// The first week of the year is the week that contains the first
|
|
12237
12324
|
// Thursday of the year.
|
|
12238
12325
|
let firstThursday = 1;
|
|
12239
|
-
while (new
|
|
12326
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
12240
12327
|
firstThursday += 1;
|
|
12241
12328
|
}
|
|
12242
|
-
const firstDayOfFirstWeek = new
|
|
12329
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
12243
12330
|
// The last week of the year is the week that contains the last Thursday of
|
|
12244
12331
|
// the year.
|
|
12245
12332
|
let lastThursday = 31;
|
|
12246
|
-
while (new
|
|
12333
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
12247
12334
|
lastThursday -= 1;
|
|
12248
12335
|
}
|
|
12249
|
-
const lastDayOfLastWeek = new
|
|
12336
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
12250
12337
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
12251
12338
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
12252
12339
|
let offsetYear;
|
|
@@ -12272,17 +12359,17 @@ const ISOWEEKNUM = {
|
|
|
12272
12359
|
case 1:
|
|
12273
12360
|
// firstDay is the 1st day of the 1st week of the year after
|
|
12274
12361
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
12275
|
-
firstDay = new
|
|
12362
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
12276
12363
|
break;
|
|
12277
12364
|
case -1:
|
|
12278
12365
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
12279
12366
|
// The first week of the previous year is the week that contains the
|
|
12280
12367
|
// first Thursday of the previous year.
|
|
12281
12368
|
let firstThursdayPreviousYear = 1;
|
|
12282
|
-
while (new
|
|
12369
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
12283
12370
|
firstThursdayPreviousYear += 1;
|
|
12284
12371
|
}
|
|
12285
|
-
firstDay = new
|
|
12372
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
12286
12373
|
break;
|
|
12287
12374
|
}
|
|
12288
12375
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -12417,8 +12504,8 @@ const NETWORKDAYS_INTL = {
|
|
|
12417
12504
|
});
|
|
12418
12505
|
}
|
|
12419
12506
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
12420
|
-
const stopDate =
|
|
12421
|
-
let stepDate =
|
|
12507
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
12508
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
12422
12509
|
const timeStopDate = stopDate.getTime();
|
|
12423
12510
|
let timeStepDate = stepDate.getTime();
|
|
12424
12511
|
let netWorkingDay = 0;
|
|
@@ -12442,8 +12529,7 @@ const NOW = {
|
|
|
12442
12529
|
returns: ["DATE"],
|
|
12443
12530
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
12444
12531
|
compute: function () {
|
|
12445
|
-
let today =
|
|
12446
|
-
today.setMilliseconds(0);
|
|
12532
|
+
let today = DateTime.now();
|
|
12447
12533
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
12448
12534
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
12449
12535
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -12513,8 +12599,8 @@ const TODAY = {
|
|
|
12513
12599
|
returns: ["DATE"],
|
|
12514
12600
|
computeFormat: () => "m/d/yyyy",
|
|
12515
12601
|
compute: function () {
|
|
12516
|
-
const today =
|
|
12517
|
-
const jsDate = new
|
|
12602
|
+
const today = DateTime.now();
|
|
12603
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12518
12604
|
return jsDateToRoundNumber(jsDate);
|
|
12519
12605
|
},
|
|
12520
12606
|
isExported: true,
|
|
@@ -12569,10 +12655,10 @@ const WEEKNUM = {
|
|
|
12569
12655
|
}
|
|
12570
12656
|
const y = _date.getFullYear();
|
|
12571
12657
|
let dayStart = 1;
|
|
12572
|
-
let startDayOfFirstWeek = new
|
|
12658
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12573
12659
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
12574
12660
|
dayStart += 1;
|
|
12575
|
-
startDayOfFirstWeek = new
|
|
12661
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12576
12662
|
}
|
|
12577
12663
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
12578
12664
|
if (dif < 0) {
|
|
@@ -12626,7 +12712,7 @@ const WORKDAY_INTL = {
|
|
|
12626
12712
|
timesHoliday.add(holiday.getTime());
|
|
12627
12713
|
});
|
|
12628
12714
|
}
|
|
12629
|
-
let stepDate =
|
|
12715
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
12630
12716
|
let timeStepDate = stepDate.getTime();
|
|
12631
12717
|
const unitDay = Math.sign(_numDays);
|
|
12632
12718
|
let stepDay = Math.abs(_numDays);
|
|
@@ -12688,7 +12774,7 @@ const MONTH_START = {
|
|
|
12688
12774
|
const _startDate = toJsDate(date);
|
|
12689
12775
|
const yStart = _startDate.getFullYear();
|
|
12690
12776
|
const mStart = _startDate.getMonth();
|
|
12691
|
-
const jsDate = new
|
|
12777
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
12692
12778
|
return jsDateToRoundNumber(jsDate);
|
|
12693
12779
|
},
|
|
12694
12780
|
};
|
|
@@ -12726,7 +12812,7 @@ const QUARTER_START = {
|
|
|
12726
12812
|
compute: function (date) {
|
|
12727
12813
|
const quarter = QUARTER.compute(date);
|
|
12728
12814
|
const year = YEAR.compute(date);
|
|
12729
|
-
const jsDate = new
|
|
12815
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
12730
12816
|
return jsDateToRoundNumber(jsDate);
|
|
12731
12817
|
},
|
|
12732
12818
|
};
|
|
@@ -12741,7 +12827,7 @@ const QUARTER_END = {
|
|
|
12741
12827
|
compute: function (date) {
|
|
12742
12828
|
const quarter = QUARTER.compute(date);
|
|
12743
12829
|
const year = YEAR.compute(date);
|
|
12744
|
-
const jsDate = new
|
|
12830
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
12745
12831
|
return jsDateToRoundNumber(jsDate);
|
|
12746
12832
|
},
|
|
12747
12833
|
};
|
|
@@ -12755,7 +12841,7 @@ const YEAR_START = {
|
|
|
12755
12841
|
computeFormat: () => "m/d/yyyy",
|
|
12756
12842
|
compute: function (date) {
|
|
12757
12843
|
const year = YEAR.compute(date);
|
|
12758
|
-
const jsDate = new
|
|
12844
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
12759
12845
|
return jsDateToRoundNumber(jsDate);
|
|
12760
12846
|
},
|
|
12761
12847
|
};
|
|
@@ -12769,7 +12855,7 @@ const YEAR_END = {
|
|
|
12769
12855
|
computeFormat: () => "m/d/yyyy",
|
|
12770
12856
|
compute: function (date) {
|
|
12771
12857
|
const year = YEAR.compute(date);
|
|
12772
|
-
const jsDate = new
|
|
12858
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
12773
12859
|
return jsDateToRoundNumber(jsDate);
|
|
12774
12860
|
},
|
|
12775
12861
|
};
|
|
@@ -12817,8 +12903,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
12817
12903
|
const DELTA = {
|
|
12818
12904
|
description: _lt("Compare two numeric values, returning 1 if they're equal."),
|
|
12819
12905
|
args: [
|
|
12820
|
-
arg(" (number)", _lt("The first number to compare.")),
|
|
12821
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12906
|
+
arg("number1 (number)", _lt("The first number to compare.")),
|
|
12907
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12822
12908
|
],
|
|
12823
12909
|
returns: ["NUMBER"],
|
|
12824
12910
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -12904,7 +12990,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
12904
12990
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
12905
12991
|
const startDate = toJsDate(settlement);
|
|
12906
12992
|
const endDate = toJsDate(maturity);
|
|
12907
|
-
const startDatePlusOneYear =
|
|
12993
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
12908
12994
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
12909
12995
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
12910
12996
|
}
|
|
@@ -13039,7 +13125,7 @@ const AMORLINC = {
|
|
|
13039
13125
|
arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
|
|
13040
13126
|
arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
|
|
13041
13127
|
arg("rate (number)", _lt("The deprecation rate.")),
|
|
13042
|
-
arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13128
|
+
arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13043
13129
|
],
|
|
13044
13130
|
returns: ["NUMBER"],
|
|
13045
13131
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -16022,8 +16108,8 @@ const MID = {
|
|
|
16022
16108
|
description: _lt("A segment of a string."),
|
|
16023
16109
|
args: [
|
|
16024
16110
|
arg("text (string)", _lt("The string to extract a segment from.")),
|
|
16025
|
-
arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
16026
|
-
arg(" (number)", _lt("The length of the segment to extract.")),
|
|
16111
|
+
arg("starting_at (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
16112
|
+
arg("extract_length (number)", _lt("The length of the segment to extract.")),
|
|
16027
16113
|
],
|
|
16028
16114
|
returns: ["STRING"],
|
|
16029
16115
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -17692,10 +17778,10 @@ const arrowMap = {
|
|
|
17692
17778
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
17693
17779
|
const direction = arrowMap[ev.key];
|
|
17694
17780
|
if (ev.shiftKey) {
|
|
17695
|
-
selection.resizeAnchorZone(direction, ev
|
|
17781
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17696
17782
|
}
|
|
17697
17783
|
else {
|
|
17698
|
-
selection.moveAnchorCell(direction, ev
|
|
17784
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17699
17785
|
}
|
|
17700
17786
|
}
|
|
17701
17787
|
|
|
@@ -22392,7 +22478,10 @@ class GridOverlay extends Component {
|
|
|
22392
22478
|
return;
|
|
22393
22479
|
}
|
|
22394
22480
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
22395
|
-
this.props.onCellClicked(col, row, {
|
|
22481
|
+
this.props.onCellClicked(col, row, {
|
|
22482
|
+
expandZone: ev.shiftKey,
|
|
22483
|
+
addZone: isCtrlKey(ev),
|
|
22484
|
+
});
|
|
22396
22485
|
}
|
|
22397
22486
|
onDoubleClick(ev) {
|
|
22398
22487
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -22465,6 +22554,7 @@ class AbstractResizer extends Component {
|
|
|
22465
22554
|
draggerShadowThickness: 0,
|
|
22466
22555
|
delta: 0,
|
|
22467
22556
|
base: 0,
|
|
22557
|
+
position: "before",
|
|
22468
22558
|
});
|
|
22469
22559
|
_computeHandleDisplay(ev) {
|
|
22470
22560
|
const position = this._getEvOffset(ev);
|
|
@@ -22589,11 +22679,13 @@ class AbstractResizer extends Component {
|
|
|
22589
22679
|
this.state.draggerLinePosition = dimensions.start;
|
|
22590
22680
|
this.state.draggerShadowPosition = dimensions.start;
|
|
22591
22681
|
this.state.base = elementIndex;
|
|
22682
|
+
this.state.position = "before";
|
|
22592
22683
|
}
|
|
22593
22684
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
22594
22685
|
this.state.draggerLinePosition = dimensions.end;
|
|
22595
22686
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
22596
|
-
this.state.base = elementIndex
|
|
22687
|
+
this.state.base = elementIndex;
|
|
22688
|
+
this.state.position = "after";
|
|
22597
22689
|
}
|
|
22598
22690
|
else {
|
|
22599
22691
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -22617,7 +22709,7 @@ class AbstractResizer extends Component {
|
|
|
22617
22709
|
this._increaseSelection(index);
|
|
22618
22710
|
}
|
|
22619
22711
|
else {
|
|
22620
|
-
this._selectElement(index, ev
|
|
22712
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
22621
22713
|
}
|
|
22622
22714
|
this.lastSelectedElementIndex = index;
|
|
22623
22715
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -22630,7 +22722,7 @@ class AbstractResizer extends Component {
|
|
|
22630
22722
|
const mouseUpSelect = () => {
|
|
22631
22723
|
this.state.isSelecting = false;
|
|
22632
22724
|
this.lastSelectedElementIndex = null;
|
|
22633
|
-
this.env.model.dispatch(ev
|
|
22725
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
22634
22726
|
this._computeGrabDisplay(ev);
|
|
22635
22727
|
};
|
|
22636
22728
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -22776,13 +22868,14 @@ class ColResizer extends AbstractResizer {
|
|
|
22776
22868
|
dimension: "COL",
|
|
22777
22869
|
base: this.state.base,
|
|
22778
22870
|
elements,
|
|
22871
|
+
position: this.state.position,
|
|
22779
22872
|
});
|
|
22780
22873
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22781
22874
|
this.env.raiseError(MergeErrorMessage);
|
|
22782
22875
|
}
|
|
22783
22876
|
}
|
|
22784
|
-
_selectElement(index,
|
|
22785
|
-
this.env.model.selection.selectColumn(index,
|
|
22877
|
+
_selectElement(index, addDistinctHeader) {
|
|
22878
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22786
22879
|
}
|
|
22787
22880
|
_increaseSelection(index) {
|
|
22788
22881
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -22949,13 +23042,14 @@ class RowResizer extends AbstractResizer {
|
|
|
22949
23042
|
dimension: "ROW",
|
|
22950
23043
|
base: this.state.base,
|
|
22951
23044
|
elements,
|
|
23045
|
+
position: this.state.position,
|
|
22952
23046
|
});
|
|
22953
23047
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22954
23048
|
this.env.raiseError(MergeErrorMessage);
|
|
22955
23049
|
}
|
|
22956
23050
|
}
|
|
22957
|
-
_selectElement(index,
|
|
22958
|
-
this.env.model.selection.selectRow(index,
|
|
23051
|
+
_selectElement(index, addDistinctHeader) {
|
|
23052
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22959
23053
|
}
|
|
22960
23054
|
_increaseSelection(index) {
|
|
22961
23055
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -23056,8 +23150,8 @@ function useWheelHandler(handler) {
|
|
|
23056
23150
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
23057
23151
|
}
|
|
23058
23152
|
const onMouseWheel = (ev) => {
|
|
23059
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23060
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23153
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23154
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23061
23155
|
handler(deltaX, deltaY);
|
|
23062
23156
|
};
|
|
23063
23157
|
return onMouseWheel;
|
|
@@ -23759,8 +23853,8 @@ class Grid extends Component {
|
|
|
23759
23853
|
// ---------------------------------------------------------------------------
|
|
23760
23854
|
// Zone selection with mouse
|
|
23761
23855
|
// ---------------------------------------------------------------------------
|
|
23762
|
-
onCellClicked(col, row, {
|
|
23763
|
-
if (
|
|
23856
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
23857
|
+
if (addZone) {
|
|
23764
23858
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
23765
23859
|
}
|
|
23766
23860
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -23769,10 +23863,10 @@ class Grid extends Component {
|
|
|
23769
23863
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
23770
23864
|
this.env.model.dispatch("STOP_EDITION");
|
|
23771
23865
|
}
|
|
23772
|
-
if (
|
|
23866
|
+
if (expandZone) {
|
|
23773
23867
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
23774
23868
|
}
|
|
23775
|
-
else if (
|
|
23869
|
+
else if (addZone) {
|
|
23776
23870
|
this.env.model.selection.addCellToSelection(col, row);
|
|
23777
23871
|
}
|
|
23778
23872
|
else {
|
|
@@ -23834,9 +23928,7 @@ class Grid extends Component {
|
|
|
23834
23928
|
return;
|
|
23835
23929
|
}
|
|
23836
23930
|
let keyDownString = "";
|
|
23837
|
-
if (ev
|
|
23838
|
-
keyDownString += "CTRL+";
|
|
23839
|
-
if (ev.metaKey)
|
|
23931
|
+
if (isCtrlKey(ev))
|
|
23840
23932
|
keyDownString += "CTRL+";
|
|
23841
23933
|
if (ev.altKey)
|
|
23842
23934
|
keyDownString += "ALT+";
|
|
@@ -25744,7 +25836,7 @@ const machine = {
|
|
|
25744
25836
|
SPACE: goTo(State.RightRef),
|
|
25745
25837
|
NUMBER: goTo(State.Found),
|
|
25746
25838
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25747
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
25839
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
25748
25840
|
},
|
|
25749
25841
|
[State.RightColumnRef]: {
|
|
25750
25842
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -25755,6 +25847,7 @@ const machine = {
|
|
|
25755
25847
|
SPACE: goTo(State.RightRowRef),
|
|
25756
25848
|
NUMBER: goTo(State.Found),
|
|
25757
25849
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25850
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
25758
25851
|
},
|
|
25759
25852
|
[State.Found]: {},
|
|
25760
25853
|
};
|
|
@@ -28991,6 +29084,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
28991
29084
|
// ---------------------------------------------------------------------------
|
|
28992
29085
|
// Command Handling
|
|
28993
29086
|
// ---------------------------------------------------------------------------
|
|
29087
|
+
allowDispatch(cmd) {
|
|
29088
|
+
switch (cmd.type) {
|
|
29089
|
+
case "SET_BORDER":
|
|
29090
|
+
return this.checkBordersUnchanged(cmd);
|
|
29091
|
+
default:
|
|
29092
|
+
return 0 /* CommandResult.Success */;
|
|
29093
|
+
}
|
|
29094
|
+
}
|
|
28994
29095
|
handle(cmd) {
|
|
28995
29096
|
switch (cmd.type) {
|
|
28996
29097
|
case "ADD_MERGE":
|
|
@@ -29410,6 +29511,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
29410
29511
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
29411
29512
|
}
|
|
29412
29513
|
}
|
|
29514
|
+
checkBordersUnchanged(cmd) {
|
|
29515
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
29516
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
29517
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
29518
|
+
return 93 /* CommandResult.NoChanges */;
|
|
29519
|
+
}
|
|
29520
|
+
return 0 /* CommandResult.Success */;
|
|
29521
|
+
}
|
|
29413
29522
|
// ---------------------------------------------------------------------------
|
|
29414
29523
|
// Import/Export
|
|
29415
29524
|
// ---------------------------------------------------------------------------
|
|
@@ -29446,7 +29555,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
29446
29555
|
*/
|
|
29447
29556
|
function getBorderId(border) {
|
|
29448
29557
|
for (let [key, value] of Object.entries(borders)) {
|
|
29449
|
-
if (
|
|
29558
|
+
if (deepEquals(value, border)) {
|
|
29450
29559
|
return parseInt(key, 10);
|
|
29451
29560
|
}
|
|
29452
29561
|
}
|
|
@@ -29517,8 +29626,9 @@ class CellPlugin extends CorePlugin {
|
|
|
29517
29626
|
allowDispatch(cmd) {
|
|
29518
29627
|
switch (cmd.type) {
|
|
29519
29628
|
case "UPDATE_CELL":
|
|
29629
|
+
return this.checkCellOutOfSheet(cmd);
|
|
29520
29630
|
case "CLEAR_CELL":
|
|
29521
|
-
return this.
|
|
29631
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
29522
29632
|
default:
|
|
29523
29633
|
return 0 /* CommandResult.Success */;
|
|
29524
29634
|
}
|
|
@@ -29677,14 +29787,9 @@ class CellPlugin extends CorePlugin {
|
|
|
29677
29787
|
*/
|
|
29678
29788
|
getCellById(cellId) {
|
|
29679
29789
|
// this must be as fast as possible
|
|
29680
|
-
|
|
29681
|
-
|
|
29682
|
-
|
|
29683
|
-
if (cell) {
|
|
29684
|
-
return cell;
|
|
29685
|
-
}
|
|
29686
|
-
}
|
|
29687
|
-
return undefined;
|
|
29790
|
+
const position = this.getters.getCellPosition(cellId);
|
|
29791
|
+
const sheet = this.cells[position.sheetId];
|
|
29792
|
+
return sheet[cellId];
|
|
29688
29793
|
}
|
|
29689
29794
|
/*
|
|
29690
29795
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -29921,13 +30026,23 @@ class CellPlugin extends CorePlugin {
|
|
|
29921
30026
|
dependencies: [],
|
|
29922
30027
|
};
|
|
29923
30028
|
}
|
|
29924
|
-
checkCellOutOfSheet(
|
|
30029
|
+
checkCellOutOfSheet(cmd) {
|
|
30030
|
+
const { sheetId, col, row } = cmd;
|
|
29925
30031
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
29926
30032
|
if (!sheet)
|
|
29927
30033
|
return 27 /* CommandResult.InvalidSheetId */;
|
|
29928
30034
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
29929
30035
|
return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
|
|
29930
30036
|
}
|
|
30037
|
+
checkUselessClearCell(cmd) {
|
|
30038
|
+
const cell = this.getters.getCell(cmd);
|
|
30039
|
+
if (!cell)
|
|
30040
|
+
return 93 /* CommandResult.NoChanges */;
|
|
30041
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
30042
|
+
return 93 /* CommandResult.NoChanges */;
|
|
30043
|
+
}
|
|
30044
|
+
return 0 /* CommandResult.Success */;
|
|
30045
|
+
}
|
|
29931
30046
|
}
|
|
29932
30047
|
|
|
29933
30048
|
class ChartPlugin extends CorePlugin {
|
|
@@ -32408,7 +32523,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
32408
32523
|
const elements = cmd.dimension === "COL"
|
|
32409
32524
|
? this.getNumberCols(cmd.sheetId)
|
|
32410
32525
|
: this.getNumberRows(cmd.sheetId);
|
|
32411
|
-
if (cmd.base < 0 || cmd.base
|
|
32526
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
32412
32527
|
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
32413
32528
|
}
|
|
32414
32529
|
else if (cmd.quantity <= 0) {
|
|
@@ -33030,10 +33145,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
33030
33145
|
// begin with the end.
|
|
33031
33146
|
rows.sort((a, b) => b - a);
|
|
33032
33147
|
for (let group of groupConsecutive(rows)) {
|
|
33148
|
+
// indexes are sorted in the descending order
|
|
33149
|
+
const from = group[group.length - 1];
|
|
33150
|
+
const to = group[0];
|
|
33033
33151
|
// Move the cells.
|
|
33034
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
33035
|
-
// Effectively delete the
|
|
33036
|
-
|
|
33152
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
33153
|
+
// Effectively delete the rows
|
|
33154
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
33037
33155
|
}
|
|
33038
33156
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
33039
33157
|
if (count) {
|
|
@@ -33055,8 +33173,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
33055
33173
|
this.addEmptyRows(sheet, quantity);
|
|
33056
33174
|
// Move the cells.
|
|
33057
33175
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
33058
|
-
// Recompute the left-right/top-bottom.
|
|
33059
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
33060
33176
|
if (index < sheet.panes.ySplit) {
|
|
33061
33177
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
33062
33178
|
}
|
|
@@ -33157,35 +33273,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
33157
33273
|
}
|
|
33158
33274
|
}
|
|
33159
33275
|
}
|
|
33160
|
-
updateRowsStructureOnDeletion(
|
|
33276
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
33161
33277
|
const rows = [];
|
|
33162
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
33278
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
33163
33279
|
for (let i in sheet.rows) {
|
|
33164
|
-
|
|
33280
|
+
const row = Number(i);
|
|
33281
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
33165
33282
|
continue;
|
|
33166
33283
|
}
|
|
33167
33284
|
rows.push({
|
|
33168
|
-
cells: cellsQueue.
|
|
33285
|
+
cells: cellsQueue.pop(),
|
|
33169
33286
|
});
|
|
33170
33287
|
}
|
|
33171
33288
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
33172
33289
|
}
|
|
33173
|
-
/**
|
|
33174
|
-
* Update the rows of the sheet after an addition:
|
|
33175
|
-
* - Rename the rows
|
|
33176
|
-
*
|
|
33177
|
-
* @param sheet Sheet on which the deletion occurs
|
|
33178
|
-
* @param addedRow Index of the added row
|
|
33179
|
-
* @param rowsToAdd Number of the rows to add
|
|
33180
|
-
*/
|
|
33181
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
33182
|
-
const rows = [];
|
|
33183
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
33184
|
-
sheet.rows.forEach(() => rows.push({
|
|
33185
|
-
cells: cellsQueue.shift(),
|
|
33186
|
-
}));
|
|
33187
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
33188
|
-
}
|
|
33189
33290
|
/**
|
|
33190
33291
|
* Add empty rows at the end of the rows
|
|
33191
33292
|
*
|
|
@@ -33455,13 +33556,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33455
33556
|
// Getters
|
|
33456
33557
|
// ---------------------------------------------------------------------------
|
|
33457
33558
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
33458
|
-
|
|
33459
|
-
|
|
33460
|
-
|
|
33461
|
-
|
|
33462
|
-
|
|
33559
|
+
try {
|
|
33560
|
+
const compiledFormula = compile(formulaString);
|
|
33561
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
33562
|
+
const ranges = [];
|
|
33563
|
+
for (let xc of compiledFormula.dependencies) {
|
|
33564
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
33565
|
+
}
|
|
33566
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
33567
|
+
}
|
|
33568
|
+
catch (error) {
|
|
33569
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
33463
33570
|
}
|
|
33464
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
33465
33571
|
}
|
|
33466
33572
|
/**
|
|
33467
33573
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -33636,6 +33742,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33636
33742
|
}
|
|
33637
33743
|
return evaluatedCell;
|
|
33638
33744
|
};
|
|
33745
|
+
const rangeCache = {};
|
|
33639
33746
|
/**
|
|
33640
33747
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
33641
33748
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -33652,21 +33759,26 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33652
33759
|
// Performance issue: Avoid fetching data on positions that are out of the spreadsheet
|
|
33653
33760
|
// e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
|
|
33654
33761
|
const sheetZone = getters.getSheetZone(sheetId);
|
|
33655
|
-
const result = [];
|
|
33656
33762
|
const zone = intersection(range.zone, sheetZone);
|
|
33657
33763
|
if (!zone) {
|
|
33658
|
-
|
|
33659
|
-
|
|
33764
|
+
return [[]];
|
|
33765
|
+
}
|
|
33766
|
+
const { top, left, bottom, right } = zone;
|
|
33767
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
33768
|
+
if (cacheKey in rangeCache) {
|
|
33769
|
+
return rangeCache[cacheKey];
|
|
33660
33770
|
}
|
|
33771
|
+
const result = new Array(right - left + 1);
|
|
33661
33772
|
// Performance issue: nested loop is faster than a map here
|
|
33662
|
-
for (let col =
|
|
33663
|
-
const rowValues =
|
|
33664
|
-
for (let row =
|
|
33773
|
+
for (let col = left; col <= right; col++) {
|
|
33774
|
+
const rowValues = new Array(bottom - top + 1);
|
|
33775
|
+
for (let row = top; row <= bottom; row++) {
|
|
33665
33776
|
const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
|
|
33666
|
-
rowValues
|
|
33777
|
+
rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
|
|
33667
33778
|
}
|
|
33668
|
-
result
|
|
33779
|
+
result[col - left] = rowValues;
|
|
33669
33780
|
}
|
|
33781
|
+
rangeCache[cacheKey] = result;
|
|
33670
33782
|
return result;
|
|
33671
33783
|
}
|
|
33672
33784
|
/**
|
|
@@ -33880,39 +33992,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33880
33992
|
this.computedIcons[sheetId] = {};
|
|
33881
33993
|
const computedStyle = this.computedStyles[sheetId];
|
|
33882
33994
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
33883
|
-
|
|
33884
|
-
|
|
33885
|
-
|
|
33886
|
-
|
|
33887
|
-
|
|
33888
|
-
|
|
33889
|
-
|
|
33890
|
-
|
|
33891
|
-
|
|
33892
|
-
|
|
33893
|
-
|
|
33894
|
-
|
|
33895
|
-
|
|
33896
|
-
|
|
33897
|
-
|
|
33898
|
-
for (let
|
|
33899
|
-
|
|
33900
|
-
|
|
33901
|
-
|
|
33902
|
-
if (
|
|
33903
|
-
|
|
33904
|
-
|
|
33905
|
-
|
|
33906
|
-
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33907
|
-
}
|
|
33995
|
+
switch (cf.rule.type) {
|
|
33996
|
+
case "ColorScaleRule":
|
|
33997
|
+
for (let range of cf.ranges) {
|
|
33998
|
+
this.applyColorScale(range, cf.rule);
|
|
33999
|
+
}
|
|
34000
|
+
break;
|
|
34001
|
+
case "IconSetRule":
|
|
34002
|
+
for (let range of cf.ranges) {
|
|
34003
|
+
this.applyIcon(range, cf.rule);
|
|
34004
|
+
}
|
|
34005
|
+
break;
|
|
34006
|
+
default:
|
|
34007
|
+
for (let ref of cf.ranges) {
|
|
34008
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
34009
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
34010
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
34011
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
34012
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
34013
|
+
if (pr && pr(cell, cf.rule)) {
|
|
34014
|
+
if (!computedStyle[col])
|
|
34015
|
+
computedStyle[col] = [];
|
|
34016
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
34017
|
+
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33908
34018
|
}
|
|
33909
34019
|
}
|
|
33910
34020
|
}
|
|
33911
|
-
|
|
33912
|
-
|
|
33913
|
-
}
|
|
33914
|
-
catch (_) {
|
|
33915
|
-
// we don't care about the errors within the evaluation of a rule
|
|
34021
|
+
}
|
|
34022
|
+
break;
|
|
33916
34023
|
}
|
|
33917
34024
|
}
|
|
33918
34025
|
}
|
|
@@ -33937,7 +34044,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33937
34044
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
33938
34045
|
case "formula":
|
|
33939
34046
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
33940
|
-
return
|
|
34047
|
+
return typeof value === "number" ? value : null;
|
|
33941
34048
|
default:
|
|
33942
34049
|
return null;
|
|
33943
34050
|
}
|
|
@@ -35586,19 +35693,21 @@ class AutofillPlugin extends UIPlugin {
|
|
|
35586
35693
|
let col = zone.left;
|
|
35587
35694
|
let row = zone.bottom;
|
|
35588
35695
|
if (col > 0) {
|
|
35589
|
-
let
|
|
35590
|
-
while (
|
|
35696
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
35697
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
35698
|
+
this.getters.getCell(leftPosition)?.content) {
|
|
35591
35699
|
row += 1;
|
|
35592
|
-
|
|
35700
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
35593
35701
|
}
|
|
35594
35702
|
}
|
|
35595
35703
|
if (row === zone.bottom) {
|
|
35596
35704
|
col = zone.right;
|
|
35597
35705
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
35598
|
-
let
|
|
35599
|
-
while (
|
|
35706
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
35707
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
35708
|
+
this.getters.getCell(rightPosition)?.content) {
|
|
35600
35709
|
row += 1;
|
|
35601
|
-
|
|
35710
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
35602
35711
|
}
|
|
35603
35712
|
}
|
|
35604
35713
|
}
|
|
@@ -40546,6 +40655,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
40546
40655
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40547
40656
|
case "colrow":
|
|
40548
40657
|
indexOfNumber = xc.search(/[0-9]/);
|
|
40658
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
40659
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
40660
|
+
return "$" + xc;
|
|
40661
|
+
}
|
|
40549
40662
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40550
40663
|
return "$" + xc;
|
|
40551
40664
|
case "none":
|
|
@@ -41727,7 +41840,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41727
41840
|
sheetId: cmd.sheetId,
|
|
41728
41841
|
base: cmd.base,
|
|
41729
41842
|
quantity: thickness,
|
|
41730
|
-
position:
|
|
41843
|
+
position: cmd.position,
|
|
41731
41844
|
});
|
|
41732
41845
|
const isCol = cmd.dimension === "COL";
|
|
41733
41846
|
const start = cmd.elements[0];
|
|
@@ -41744,12 +41857,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41744
41857
|
},
|
|
41745
41858
|
];
|
|
41746
41859
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
41860
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
41747
41861
|
const pasteTarget = [
|
|
41748
41862
|
{
|
|
41749
|
-
left: isCol ?
|
|
41750
|
-
right: isCol ?
|
|
41751
|
-
top: !isCol ?
|
|
41752
|
-
bottom: !isCol ?
|
|
41863
|
+
left: isCol ? base : 0,
|
|
41864
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
41865
|
+
top: !isCol ? base : 0,
|
|
41866
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
41753
41867
|
},
|
|
41754
41868
|
];
|
|
41755
41869
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -41786,6 +41900,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41786
41900
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
41787
41901
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
41788
41902
|
}
|
|
41903
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
41904
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
41905
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
41906
|
+
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
41907
|
+
}
|
|
41789
41908
|
return 0 /* CommandResult.Success */;
|
|
41790
41909
|
}
|
|
41791
41910
|
//-------------------------------------------
|
|
@@ -44067,7 +44186,7 @@ class Spreadsheet extends Component {
|
|
|
44067
44186
|
}
|
|
44068
44187
|
onKeydown(ev) {
|
|
44069
44188
|
let keyDownString = "";
|
|
44070
|
-
if (ev
|
|
44189
|
+
if (isCtrlKey(ev)) {
|
|
44071
44190
|
keyDownString += "CTRL+";
|
|
44072
44191
|
}
|
|
44073
44192
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -44938,9 +45057,9 @@ function revertChanges(revisions) {
|
|
|
44938
45057
|
* Apply the changes of the given HistoryChange to the state
|
|
44939
45058
|
*/
|
|
44940
45059
|
function applyChange(change, target) {
|
|
44941
|
-
let val = change.
|
|
44942
|
-
|
|
44943
|
-
for (let pathIndex =
|
|
45060
|
+
let val = change.path[0];
|
|
45061
|
+
const key = change.path[change.path.length - 1];
|
|
45062
|
+
for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
|
|
44944
45063
|
const p = change.path[pathIndex];
|
|
44945
45064
|
if (val[p] === undefined) {
|
|
44946
45065
|
const nextPath = change.path[pathIndex + 1];
|
|
@@ -45607,13 +45726,14 @@ class StateObserver {
|
|
|
45607
45726
|
}
|
|
45608
45727
|
addChange(...args) {
|
|
45609
45728
|
const val = args.pop();
|
|
45610
|
-
const
|
|
45729
|
+
const root = args[0];
|
|
45611
45730
|
let value = root;
|
|
45612
|
-
let key =
|
|
45613
|
-
|
|
45614
|
-
|
|
45731
|
+
let key = args[args.length - 1];
|
|
45732
|
+
const pathLength = args.length - 2;
|
|
45733
|
+
for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
|
|
45734
|
+
const p = args[pathIndex];
|
|
45615
45735
|
if (value[p] === undefined) {
|
|
45616
|
-
const nextPath =
|
|
45736
|
+
const nextPath = args[pathIndex + 1];
|
|
45617
45737
|
value[p] = createEmptyStructure(nextPath);
|
|
45618
45738
|
}
|
|
45619
45739
|
value = value[p];
|
|
@@ -45622,8 +45742,7 @@ class StateObserver {
|
|
|
45622
45742
|
return;
|
|
45623
45743
|
}
|
|
45624
45744
|
this.changes.push({
|
|
45625
|
-
|
|
45626
|
-
path,
|
|
45745
|
+
path: args,
|
|
45627
45746
|
before: value[key],
|
|
45628
45747
|
after: val,
|
|
45629
45748
|
});
|
|
@@ -47473,19 +47592,22 @@ class Model extends EventBus {
|
|
|
47473
47592
|
* Check if the given command is allowed by all the plugins and the history.
|
|
47474
47593
|
*/
|
|
47475
47594
|
checkDispatchAllowed(command) {
|
|
47476
|
-
|
|
47477
|
-
|
|
47595
|
+
const results = isCoreCommand(command)
|
|
47596
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
47597
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
47598
|
+
if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
|
|
47599
|
+
return new DispatchResult(results.flat());
|
|
47478
47600
|
}
|
|
47479
|
-
return
|
|
47601
|
+
return DispatchResult.Success;
|
|
47480
47602
|
}
|
|
47481
47603
|
checkDispatchAllowedCoreCommand(command) {
|
|
47482
47604
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
47483
47605
|
results.push(this.range.allowDispatch(command));
|
|
47484
|
-
return
|
|
47606
|
+
return results;
|
|
47485
47607
|
}
|
|
47486
47608
|
checkDispatchAllowedLocalCommand(command) {
|
|
47487
47609
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
47488
|
-
return
|
|
47610
|
+
return results;
|
|
47489
47611
|
}
|
|
47490
47612
|
finalize() {
|
|
47491
47613
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -47773,6 +47895,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
47773
47895
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
47774
47896
|
|
|
47775
47897
|
|
|
47776
|
-
__info__.version = '16.3.
|
|
47777
|
-
__info__.date = '
|
|
47778
|
-
__info__.hash = '
|
|
47898
|
+
__info__.version = '16.3.22';
|
|
47899
|
+
__info__.date = '2024-01-17T10:24:07.652Z';
|
|
47900
|
+
__info__.hash = '2c1b136';
|