@odoo/o-spreadsheet 17.0.51 → 17.0.53
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 +222 -98
- package/dist/o-spreadsheet.d.ts +6 -1
- package/dist/o-spreadsheet.esm.js +222 -98
- package/dist/o-spreadsheet.iife.js +222 -98
- package/dist/o-spreadsheet.iife.min.js +247 -225
- package/dist/o_spreadsheet.xml +21 -13
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 17.0.
|
|
6
|
-
* @date 2025-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.53
|
|
6
|
+
* @date 2025-03-12T15:26:58.496Z
|
|
7
|
+
* @hash 47dfd62
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -6214,7 +6214,7 @@ autofillRulesRegistry
|
|
|
6214
6214
|
condition: (cell) => !cell.isFormula &&
|
|
6215
6215
|
evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.text &&
|
|
6216
6216
|
alphaNumericValueRegExp.test(cell.content),
|
|
6217
|
-
generateRule: (cell, cells) => {
|
|
6217
|
+
generateRule: (cell, cells, direction) => {
|
|
6218
6218
|
const numberPostfix = parseInt(cell.content.match(numberPostfixRegExp)[0]);
|
|
6219
6219
|
const prefix = cell.content.match(stringPrefixRegExp)[0];
|
|
6220
6220
|
const numberPostfixLength = cell.content.length - prefix.length;
|
|
@@ -6222,7 +6222,10 @@ autofillRulesRegistry
|
|
|
6222
6222
|
alphaNumericValueRegExp.test(evaluatedCell.value)) // get consecutive alphanumeric cells, no matter what the prefix is
|
|
6223
6223
|
.filter((cell) => prefix === cell.value.toString().match(stringPrefixRegExp)[0])
|
|
6224
6224
|
.map((cell) => parseInt(cell.value.toString().match(numberPostfixRegExp)[0]));
|
|
6225
|
-
|
|
6225
|
+
let increment = calculateIncrementBasedOnGroup(group);
|
|
6226
|
+
if (["up", "left"].includes(direction) && group.length === 1) {
|
|
6227
|
+
increment = -increment;
|
|
6228
|
+
}
|
|
6226
6229
|
return {
|
|
6227
6230
|
type: "ALPHANUMERIC_INCREMENT_MODIFIER",
|
|
6228
6231
|
prefix,
|
|
@@ -6251,9 +6254,12 @@ autofillRulesRegistry
|
|
|
6251
6254
|
.add("increment_number", {
|
|
6252
6255
|
condition: (cell) => !cell.isFormula &&
|
|
6253
6256
|
evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
|
|
6254
|
-
generateRule: (cell, cells) => {
|
|
6257
|
+
generateRule: (cell, cells, direction) => {
|
|
6255
6258
|
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number).map((cell) => Number(cell.value));
|
|
6256
|
-
|
|
6259
|
+
let increment = calculateIncrementBasedOnGroup(group);
|
|
6260
|
+
if (["up", "left"].includes(direction) && group.length === 1) {
|
|
6261
|
+
increment = -increment;
|
|
6262
|
+
}
|
|
6257
6263
|
const evaluation = evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE });
|
|
6258
6264
|
return {
|
|
6259
6265
|
type: "INCREMENT_MODIFIER",
|
|
@@ -28963,6 +28969,9 @@ class ColResizer extends AbstractResizer {
|
|
|
28963
28969
|
this.MAX_SIZE_MARGIN = 90;
|
|
28964
28970
|
this.MIN_ELEMENT_SIZE = MIN_COL_WIDTH;
|
|
28965
28971
|
}
|
|
28972
|
+
get sheetId() {
|
|
28973
|
+
return this.env.model.getters.getActiveSheetId();
|
|
28974
|
+
}
|
|
28966
28975
|
_getEvOffset(ev) {
|
|
28967
28976
|
return ev.offsetX;
|
|
28968
28977
|
}
|
|
@@ -28985,10 +28994,10 @@ class ColResizer extends AbstractResizer {
|
|
|
28985
28994
|
return this.env.model.getters.getEdgeScrollCol(position, position, position);
|
|
28986
28995
|
}
|
|
28987
28996
|
_getDimensionsInViewport(index) {
|
|
28988
|
-
return this.env.model.getters.getColDimensionsInViewport(this.
|
|
28997
|
+
return this.env.model.getters.getColDimensionsInViewport(this.sheetId, index);
|
|
28989
28998
|
}
|
|
28990
28999
|
_getElementSize(index) {
|
|
28991
|
-
return this.env.model.getters.getColSize(this.
|
|
29000
|
+
return this.env.model.getters.getColSize(this.sheetId, index);
|
|
28992
29001
|
}
|
|
28993
29002
|
_getMaxSize() {
|
|
28994
29003
|
return this.colResizerRef.el.clientWidth;
|
|
@@ -28999,7 +29008,7 @@ class ColResizer extends AbstractResizer {
|
|
|
28999
29008
|
const cols = this.env.model.getters.getActiveCols();
|
|
29000
29009
|
this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
29001
29010
|
dimension: "COL",
|
|
29002
|
-
sheetId: this.
|
|
29011
|
+
sheetId: this.sheetId,
|
|
29003
29012
|
elements: cols.has(index) ? [...cols] : [index],
|
|
29004
29013
|
size,
|
|
29005
29014
|
});
|
|
@@ -29012,7 +29021,7 @@ class ColResizer extends AbstractResizer {
|
|
|
29012
29021
|
elements.push(colIndex);
|
|
29013
29022
|
}
|
|
29014
29023
|
const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
|
|
29015
|
-
sheetId: this.
|
|
29024
|
+
sheetId: this.sheetId,
|
|
29016
29025
|
dimension: "COL",
|
|
29017
29026
|
base: this.state.base,
|
|
29018
29027
|
elements,
|
|
@@ -29031,7 +29040,7 @@ class ColResizer extends AbstractResizer {
|
|
|
29031
29040
|
_fitElementSize(index) {
|
|
29032
29041
|
const cols = this.env.model.getters.getActiveCols();
|
|
29033
29042
|
this.env.model.dispatch("AUTORESIZE_COLUMNS", {
|
|
29034
|
-
sheetId: this.
|
|
29043
|
+
sheetId: this.sheetId,
|
|
29035
29044
|
cols: cols.has(index) ? [...cols] : [index],
|
|
29036
29045
|
});
|
|
29037
29046
|
}
|
|
@@ -29042,7 +29051,7 @@ class ColResizer extends AbstractResizer {
|
|
|
29042
29051
|
return this.env.model.getters.getActiveCols();
|
|
29043
29052
|
}
|
|
29044
29053
|
_getPreviousVisibleElement(index) {
|
|
29045
|
-
const sheetId = this.
|
|
29054
|
+
const sheetId = this.sheetId;
|
|
29046
29055
|
let row;
|
|
29047
29056
|
for (row = index - 1; row >= 0; row--) {
|
|
29048
29057
|
if (!this.env.model.getters.isColHidden(sheetId, row)) {
|
|
@@ -29053,7 +29062,7 @@ class ColResizer extends AbstractResizer {
|
|
|
29053
29062
|
}
|
|
29054
29063
|
unhide(hiddenElements) {
|
|
29055
29064
|
this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
|
|
29056
|
-
sheetId: this.
|
|
29065
|
+
sheetId: this.sheetId,
|
|
29057
29066
|
elements: hiddenElements,
|
|
29058
29067
|
dimension: "COL",
|
|
29059
29068
|
});
|
|
@@ -29069,7 +29078,7 @@ css /* scss */ `
|
|
|
29069
29078
|
left: 0;
|
|
29070
29079
|
right: 0;
|
|
29071
29080
|
width: ${HEADER_WIDTH}px;
|
|
29072
|
-
height: 100
|
|
29081
|
+
height: calc(100% - ${HEADER_HEIGHT + SCROLLBAR_WIDTH}px);
|
|
29073
29082
|
&.o-dragging {
|
|
29074
29083
|
cursor: grabbing;
|
|
29075
29084
|
}
|
|
@@ -29137,6 +29146,9 @@ class RowResizer extends AbstractResizer {
|
|
|
29137
29146
|
this.MIN_ELEMENT_SIZE = MIN_ROW_HEIGHT;
|
|
29138
29147
|
}
|
|
29139
29148
|
rowResizerRef;
|
|
29149
|
+
get sheetId() {
|
|
29150
|
+
return this.env.model.getters.getActiveSheetId();
|
|
29151
|
+
}
|
|
29140
29152
|
_getEvOffset(ev) {
|
|
29141
29153
|
return ev.offsetY;
|
|
29142
29154
|
}
|
|
@@ -29159,10 +29171,10 @@ class RowResizer extends AbstractResizer {
|
|
|
29159
29171
|
return this.env.model.getters.getEdgeScrollRow(position, position, position);
|
|
29160
29172
|
}
|
|
29161
29173
|
_getDimensionsInViewport(index) {
|
|
29162
|
-
return this.env.model.getters.getRowDimensionsInViewport(this.
|
|
29174
|
+
return this.env.model.getters.getRowDimensionsInViewport(this.sheetId, index);
|
|
29163
29175
|
}
|
|
29164
29176
|
_getElementSize(index) {
|
|
29165
|
-
return this.env.model.getters.getRowSize(this.
|
|
29177
|
+
return this.env.model.getters.getRowSize(this.sheetId, index);
|
|
29166
29178
|
}
|
|
29167
29179
|
_getMaxSize() {
|
|
29168
29180
|
return this.rowResizerRef.el.clientHeight;
|
|
@@ -29173,7 +29185,7 @@ class RowResizer extends AbstractResizer {
|
|
|
29173
29185
|
const rows = this.env.model.getters.getActiveRows();
|
|
29174
29186
|
this.env.model.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
29175
29187
|
dimension: "ROW",
|
|
29176
|
-
sheetId: this.
|
|
29188
|
+
sheetId: this.sheetId,
|
|
29177
29189
|
elements: rows.has(index) ? [...rows] : [index],
|
|
29178
29190
|
size,
|
|
29179
29191
|
});
|
|
@@ -29186,7 +29198,7 @@ class RowResizer extends AbstractResizer {
|
|
|
29186
29198
|
elements.push(rowIndex);
|
|
29187
29199
|
}
|
|
29188
29200
|
const result = this.env.model.dispatch("MOVE_COLUMNS_ROWS", {
|
|
29189
|
-
sheetId: this.
|
|
29201
|
+
sheetId: this.sheetId,
|
|
29190
29202
|
dimension: "ROW",
|
|
29191
29203
|
base: this.state.base,
|
|
29192
29204
|
elements,
|
|
@@ -29205,7 +29217,7 @@ class RowResizer extends AbstractResizer {
|
|
|
29205
29217
|
_fitElementSize(index) {
|
|
29206
29218
|
const rows = this.env.model.getters.getActiveRows();
|
|
29207
29219
|
this.env.model.dispatch("AUTORESIZE_ROWS", {
|
|
29208
|
-
sheetId: this.
|
|
29220
|
+
sheetId: this.sheetId,
|
|
29209
29221
|
rows: rows.has(index) ? [...rows] : [index],
|
|
29210
29222
|
});
|
|
29211
29223
|
}
|
|
@@ -29216,7 +29228,7 @@ class RowResizer extends AbstractResizer {
|
|
|
29216
29228
|
return this.env.model.getters.getActiveRows();
|
|
29217
29229
|
}
|
|
29218
29230
|
_getPreviousVisibleElement(index) {
|
|
29219
|
-
const sheetId = this.
|
|
29231
|
+
const sheetId = this.sheetId;
|
|
29220
29232
|
let row;
|
|
29221
29233
|
for (row = index - 1; row >= 0; row--) {
|
|
29222
29234
|
if (!this.env.model.getters.isRowHidden(sheetId, row)) {
|
|
@@ -29227,7 +29239,7 @@ class RowResizer extends AbstractResizer {
|
|
|
29227
29239
|
}
|
|
29228
29240
|
unhide(hiddenElements) {
|
|
29229
29241
|
this.env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
|
|
29230
|
-
sheetId: this.
|
|
29242
|
+
sheetId: this.sheetId,
|
|
29231
29243
|
dimension: "ROW",
|
|
29232
29244
|
elements: hiddenElements,
|
|
29233
29245
|
});
|
|
@@ -30372,6 +30384,7 @@ const DRAWING_NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart";
|
|
|
30372
30384
|
const CONTENT_TYPES = {
|
|
30373
30385
|
workbook: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
|
|
30374
30386
|
sheet: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
|
30387
|
+
metadata: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml",
|
|
30375
30388
|
sharedStrings: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
|
|
30376
30389
|
styles: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
|
|
30377
30390
|
drawing: "application/vnd.openxmlformats-officedocument.drawing+xml",
|
|
@@ -30384,6 +30397,7 @@ const CONTENT_TYPES = {
|
|
|
30384
30397
|
const XLSX_RELATION_TYPE = {
|
|
30385
30398
|
document: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
|
30386
30399
|
sheet: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
|
|
30400
|
+
metadata: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata",
|
|
30387
30401
|
sharedStrings: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
|
|
30388
30402
|
styles: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
|
|
30389
30403
|
drawing: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
|
|
@@ -30393,6 +30407,7 @@ const XLSX_RELATION_TYPE = {
|
|
|
30393
30407
|
hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
|
30394
30408
|
image: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
|
30395
30409
|
};
|
|
30410
|
+
const ARRAY_FORMULA_URI = "bdbb8cdc-fa1e-496e-a857-3c3f30c029c3";
|
|
30396
30411
|
const RELATIONSHIP_NSR = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
30397
30412
|
const HEIGHT_FACTOR = 0.75; // 100px => 75 u
|
|
30398
30413
|
/**
|
|
@@ -32222,29 +32237,33 @@ function applyStyleToZone(appliedStyle, zone, cells, styles) {
|
|
|
32222
32237
|
* In all the sheets, replace the table-only references in the formula cells with standard references.
|
|
32223
32238
|
*/
|
|
32224
32239
|
function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
|
|
32225
|
-
for (let
|
|
32226
|
-
const tables = xlsxSheets.find((s) => s.sheetName ===
|
|
32240
|
+
for (let tableSheet of convertedSheets) {
|
|
32241
|
+
const tables = xlsxSheets.find((s) => s.sheetName === tableSheet.name).tables;
|
|
32227
32242
|
for (let table of tables) {
|
|
32228
32243
|
const tabRef = table.name + "[";
|
|
32229
|
-
for (let
|
|
32230
|
-
|
|
32231
|
-
|
|
32232
|
-
|
|
32233
|
-
|
|
32234
|
-
|
|
32235
|
-
|
|
32236
|
-
|
|
32237
|
-
|
|
32238
|
-
|
|
32239
|
-
|
|
32240
|
-
|
|
32244
|
+
for (let sheet of convertedSheets) {
|
|
32245
|
+
for (let xc in sheet.cells) {
|
|
32246
|
+
const cell = sheet.cells[xc];
|
|
32247
|
+
if (cell && cell.content && cell.content.startsWith("=")) {
|
|
32248
|
+
let refIndex;
|
|
32249
|
+
while ((refIndex = cell.content.indexOf(tabRef)) !== -1) {
|
|
32250
|
+
let endIndex = refIndex + tabRef.length;
|
|
32251
|
+
let openBrackets = 1;
|
|
32252
|
+
while (openBrackets > 0 && endIndex < cell.content.length) {
|
|
32253
|
+
if (cell.content[endIndex] === "[") {
|
|
32254
|
+
openBrackets++;
|
|
32255
|
+
}
|
|
32256
|
+
else if (cell.content[endIndex] === "]") {
|
|
32257
|
+
openBrackets--;
|
|
32258
|
+
}
|
|
32259
|
+
endIndex++;
|
|
32260
|
+
}
|
|
32261
|
+
let reference = cell.content.slice(refIndex + tabRef.length, endIndex - 1);
|
|
32262
|
+
const sheetPrefix = tableSheet.id === sheet.id ? "" : tableSheet.name + "!";
|
|
32263
|
+
const convertedRef = convertTableReference(sheetPrefix, reference, table, xc);
|
|
32264
|
+
cell.content =
|
|
32265
|
+
cell.content.slice(0, refIndex) + convertedRef + cell.content.slice(endIndex);
|
|
32241
32266
|
}
|
|
32242
|
-
reference = reference.slice(0, endIndex);
|
|
32243
|
-
const convertedRef = convertTableReference(reference, table, xc);
|
|
32244
|
-
cell.content =
|
|
32245
|
-
cell.content.slice(0, refIndex) +
|
|
32246
|
-
convertedRef +
|
|
32247
|
-
cell.content.slice(tabRef.length + refIndex + endIndex + 1);
|
|
32248
32267
|
}
|
|
32249
32268
|
}
|
|
32250
32269
|
}
|
|
@@ -32252,11 +32271,17 @@ function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
|
|
|
32252
32271
|
}
|
|
32253
32272
|
}
|
|
32254
32273
|
/**
|
|
32255
|
-
* Convert table-specific references in formulas into standard references.
|
|
32274
|
+
* Convert table-specific references in formulas into standard references. A table reference is composed of columns names,
|
|
32275
|
+
* and of keywords determining the rows of the table to reference.
|
|
32256
32276
|
*
|
|
32257
32277
|
* A reference in a table can have the form (only the part between brackets should be given to this function):
|
|
32258
32278
|
* - tableName[colName] : reference to the whole column "colName"
|
|
32279
|
+
* - tableName[#keyword] : reference to the whatever row the keyword refers to
|
|
32259
32280
|
* - tableName[[#keyword], [colName]] : reference to some of the element(s) of the column colName
|
|
32281
|
+
* - tableName[[#keyword], [colName]:[col2Name]] : reference to some of the element(s) of the columns colName to col2Name
|
|
32282
|
+
* - tableName[[#keyword1], [#keyword2], [colName]] : reference to all the rows referenced by the keywords in the column colName
|
|
32283
|
+
* - tableName[[#keyword1], [colName], [#keyword2]]: the keywords and colName can be in any order
|
|
32284
|
+
*
|
|
32260
32285
|
*
|
|
32261
32286
|
* The available keywords are :
|
|
32262
32287
|
* - #All : all the column (including totals)
|
|
@@ -32264,58 +32289,109 @@ function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
|
|
|
32264
32289
|
* - #Headers : only the header of the column
|
|
32265
32290
|
* - #Totals : only the totals of the column
|
|
32266
32291
|
* - #This Row : only the element in the same row as the cell
|
|
32292
|
+
*
|
|
32293
|
+
* Note that the only valid combination of multiple keywords are #Data + #Totals and #Headers + #Data.
|
|
32267
32294
|
*/
|
|
32268
|
-
function convertTableReference(expr, table, cellXc) {
|
|
32269
|
-
|
|
32295
|
+
function convertTableReference(sheetPrefix, expr, table, cellXc) {
|
|
32296
|
+
// TODO: Ideally we'd want to make a real tokenizer, this simple approach won't work if for example the column name
|
|
32297
|
+
// contain # or , characters. But that's probably an edge case that we can ignore for now.
|
|
32298
|
+
const parts = expr.split(",").map((part) => part.trim());
|
|
32270
32299
|
const tableZone = toZone(table.ref);
|
|
32271
|
-
const
|
|
32272
|
-
|
|
32273
|
-
|
|
32274
|
-
|
|
32275
|
-
|
|
32276
|
-
|
|
32277
|
-
|
|
32278
|
-
|
|
32279
|
-
|
|
32280
|
-
|
|
32281
|
-
|
|
32300
|
+
const colIndexes = [];
|
|
32301
|
+
const rowIndexes = [];
|
|
32302
|
+
const foundKeywords = [];
|
|
32303
|
+
for (const part of parts) {
|
|
32304
|
+
if (removeBrackets(part).startsWith("#")) {
|
|
32305
|
+
const keyWord = removeBrackets(part);
|
|
32306
|
+
foundKeywords.push(keyWord);
|
|
32307
|
+
switch (keyWord) {
|
|
32308
|
+
case "#All":
|
|
32309
|
+
rowIndexes.push(tableZone.top, tableZone.bottom);
|
|
32310
|
+
break;
|
|
32311
|
+
case "#Data":
|
|
32312
|
+
const top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
|
|
32313
|
+
const bottom = table.totalsRowCount
|
|
32314
|
+
? tableZone.bottom - table.totalsRowCount
|
|
32315
|
+
: tableZone.bottom;
|
|
32316
|
+
rowIndexes.push(top, bottom);
|
|
32317
|
+
break;
|
|
32318
|
+
case "#This Row":
|
|
32319
|
+
rowIndexes.push(toCartesian(cellXc).row);
|
|
32320
|
+
break;
|
|
32321
|
+
case "#Headers":
|
|
32322
|
+
if (!table.headerRowCount) {
|
|
32323
|
+
return INCORRECT_RANGE_STRING;
|
|
32324
|
+
}
|
|
32325
|
+
rowIndexes.push(tableZone.top);
|
|
32326
|
+
break;
|
|
32327
|
+
case "#Totals":
|
|
32328
|
+
if (!table.totalsRowCount) {
|
|
32329
|
+
return INCORRECT_RANGE_STRING;
|
|
32330
|
+
}
|
|
32331
|
+
rowIndexes.push(tableZone.bottom);
|
|
32332
|
+
break;
|
|
32333
|
+
}
|
|
32282
32334
|
}
|
|
32283
|
-
|
|
32284
|
-
|
|
32285
|
-
|
|
32286
|
-
|
|
32287
|
-
|
|
32288
|
-
|
|
32289
|
-
|
|
32290
|
-
|
|
32291
|
-
|
|
32292
|
-
|
|
32293
|
-
|
|
32294
|
-
|
|
32295
|
-
|
|
32296
|
-
|
|
32297
|
-
|
|
32298
|
-
|
|
32299
|
-
|
|
32300
|
-
if (!table.headerRowCount) {
|
|
32301
|
-
isReferencedZoneValid = false;
|
|
32302
|
-
}
|
|
32303
|
-
break;
|
|
32304
|
-
case "#Totals":
|
|
32305
|
-
refZone.top = refZone.bottom = tableZone.bottom;
|
|
32306
|
-
if (!table.totalsRowCount) {
|
|
32307
|
-
isReferencedZoneValid = false;
|
|
32335
|
+
else {
|
|
32336
|
+
const columns = part
|
|
32337
|
+
.split(":")
|
|
32338
|
+
.map((part) => part.trim())
|
|
32339
|
+
.map(removeBrackets);
|
|
32340
|
+
if (colIndexes.length) {
|
|
32341
|
+
return INCORRECT_RANGE_STRING;
|
|
32342
|
+
}
|
|
32343
|
+
const colRelativeIndex = table.cols.findIndex((col) => col.name === columns[0]);
|
|
32344
|
+
if (colRelativeIndex === -1) {
|
|
32345
|
+
return INCORRECT_RANGE_STRING;
|
|
32346
|
+
}
|
|
32347
|
+
colIndexes.push(colRelativeIndex + tableZone.left);
|
|
32348
|
+
if (columns[1]) {
|
|
32349
|
+
const colRelativeIndex2 = table.cols.findIndex((col) => col.name === columns[1]);
|
|
32350
|
+
if (colRelativeIndex2 === -1) {
|
|
32351
|
+
return INCORRECT_RANGE_STRING;
|
|
32308
32352
|
}
|
|
32309
|
-
|
|
32353
|
+
colIndexes.push(colRelativeIndex2 + tableZone.left);
|
|
32354
|
+
}
|
|
32310
32355
|
}
|
|
32311
|
-
const colRef = refElements[1].slice(1, refElements[1].length - 1);
|
|
32312
|
-
const colRelativeIndex = table.cols.findIndex((col) => col.name === colRef);
|
|
32313
|
-
refZone.left = refZone.right = colRelativeIndex + tableZone.left;
|
|
32314
32356
|
}
|
|
32315
|
-
if (!
|
|
32357
|
+
if (!areKeywordsCompatible(foundKeywords)) {
|
|
32316
32358
|
return INCORRECT_RANGE_STRING;
|
|
32317
32359
|
}
|
|
32318
|
-
|
|
32360
|
+
if (rowIndexes.length === 0) {
|
|
32361
|
+
const top = table.headerRowCount ? tableZone.top + table.headerRowCount : tableZone.top;
|
|
32362
|
+
const bottom = table.totalsRowCount
|
|
32363
|
+
? tableZone.bottom - table.totalsRowCount
|
|
32364
|
+
: tableZone.bottom;
|
|
32365
|
+
rowIndexes.push(top, bottom);
|
|
32366
|
+
}
|
|
32367
|
+
if (colIndexes.length === 0) {
|
|
32368
|
+
colIndexes.push(tableZone.left, tableZone.right);
|
|
32369
|
+
}
|
|
32370
|
+
const refZone = {
|
|
32371
|
+
top: Math.min(...rowIndexes),
|
|
32372
|
+
left: Math.min(...colIndexes),
|
|
32373
|
+
bottom: Math.max(...rowIndexes),
|
|
32374
|
+
right: Math.max(...colIndexes),
|
|
32375
|
+
};
|
|
32376
|
+
return sheetPrefix + zoneToXc(refZone);
|
|
32377
|
+
}
|
|
32378
|
+
function removeBrackets(str) {
|
|
32379
|
+
return str.startsWith("[") && str.endsWith("]") ? str.slice(1, str.length - 1) : str;
|
|
32380
|
+
}
|
|
32381
|
+
function areKeywordsCompatible(keywords) {
|
|
32382
|
+
if (keywords.length < 2) {
|
|
32383
|
+
return true;
|
|
32384
|
+
}
|
|
32385
|
+
else if (keywords.length > 2) {
|
|
32386
|
+
return false;
|
|
32387
|
+
}
|
|
32388
|
+
else if (keywords.includes("#Data") && keywords.includes("#Totals")) {
|
|
32389
|
+
return true;
|
|
32390
|
+
}
|
|
32391
|
+
else if (keywords.includes("#Headers") && keywords.includes("#Data")) {
|
|
32392
|
+
return true;
|
|
32393
|
+
}
|
|
32394
|
+
return false;
|
|
32319
32395
|
}
|
|
32320
32396
|
|
|
32321
32397
|
// -------------------------------------
|
|
@@ -42377,6 +42453,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
42377
42453
|
// Export
|
|
42378
42454
|
// ---------------------------------------------------------------------------
|
|
42379
42455
|
exportForExcel(data) {
|
|
42456
|
+
for (const sheet of data.sheets) {
|
|
42457
|
+
sheet.formulaSpillRanges = {};
|
|
42458
|
+
}
|
|
42380
42459
|
for (const position of this.evaluator.getEvaluatedPositions()) {
|
|
42381
42460
|
const evaluatedCell = this.evaluator.getEvaluatedCell(position);
|
|
42382
42461
|
const xc = toXC(position.col, position.row);
|
|
@@ -42388,8 +42467,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
42388
42467
|
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
42389
42468
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
42390
42469
|
if (formulaCell) {
|
|
42470
|
+
const cell = this.getters.getCell(position);
|
|
42391
42471
|
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
42392
|
-
isFormula = isExported;
|
|
42472
|
+
isFormula = isExported && cell?.content === formulaCell.content;
|
|
42393
42473
|
if (!isExported) {
|
|
42394
42474
|
// If the cell contains a non-exported formula and that is evaluates to
|
|
42395
42475
|
// nothing* ,we don't export it.
|
|
@@ -42413,6 +42493,14 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
42413
42493
|
content = !isExported ? newContent : exportedCellData.content;
|
|
42414
42494
|
}
|
|
42415
42495
|
exportedSheetData.cells[xc] = { ...exportedCellData, value, isFormula, content, format };
|
|
42496
|
+
const spillCells = this.getSpreadPositionsOf(position);
|
|
42497
|
+
spillCells.push(position);
|
|
42498
|
+
const spillZones = spillCells.map((cell) => positionToZone(cell));
|
|
42499
|
+
const spillZone = union(...spillZones);
|
|
42500
|
+
const spillZoneXc = this.getters.getRangeString(this.getters.getRangeFromZone(position.sheetId, spillZone), position.sheetId);
|
|
42501
|
+
if (spillZoneXc && spillZoneXc !== "#REF") {
|
|
42502
|
+
exportedSheetData.formulaSpillRanges[xc] = spillZoneXc;
|
|
42503
|
+
}
|
|
42416
42504
|
}
|
|
42417
42505
|
}
|
|
42418
42506
|
/**
|
|
@@ -43613,7 +43701,7 @@ class AutofillPlugin extends UIPlugin {
|
|
|
43613
43701
|
getRule(cell, cells) {
|
|
43614
43702
|
const rules = autofillRulesRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
|
|
43615
43703
|
const rule = rules.find((rule) => rule.condition(cell, cells));
|
|
43616
|
-
return rule && rule.generateRule(cell, cells);
|
|
43704
|
+
return rule && this.direction && rule.generateRule(cell, cells, this.direction);
|
|
43617
43705
|
}
|
|
43618
43706
|
/**
|
|
43619
43707
|
* Create the generator to be able to autofill the next cells.
|
|
@@ -51283,7 +51371,8 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
51283
51371
|
? this.getters.getSheetViewVisibleCols()
|
|
51284
51372
|
: this.getters.getSheetViewVisibleRows();
|
|
51285
51373
|
const startIndex = visibleHeaders.findIndex((header) => referenceHeaderIndex >= header);
|
|
51286
|
-
|
|
51374
|
+
let endIndex = visibleHeaders.findIndex((header) => targetHeaderIndex <= header);
|
|
51375
|
+
endIndex = endIndex === -1 ? visibleHeaders.length : endIndex;
|
|
51287
51376
|
const relevantIndexes = visibleHeaders.slice(startIndex, endIndex);
|
|
51288
51377
|
let offset = 0;
|
|
51289
51378
|
for (const i of relevantIndexes) {
|
|
@@ -56082,7 +56171,7 @@ function numberRef(reference) {
|
|
|
56082
56171
|
`;
|
|
56083
56172
|
}
|
|
56084
56173
|
|
|
56085
|
-
function addFormula(cell) {
|
|
56174
|
+
function addFormula(cell, formulaSpillRange) {
|
|
56086
56175
|
const formula = cell.content;
|
|
56087
56176
|
if (!formula) {
|
|
56088
56177
|
return { attrs: [], node: escapeXml `` };
|
|
@@ -56091,10 +56180,17 @@ function addFormula(cell) {
|
|
|
56091
56180
|
if (type === undefined) {
|
|
56092
56181
|
return { attrs: [], node: escapeXml `` };
|
|
56093
56182
|
}
|
|
56094
|
-
const attrs = [
|
|
56183
|
+
const attrs = [
|
|
56184
|
+
["cm", "1"],
|
|
56185
|
+
["t", type],
|
|
56186
|
+
];
|
|
56095
56187
|
const XlsxFormula = adaptFormulaToExcel(formula);
|
|
56096
56188
|
const exportedValue = adaptFormulaValueToExcel(cell.value);
|
|
56097
|
-
|
|
56189
|
+
// We treat all formulas as array formulas (a simple formula
|
|
56190
|
+
// is an array formula that spills on only one cell) to avoid
|
|
56191
|
+
// trying to detect spilling sub-formulas which is not a trivial task.
|
|
56192
|
+
let node;
|
|
56193
|
+
node = escapeXml /*xml*/ `<f t="array" ref="${formulaSpillRange}">${XlsxFormula}</f><v>${exportedValue}</v>`;
|
|
56098
56194
|
return { attrs, node };
|
|
56099
56195
|
}
|
|
56100
56196
|
function addContent(content, sharedStrings, forceString = false) {
|
|
@@ -56739,7 +56835,7 @@ function addStyles(styles) {
|
|
|
56739
56835
|
}
|
|
56740
56836
|
if (alignAttrs.length > 0) {
|
|
56741
56837
|
attributes.push(["applyAlignment", "1"]); // for Libre Office
|
|
56742
|
-
styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}
|
|
56838
|
+
styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)}><alignment ${formatAttributes(alignAttrs)} /></xf> `);
|
|
56743
56839
|
}
|
|
56744
56840
|
else {
|
|
56745
56841
|
styleNodes.push(escapeXml /*xml*/ `<xf ${formatAttributes(attributes)} />`);
|
|
@@ -56906,7 +57002,7 @@ function addRows(construct, data, sheet) {
|
|
|
56906
57002
|
let cellNode = escapeXml ``;
|
|
56907
57003
|
// Either formula or static value inside the cell
|
|
56908
57004
|
if (cell.isFormula) {
|
|
56909
|
-
const res = addFormula(cell);
|
|
57005
|
+
const res = addFormula(cell, sheet.formulaSpillRanges[xc] ?? xc);
|
|
56910
57006
|
if (!res) {
|
|
56911
57007
|
continue;
|
|
56912
57008
|
}
|
|
@@ -57163,6 +57259,30 @@ function createWorksheets(data, construct) {
|
|
|
57163
57259
|
`;
|
|
57164
57260
|
files.push(createXMLFile(parseXML(sheetXml), `xl/worksheets/sheet${sheetIndex}.xml`, "sheet"));
|
|
57165
57261
|
}
|
|
57262
|
+
const sheetMetadataXml = escapeXml /*xml*/ `
|
|
57263
|
+
<metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:xda="http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray">
|
|
57264
|
+
<metadataTypes count="1">
|
|
57265
|
+
<metadataType name="XLDAPR" minSupportedVersion="120000" copy="1" pasteAll="1"
|
|
57266
|
+
pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1"
|
|
57267
|
+
clearComments="1" assign="1" coerce="1" cellMeta="1" />
|
|
57268
|
+
</metadataTypes>
|
|
57269
|
+
<futureMetadata name="XLDAPR" count="1">
|
|
57270
|
+
<bk>
|
|
57271
|
+
<extLst>
|
|
57272
|
+
<ext uri="{${ARRAY_FORMULA_URI}}">
|
|
57273
|
+
<xda:dynamicArrayProperties fDynamic="1" fCollapsed="0" />
|
|
57274
|
+
</ext>
|
|
57275
|
+
</extLst>
|
|
57276
|
+
</bk>
|
|
57277
|
+
</futureMetadata>
|
|
57278
|
+
<cellMetadata count="1">
|
|
57279
|
+
<bk>
|
|
57280
|
+
<rc t="1" v="0" />
|
|
57281
|
+
</bk>
|
|
57282
|
+
</cellMetadata>
|
|
57283
|
+
</metadata>
|
|
57284
|
+
`;
|
|
57285
|
+
files.push(createXMLFile(parseXML(sheetMetadataXml), "xl/metadata.xml", "metadata"));
|
|
57166
57286
|
addRelsToFile(construct.relsFiles, "xl/_rels/workbook.xml.rels", {
|
|
57167
57287
|
type: XLSX_RELATION_TYPE.sharedStrings,
|
|
57168
57288
|
target: "sharedStrings.xml",
|
|
@@ -57171,6 +57291,10 @@ function createWorksheets(data, construct) {
|
|
|
57171
57291
|
type: XLSX_RELATION_TYPE.styles,
|
|
57172
57292
|
target: "styles.xml",
|
|
57173
57293
|
});
|
|
57294
|
+
addRelsToFile(construct.relsFiles, "xl/_rels/workbook.xml.rels", {
|
|
57295
|
+
type: XLSX_RELATION_TYPE.metadata,
|
|
57296
|
+
target: "metadata.xml",
|
|
57297
|
+
});
|
|
57174
57298
|
return files;
|
|
57175
57299
|
}
|
|
57176
57300
|
/**
|
|
@@ -57945,6 +58069,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
57945
58069
|
exports.tokenize = tokenize;
|
|
57946
58070
|
|
|
57947
58071
|
|
|
57948
|
-
__info__.version = "17.0.
|
|
57949
|
-
__info__.date = "2025-
|
|
57950
|
-
__info__.hash = "
|
|
58072
|
+
__info__.version = "17.0.53";
|
|
58073
|
+
__info__.date = "2025-03-12T15:26:58.496Z";
|
|
58074
|
+
__info__.hash = "47dfd62";
|
package/dist/o-spreadsheet.d.ts
CHANGED
|
@@ -664,6 +664,9 @@ interface ExcelSheetData extends Omit<SheetData, "figureTables"> {
|
|
|
664
664
|
cells: {
|
|
665
665
|
[key: string]: ExcelCellData | undefined;
|
|
666
666
|
};
|
|
667
|
+
formulaSpillRanges: {
|
|
668
|
+
[xc: string]: string;
|
|
669
|
+
};
|
|
667
670
|
charts: FigureData<ExcelChartDefinition>[];
|
|
668
671
|
images: FigureData<Image>[];
|
|
669
672
|
filterTables: ExcelFilterTableData[];
|
|
@@ -5989,7 +5992,7 @@ declare class MenuItemRegistry extends Registry<ActionSpec> {
|
|
|
5989
5992
|
*/
|
|
5990
5993
|
interface AutofillRule {
|
|
5991
5994
|
condition: (cell: Cell, cells: (Cell | undefined)[]) => boolean;
|
|
5992
|
-
generateRule: (cell: Cell, cells: (Cell | undefined)[]) => AutofillModifier;
|
|
5995
|
+
generateRule: (cell: Cell, cells: (Cell | undefined)[], direction: DIRECTION) => AutofillModifier;
|
|
5993
5996
|
sequence: number;
|
|
5994
5997
|
}
|
|
5995
5998
|
|
|
@@ -7598,6 +7601,7 @@ declare class ColResizer extends AbstractResizer {
|
|
|
7598
7601
|
static template: string;
|
|
7599
7602
|
private colResizerRef;
|
|
7600
7603
|
setup(): void;
|
|
7604
|
+
get sheetId(): UID;
|
|
7601
7605
|
_getEvOffset(ev: MouseEvent): Pixel;
|
|
7602
7606
|
_getViewportOffset(): Pixel;
|
|
7603
7607
|
_getClientPosition(ev: MouseEvent): Pixel;
|
|
@@ -7623,6 +7627,7 @@ declare class RowResizer extends AbstractResizer {
|
|
|
7623
7627
|
static template: string;
|
|
7624
7628
|
setup(): void;
|
|
7625
7629
|
private rowResizerRef;
|
|
7630
|
+
get sheetId(): UID;
|
|
7626
7631
|
_getEvOffset(ev: MouseEvent): Pixel;
|
|
7627
7632
|
_getViewportOffset(): Pixel;
|
|
7628
7633
|
_getClientPosition(ev: MouseEvent): Pixel;
|