@odoo/o-spreadsheet 16.2.24 → 16.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet.cjs.js +172 -99
- package/dist/o-spreadsheet.d.ts +37 -10
- package/dist/o-spreadsheet.esm.js +172 -99
- package/dist/o-spreadsheet.iife.js +172 -99
- package/dist/o-spreadsheet.iife.min.js +243 -243
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -290,15 +290,76 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
290
290
|
// -----------------------------------------------------------------------------
|
|
291
291
|
// Date Type
|
|
292
292
|
// -----------------------------------------------------------------------------
|
|
293
|
+
/**
|
|
294
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
295
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
296
|
+
* and it is timezone-agnostic.
|
|
297
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
298
|
+
*/
|
|
299
|
+
class DateTime {
|
|
300
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
301
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
302
|
+
}
|
|
303
|
+
static fromTimestamp(timestamp) {
|
|
304
|
+
const date = new Date(timestamp);
|
|
305
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
306
|
+
}
|
|
307
|
+
static now() {
|
|
308
|
+
const now = new Date();
|
|
309
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
310
|
+
}
|
|
311
|
+
toString() {
|
|
312
|
+
return this.jsDate.toString();
|
|
313
|
+
}
|
|
314
|
+
getTime() {
|
|
315
|
+
return this.jsDate.getTime();
|
|
316
|
+
}
|
|
317
|
+
getFullYear() {
|
|
318
|
+
return this.jsDate.getUTCFullYear();
|
|
319
|
+
}
|
|
320
|
+
getMonth() {
|
|
321
|
+
return this.jsDate.getUTCMonth();
|
|
322
|
+
}
|
|
323
|
+
getDate() {
|
|
324
|
+
return this.jsDate.getUTCDate();
|
|
325
|
+
}
|
|
326
|
+
getDay() {
|
|
327
|
+
return this.jsDate.getUTCDay();
|
|
328
|
+
}
|
|
329
|
+
getHours() {
|
|
330
|
+
return this.jsDate.getUTCHours();
|
|
331
|
+
}
|
|
332
|
+
getMinutes() {
|
|
333
|
+
return this.jsDate.getUTCMinutes();
|
|
334
|
+
}
|
|
335
|
+
getSeconds() {
|
|
336
|
+
return this.jsDate.getUTCSeconds();
|
|
337
|
+
}
|
|
338
|
+
setFullYear(year) {
|
|
339
|
+
this.jsDate.setFullYear(year);
|
|
340
|
+
}
|
|
341
|
+
setDate(date) {
|
|
342
|
+
this.jsDate.setUTCDate(date);
|
|
343
|
+
}
|
|
344
|
+
setHours(hours) {
|
|
345
|
+
this.jsDate.setUTCHours(hours);
|
|
346
|
+
}
|
|
347
|
+
setMinutes(minutes) {
|
|
348
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
349
|
+
}
|
|
350
|
+
setSeconds(seconds) {
|
|
351
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
293
354
|
// -----------------------------------------------------------------------------
|
|
294
355
|
// Parsing
|
|
295
356
|
// -----------------------------------------------------------------------------
|
|
296
|
-
const INITIAL_1900_DAY = new
|
|
357
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
297
358
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
298
359
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
299
|
-
const CURRENT_YEAR =
|
|
300
|
-
const INITIAL_JS_DAY =
|
|
301
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
360
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
361
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
362
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
302
363
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
303
364
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
304
365
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -347,7 +408,7 @@ function _parseDateTime(str) {
|
|
|
347
408
|
return {
|
|
348
409
|
value: date.value + time.value,
|
|
349
410
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
350
|
-
jsDate: new
|
|
411
|
+
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()),
|
|
351
412
|
};
|
|
352
413
|
}
|
|
353
414
|
return date || time;
|
|
@@ -364,13 +425,13 @@ function parseDate(str, dateFormat) {
|
|
|
364
425
|
const day = Number(parts[dayIndex]);
|
|
365
426
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
366
427
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
367
|
-
const jsDate = new
|
|
428
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
368
429
|
const sep = str.match(/\/|-|\s/)[0];
|
|
369
430
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
370
431
|
// invalid date
|
|
371
432
|
return null;
|
|
372
433
|
}
|
|
373
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
434
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
374
435
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
375
436
|
if (parts[yearIndex]) {
|
|
376
437
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -430,7 +491,7 @@ function parseTime(str) {
|
|
|
430
491
|
if (hours >= 24) {
|
|
431
492
|
format = "hhhh:mm:ss";
|
|
432
493
|
}
|
|
433
|
-
const jsDate = new
|
|
494
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
434
495
|
return {
|
|
435
496
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
436
497
|
format: format,
|
|
@@ -444,7 +505,7 @@ function parseTime(str) {
|
|
|
444
505
|
// -----------------------------------------------------------------------------
|
|
445
506
|
function numberToJsDate(value) {
|
|
446
507
|
const truncValue = Math.trunc(value);
|
|
447
|
-
let date =
|
|
508
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
448
509
|
let time = value - truncValue;
|
|
449
510
|
time = time < 0 ? 1 + time : time;
|
|
450
511
|
const hours = Math.round(time * 24);
|
|
@@ -461,7 +522,7 @@ function jsDateToRoundNumber(date) {
|
|
|
461
522
|
}
|
|
462
523
|
/** Return the number of days in the current month of the given date */
|
|
463
524
|
function getDaysInMonth(date) {
|
|
464
|
-
return new
|
|
525
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
465
526
|
}
|
|
466
527
|
function isLastDayOfMonth(date) {
|
|
467
528
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -479,7 +540,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
479
540
|
const yStart = date.getFullYear();
|
|
480
541
|
const mStart = date.getMonth();
|
|
481
542
|
const dStart = date.getDate();
|
|
482
|
-
const jsDate = new
|
|
543
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
483
544
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
484
545
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
485
546
|
}
|
|
@@ -1900,7 +1961,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1900
1961
|
.map((p) => {
|
|
1901
1962
|
switch (p) {
|
|
1902
1963
|
case "hhhh":
|
|
1903
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
1964
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1904
1965
|
return helapsedHours.toString();
|
|
1905
1966
|
case "hh":
|
|
1906
1967
|
return hours.toString().padStart(2, "0");
|
|
@@ -5048,6 +5109,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
5048
5109
|
},
|
|
5049
5110
|
};
|
|
5050
5111
|
|
|
5112
|
+
const macRegex = /Mac/i;
|
|
5051
5113
|
/**
|
|
5052
5114
|
* Return true if the event was triggered from
|
|
5053
5115
|
* a child element.
|
|
@@ -5095,7 +5157,15 @@ function getOpenedMenus() {
|
|
|
5095
5157
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5096
5158
|
}
|
|
5097
5159
|
function isMacOS() {
|
|
5098
|
-
return navigator.userAgent
|
|
5160
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5161
|
+
}
|
|
5162
|
+
/**
|
|
5163
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5164
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5165
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5166
|
+
*/
|
|
5167
|
+
function isCtrlKey(ev) {
|
|
5168
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5099
5169
|
}
|
|
5100
5170
|
|
|
5101
5171
|
/**
|
|
@@ -9487,6 +9557,9 @@ function arg(definition, description = "") {
|
|
|
9487
9557
|
function makeArg(str) {
|
|
9488
9558
|
let parts = str.match(ARG_REGEXP);
|
|
9489
9559
|
let name = parts[1].trim();
|
|
9560
|
+
if (!name) {
|
|
9561
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
9562
|
+
}
|
|
9490
9563
|
let types = [];
|
|
9491
9564
|
let isOptional = false;
|
|
9492
9565
|
let isRepeating = false;
|
|
@@ -11950,7 +12023,7 @@ const DATE = {
|
|
|
11950
12023
|
if (_year < 1900) {
|
|
11951
12024
|
_year += 1900;
|
|
11952
12025
|
}
|
|
11953
|
-
const jsDate = new
|
|
12026
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
11954
12027
|
const result = jsDateToRoundNumber(jsDate);
|
|
11955
12028
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
11956
12029
|
return result;
|
|
@@ -12058,7 +12131,7 @@ const EOMONTH = {
|
|
|
12058
12131
|
const _months = Math.trunc(toNumber(months));
|
|
12059
12132
|
const yStart = _startDate.getFullYear();
|
|
12060
12133
|
const mStart = _startDate.getMonth();
|
|
12061
|
-
const jsDate = new
|
|
12134
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
12062
12135
|
return jsDateToRoundNumber(jsDate);
|
|
12063
12136
|
},
|
|
12064
12137
|
isExported: true,
|
|
@@ -12095,17 +12168,17 @@ const ISOWEEKNUM = {
|
|
|
12095
12168
|
// The first week of the year is the week that contains the first
|
|
12096
12169
|
// Thursday of the year.
|
|
12097
12170
|
let firstThursday = 1;
|
|
12098
|
-
while (new
|
|
12171
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
12099
12172
|
firstThursday += 1;
|
|
12100
12173
|
}
|
|
12101
|
-
const firstDayOfFirstWeek = new
|
|
12174
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
12102
12175
|
// The last week of the year is the week that contains the last Thursday of
|
|
12103
12176
|
// the year.
|
|
12104
12177
|
let lastThursday = 31;
|
|
12105
|
-
while (new
|
|
12178
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
12106
12179
|
lastThursday -= 1;
|
|
12107
12180
|
}
|
|
12108
|
-
const lastDayOfLastWeek = new
|
|
12181
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
12109
12182
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
12110
12183
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
12111
12184
|
let offsetYear;
|
|
@@ -12131,17 +12204,17 @@ const ISOWEEKNUM = {
|
|
|
12131
12204
|
case 1:
|
|
12132
12205
|
// firstDay is the 1st day of the 1st week of the year after
|
|
12133
12206
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
12134
|
-
firstDay = new
|
|
12207
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
12135
12208
|
break;
|
|
12136
12209
|
case -1:
|
|
12137
12210
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
12138
12211
|
// The first week of the previous year is the week that contains the
|
|
12139
12212
|
// first Thursday of the previous year.
|
|
12140
12213
|
let firstThursdayPreviousYear = 1;
|
|
12141
|
-
while (new
|
|
12214
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
12142
12215
|
firstThursdayPreviousYear += 1;
|
|
12143
12216
|
}
|
|
12144
|
-
firstDay = new
|
|
12217
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
12145
12218
|
break;
|
|
12146
12219
|
}
|
|
12147
12220
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -12276,8 +12349,8 @@ const NETWORKDAYS_INTL = {
|
|
|
12276
12349
|
});
|
|
12277
12350
|
}
|
|
12278
12351
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
12279
|
-
const stopDate =
|
|
12280
|
-
let stepDate =
|
|
12352
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
12353
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
12281
12354
|
const timeStopDate = stopDate.getTime();
|
|
12282
12355
|
let timeStepDate = stepDate.getTime();
|
|
12283
12356
|
let netWorkingDay = 0;
|
|
@@ -12301,8 +12374,7 @@ const NOW = {
|
|
|
12301
12374
|
returns: ["DATE"],
|
|
12302
12375
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
12303
12376
|
compute: function () {
|
|
12304
|
-
let today =
|
|
12305
|
-
today.setMilliseconds(0);
|
|
12377
|
+
let today = DateTime.now();
|
|
12306
12378
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
12307
12379
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
12308
12380
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -12372,8 +12444,8 @@ const TODAY = {
|
|
|
12372
12444
|
returns: ["DATE"],
|
|
12373
12445
|
computeFormat: () => "m/d/yyyy",
|
|
12374
12446
|
compute: function () {
|
|
12375
|
-
const today =
|
|
12376
|
-
const jsDate = new
|
|
12447
|
+
const today = DateTime.now();
|
|
12448
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12377
12449
|
return jsDateToRoundNumber(jsDate);
|
|
12378
12450
|
},
|
|
12379
12451
|
isExported: true,
|
|
@@ -12428,10 +12500,10 @@ const WEEKNUM = {
|
|
|
12428
12500
|
}
|
|
12429
12501
|
const y = _date.getFullYear();
|
|
12430
12502
|
let dayStart = 1;
|
|
12431
|
-
let startDayOfFirstWeek = new
|
|
12503
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12432
12504
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
12433
12505
|
dayStart += 1;
|
|
12434
|
-
startDayOfFirstWeek = new
|
|
12506
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12435
12507
|
}
|
|
12436
12508
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
12437
12509
|
if (dif < 0) {
|
|
@@ -12485,7 +12557,7 @@ const WORKDAY_INTL = {
|
|
|
12485
12557
|
timesHoliday.add(holiday.getTime());
|
|
12486
12558
|
});
|
|
12487
12559
|
}
|
|
12488
|
-
let stepDate =
|
|
12560
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
12489
12561
|
let timeStepDate = stepDate.getTime();
|
|
12490
12562
|
const unitDay = Math.sign(_numDays);
|
|
12491
12563
|
let stepDay = Math.abs(_numDays);
|
|
@@ -12547,7 +12619,7 @@ const MONTH_START = {
|
|
|
12547
12619
|
const _startDate = toJsDate(date);
|
|
12548
12620
|
const yStart = _startDate.getFullYear();
|
|
12549
12621
|
const mStart = _startDate.getMonth();
|
|
12550
|
-
const jsDate = new
|
|
12622
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
12551
12623
|
return jsDateToRoundNumber(jsDate);
|
|
12552
12624
|
},
|
|
12553
12625
|
};
|
|
@@ -12585,7 +12657,7 @@ const QUARTER_START = {
|
|
|
12585
12657
|
compute: function (date) {
|
|
12586
12658
|
const quarter = QUARTER.compute(date);
|
|
12587
12659
|
const year = YEAR.compute(date);
|
|
12588
|
-
const jsDate = new
|
|
12660
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
12589
12661
|
return jsDateToRoundNumber(jsDate);
|
|
12590
12662
|
},
|
|
12591
12663
|
};
|
|
@@ -12600,7 +12672,7 @@ const QUARTER_END = {
|
|
|
12600
12672
|
compute: function (date) {
|
|
12601
12673
|
const quarter = QUARTER.compute(date);
|
|
12602
12674
|
const year = YEAR.compute(date);
|
|
12603
|
-
const jsDate = new
|
|
12675
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
12604
12676
|
return jsDateToRoundNumber(jsDate);
|
|
12605
12677
|
},
|
|
12606
12678
|
};
|
|
@@ -12614,7 +12686,7 @@ const YEAR_START = {
|
|
|
12614
12686
|
computeFormat: () => "m/d/yyyy",
|
|
12615
12687
|
compute: function (date) {
|
|
12616
12688
|
const year = YEAR.compute(date);
|
|
12617
|
-
const jsDate = new
|
|
12689
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
12618
12690
|
return jsDateToRoundNumber(jsDate);
|
|
12619
12691
|
},
|
|
12620
12692
|
};
|
|
@@ -12628,7 +12700,7 @@ const YEAR_END = {
|
|
|
12628
12700
|
computeFormat: () => "m/d/yyyy",
|
|
12629
12701
|
compute: function (date) {
|
|
12630
12702
|
const year = YEAR.compute(date);
|
|
12631
|
-
const jsDate = new
|
|
12703
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
12632
12704
|
return jsDateToRoundNumber(jsDate);
|
|
12633
12705
|
},
|
|
12634
12706
|
};
|
|
@@ -12675,8 +12747,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
12675
12747
|
const DELTA = {
|
|
12676
12748
|
description: _lt("Compare two numeric values, returning 1 if they're equal."),
|
|
12677
12749
|
args: [
|
|
12678
|
-
arg(" (number)", _lt("The first number to compare.")),
|
|
12679
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12750
|
+
arg("number1 (number)", _lt("The first number to compare.")),
|
|
12751
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12680
12752
|
],
|
|
12681
12753
|
returns: ["NUMBER"],
|
|
12682
12754
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -12762,7 +12834,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
12762
12834
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
12763
12835
|
const startDate = toJsDate(settlement);
|
|
12764
12836
|
const endDate = toJsDate(maturity);
|
|
12765
|
-
const startDatePlusOneYear =
|
|
12837
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
12766
12838
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
12767
12839
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
12768
12840
|
}
|
|
@@ -12897,7 +12969,7 @@ const AMORLINC = {
|
|
|
12897
12969
|
arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
|
|
12898
12970
|
arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
|
|
12899
12971
|
arg("rate (number)", _lt("The deprecation rate.")),
|
|
12900
|
-
arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
12972
|
+
arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
12901
12973
|
],
|
|
12902
12974
|
returns: ["NUMBER"],
|
|
12903
12975
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -15841,8 +15913,8 @@ const MID = {
|
|
|
15841
15913
|
description: _lt("A segment of a string."),
|
|
15842
15914
|
args: [
|
|
15843
15915
|
arg("text (string)", _lt("The string to extract a segment from.")),
|
|
15844
|
-
arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
15845
|
-
arg(" (number)", _lt("The length of the segment to extract.")),
|
|
15916
|
+
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.")),
|
|
15917
|
+
arg("extract_length (number)", _lt("The length of the segment to extract.")),
|
|
15846
15918
|
],
|
|
15847
15919
|
returns: ["STRING"],
|
|
15848
15920
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -16713,10 +16785,10 @@ const arrowMap = {
|
|
|
16713
16785
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
16714
16786
|
const direction = arrowMap[ev.key];
|
|
16715
16787
|
if (ev.shiftKey) {
|
|
16716
|
-
selection.resizeAnchorZone(direction, ev
|
|
16788
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16717
16789
|
}
|
|
16718
16790
|
else {
|
|
16719
|
-
selection.moveAnchorCell(direction, ev
|
|
16791
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16720
16792
|
}
|
|
16721
16793
|
}
|
|
16722
16794
|
|
|
@@ -21051,7 +21123,10 @@ class GridOverlay extends owl.Component {
|
|
|
21051
21123
|
return;
|
|
21052
21124
|
}
|
|
21053
21125
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
21054
|
-
this.props.onCellClicked(col, row, {
|
|
21126
|
+
this.props.onCellClicked(col, row, {
|
|
21127
|
+
expandZone: ev.shiftKey,
|
|
21128
|
+
addZone: isCtrlKey(ev),
|
|
21129
|
+
});
|
|
21055
21130
|
}
|
|
21056
21131
|
onDoubleClick(ev) {
|
|
21057
21132
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -21295,7 +21370,7 @@ class AbstractResizer extends owl.Component {
|
|
|
21295
21370
|
this._increaseSelection(index);
|
|
21296
21371
|
}
|
|
21297
21372
|
else {
|
|
21298
|
-
this._selectElement(index, ev
|
|
21373
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
21299
21374
|
}
|
|
21300
21375
|
this.lastSelectedElementIndex = index;
|
|
21301
21376
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -21308,7 +21383,7 @@ class AbstractResizer extends owl.Component {
|
|
|
21308
21383
|
const mouseUpSelect = () => {
|
|
21309
21384
|
this.state.isSelecting = false;
|
|
21310
21385
|
this.lastSelectedElementIndex = null;
|
|
21311
|
-
this.env.model.dispatch(ev
|
|
21386
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
21312
21387
|
this._computeGrabDisplay(ev);
|
|
21313
21388
|
};
|
|
21314
21389
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -21458,8 +21533,8 @@ class ColResizer extends AbstractResizer {
|
|
|
21458
21533
|
this.env.raiseError(MergeErrorMessage);
|
|
21459
21534
|
}
|
|
21460
21535
|
}
|
|
21461
|
-
_selectElement(index,
|
|
21462
|
-
this.env.model.selection.selectColumn(index,
|
|
21536
|
+
_selectElement(index, addDistinctHeader) {
|
|
21537
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
21463
21538
|
}
|
|
21464
21539
|
_increaseSelection(index) {
|
|
21465
21540
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -21631,8 +21706,8 @@ class RowResizer extends AbstractResizer {
|
|
|
21631
21706
|
this.env.raiseError(MergeErrorMessage);
|
|
21632
21707
|
}
|
|
21633
21708
|
}
|
|
21634
|
-
_selectElement(index,
|
|
21635
|
-
this.env.model.selection.selectRow(index,
|
|
21709
|
+
_selectElement(index, addDistinctHeader) {
|
|
21710
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
21636
21711
|
}
|
|
21637
21712
|
_increaseSelection(index) {
|
|
21638
21713
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -22379,8 +22454,8 @@ class Grid extends owl.Component {
|
|
|
22379
22454
|
// ---------------------------------------------------------------------------
|
|
22380
22455
|
// Zone selection with mouse
|
|
22381
22456
|
// ---------------------------------------------------------------------------
|
|
22382
|
-
onCellClicked(col, row, {
|
|
22383
|
-
if (
|
|
22457
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
22458
|
+
if (addZone) {
|
|
22384
22459
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
22385
22460
|
}
|
|
22386
22461
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -22389,10 +22464,10 @@ class Grid extends owl.Component {
|
|
|
22389
22464
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
22390
22465
|
this.env.model.dispatch("STOP_EDITION");
|
|
22391
22466
|
}
|
|
22392
|
-
if (
|
|
22467
|
+
if (expandZone) {
|
|
22393
22468
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
22394
22469
|
}
|
|
22395
|
-
else if (
|
|
22470
|
+
else if (addZone) {
|
|
22396
22471
|
this.env.model.selection.addCellToSelection(col, row);
|
|
22397
22472
|
}
|
|
22398
22473
|
else {
|
|
@@ -22454,9 +22529,7 @@ class Grid extends owl.Component {
|
|
|
22454
22529
|
return;
|
|
22455
22530
|
}
|
|
22456
22531
|
let keyDownString = "";
|
|
22457
|
-
if (ev
|
|
22458
|
-
keyDownString += "CTRL+";
|
|
22459
|
-
if (ev.metaKey)
|
|
22532
|
+
if (isCtrlKey(ev))
|
|
22460
22533
|
keyDownString += "CTRL+";
|
|
22461
22534
|
if (ev.altKey)
|
|
22462
22535
|
keyDownString += "ALT+";
|
|
@@ -31974,13 +32047,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
31974
32047
|
// Getters
|
|
31975
32048
|
// ---------------------------------------------------------------------------
|
|
31976
32049
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
31977
|
-
|
|
31978
|
-
|
|
31979
|
-
|
|
31980
|
-
|
|
31981
|
-
|
|
32050
|
+
try {
|
|
32051
|
+
const compiledFormula = compile(formulaString);
|
|
32052
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
32053
|
+
const ranges = [];
|
|
32054
|
+
for (let xc of compiledFormula.dependencies) {
|
|
32055
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
32056
|
+
}
|
|
32057
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
32058
|
+
}
|
|
32059
|
+
catch (error) {
|
|
32060
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
31982
32061
|
}
|
|
31983
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
31984
32062
|
}
|
|
31985
32063
|
/**
|
|
31986
32064
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -32482,39 +32560,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32482
32560
|
this.computedIcons[sheetId] = {};
|
|
32483
32561
|
const computedStyle = this.computedStyles[sheetId];
|
|
32484
32562
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
32485
|
-
|
|
32486
|
-
|
|
32487
|
-
|
|
32488
|
-
|
|
32489
|
-
|
|
32490
|
-
|
|
32491
|
-
|
|
32492
|
-
|
|
32493
|
-
|
|
32494
|
-
|
|
32495
|
-
|
|
32496
|
-
|
|
32497
|
-
|
|
32498
|
-
|
|
32499
|
-
|
|
32500
|
-
for (let
|
|
32501
|
-
|
|
32502
|
-
|
|
32503
|
-
|
|
32504
|
-
if (
|
|
32505
|
-
|
|
32506
|
-
|
|
32507
|
-
|
|
32508
|
-
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32509
|
-
}
|
|
32563
|
+
switch (cf.rule.type) {
|
|
32564
|
+
case "ColorScaleRule":
|
|
32565
|
+
for (let range of cf.ranges) {
|
|
32566
|
+
this.applyColorScale(range, cf.rule);
|
|
32567
|
+
}
|
|
32568
|
+
break;
|
|
32569
|
+
case "IconSetRule":
|
|
32570
|
+
for (let range of cf.ranges) {
|
|
32571
|
+
this.applyIcon(range, cf.rule);
|
|
32572
|
+
}
|
|
32573
|
+
break;
|
|
32574
|
+
default:
|
|
32575
|
+
for (let ref of cf.ranges) {
|
|
32576
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
32577
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
32578
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
32579
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
32580
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
32581
|
+
if (pr && pr(cell, cf.rule)) {
|
|
32582
|
+
if (!computedStyle[col])
|
|
32583
|
+
computedStyle[col] = [];
|
|
32584
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
32585
|
+
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32510
32586
|
}
|
|
32511
32587
|
}
|
|
32512
32588
|
}
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
}
|
|
32516
|
-
catch (_) {
|
|
32517
|
-
// we don't care about the errors within the evaluation of a rule
|
|
32589
|
+
}
|
|
32590
|
+
break;
|
|
32518
32591
|
}
|
|
32519
32592
|
}
|
|
32520
32593
|
}
|
|
@@ -32539,7 +32612,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32539
32612
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
32540
32613
|
case "formula":
|
|
32541
32614
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
32542
|
-
return
|
|
32615
|
+
return typeof value === "number" ? value : null;
|
|
32543
32616
|
default:
|
|
32544
32617
|
return null;
|
|
32545
32618
|
}
|
|
@@ -41887,7 +41960,7 @@ class Spreadsheet extends owl.Component {
|
|
|
41887
41960
|
}
|
|
41888
41961
|
onKeydown(ev) {
|
|
41889
41962
|
let keyDownString = "";
|
|
41890
|
-
if (ev
|
|
41963
|
+
if (isCtrlKey(ev)) {
|
|
41891
41964
|
keyDownString += "CTRL+";
|
|
41892
41965
|
}
|
|
41893
41966
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -45591,6 +45664,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
45591
45664
|
exports.tokenize = tokenize;
|
|
45592
45665
|
|
|
45593
45666
|
|
|
45594
|
-
__info__.version = '16.2.
|
|
45595
|
-
__info__.date = '
|
|
45596
|
-
__info__.hash = '
|
|
45667
|
+
__info__.version = '16.2.27';
|
|
45668
|
+
__info__.date = '2024-01-12T13:42:07.889Z';
|
|
45669
|
+
__info__.hash = 'd8b1d67';
|