@odoo/o-spreadsheet 15.0.14 → 15.0.16

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.
@@ -126,14 +126,72 @@
126
126
  // -----------------------------------------------------------------------------
127
127
  // Date Type
128
128
  // -----------------------------------------------------------------------------
129
+ /**
130
+ * A DateTime object that can be used to manipulate spreadsheet dates.
131
+ * Conceptually, a spreadsheet date is simply a number with a date format,
132
+ * and it is timezone-agnostic.
133
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
134
+ */
135
+ class DateTime {
136
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
137
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
138
+ }
139
+ static fromTimestamp(timestamp) {
140
+ const date = new Date(timestamp);
141
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
142
+ }
143
+ static now() {
144
+ const now = new Date();
145
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
146
+ }
147
+ toString() {
148
+ return this.jsDate.toString();
149
+ }
150
+ getTime() {
151
+ return this.jsDate.getTime();
152
+ }
153
+ getFullYear() {
154
+ return this.jsDate.getUTCFullYear();
155
+ }
156
+ getMonth() {
157
+ return this.jsDate.getUTCMonth();
158
+ }
159
+ getDate() {
160
+ return this.jsDate.getUTCDate();
161
+ }
162
+ getDay() {
163
+ return this.jsDate.getUTCDay();
164
+ }
165
+ getHours() {
166
+ return this.jsDate.getUTCHours();
167
+ }
168
+ getMinutes() {
169
+ return this.jsDate.getUTCMinutes();
170
+ }
171
+ getSeconds() {
172
+ return this.jsDate.getUTCSeconds();
173
+ }
174
+ setDate(date) {
175
+ this.jsDate.setUTCDate(date);
176
+ }
177
+ setHours(hours) {
178
+ this.jsDate.setUTCHours(hours);
179
+ }
180
+ setMinutes(minutes) {
181
+ this.jsDate.setUTCMinutes(minutes);
182
+ }
183
+ setSeconds(seconds) {
184
+ this.jsDate.setUTCSeconds(seconds);
185
+ }
186
+ }
129
187
  // -----------------------------------------------------------------------------
130
188
  // Parsing
131
189
  // -----------------------------------------------------------------------------
132
190
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
133
- const CURRENT_YEAR = new Date().getFullYear();
134
- const INITIAL_1900_DAY$1 = new Date(1899, 11, 30);
135
- const INITIAL_JS_DAY = new Date(0);
136
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY$1;
191
+ const CURRENT_YEAR = DateTime.now().getFullYear();
192
+ const INITIAL_1900_DAY$1 = new DateTime(1899, 11, 30);
193
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
194
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY$1.getTime();
137
195
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
138
196
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
139
197
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -173,7 +231,7 @@
173
231
  return {
174
232
  value: date.value + time.value,
175
233
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
176
- jsDate: new Date(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()),
234
+ 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()),
177
235
  };
178
236
  }
179
237
  return date || time;
@@ -190,13 +248,13 @@
190
248
  const day = Number(parts[dayIndex]);
191
249
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
192
250
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
193
- const jsDate = new Date(year, month - 1, day);
251
+ const jsDate = new DateTime(year, month - 1, day);
194
252
  const sep = str.match(/\/|-|\s/)[0];
195
253
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
196
254
  // invalid date
197
255
  return null;
198
256
  }
