@odoo/o-spreadsheet 16.3.18 → 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 +224 -136
- package/dist/o-spreadsheet.d.ts +40 -10
- package/dist/o-spreadsheet.esm.js +224 -136
- package/dist/o-spreadsheet.iife.js +224 -136
- package/dist/o-spreadsheet.iife.min.js +256 -256
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -302,15 +302,80 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
302
302
|
// -----------------------------------------------------------------------------
|
|
303
303
|
// Date Type
|
|
304
304
|
// -----------------------------------------------------------------------------
|
|
305
|
+
/**
|
|
306
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
307
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
308
|
+
* and it is timezone-agnostic.
|
|
309
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
310
|
+
*/
|
|
311
|
+
class DateTime {
|
|
312
|
+
jsDate;
|
|
313
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
314
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
315
|
+
}
|
|
316
|
+
static fromTimestamp(timestamp) {
|
|
317
|
+
const date = new Date(timestamp);
|
|
318
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
319
|
+
}
|
|
320
|
+
static now() {
|
|
321
|
+
const now = new Date();
|
|
322
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
323
|
+
}
|
|
324
|
+
toString() {
|
|
325
|
+
return this.jsDate.toString();
|
|
326
|
+
}
|
|
327
|
+
toLocaleDateString() {
|
|
328
|
+
return this.jsDate.toLocaleDateString();
|
|
329
|
+
}
|
|
330
|
+
getTime() {
|
|
331
|
+
return this.jsDate.getTime();
|
|
332
|
+
}
|
|
333
|
+
getFullYear() {
|
|
334
|
+
return this.jsDate.getUTCFullYear();
|
|
335
|
+
}
|
|
336
|
+
getMonth() {
|
|
337
|
+
return this.jsDate.getUTCMonth();
|
|
338
|
+
}
|
|
339
|
+
getDate() {
|
|
340
|
+
return this.jsDate.getUTCDate();
|
|
341
|
+
}
|
|
342
|
+
getDay() {
|
|
343
|
+
return this.jsDate.getUTCDay();
|
|
344
|
+
}
|
|
345
|
+
getHours() {
|
|
346
|
+
return this.jsDate.getUTCHours();
|
|
347
|
+
}
|
|
348
|
+
getMinutes() {
|
|
349
|
+
return this.jsDate.getUTCMinutes();
|
|
350
|
+
}
|
|
351
|
+
getSeconds() {
|
|
352
|
+
return this.jsDate.getUTCSeconds();
|
|
353
|
+
}
|
|
354
|
+
setFullYear(year) {
|
|
355
|
+
this.jsDate.setFullYear(year);
|
|
356
|
+
}
|
|
357
|
+
setDate(date) {
|
|
358
|
+
this.jsDate.setUTCDate(date);
|
|
359
|
+
}
|
|
360
|
+
setHours(hours) {
|
|
361
|
+
this.jsDate.setUTCHours(hours);
|
|
362
|
+
}
|
|
363
|
+
setMinutes(minutes) {
|
|
364
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
365
|
+
}
|
|
366
|
+
setSeconds(seconds) {
|
|
367
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
305
370
|
// -----------------------------------------------------------------------------
|
|
306
371
|
// Parsing
|
|
307
372
|
// -----------------------------------------------------------------------------
|
|
308
|
-
const INITIAL_1900_DAY = new
|
|
373
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
309
374
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
310
375
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
311
|
-
const CURRENT_YEAR =
|
|
312
|
-
const INITIAL_JS_DAY =
|
|
313
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
376
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
377
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
378
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
314
379
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
315
380
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
316
381
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -359,7 +424,7 @@ function _parseDateTime(str) {
|
|
|
359
424
|
return {
|
|
360
425
|
value: date.value + time.value,
|
|
361
426
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
362
|
-
jsDate: new
|
|
427
|
+
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()),
|
|
363
428
|
};
|
|
364
429
|
}
|
|
365
430
|
return date || time;
|
|
@@ -376,13 +441,13 @@ function parseDate(str, dateFormat) {
|
|
|
376
441
|
const day = Number(parts[dayIndex]);
|
|
377
442
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
378
443
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
379
|
-
const jsDate = new
|
|
444
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
380
445
|
const sep = str.match(/\/|-|\s/)[0];
|
|
381
446
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
382
447
|
// invalid date
|
|
383
448
|
return null;
|
|
384
449
|
}
|
|
385
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
450
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
386
451
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
387
452
|
if (parts[yearIndex]) {
|
|
388
453
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -442,7 +507,7 @@ function parseTime(str) {
|
|
|
442
507
|
if (hours >= 24) {
|
|
443
508
|
format = "hhhh:mm:ss";
|
|
444
509
|
}
|
|
445
|
-
const jsDate = new
|
|
510
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
446
511
|
return {
|
|
447
512
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
448
513
|
format: format,
|
|
@@ -456,7 +521,7 @@ function parseTime(str) {
|
|
|
456
521
|
// -----------------------------------------------------------------------------
|
|
457
522
|
function numberToJsDate(value) {
|
|
458
523
|
const truncValue = Math.trunc(value);
|
|
459
|
-
let date =
|
|
524
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
460
525
|
let time = value - truncValue;
|
|
461
526
|
time = time < 0 ? 1 + time : time;
|
|
462
527
|
const hours = Math.round(time * 24);
|
|
@@ -473,7 +538,7 @@ function jsDateToRoundNumber(date) {
|
|
|
473
538
|
}
|
|
474
539
|
/** Return the number of days in the current month of the given date */
|
|
475
540
|
function getDaysInMonth(date) {
|
|
476
|
-
return new
|
|
541
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
477
542
|
}
|
|
478
543
|
function isLastDayOfMonth(date) {
|
|
479
544
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -491,7 +556,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
491
556
|
const yStart = date.getFullYear();
|
|
492
557
|
const mStart = date.getMonth();
|
|
493
558
|
const dStart = date.getDate();
|
|
494
|
-
const jsDate = new
|
|
559
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
495
560
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
496
561
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
497
562
|
}
|
|
@@ -651,13 +716,6 @@ function areTwoDatesWithinOneYear(startDate, endDate) {
|
|
|
651
716
|
}
|
|
652
717
|
|
|
653
718
|
//------------------------------------------------------------------------------
|
|
654
|
-
/**
|
|
655
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
656
|
-
* is ordered.
|
|
657
|
-
*/
|
|
658
|
-
function stringify(obj) {
|
|
659
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
660
|
-
}
|
|
661
719
|
/**
|
|
662
720
|
* Remove quotes from a quoted string
|
|
663
721
|
* ```js
|
|
@@ -887,7 +945,7 @@ function isBoolean(str) {
|
|
|
887
945
|
function isDateTime(str) {
|
|
888
946
|
return parseDateTime(str) !== null;
|
|
889
947
|
}
|
|
890
|
-
const MARKDOWN_LINK_REGEX = /^\[(
|
|
948
|
+
const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
|
|
891
949
|
//link must start with http or https
|
|
892
950
|
//https://stackoverflow.com/a/3809435/4760614
|
|
893
951
|
const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
|
|
@@ -956,7 +1014,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
956
1014
|
*/
|
|
957
1015
|
function getItemId(item, itemsDic) {
|
|
958
1016
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
959
|
-
if (
|
|
1017
|
+
if (deepEquals(value, item)) {
|
|
960
1018
|
return parseInt(key, 10);
|
|
961
1019
|
}
|
|
962
1020
|
}
|
|
@@ -1956,7 +2014,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1956
2014
|
.map((p) => {
|
|
1957
2015
|
switch (p) {
|
|
1958
2016
|
case "hhhh":
|
|
1959
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
2017
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1960
2018
|
return helapsedHours.toString();
|
|
1961
2019
|
case "hh":
|
|
1962
2020
|
return hours.toString().padStart(2, "0");
|
|
@@ -2203,8 +2261,10 @@ function convertInternalFormatToFormat(internalFormat) {
|
|
|
2203
2261
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
2204
2262
|
// Same as above, but matches the exact string (nothing before or after)
|
|
2205
2263
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
2206
|
-
/** Reference of a column header (eg. A, AB) */
|
|
2207
|
-
const colHeader = new RegExp(
|
|
2264
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
2265
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
2266
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
2267
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
2208
2268
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
2209
2269
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
2210
2270
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -2234,6 +2294,9 @@ function isRowReference(xc) {
|
|
|
2234
2294
|
function isColHeader(str) {
|
|
2235
2295
|
return colHeader.test(str);
|
|
2236
2296
|
}
|
|
2297
|
+
function isRowHeader(str) {
|
|
2298
|
+
return rowHeader.test(str);
|
|
2299
|
+
}
|
|
2237
2300
|
/**
|
|
2238
2301
|
* Return true if the given xc is the reference of a single cell,
|
|
2239
2302
|
* without any specified sheet (e.g. A1)
|
|
@@ -2300,18 +2363,10 @@ class RangeImpl {
|
|
|
2300
2363
|
if (isFullCol) {
|
|
2301
2364
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2302
2365
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2303
|
-
if (zone.left === zone.right) {
|
|
2304
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2305
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2306
|
-
}
|
|
2307
2366
|
}
|
|
2308
2367
|
if (isFullRow) {
|
|
2309
2368
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2310
2369
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2311
|
-
if (zone.top === zone.bottom) {
|
|
2312
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2313
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2314
|
-
}
|
|
2315
2370
|
}
|
|
2316
2371
|
return parts;
|
|
2317
2372
|
}
|
|
@@ -5171,6 +5226,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
5171
5226
|
},
|
|
5172
5227
|
};
|
|
5173
5228
|
|
|
5229
|
+
const macRegex = /Mac/i;
|
|
5174
5230
|
/**
|
|
5175
5231
|
* Return true if the event was triggered from
|
|
5176
5232
|
* a child element.
|
|
@@ -5216,6 +5272,17 @@ function setElementScrollTop(el, scroll) {
|
|
|
5216
5272
|
}
|
|
5217
5273
|
function getOpenedMenus() {
|
|
5218
5274
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5275
|
+
}
|
|
5276
|
+
function isMacOS() {
|
|
5277
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5278
|
+
}
|
|
5279
|
+
/**
|
|
5280
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5281
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5282
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5283
|
+
*/
|
|
5284
|
+
function isCtrlKey(ev) {
|
|
5285
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5219
5286
|
}
|
|
5220
5287
|
|
|
5221
5288
|
/**
|
|
@@ -9602,6 +9669,9 @@ function arg(definition, description = "") {
|
|
|
9602
9669
|
function makeArg(str, description) {
|
|
9603
9670
|
let parts = str.match(ARG_REGEXP);
|
|
9604
9671
|
let name = parts[1].trim();
|
|
9672
|
+
if (!name) {
|
|
9673
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
9674
|
+
}
|
|
9605
9675
|
let types = [];
|
|
9606
9676
|
let isOptional = false;
|
|
9607
9677
|
let isRepeating = false;
|
|
@@ -12055,7 +12125,7 @@ const DATE = {
|
|
|
12055
12125
|
if (_year < 1900) {
|
|
12056
12126
|
_year += 1900;
|
|
12057
12127
|
}
|
|
12058
|
-
const jsDate = new
|
|
12128
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
12059
12129
|
const result = jsDateToRoundNumber(jsDate);
|
|
12060
12130
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
12061
12131
|
return result;
|
|
@@ -12098,7 +12168,7 @@ const DATEDIF = {
|
|
|
12098
12168
|
// See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
|
|
12099
12169
|
let days = jsEndDate.getDate() - jsStartDate.getDate();
|
|
12100
12170
|
if (days < 0) {
|
|
12101
|
-
const monthBeforeEndMonth = new
|
|
12171
|
+
const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
|
|
12102
12172
|
const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
|
|
12103
12173
|
days = daysInMonthBeforeEndMonth - Math.abs(days);
|
|
12104
12174
|
}
|
|
@@ -12107,7 +12177,7 @@ const DATEDIF = {
|
|
|
12107
12177
|
if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
|
|
12108
12178
|
return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
|
|
12109
12179
|
}
|
|
12110
|
-
const endDateWithinOneYear = new
|
|
12180
|
+
const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
|
|
12111
12181
|
let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
|
|
12112
12182
|
if (days < 0) {
|
|
12113
12183
|
endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
|
|
@@ -12220,7 +12290,7 @@ const EOMONTH = {
|
|
|
12220
12290
|
const _months = Math.trunc(toNumber(months));
|
|
12221
12291
|
const yStart = _startDate.getFullYear();
|
|
12222
12292
|
const mStart = _startDate.getMonth();
|
|
12223
|
-
const jsDate = new
|
|
12293
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
12224
12294
|
return jsDateToRoundNumber(jsDate);
|
|
12225
12295
|
},
|
|
12226
12296
|
isExported: true,
|
|
@@ -12257,17 +12327,17 @@ const ISOWEEKNUM = {
|
|
|
12257
12327
|
// The first week of the year is the week that contains the first
|
|
12258
12328
|
// Thursday of the year.
|
|
12259
12329
|
let firstThursday = 1;
|
|
12260
|
-
while (new
|
|
12330
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
12261
12331
|
firstThursday += 1;
|
|
12262
12332
|
}
|
|
12263
|
-
const firstDayOfFirstWeek = new
|
|
12333
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
12264
12334
|
// The last week of the year is the week that contains the last Thursday of
|
|
12265
12335
|
// the year.
|
|
12266
12336
|
let lastThursday = 31;
|
|
12267
|
-
while (new
|
|
12337
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
12268
12338
|
lastThursday -= 1;
|
|
12269
12339
|
}
|
|
12270
|
-
const lastDayOfLastWeek = new
|
|
12340
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
12271
12341
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
12272
12342
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
12273
12343
|
let offsetYear;
|
|
@@ -12293,17 +12363,17 @@ const ISOWEEKNUM = {
|
|
|
12293
12363
|
case 1:
|
|
12294
12364
|
// firstDay is the 1st day of the 1st week of the year after
|
|
12295
12365
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
12296
|
-
firstDay = new
|
|
12366
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
12297
12367
|
break;
|
|
12298
12368
|
case -1:
|
|
12299
12369
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
12300
12370
|
// The first week of the previous year is the week that contains the
|
|
12301
12371
|
// first Thursday of the previous year.
|
|
12302
12372
|
let firstThursdayPreviousYear = 1;
|
|
12303
|
-
while (new
|
|
12373
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
12304
12374
|
firstThursdayPreviousYear += 1;
|
|
12305
12375
|
}
|
|
12306
|
-
firstDay = new
|
|
12376
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
12307
12377
|
break;
|
|
12308
12378
|
}
|
|
12309
12379
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -12438,8 +12508,8 @@ const NETWORKDAYS_INTL = {
|
|
|
12438
12508
|
});
|
|
12439
12509
|
}
|
|
12440
12510
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
12441
|
-
const stopDate =
|
|
12442
|
-
let stepDate =
|
|
12511
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
12512
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
12443
12513
|
const timeStopDate = stopDate.getTime();
|
|
12444
12514
|
let timeStepDate = stepDate.getTime();
|
|
12445
12515
|
let netWorkingDay = 0;
|
|
@@ -12463,8 +12533,7 @@ const NOW = {
|
|
|
12463
12533
|
returns: ["DATE"],
|
|
12464
12534
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
12465
12535
|
compute: function () {
|
|
12466
|
-
let today =
|
|
12467
|
-
today.setMilliseconds(0);
|
|
12536
|
+
let today = DateTime.now();
|
|
12468
12537
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
12469
12538
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
12470
12539
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -12534,8 +12603,8 @@ const TODAY = {
|
|
|
12534
12603
|
returns: ["DATE"],
|
|
12535
12604
|
computeFormat: () => "m/d/yyyy",
|
|
12536
12605
|
compute: function () {
|
|
12537
|
-
const today =
|
|
12538
|
-
const jsDate = new
|
|
12606
|
+
const today = DateTime.now();
|
|
12607
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12539
12608
|
return jsDateToRoundNumber(jsDate);
|
|
12540
12609
|
},
|
|
12541
12610
|
isExported: true,
|
|
@@ -12590,10 +12659,10 @@ const WEEKNUM = {
|
|
|
12590
12659
|
}
|
|
12591
12660
|
const y = _date.getFullYear();
|
|
12592
12661
|
let dayStart = 1;
|
|
12593
|
-
let startDayOfFirstWeek = new
|
|
12662
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12594
12663
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
12595
12664
|
dayStart += 1;
|
|
12596
|
-
startDayOfFirstWeek = new
|
|
12665
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12597
12666
|
}
|
|
12598
12667
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
12599
12668
|
if (dif < 0) {
|
|
@@ -12647,7 +12716,7 @@ const WORKDAY_INTL = {
|
|
|
12647
12716
|
timesHoliday.add(holiday.getTime());
|
|
12648
12717
|
});
|
|
12649
12718
|
}
|
|
12650
|
-
let stepDate =
|
|
12719
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
12651
12720
|
let timeStepDate = stepDate.getTime();
|
|
12652
12721
|
const unitDay = Math.sign(_numDays);
|
|
12653
12722
|
let stepDay = Math.abs(_numDays);
|
|
@@ -12709,7 +12778,7 @@ const MONTH_START = {
|
|
|
12709
12778
|
const _startDate = toJsDate(date);
|
|
12710
12779
|
const yStart = _startDate.getFullYear();
|
|
12711
12780
|
const mStart = _startDate.getMonth();
|
|
12712
|
-
const jsDate = new
|
|
12781
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
12713
12782
|
return jsDateToRoundNumber(jsDate);
|
|
12714
12783
|
},
|
|
12715
12784
|
};
|
|
@@ -12747,7 +12816,7 @@ const QUARTER_START = {
|
|
|
12747
12816
|
compute: function (date) {
|
|
12748
12817
|
const quarter = QUARTER.compute(date);
|
|
12749
12818
|
const year = YEAR.compute(date);
|
|
12750
|
-
const jsDate = new
|
|
12819
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
12751
12820
|
return jsDateToRoundNumber(jsDate);
|
|
12752
12821
|
},
|
|
12753
12822
|
};
|
|
@@ -12762,7 +12831,7 @@ const QUARTER_END = {
|
|
|
12762
12831
|
compute: function (date) {
|
|
12763
12832
|
const quarter = QUARTER.compute(date);
|
|
12764
12833
|
const year = YEAR.compute(date);
|
|
12765
|
-
const jsDate = new
|
|
12834
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
12766
12835
|
return jsDateToRoundNumber(jsDate);
|
|
12767
12836
|
},
|
|
12768
12837
|
};
|
|
@@ -12776,7 +12845,7 @@ const YEAR_START = {
|
|
|
12776
12845
|
computeFormat: () => "m/d/yyyy",
|
|
12777
12846
|
compute: function (date) {
|
|
12778
12847
|
const year = YEAR.compute(date);
|
|
12779
|
-
const jsDate = new
|
|
12848
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
12780
12849
|
return jsDateToRoundNumber(jsDate);
|
|
12781
12850
|
},
|
|
12782
12851
|
};
|
|
@@ -12790,7 +12859,7 @@ const YEAR_END = {
|
|
|
12790
12859
|
computeFormat: () => "m/d/yyyy",
|
|
12791
12860
|
compute: function (date) {
|
|
12792
12861
|
const year = YEAR.compute(date);
|
|
12793
|
-
const jsDate = new
|
|
12862
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
12794
12863
|
return jsDateToRoundNumber(jsDate);
|
|
12795
12864
|
},
|
|
12796
12865
|
};
|
|
@@ -12838,8 +12907,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
12838
12907
|
const DELTA = {
|
|
12839
12908
|
description: _lt("Compare two numeric values, returning 1 if they're equal."),
|
|
12840
12909
|
args: [
|
|
12841
|
-
arg(" (number)", _lt("The first number to compare.")),
|
|
12842
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12910
|
+
arg("number1 (number)", _lt("The first number to compare.")),
|
|
12911
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12843
12912
|
],
|
|
12844
12913
|
returns: ["NUMBER"],
|
|
12845
12914
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -12925,7 +12994,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
12925
12994
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
12926
12995
|
const startDate = toJsDate(settlement);
|
|
12927
12996
|
const endDate = toJsDate(maturity);
|
|
12928
|
-
const startDatePlusOneYear =
|
|
12997
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
12929
12998
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
12930
12999
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
12931
13000
|
}
|
|
@@ -13060,7 +13129,7 @@ const AMORLINC = {
|
|
|
13060
13129
|
arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
|
|
13061
13130
|
arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
|
|
13062
13131
|
arg("rate (number)", _lt("The deprecation rate.")),
|
|
13063
|
-
arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13132
|
+
arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13064
13133
|
],
|
|
13065
13134
|
returns: ["NUMBER"],
|
|
13066
13135
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -16043,8 +16112,8 @@ const MID = {
|
|
|
16043
16112
|
description: _lt("A segment of a string."),
|
|
16044
16113
|
args: [
|
|
16045
16114
|
arg("text (string)", _lt("The string to extract a segment from.")),
|
|
16046
|
-
arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
16047
|
-
arg(" (number)", _lt("The length of the segment to extract.")),
|
|
16115
|
+
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.")),
|
|
16116
|
+
arg("extract_length (number)", _lt("The length of the segment to extract.")),
|
|
16048
16117
|
],
|
|
16049
16118
|
returns: ["STRING"],
|
|
16050
16119
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -17713,10 +17782,10 @@ const arrowMap = {
|
|
|
17713
17782
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
17714
17783
|
const direction = arrowMap[ev.key];
|
|
17715
17784
|
if (ev.shiftKey) {
|
|
17716
|
-
selection.resizeAnchorZone(direction, ev
|
|
17785
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17717
17786
|
}
|
|
17718
17787
|
else {
|
|
17719
|
-
selection.moveAnchorCell(direction, ev
|
|
17788
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17720
17789
|
}
|
|
17721
17790
|
}
|
|
17722
17791
|
|
|
@@ -22413,7 +22482,10 @@ class GridOverlay extends owl.Component {
|
|
|
22413
22482
|
return;
|
|
22414
22483
|
}
|
|
22415
22484
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
22416
|
-
this.props.onCellClicked(col, row, {
|
|
22485
|
+
this.props.onCellClicked(col, row, {
|
|
22486
|
+
expandZone: ev.shiftKey,
|
|
22487
|
+
addZone: isCtrlKey(ev),
|
|
22488
|
+
});
|
|
22417
22489
|
}
|
|
22418
22490
|
onDoubleClick(ev) {
|
|
22419
22491
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -22486,6 +22558,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22486
22558
|
draggerShadowThickness: 0,
|
|
22487
22559
|
delta: 0,
|
|
22488
22560
|
base: 0,
|
|
22561
|
+
position: "before",
|
|
22489
22562
|
});
|
|
22490
22563
|
_computeHandleDisplay(ev) {
|
|
22491
22564
|
const position = this._getEvOffset(ev);
|
|
@@ -22610,11 +22683,13 @@ class AbstractResizer extends owl.Component {
|
|
|
22610
22683
|
this.state.draggerLinePosition = dimensions.start;
|
|
22611
22684
|
this.state.draggerShadowPosition = dimensions.start;
|
|
22612
22685
|
this.state.base = elementIndex;
|
|
22686
|
+
this.state.position = "before";
|
|
22613
22687
|
}
|
|
22614
22688
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
22615
22689
|
this.state.draggerLinePosition = dimensions.end;
|
|
22616
22690
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
22617
|
-
this.state.base = elementIndex
|
|
22691
|
+
this.state.base = elementIndex;
|
|
22692
|
+
this.state.position = "after";
|
|
22618
22693
|
}
|
|
22619
22694
|
else {
|
|
22620
22695
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -22638,7 +22713,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22638
22713
|
this._increaseSelection(index);
|
|
22639
22714
|
}
|
|
22640
22715
|
else {
|
|
22641
|
-
this._selectElement(index, ev
|
|
22716
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
22642
22717
|
}
|
|
22643
22718
|
this.lastSelectedElementIndex = index;
|
|
22644
22719
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -22651,7 +22726,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22651
22726
|
const mouseUpSelect = () => {
|
|
22652
22727
|
this.state.isSelecting = false;
|
|
22653
22728
|
this.lastSelectedElementIndex = null;
|
|
22654
|
-
this.env.model.dispatch(ev
|
|
22729
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
22655
22730
|
this._computeGrabDisplay(ev);
|
|
22656
22731
|
};
|
|
22657
22732
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -22797,13 +22872,14 @@ class ColResizer extends AbstractResizer {
|
|
|
22797
22872
|
dimension: "COL",
|
|
22798
22873
|
base: this.state.base,
|
|
22799
22874
|
elements,
|
|
22875
|
+
position: this.state.position,
|
|
22800
22876
|
});
|
|
22801
22877
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22802
22878
|
this.env.raiseError(MergeErrorMessage);
|
|
22803
22879
|
}
|
|
22804
22880
|
}
|
|
22805
|
-
_selectElement(index,
|
|
22806
|
-
this.env.model.selection.selectColumn(index,
|
|
22881
|
+
_selectElement(index, addDistinctHeader) {
|
|
22882
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22807
22883
|
}
|
|
22808
22884
|
_increaseSelection(index) {
|
|
22809
22885
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -22970,13 +23046,14 @@ class RowResizer extends AbstractResizer {
|
|
|
22970
23046
|
dimension: "ROW",
|
|
22971
23047
|
base: this.state.base,
|
|
22972
23048
|
elements,
|
|
23049
|
+
position: this.state.position,
|
|
22973
23050
|
});
|
|
22974
23051
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22975
23052
|
this.env.raiseError(MergeErrorMessage);
|
|
22976
23053
|
}
|
|
22977
23054
|
}
|
|
22978
|
-
_selectElement(index,
|
|
22979
|
-
this.env.model.selection.selectRow(index,
|
|
23055
|
+
_selectElement(index, addDistinctHeader) {
|
|
23056
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22980
23057
|
}
|
|
22981
23058
|
_increaseSelection(index) {
|
|
22982
23059
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -23077,8 +23154,8 @@ function useWheelHandler(handler) {
|
|
|
23077
23154
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
23078
23155
|
}
|
|
23079
23156
|
const onMouseWheel = (ev) => {
|
|
23080
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23081
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23157
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23158
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23082
23159
|
handler(deltaX, deltaY);
|
|
23083
23160
|
};
|
|
23084
23161
|
return onMouseWheel;
|
|
@@ -23780,8 +23857,8 @@ class Grid extends owl.Component {
|
|
|
23780
23857
|
// ---------------------------------------------------------------------------
|
|
23781
23858
|
// Zone selection with mouse
|
|
23782
23859
|
// ---------------------------------------------------------------------------
|
|
23783
|
-
onCellClicked(col, row, {
|
|
23784
|
-
if (
|
|
23860
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
23861
|
+
if (addZone) {
|
|
23785
23862
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
23786
23863
|
}
|
|
23787
23864
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -23790,10 +23867,10 @@ class Grid extends owl.Component {
|
|
|
23790
23867
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
23791
23868
|
this.env.model.dispatch("STOP_EDITION");
|
|
23792
23869
|
}
|
|
23793
|
-
if (
|
|
23870
|
+
if (expandZone) {
|
|
23794
23871
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
23795
23872
|
}
|
|
23796
|
-
else if (
|
|
23873
|
+
else if (addZone) {
|
|
23797
23874
|
this.env.model.selection.addCellToSelection(col, row);
|
|
23798
23875
|
}
|
|
23799
23876
|
else {
|
|
@@ -23855,9 +23932,7 @@ class Grid extends owl.Component {
|
|
|
23855
23932
|
return;
|
|
23856
23933
|
}
|
|
23857
23934
|
let keyDownString = "";
|
|
23858
|
-
if (ev
|
|
23859
|
-
keyDownString += "CTRL+";
|
|
23860
|
-
if (ev.metaKey)
|
|
23935
|
+
if (isCtrlKey(ev))
|
|
23861
23936
|
keyDownString += "CTRL+";
|
|
23862
23937
|
if (ev.altKey)
|
|
23863
23938
|
keyDownString += "ALT+";
|
|
@@ -25765,7 +25840,7 @@ const machine = {
|
|
|
25765
25840
|
SPACE: goTo(State.RightRef),
|
|
25766
25841
|
NUMBER: goTo(State.Found),
|
|
25767
25842
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25768
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
25843
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
25769
25844
|
},
|
|
25770
25845
|
[State.RightColumnRef]: {
|
|
25771
25846
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -25776,6 +25851,7 @@ const machine = {
|
|
|
25776
25851
|
SPACE: goTo(State.RightRowRef),
|
|
25777
25852
|
NUMBER: goTo(State.Found),
|
|
25778
25853
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25854
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
25779
25855
|
},
|
|
25780
25856
|
[State.Found]: {},
|
|
25781
25857
|
};
|
|
@@ -29483,7 +29559,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
29483
29559
|
*/
|
|
29484
29560
|
function getBorderId(border) {
|
|
29485
29561
|
for (let [key, value] of Object.entries(borders)) {
|
|
29486
|
-
if (
|
|
29562
|
+
if (deepEquals(value, border)) {
|
|
29487
29563
|
return parseInt(key, 10);
|
|
29488
29564
|
}
|
|
29489
29565
|
}
|
|
@@ -32451,7 +32527,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
32451
32527
|
const elements = cmd.dimension === "COL"
|
|
32452
32528
|
? this.getNumberCols(cmd.sheetId)
|
|
32453
32529
|
: this.getNumberRows(cmd.sheetId);
|
|
32454
|
-
if (cmd.base < 0 || cmd.base
|
|
32530
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
32455
32531
|
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
32456
32532
|
}
|
|
32457
32533
|
else if (cmd.quantity <= 0) {
|
|
@@ -33484,13 +33560,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33484
33560
|
// Getters
|
|
33485
33561
|
// ---------------------------------------------------------------------------
|
|
33486
33562
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
33487
|
-
|
|
33488
|
-
|
|
33489
|
-
|
|
33490
|
-
|
|
33491
|
-
|
|
33563
|
+
try {
|
|
33564
|
+
const compiledFormula = compile(formulaString);
|
|
33565
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
33566
|
+
const ranges = [];
|
|
33567
|
+
for (let xc of compiledFormula.dependencies) {
|
|
33568
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
33569
|
+
}
|
|
33570
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
33571
|
+
}
|
|
33572
|
+
catch (error) {
|
|
33573
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
33492
33574
|
}
|
|
33493
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
33494
33575
|
}
|
|
33495
33576
|
/**
|
|
33496
33577
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -33915,39 +33996,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33915
33996
|
this.computedIcons[sheetId] = {};
|
|
33916
33997
|
const computedStyle = this.computedStyles[sheetId];
|
|
33917
33998
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
33918
|
-
|
|
33919
|
-
|
|
33920
|
-
|
|
33921
|
-
|
|
33922
|
-
|
|
33923
|
-
|
|
33924
|
-
|
|
33925
|
-
|
|
33926
|
-
|
|
33927
|
-
|
|
33928
|
-
|
|
33929
|
-
|
|
33930
|
-
|
|
33931
|
-
|
|
33932
|
-
|
|
33933
|
-
for (let
|
|
33934
|
-
|
|
33935
|
-
|
|
33936
|
-
|
|
33937
|
-
if (
|
|
33938
|
-
|
|
33939
|
-
|
|
33940
|
-
|
|
33941
|
-
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33942
|
-
}
|
|
33999
|
+
switch (cf.rule.type) {
|
|
34000
|
+
case "ColorScaleRule":
|
|
34001
|
+
for (let range of cf.ranges) {
|
|
34002
|
+
this.applyColorScale(range, cf.rule);
|
|
34003
|
+
}
|
|
34004
|
+
break;
|
|
34005
|
+
case "IconSetRule":
|
|
34006
|
+
for (let range of cf.ranges) {
|
|
34007
|
+
this.applyIcon(range, cf.rule);
|
|
34008
|
+
}
|
|
34009
|
+
break;
|
|
34010
|
+
default:
|
|
34011
|
+
for (let ref of cf.ranges) {
|
|
34012
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
34013
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
34014
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
34015
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
34016
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
34017
|
+
if (pr && pr(cell, cf.rule)) {
|
|
34018
|
+
if (!computedStyle[col])
|
|
34019
|
+
computedStyle[col] = [];
|
|
34020
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
34021
|
+
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33943
34022
|
}
|
|
33944
34023
|
}
|
|
33945
34024
|
}
|
|
33946
|
-
|
|
33947
|
-
|
|
33948
|
-
}
|
|
33949
|
-
catch (_) {
|
|
33950
|
-
// we don't care about the errors within the evaluation of a rule
|
|
34025
|
+
}
|
|
34026
|
+
break;
|
|
33951
34027
|
}
|
|
33952
34028
|
}
|
|
33953
34029
|
}
|
|
@@ -33972,7 +34048,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33972
34048
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
33973
34049
|
case "formula":
|
|
33974
34050
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
33975
|
-
return
|
|
34051
|
+
return typeof value === "number" ? value : null;
|
|
33976
34052
|
default:
|
|
33977
34053
|
return null;
|
|
33978
34054
|
}
|
|
@@ -35621,19 +35697,21 @@ class AutofillPlugin extends UIPlugin {
|
|
|
35621
35697
|
let col = zone.left;
|
|
35622
35698
|
let row = zone.bottom;
|
|
35623
35699
|
if (col > 0) {
|
|
35624
|
-
let
|
|
35625
|
-
while (
|
|
35700
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
35701
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
35702
|
+
this.getters.getCell(leftPosition)?.content) {
|
|
35626
35703
|
row += 1;
|
|
35627
|
-
|
|
35704
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
35628
35705
|
}
|
|
35629
35706
|
}
|
|
35630
35707
|
if (row === zone.bottom) {
|
|
35631
35708
|
col = zone.right;
|
|
35632
35709
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
35633
|
-
let
|
|
35634
|
-
while (
|
|
35710
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
35711
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
35712
|
+
this.getters.getCell(rightPosition)?.content) {
|
|
35635
35713
|
row += 1;
|
|
35636
|
-
|
|
35714
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
35637
35715
|
}
|
|
35638
35716
|
}
|
|
35639
35717
|
}
|
|
@@ -40581,6 +40659,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
40581
40659
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40582
40660
|
case "colrow":
|
|
40583
40661
|
indexOfNumber = xc.search(/[0-9]/);
|
|
40662
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
40663
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
40664
|
+
return "$" + xc;
|
|
40665
|
+
}
|
|
40584
40666
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40585
40667
|
return "$" + xc;
|
|
40586
40668
|
case "none":
|
|
@@ -41762,7 +41844,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41762
41844
|
sheetId: cmd.sheetId,
|
|
41763
41845
|
base: cmd.base,
|
|
41764
41846
|
quantity: thickness,
|
|
41765
|
-
position:
|
|
41847
|
+
position: cmd.position,
|
|
41766
41848
|
});
|
|
41767
41849
|
const isCol = cmd.dimension === "COL";
|
|
41768
41850
|
const start = cmd.elements[0];
|
|
@@ -41779,12 +41861,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41779
41861
|
},
|
|
41780
41862
|
];
|
|
41781
41863
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
41864
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
41782
41865
|
const pasteTarget = [
|
|
41783
41866
|
{
|
|
41784
|
-
left: isCol ?
|
|
41785
|
-
right: isCol ?
|
|
41786
|
-
top: !isCol ?
|
|
41787
|
-
bottom: !isCol ?
|
|
41867
|
+
left: isCol ? base : 0,
|
|
41868
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
41869
|
+
top: !isCol ? base : 0,
|
|
41870
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
41788
41871
|
},
|
|
41789
41872
|
];
|
|
41790
41873
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -41821,6 +41904,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41821
41904
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
41822
41905
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
41823
41906
|
}
|
|
41907
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
41908
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
41909
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
41910
|
+
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
41911
|
+
}
|
|
41824
41912
|
return 0 /* CommandResult.Success */;
|
|
41825
41913
|
}
|
|
41826
41914
|
//-------------------------------------------
|
|
@@ -44102,7 +44190,7 @@ class Spreadsheet extends owl.Component {
|
|
|
44102
44190
|
}
|
|
44103
44191
|
onKeydown(ev) {
|
|
44104
44192
|
let keyDownString = "";
|
|
44105
|
-
if (ev
|
|
44193
|
+
if (isCtrlKey(ev)) {
|
|
44106
44194
|
keyDownString += "CTRL+";
|
|
44107
44195
|
}
|
|
44108
44196
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -47839,6 +47927,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
47839
47927
|
exports.tokenize = tokenize;
|
|
47840
47928
|
|
|
47841
47929
|
|
|
47842
|
-
__info__.version = '16.3.
|
|
47843
|
-
__info__.date = '
|
|
47844
|
-
__info__.hash = '
|
|
47930
|
+
__info__.version = '16.3.22';
|
|
47931
|
+
__info__.date = '2024-01-17T10:24:07.652Z';
|
|
47932
|
+
__info__.hash = '2c1b136';
|