@odoo/o-spreadsheet 16.0.63 → 16.0.64

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.
@@ -3581,10 +3581,13 @@
3581
3581
  })
3582
3582
  .add("increment_number", {
3583
3583
  condition: (cell) => cell.evaluated.type === CellValueType.number,
3584
- generateRule: (cell, cells) => {
3584
+ generateRule: (cell, cells, direction) => {
3585
3585
  const group = getGroup(cell, cells);
3586
3586
  let increment = 1;
3587
- if (group.length == 2) {
3587
+ if (group.length === 1 && ["up", "left"].includes(direction)) {
3588
+ increment = -1;
3589
+ }
3590
+ else if (group.length == 2) {
3588
3591
  increment = (group[1] - group[0]) * 2;
3589
3592
  }
3590
3593
  else if (group.length > 2) {
@@ -22184,6 +22187,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22184
22187
  this.MAX_SIZE_MARGIN = 90;
22185
22188
  this.MIN_ELEMENT_SIZE = MIN_COL_WIDTH;
22186
22189
  }
22190
+ get sheetId() {
22191
+ return this.env.model.getters.getActiveSheetId();
22192
+ }
22187
22193
  _getEvOffset(ev) {
22188
22194
  return ev.offsetX;
22189
22195
  }
@@ -22206,10 +22212,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22206
22212
  return this.env.model.getters.getEdgeScrollCol(position, position, position);
22207
22213
  }
22208
22214
  _getDimensionsInViewport(index) {
22209
- return this.env.model.getters.getColDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
22215
+ return this.env.model.getters.getColDimensionsInViewport(this.sheetId, index);
22210
22216
  }
22211
22217
  _getElementSize(index) {
22212
- return this.env.model.getters.getColSize(this.env.model.getters.getActiveSheetId(), index);
22218
+ return this.env.model.getters.getColSize(this.sheetId, index);
22213
22219
  }
22214
22220
  _getMaxSize() {
22215
22221
  return this.colResizerRef.el.clientWidth;
@@ -22220,7 +22226,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22220
22226
  const cols = this.env.model.getters.getActiveCols();
22221
22227
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
22222
22228
  dimension: "COL",
22223
- sheetId: this.env.model.getters.getActiveSheetId(),
22229
+ sheetId: this.sheetId,
22224
22230
  elements: cols.has(index) ? [...cols] : [index],
22225
22231
  size,
22226
22232
  });
@@ -22233,7 +22239,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22233
22239
  elements.push(colIndex);
22234
22240
  }
22235
22241
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
22236
- sheetId: this.env.model.getters.getActiveSheetId(),
22242
+ sheetId: this.sheetId,
22237
22243
  dimension: "COL",
22238
22244
  base: this.state.base,
22239
22245
  elements,
@@ -22252,7 +22258,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22252
22258
  _fitElementSize(index) {
22253
22259
  const cols = this.env.model.getters.getActiveCols();
22254
22260
  this.env.model.dispatch("AUTORESIZE_COLUMNS", {
22255
- sheetId: this.env.model.getters.getActiveSheetId(),
22261
+ sheetId: this.sheetId,
22256
22262
  cols: cols.has(index) ? [...cols] : [index],
22257
22263
  });
22258
22264
  }
@@ -22263,7 +22269,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22263
22269
  return this.env.model.getters.getActiveCols();
22264
22270
  }
22265
22271
  _getPreviousVisibleElement(index) {
22266
- const sheetId = this.env.model.getters.getActiveSheetId();
22272
+ const sheetId = this.sheetId;
22267
22273
  let row;
22268
22274
  for (row = index - 1; row >= 0; row--) {
22269
22275
  if (!this.env.model.getters.isColHidden(sheetId, row)) {
@@ -22274,7 +22280,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22274
22280
  }
22275
22281
  unhide(hiddenElements) {
22276
22282
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
22277
- sheetId: this.env.model.getters.getActiveSheetId(),
22283
+ sheetId: this.sheetId,
22278
22284
  elements: hiddenElements,
22279
22285
  dimension: "COL",
22280
22286
  });
@@ -22291,7 +22297,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22291
22297
  left: 0;
22292
22298
  right: 0;
22293
22299
  width: ${HEADER_WIDTH}px;
22294
- height: 100%;
22300
+ height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
22295
22301
  &.o-dragging {
22296
22302
  cursor: grabbing;
22297
22303
  }
@@ -22354,6 +22360,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22354
22360
  this.MAX_SIZE_MARGIN = 60;
22355
22361
  this.MIN_ELEMENT_SIZE = MIN_ROW_HEIGHT;
22356
22362
  }
22363
+ get sheetId() {
22364
+ return this.env.model.getters.getActiveSheetId();
22365
+ }
22357
22366
  _getEvOffset(ev) {
22358
22367
  return ev.offsetY;
22359
22368
  }
@@ -22376,10 +22385,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22376
22385
  return this.env.model.getters.getEdgeScrollRow(position, position, position);
22377
22386
  }