199
- const delta = jsDate - INITIAL_1900_DAY$1;
257
+ const delta = jsDate.getTime() - INITIAL_1900_DAY$1.getTime();
200
258
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
201
259
  if (parts[yearIndex]) {
202
260
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -256,7 +314,7 @@
256
314
  if (hours >= 24) {
257
315
  format = "hhhh:mm:ss";
258
316
  }
259
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
317
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
260
318
  return {
261
319
  value: hours / 24 + minutes / 1440 + seconds / 86400,
262
320
  format: format,
@@ -270,7 +328,7 @@
270
328
  // -----------------------------------------------------------------------------
271
329
  function numberToJsDate(value) {
272
330
  const truncValue = Math.trunc(value);
273
- let date = new Date(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
331
+ let date = DateTime.fromTimestamp(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
274
332
  let time = value - truncValue;
275
333
  time = time < 0 ? 1 + time : time;
276
334
  const hours = Math.round(time * 24);
@@ -343,7 +401,7 @@
343
401
  .map((p) => {
344
402
  switch (p) {
345
403
  case "hhhh":
346
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1) / (60 * 60 * 1000));
404
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1.getTime()) / (60 * 60 * 1000));
347
405
  return helapsedHours.toString();
348
406
  case "hh":
349
407
  return hours.toString().padStart(2, "0");
@@ -2843,7 +2901,7 @@
2843
2901
  function isDateTime(str) {
2844
2902
  return parseDateTime(str) !== null;
2845
2903
  }
2846
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
2904
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
2847
2905
  //link must start with http or https
2848
2906
  //https://stackoverflow.com/a/3809435/4760614
2849
2907
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -4746,7 +4804,7 @@
4746
4804
  DVARP: DVARP
4747
4805
  });
4748
4806
 
4749
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
4807
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
4750
4808
  const DEFAULT_TYPE = 1;
4751
4809
  const DEFAULT_WEEKEND = 1;
4752
4810
  function isLeapYear(year) {
@@ -4775,7 +4833,7 @@
4775
4833
  if (_year < 1900) {
4776
4834
  _year += 1900;
4777
4835
  }
4778
- const jsDate = new Date(_year, _month - 1, _day);
4836
+ const jsDate = new DateTime(_year, _month - 1, _day);
4779
4837
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4780
4838
  assert(() => delta >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
4781
4839
  return Math.round(delta / 86400000);
@@ -4848,7 +4906,7 @@
4848
4906
  const yStart = _startDate.getFullYear();
4849
4907
  const mStart = _startDate.getMonth();
4850
4908
  const dStart = _startDate.getDate();
4851
- const jsDate = new Date(yStart, mStart + _months, dStart);
4909
+ const jsDate = new DateTime(yStart, mStart + _months, dStart);
4852
4910
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4853
4911
  return Math.round(delta / 86400000);
4854
4912
  },
@@ -4870,7 +4928,7 @@
4870
4928
  const _months = Math.trunc(toNumber(months));
4871
4929
  const yStart = _startDate.getFullYear();
4872
4930
  const mStart = _startDate.getMonth();
4873
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
4931
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
4874
4932
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4875
4933
  return Math.round(delta / 86400000);
4876
4934
  },
@@ -4910,17 +4968,17 @@
4910
4968
  // The first week of the year is the week that contains the first
4911
4969
  // Thursday of the year.
4912
4970
  let firstThursday = 1;
4913
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
4971
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
4914
4972
  firstThursday += 1;
4915
4973
  }
4916
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
4974
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
4917
4975
  // The last week of the year is the week that contains the last Thursday of
4918
4976
  // the year.
4919
4977
  let lastThursday = 31;
4920
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
4978
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
4921
4979
  lastThursday -= 1;
4922
4980
  }
4923
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
4981
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
4924
4982
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
4925
4983
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
4926
4984
  let offsetYear;
@@ -4946,17 +5004,17 @@
4946
5004
  case 1:
4947
5005
  // firstDay is the 1st day of the 1st week of the year after
4948
5006
  // firstDay = lastDayOfLastWeek + 1 Day
4949
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
5007
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
4950
5008
  break;
4951
5009
  case -1:
4952
5010
  // firstDay is the 1st day of the 1st week of the previous year.
4953
5011
  // The first week of the previous year is the week that contains the
4954
5012
  // first Thursday of the previous year.
4955
5013
  let firstThursdayPreviousYear = 1;
4956
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
5014
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
4957
5015
  firstThursdayPreviousYear += 1;
4958
5016
  }
4959
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
5017
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
4960
5018
  break;
4961
5019
  }
4962
5020
  const dif = (_date.getTime() - firstDay.getTime()) / 86400000;
@@ -5095,8 +5153,8 @@
5095
5153
  });
5096
5154
  }
5097
5155
  const invertDate = _startDate.getTime() > _endDate.getTime();
5098
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
5099
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
5156
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
5157
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
5100
5158
  const timeStopDate = stopDate.getTime();
5101
5159
  let timeStepDate = stepDate.getTime();
5102
5160
  let netWorkingDay = 0;
@@ -5120,8 +5178,7 @@
5120
5178
  returns: ["DATE"],
5121
5179
  returnFormat: { specificFormat: "m/d/yyyy hh:mm:ss" },
5122
5180
  compute: function () {
5123
- let today = new Date();
5124
- today.setMilliseconds(0);
5181
+ let today = DateTime.now();
5125
5182
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
5126
5183
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
5127
5184
  return Math.floor(delta / 86400000) + time;
@@ -5195,8 +5252,8 @@
5195
5252
  returns: ["DATE"],
5196
5253
  returnFormat: { specificFormat: "m/d/yyyy" },
5197
5254
  compute: function () {
5198
- const today = new Date();
5199
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
5255
+ const today = DateTime.now();
5256
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
5200
5257
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
5201
5258
  return Math.round(delta / 86400000);
5202
5259
  },
@@ -5252,10 +5309,10 @@
5252
5309
  }