22378
22387
  _getDimensionsInViewport(index) {
22379
- return this.env.model.getters.getRowDimensionsInViewport(this.env.model.getters.getActiveSheetId(), index);
22388
+ return this.env.model.getters.getRowDimensionsInViewport(this.sheetId, index);
22380
22389
  }
22381
22390
  _getElementSize(index) {
22382
- return this.env.model.getters.getRowSize(this.env.model.getters.getActiveSheetId(), index);
22391
+ return this.env.model.getters.getRowSize(this.sheetId, index);
22383
22392
  }
22384
22393
  _getMaxSize() {
22385
22394
  return this.rowResizerRef.el.clientHeight;
@@ -22390,7 +22399,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22390
22399
  const rows = this.env.model.getters.getActiveRows();
22391
22400
  this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
22392
22401
  dimension: "ROW",
22393
- sheetId: this.env.model.getters.getActiveSheetId(),
22402
+ sheetId: this.sheetId,
22394
22403
  elements: rows.has(index) ? [...rows] : [index],
22395
22404
  size,
22396
22405
  });
@@ -22403,7 +22412,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22403
22412
  elements.push(rowIndex);
22404
22413
  }
22405
22414
  const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
22406
- sheetId: this.env.model.getters.getActiveSheetId(),
22415
+ sheetId: this.sheetId,
22407
22416
  dimension: "ROW",
22408
22417
  base: this.state.base,
22409
22418
  elements,
@@ -22422,7 +22431,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22422
22431
  _fitElementSize(index) {
22423
22432
  const rows = this.env.model.getters.getActiveRows();
22424
22433
  this.env.model.dispatch("AUTORESIZE_ROWS", {
22425
- sheetId: this.env.model.getters.getActiveSheetId(),
22434
+ sheetId: this.sheetId,
22426
22435
  rows: rows.has(index) ? [...rows] : [index],
22427
22436
  });
22428
22437
  }
@@ -22433,7 +22442,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22433
22442
  return this.env.model.getters.getActiveRows();
22434
22443
  }