5253
5310
  const y = _date.getFullYear();
5254
5311
  let dayStart = 1;
5255
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
5312
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5256
5313
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
5257
5314
  dayStart += 1;
5258
- startDayOfFirstWeek = new Date(y, 0, dayStart);
5315
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5259
5316
  }
5260
5317
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / 86400000;
5261
5318
  if (dif < 0) {
@@ -5309,7 +5366,7 @@
5309
5366
  timesHoliday.add(holiday.getTime());
5310
5367
  });
5311
5368
  }
5312
- let stepDate = new Date(_startDate.getTime());
5369
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
5313
5370
  let timeStepDate = stepDate.getTime();
5314
5371
  const unitDay = Math.sign(_numDays);
5315
5372
  let stepDay = Math.abs(_numDays);
@@ -18670,15 +18727,20 @@
18670
18727
  // Getters
18671
18728
  // ---------------------------------------------------------------------------
18672
18729
  evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
18673
- let formula = normalize(formulaString);
18674
- const compiledFormula = compile(formula);
18675
- const params = this.getFormulaParameters(() => { });
18676
- const ranges = [];
18677
- for (let xc of formula.dependencies.references) {
18678
- ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
18730
+ try {
18731
+ let formula = normalize(formulaString);
18732
+ const compiledFormula = compile(formula);
18733
+ const params = this.getFormulaParameters(() => { });
18734
+ const ranges = [];
18735
+ for (let xc of formula.dependencies.references) {
18736
+ ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
18737
+ }
18738
+ const dependencies = { ...formula.dependencies, references: ranges };
18739
+ return compiledFormula(dependencies, sheetId, ...params);
18740
+ }
18741
+ catch (error) {
18742
+ return "#ERROR";
18679
18743
  }
18680
- const dependencies = { ...formula.dependencies, references: ranges };
18681
- return compiledFormula(dependencies, sheetId, ...params);
18682
18744
  }
18683
18745
  /**
18684
18746
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -19173,25 +19235,26 @@
19173
19235
  */