22435
22444
  _getPreviousVisibleElement(index) {
22436
- const sheetId = this.env.model.getters.getActiveSheetId();
22445
+ const sheetId = this.sheetId;
22437
22446
  let row;
22438
22447
  for (row = index - 1; row >= 0; row--) {
22439
22448
  if (!this.env.model.getters.isRowHidden(sheetId, row)) {
@@ -22444,7 +22453,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22444
22453
  }
22445
22454
  unhide(hiddenElements) {
22446
22455
  this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
22447
- sheetId: this.env.model.getters.getActiveSheetId(),
22456
+ sheetId: this.sheetId,
22448
22457
  dimension: "ROW",
22449
22458
  elements: hiddenElements,
22450
22459
  });
@@ -25522,29 +25531,33 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
25522
25531
  * In all the sheets, replace the table-only references in the formula cells with standard references.
25523
25532
  */
25524
25533
  function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
25525
- for (let sheet of convertedSheets) {
25526
- const tables = xlsxSheets.find((s) => s.sheetName === sheet.name).tables;
25534
+ for (let tableSheet of convertedSheets) {
25535
+ const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
25527
25536
  for (let table of tables) {
25528
25537
  const tabRef = table.name + "[";
25529
- for (let position of positions(toZone(table.ref))) {
25530
- const xc = toXC(position.col, position.row);
25531
- const cell = sheet.cells[xc];
25532
- if (cell && cell.content && cell.content.startsWith("=")) {
25533
- let refIndex;
25534
- while ((refIndex = cell.content.indexOf(tabRef)) !== -1) {
25535
- let reference = cell.content.slice(refIndex + tabRef.length);
25536
- // Expression can either be tableName[colName] or tableName[[#This Row], [colName]]
25537
- let endIndex = reference.indexOf("]");
25538
- if (reference.startsWith(`[`)) {
25539
- endIndex = reference.indexOf("]", endIndex + 1);
25540
- endIndex = reference.indexOf("]", endIndex + 1);
25538
+ for (let sheet of convertedSheets) {
25539
+ for (let xc in sheet.cells) {
25540
+ const cell = sheet.cells[xc];
25541
+ if (cell && cell.content && cell.content.startsWith("=")) {
25542
+ let refIndex;
25543
+ while ((refIndex = cell.content.indexOf(tabRef)) !== -1) {
25544
+ let endIndex = refIndex + tabRef.length;
25545
+ let openBrackets = 1;
25546
+ while (openBrackets > 0 && endIndex < cell.content.length) {
25547
+ if (cell.content[endIndex] === "[") {
25548
+ openBrackets++;
25549
+ }
25550
+ else if (cell.content[endIndex] === "]") {
25551
+ openBrackets--;
25552
+ }
25553
+ endIndex++;
25554
+ }
25555
+ let reference = cell.content.slice(refIndex + tabRef.length, endIndex - 1);
25556
+ const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
25557
+ const convertedRef = convertTableReference(sheetPrefix, reference, table, xc);
25558
+ cell.content =
25559
+ cell.content.slice(0, refIndex) + convertedRef + cell.content.slice(endIndex);
25541
25560
  }
25542
- reference = reference.slice(0, endIndex);
25543
- const convertedRef = convertTableReference(reference, table, xc);
25544
- cell.content =
25545
- cell.content.slice(0, refIndex) +
25546
- convertedRef +
25547
- cell.content.slice(tabRef.length + refIndex + endIndex + 1);
25548
25561
  }
25549
25562
  }
25550
25563
  }
@@ -25552,11 +25565,17 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
25552
25565
  }
25553
25566
  }
25554
25567
  /**
25555
- * Convert table-specific references in formulas into standard references.
25568
+ * Convert table-specific references in formulas into standard references. A table reference is composed of columns names,
25569
+ * and of keywords determining the rows of the table to reference.
25556
25570
  *
25557
25571
  * A reference in a table can have the form (only the part between brackets should be given to this function):
25558
25572
  * - tableName[colName] : reference to the whole column "colName"
25573
+ * - tableName[#keyword] : reference to the whatever row the keyword refers to
25559
25574
  * - tableName[[#keyword], [colName]] : reference to some of the element(s) of the column colName
25575
+ * - tableName[[#keyword], [colName]:[col2Name]] : reference to some of the element(s) of the columns colName to col2Name
25576
+ * - tableName[[#keyword1], [#keyword2], [colName]] : reference to all the rows referenced by the keywords in the column colName
25577
+ * - tableName[[#keyword1], [colName], [#keyword2]]: the keywords and colName can be in any order
25578
+ *
25560
25579
  *
25561
25580
  * The available keywords are :
25562
25581
  * - #All : all the column (including totals)
@@ -25564,58 +25583,109 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
25564
25583
  * - #Headers : only the header of the column
25565
25584
  * - #Totals : only the totals of the column
25566
25585
  * - #This Row : only the element in the same row as the cell
25586
+ *
25587
+ * Note that the only valid combination of multiple keywords are #Data + #Totals and #Headers + #Data.
25567
25588
  */
25568
- function convertTableReference(expr, table, cellXc) {
25569
- const refElements = expr.split(",");
25589
+ function convertTableReference(sheetPrefix, expr, table, cellXc) {
25590
+ // TODO: Ideally we'd want to make a real tokenizer, this simple approach won't work if for example the column name
25591
+ // contain # or , characters. But that's probably an edge case that we can ignore for now.
25592
+ const parts = expr.split(",").map((part) => part.trim());
25570
25593
  const tableZone = toZone(table.ref);
25571
- const refZone = { ...tableZone };
25572
- let isReferencedZoneValid = true;
25573
- // Single column reference
25574
- if (refElements.length === 1) {
25575
- const colRelativeIndex = table.cols.findIndex((col) => col.name === refElements[0]);
25576
- refZone.left = refZone.right = colRelativeIndex + tableZone.left;
25577
- if (table.headerRowCount) {
25578
- refZone.top += table.headerRowCount;
25579
- }
25580
- if (table.totalsRowCount) {
25581
- refZone.bottom -= 1;
25594
+ const colIndexes = [];
25595
+ const rowIndexes = [];
25596
+ const foundKeywords = [];
25597
+ for (const part of parts) {
25598
+ if (removeBrackets(part).startsWith("#")) {
25599
+ const keyWord = removeBrackets(part);
25600
+ foundKeywords.push(keyWord);
25601
+ switch (keyWord) {
25602
+ case "#All":
25603
+ rowIndexes.push(tableZone.top, tableZone.bottom);
25604
+ break;
25605
+ case "#Data":
25606
+ const top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
25607
+ const bottom = table.totalsRowCount
25608
+ ? tableZone.bottom - table.totalsRowCount
25609
+ : tableZone.bottom;
25610
+ rowIndexes.push(top, bottom);
25611
+ break;
25612
+ case "#This Row":
25613
+ rowIndexes.push(toCartesian(cellXc).row);
25614
+ break;
25615
+ case "#Headers":
25616
+ if (!table.headerRowCount) {
25617
+ return INCORRECT_RANGE_STRING;
25618
+ }
25619
+ rowIndexes.push(tableZone.top);
25620
+ break;
25621
+ case "#Totals":
25622
+ if (!table.totalsRowCount) {
25623
+ return INCORRECT_RANGE_STRING;
25624
+ }
25625
+ rowIndexes.push(tableZone.bottom);
25626
+ break;
25627
+ }
25582
25628
  }
25583
- }
25584
- // Other references
25585
- else {
25586
- switch (refElements[0].slice(1, refElements[0].length - 1)) {
25587
- case "#All":
25588
- refZone.top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
25589
- refZone.bottom = tableZone.bottom;
25590
- break;
25591
- case "#Data":
25592
- refZone.top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
25593
- refZone.bottom = table.totalsRowCount ? tableZone.bottom + 1 : tableZone.bottom;
25594
- break;
25595
- case "#This Row":
25596
- refZone.top = refZone.bottom = toCartesian(cellXc).row;
25597
- break;
25598
- case "#Headers":
25599
- refZone.top = refZone.bottom = tableZone.top;
25600
- if (!table.headerRowCount) {
25601
- isReferencedZoneValid = false;
25602
- }
25603
- break;
25604
- case "#Totals":
25605
- refZone.top = refZone.bottom = tableZone.bottom;
25606
- if (!table.totalsRowCount) {
25607
- isReferencedZoneValid = false;
25629
+ else {
25630
+ const columns = part
25631
+ .split(":")
25632
+ .map((part) => part.trim())
25633
+ .map(removeBrackets);
25634
+ if (colIndexes.length) {
25635
+ return INCORRECT_RANGE_STRING;
25636
+ }
25637
+ const colRelativeIndex = table.cols.findIndex((col) => col.name === columns[0]);
25638
+ if (colRelativeIndex === -1) {
25639
+ return INCORRECT_RANGE_STRING;
25640
+ }
25641
+ colIndexes.push(colRelativeIndex + tableZone.left);
25642
+ if (columns[1]) {
25643
+ const colRelativeIndex2 = table.cols.findIndex((col) => col.name === columns[1]);
25644
+ if (colRelativeIndex2 === -1) {
25645
+ return INCORRECT_RANGE_STRING;
25608
25646
  }
25609
- break;
25647
+ colIndexes.push(colRelativeIndex2 + tableZone.left);
25648
+ }
25610
25649
  }
25611
- const colRef = refElements[1].slice(1, refElements[1].length - 1);
25612
- const colRelativeIndex = table.cols.findIndex((col) => col.name === colRef);
25613
- refZone.left = refZone.right = colRelativeIndex + tableZone.left;
25614
25650
  }
25615
- if (!isReferencedZoneValid) {
25651
+ if (!areKeywordsCompatible(foundKeywords)) {
25616
25652
  return INCORRECT_RANGE_STRING;
25617
25653
  }
25618
- return refZone.top !== refZone.bottom ? zoneToXc(refZone) : toXC(refZone.left, refZone.top);
25654
+ if (rowIndexes.length === 0) {
25655
+ const top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
25656
+ const bottom = table.totalsRowCount
25657
+ ? tableZone.bottom - table.totalsRowCount
25658
+ : tableZone.bottom;
25659
+ rowIndexes.push(top, bottom);
25660
+ }
25661
+ if (colIndexes.length === 0) {
25662
+ colIndexes.push(tableZone.left, tableZone.right);
25663
+ }
25664
+ const refZone = {
25665
+ top: Math.min(...rowIndexes),
25666
+ left: Math.min(...colIndexes),
25667
+ bottom: Math.max(...rowIndexes),
25668
+ right: Math.max(...colIndexes),
25669
+ };
25670
+ return sheetPrefix + zoneToXc(refZone);
25671
+ }
25672
+ function removeBrackets(str) {
25673
+ return str.startsWith("[") && str.endsWith("]") ? str.slice(1, str.length - 1) : str;
25674
+ }
25675
+ function areKeywordsCompatible(keywords) {
25676
+ if (keywords.length < 2) {
25677
+ return true;
25678
+ }
25679
+ else if (keywords.length > 2) {
25680
+ return false;
25681
+ }
25682
+ else if (keywords.includes("#Data") && keywords.includes("#Totals")) {
25683
+ return true;
25684
+ }
25685
+ else if (keywords.includes("#Headers") && keywords.includes("#Data")) {
25686
+ return true;
25687
+ }
25688
+ return false;
25619
25689
  }
25620
25690
 
25621
25691
  // -------------------------------------
@@ -31593,7 +31663,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31593
31663
  getRule(cell, cells) {
31594
31664
  const rules = autofillRulesRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
31595
31665
  const rule = rules.find((rule) => rule.condition(cell, cells));
31596
- return rule && rule.generateRule(cell, cells);
31666
+ return rule && this.direction && rule.generateRule(cell, cells, this.direction);
31597
31667
  }
31598
31668
  /**
31599
31669
  * Create the generator to be able to autofill the next cells.
@@ -37495,7 +37565,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
37495
37565
  ? this.getters.getSheetViewVisibleCols()
37496
37566
  : this.getters.getSheetViewVisibleRows();
37497
37567
  const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
37498
- const endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
37568
+ let endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
37569
+ endIndex = endIndex === -1 ? visibleHeaders.length : endIndex;
37499
37570
  const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
37500
37571
  let offset = 0;
37501
37572
  for (const i of relevantIndexes) {
@@ -43690,9 +43761,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43690
43761
  Object.defineProperty(exports, '__esModule', { value: true });
43691
43762
 
43692
43763
 
43693
- __info__.version = '16.0.63';
43694
- __info__.date = '2025-02-25T05:54:41.386Z';
43695
- __info__.hash = 'b01aca6';
43764
+ __info__.version = '16.0.64';
43765
+ __info__.date = '2025-03-07T10:29:50.957Z';
43766
+ __info__.hash = '20def15';
43696
43767
 
43697
43768
 
43698
43769
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);