19174
19236
  this.rulePredicate = {
19175
19237
  CellIsRule: (cell, rule) => {
19238
+ var _a, _b, _c, _d, _e, _f;
19176
19239
  if (cell && cell.evaluated.type === CellValueType.error) {
19177
19240
  return false;
19178
19241
  }
19179
19242
  const values = rule.values.map(parsePrimitiveContent);
19180
19243
  switch (rule.operator) {
19181
19244
  case "IsEmpty":
19182
- return !isDefined(cell) || cell.evaluated.value.toString().trim() === "";
19245
+ return !isDefined(cell) || ((_a = cell.evaluated.value) === null || _a === void 0 ? void 0 : _a.toString().trim()) === "";
19183
19246
  case "IsNotEmpty":
19184
- return isDefined(cell) && cell.evaluated.value.toString().trim() !== "";
19247
+ return isDefined(cell) && ((_b = cell.evaluated.value) === null || _b === void 0 ? void 0 : _b.toString().trim()) !== "";
19185
19248
  case "BeginsWith":
19186
19249
  if (!cell && values[0] === "") {
19187
19250
  return false;
19188
19251
  }
19189
- return (isDefined(cell) && (cell === null || cell === void 0 ? void 0 : cell.evaluated.value.toString().startsWith(values[0].toString())));
19252
+ return (isDefined(cell) && ((_c = cell.evaluated.value) === null || _c === void 0 ? void 0 : _c.toString().startsWith(values[0].toString())));
19190
19253
  case "EndsWith":
19191
19254
  if (!cell && values[0] === "") {
19192
19255
  return false;
19193
19256
  }
19194
- return isDefined(cell) && cell.evaluated.value.toString().endsWith(values[0].toString());
19257
+ return isDefined(cell) && ((_d = cell.evaluated.value) === null || _d === void 0 ? void 0 : _d.toString().endsWith(values[0].toString()));
19195
19258
  case "Between":
19196
19259
  return (isDefined(cell) &&
19197
19260
  cell.evaluated.value >= values[0] &&
@@ -19201,11 +19264,11 @@
19201
19264
  cell.evaluated.value >= values[0] &&
19202
19265
  cell.evaluated.value <= values[1]);
19203
19266
  case "ContainsText":
19204
- return (isDefined(cell) && cell.evaluated.value.toString().indexOf(values[0].toString()) > -1);
19267
+ return (isDefined(cell) && ((_e = cell.evaluated.value) === null || _e === void 0 ? void 0 : _e.toString().indexOf(values[0].toString())) > -1);
19205
19268
  case "NotContains":
19206
19269
  return (!isDefined(cell) ||
19207
19270
  !cell.evaluated.value ||
19208
- cell.evaluated.value.toString().indexOf(values[0].toString()) == -1);
19271
+ ((_f = cell.evaluated.value) === null || _f === void 0 ? void 0 : _f.toString().indexOf(values[0].toString())) == -1);
19209
19272
  case "GreaterThan":
19210
19273
  return isDefined(cell) && cell.evaluated.value > values[0];
19211
19274
  case "GreaterThanOrEqual":
@@ -19314,39 +19377,34 @@
19314
19377
  this.computedIcons[activeSheetId] = {};
19315
19378
  const computedStyle = this.computedStyles[activeSheetId];
19316
19379
  for (let cf of this.getters.getConditionalFormats(activeSheetId)) {
19317
- try {
19318
- switch (cf.rule.type) {
19319
- case "ColorScaleRule":
19320
- for (let range of cf.ranges) {
19321
- this.applyColorScale(range, cf.rule);
19322
- }
19323
- break;
19324
- case "IconSetRule":
19325
- for (let range of cf.ranges) {
19326
- this.applyIcon(range, cf.rule);
19327
- }
19328
- break;
19329
- default:
19330
- for (let ref of cf.ranges) {
19331
- const zone = toZone(ref);
19332
- for (let row = zone.top; row <= zone.bottom; row++) {
19333
- for (let col = zone.left; col <= zone.right; col++) {
19334
- const pr = this.rulePredicate[cf.rule.type];
19335
- let cell = this.getters.getCell(activeSheetId, col, row);
19336
- if (pr && pr(cell, cf.rule)) {
19337
- if (!computedStyle[col])
19338
- computedStyle[col] = [];
19339
- // we must combine all the properties of all the CF rules applied to the given cell
19340
- computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
19341
- }
19380
+ switch (cf.rule.type) {
19381
+ case "ColorScaleRule":
19382
+ for (let range of cf.ranges) {
19383
+ this.applyColorScale(range, cf.rule);
19384
+ }
19385
+ break;
19386
+ case "IconSetRule":
19387
+ for (let range of cf.ranges) {
19388
+ this.applyIcon(range, cf.rule);
19389
+ }
19390
+ break;
19391
+ default:
19392
+ for (let ref of cf.ranges) {
19393
+ const zone = toZone(ref);
19394
+ for (let row = zone.top; row <= zone.bottom; row++) {
19395
+ for (let col = zone.left; col <= zone.right; col++) {
19396
+ const pr = this.rulePredicate[cf.rule.type];
19397
+ let cell = this.getters.getCell(activeSheetId, col, row);
19398
+ if (pr && pr(cell, cf.rule)) {
19399
+ if (!computedStyle[col])
19400
+ computedStyle[col] = [];
19401
+ // we must combine all the properties of all the CF rules applied to the given cell
19402
+ computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
19342
19403
  }
19343
19404
  }
19344
19405
  }
19345
- break;
19346
- }
19347
- }
19348
- catch (_) {
19349
- // we don't care about the errors within the evaluation of a rule
19406
+ }
19407
+ break;
19350
19408
  }
19351
19409
  }
19352
19410
  }
@@ -19365,7 +19423,7 @@
19365
19423
  return this.getters.evaluateFormula(`=PERCENTILE(${range},${Number(threshold.value) / 100})`);
19366
19424
  case "formula":
19367
19425
  const value = threshold.value && this.getters.evaluateFormula(threshold.value);
19368
- return !(value instanceof Promise) ? value : null;
19426
+ return typeof value === "number" ? value : null;
19369
19427
  default:
19370
19428
  return null;
19371
19429
  }
@@ -31449,9 +31507,9 @@
31449
31507
  Object.defineProperty(exports, '__esModule', { value: true });
31450
31508
 
31451
31509
 
31452
- __info__.version = '15.0.14';
31453
- __info__.date = '2023-11-24T13:06:57.405Z';
31454
- __info__.hash = 'c9a805f';
31510
+ __info__.version = '15.0.16';
31511
+ __info__.date = '2024-01-17T10:23:17.942Z';
31512
+ __info__.hash = '3a9ce19';
31455
31513
 
31456
31514
 
31457
31515
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);