@odoo/o-spreadsheet 17.2.1 → 17.3.0-alpha.1
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 +461 -174
- package/dist/o-spreadsheet.d.ts +58 -20
- package/dist/o-spreadsheet.esm.js +461 -174
- package/dist/o-spreadsheet.iife.js +461 -174
- package/dist/o-spreadsheet.iife.min.js +269 -264
- package/dist/o_spreadsheet.xml +28 -6
- package/package.json +2 -2
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.
|
|
7
|
-
* @date 2024-03-25T09:
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.3.0-alpha.1
|
|
7
|
+
* @date 2024-03-25T09:43:36.072Z
|
|
8
|
+
* @hash 4095c41
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
(function (exports, owl) {
|
|
@@ -4202,6 +4202,10 @@
|
|
|
4202
4202
|
function positionToZone(position) {
|
|
4203
4203
|
return { left: position.col, right: position.col, top: position.row, bottom: position.row };
|
|
4204
4204
|
}
|
|
4205
|
+
/** Transform a zone into a zone with only its top-left position */
|
|
4206
|
+
function zoneToTopLeft(zone) {
|
|
4207
|
+
return { ...zone, right: zone.left, bottom: zone.top };
|
|
4208
|
+
}
|
|
4205
4209
|
function isFullRow(zone) {
|
|
4206
4210
|
return zone.right === undefined;
|
|
4207
4211
|
}
|
|
@@ -4241,6 +4245,16 @@
|
|
|
4241
4245
|
}
|
|
4242
4246
|
return set;
|
|
4243
4247
|
}
|
|
4248
|
+
function unionPositionsToZone(positions) {
|
|
4249
|
+
const zone = { top: Infinity, left: Infinity, bottom: -Infinity, right: -Infinity };
|
|
4250
|
+
for (const { col, row } of positions) {
|
|
4251
|
+
zone.top = Math.min(zone.top, row);
|
|
4252
|
+
zone.left = Math.min(zone.left, col);
|
|
4253
|
+
zone.bottom = Math.max(zone.bottom, row);
|
|
4254
|
+
zone.right = Math.max(zone.right, col);
|
|
4255
|
+
}
|
|
4256
|
+
return zone;
|
|
4257
|
+
}
|
|
4244
4258
|
|
|
4245
4259
|
class RangeImpl {
|
|
4246
4260
|
getSheetSize;
|
|
@@ -5570,7 +5584,7 @@
|
|
|
5570
5584
|
const spreader = this.getters.getArrayFormulaSpreadingOn(position);
|
|
5571
5585
|
let cell = this.getters.getCell(position);
|
|
5572
5586
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
5573
|
-
if (spreader) {
|
|
5587
|
+
if (spreader && !deepEquals(spreader, position)) {
|
|
5574
5588
|
const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
|
|
5575
5589
|
const content = isSpreaderCopied
|
|
5576
5590
|
? ""
|
|
@@ -6217,19 +6231,25 @@
|
|
|
6217
6231
|
tableCellsInRow.push({});
|
|
6218
6232
|
continue;
|
|
6219
6233
|
}
|
|
6234
|
+
const coreTable = this.getters.getCoreTable(position);
|
|
6235
|
+
const tableZone = coreTable?.range.zone;
|
|
6220
6236
|
// Copy whole table
|
|
6221
|
-
if (zones.some((z) => isZoneInside(
|
|
6222
|
-
copiedTablesIds.add(
|
|
6237
|
+
if (coreTable && tableZone && zones.some((z) => isZoneInside(tableZone, z))) {
|
|
6238
|
+
copiedTablesIds.add(coreTable.id);
|
|
6223
6239
|
const values = [];
|
|
6224
|
-
for (const col of range(
|
|
6225
|
-
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row:
|
|
6240
|
+
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
6241
|
+
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
6226
6242
|
}
|
|
6227
6243
|
tableCellsInRow.push({
|
|
6228
|
-
table: {
|
|
6244
|
+
table: {
|
|
6245
|
+
range: coreTable.range,
|
|
6246
|
+
config: coreTable.config,
|
|
6247
|
+
type: coreTable.type,
|
|
6248
|
+
},
|
|
6229
6249
|
});
|
|
6230
6250
|
}
|
|
6231
6251
|
// Copy only style of cell
|
|
6232
|
-
else {
|
|
6252
|
+
else if (table) {
|
|
6233
6253
|
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
6234
6254
|
}
|
|
6235
6255
|
}
|
|
@@ -6300,7 +6320,7 @@
|
|
|
6300
6320
|
}
|
|
6301
6321
|
pasteTableCell(sheetId, tableCell, position, options) {
|
|
6302
6322
|
if (tableCell.table && !options?.pasteOption) {
|
|
6303
|
-
const { range: tableRange
|
|
6323
|
+
const { range: tableRange } = tableCell.table;
|
|
6304
6324
|
const zoneDims = zoneToDimension(tableRange.zone);
|
|
6305
6325
|
const newTableZone = {
|
|
6306
6326
|
left: position.col,
|
|
@@ -6312,18 +6332,13 @@
|
|
|
6312
6332
|
sheetId: position.sheetId,
|
|
6313
6333
|
ranges: [this.getters.getRangeDataFromZone(sheetId, newTableZone)],
|
|
6314
6334
|
config: tableCell.table.config,
|
|
6335
|
+
tableType: tableCell.table.type,
|
|
6315
6336
|
});
|
|
6316
|
-
for (const i of range(0, filtersValues.length)) {
|
|
6317
|
-
this.dispatch("UPDATE_FILTER", {
|
|
6318
|
-
sheetId: position.sheetId,
|
|
6319
|
-
col: newTableZone.left + i,
|
|
6320
|
-
row: newTableZone.top,
|
|
6321
|
-
hiddenValues: filtersValues[i],
|
|
6322
|
-
});
|
|
6323
|
-
}
|
|
6324
6337
|
}
|
|
6325
6338
|
// Do not paste table style if we're inside another table
|
|
6326
|
-
|
|
6339
|
+
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
6340
|
+
// dynamic tables are not yet computed
|
|
6341
|
+
if (!this.getters.getCoreTable(position)) {
|
|
6327
6342
|
if (tableCell.style?.style && options?.pasteOption !== "asValue") {
|
|
6328
6343
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
6329
6344
|
}
|
|
@@ -7425,9 +7440,11 @@
|
|
|
7425
7440
|
bandedColumns: _t("Banded columns"),
|
|
7426
7441
|
automaticAutofill: _t("Automatically autofill formulas"),
|
|
7427
7442
|
totalRow: _t("Total row"),
|
|
7443
|
+
isDynamic: _t("Auto-adjust to formula result"),
|
|
7428
7444
|
},
|
|
7429
7445
|
Tooltips: {
|
|
7430
7446
|
filterWithoutHeader: _t("Cannot have filters without a header row"),
|
|
7447
|
+
isDynamic: _t("For tables based on array formulas only"),
|
|
7431
7448
|
},
|
|
7432
7449
|
};
|
|
7433
7450
|
|
|
@@ -22228,6 +22245,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22228
22245
|
}
|
|
22229
22246
|
edit() {
|
|
22230
22247
|
const { col, row } = this.props.cellPosition;
|
|
22248
|
+
this.env.model.selection.selectCell(col, row);
|
|
22231
22249
|
this.cellPopovers.open({ col, row }, "LinkEditor");
|
|
22232
22250
|
}
|
|
22233
22251
|
unlink() {
|
|
@@ -23344,13 +23362,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23344
23362
|
* If a single cell is selected, expand the selection to non-empty adjacent cells to create a table.
|
|
23345
23363
|
*/
|
|
23346
23364
|
function interactiveCreateTable(env, sheetId, tableConfig) {
|
|
23347
|
-
|
|
23348
|
-
|
|
23365
|
+
let target = env.model.getters.getSelectedZones();
|
|
23366
|
+
let isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
|
|
23367
|
+
if (target.length === 1 && !isDynamic && getZoneArea(target[0]) === 1) {
|
|
23349
23368
|
env.model.selection.selectTableAroundSelection();
|
|
23369
|
+
target = env.model.getters.getSelectedZones();
|
|
23370
|
+
isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
|
|
23350
23371
|
}
|
|
23351
|
-
const target = env.model.getters.getSelectedZones();
|
|
23352
23372
|
const ranges = target.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
|
|
23353
|
-
const result = env.model.dispatch("CREATE_TABLE", {
|
|
23373
|
+
const result = env.model.dispatch("CREATE_TABLE", {
|
|
23374
|
+
ranges,
|
|
23375
|
+
sheetId,
|
|
23376
|
+
config: tableConfig,
|
|
23377
|
+
tableType: isDynamic ? "dynamic" : "static",
|
|
23378
|
+
});
|
|
23354
23379
|
if (result.isCancelledBecause("TableOverlap" /* CommandResult.TableOverlap */)) {
|
|
23355
23380
|
env.raiseError(TableTerms.Errors.TableOverlap);
|
|
23356
23381
|
}
|
|
@@ -23798,9 +23823,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23798
23823
|
};
|
|
23799
23824
|
const DELETE_SELECTED_TABLE = (env) => {
|
|
23800
23825
|
const position = env.model.getters.getActivePosition();
|
|
23826
|
+
const table = env.model.getters.getTable(position);
|
|
23827
|
+
if (!table) {
|
|
23828
|
+
return;
|
|
23829
|
+
}
|
|
23801
23830
|
env.model.dispatch("REMOVE_TABLE", {
|
|
23802
23831
|
sheetId: position.sheetId,
|
|
23803
|
-
target: [
|
|
23832
|
+
target: [table.range.zone],
|
|
23804
23833
|
});
|
|
23805
23834
|
};
|
|
23806
23835
|
//------------------------------------------------------------------------------
|
|
@@ -30308,6 +30337,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30308
30337
|
const contentZone = { ...tableZone, top: tableZone.top + numberOfHeaders };
|
|
30309
30338
|
return contentZone.top <= contentZone.bottom ? contentZone : undefined;
|
|
30310
30339
|
}
|
|
30340
|
+
function getTableTopLeft(table) {
|
|
30341
|
+
const range = table.range;
|
|
30342
|
+
return { row: range.zone.top, col: range.zone.left, sheetId: range.sheetId };
|
|
30343
|
+
}
|
|
30344
|
+
function createFilter(id, range, config, createRange) {
|
|
30345
|
+
const zone = range.zone;
|
|
30346
|
+
if (zone.left !== zone.right) {
|
|
30347
|
+
throw new Error("Can only define a filter on a single column");
|
|
30348
|
+
}
|
|
30349
|
+
const filteredZone = { ...zone, top: zone.top + config.numberOfHeaders };
|
|
30350
|
+
const filteredRange = createRange(range.sheetId, filteredZone);
|
|
30351
|
+
return {
|
|
30352
|
+
id,
|
|
30353
|
+
rangeWithHeaders: range,
|
|
30354
|
+
col: zone.left,
|
|
30355
|
+
filteredRange: filteredZone.top > filteredZone.bottom ? undefined : filteredRange,
|
|
30356
|
+
};
|
|
30357
|
+
}
|
|
30311
30358
|
function getComputedTableStyle(tableConfig, numberOfCols, numberOfRows) {
|
|
30312
30359
|
return {
|
|
30313
30360
|
borders: getAllTableBorders(tableConfig, numberOfCols, numberOfRows),
|
|
@@ -30745,6 +30792,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30745
30792
|
color: #ffffff;
|
|
30746
30793
|
background: #d94b4b;
|
|
30747
30794
|
}
|
|
30795
|
+
|
|
30796
|
+
.o-info-icon {
|
|
30797
|
+
width: 14px;
|
|
30798
|
+
height: 14px;
|
|
30799
|
+
}
|
|
30748
30800
|
}
|
|
30749
30801
|
`;
|
|
30750
30802
|
class TablePanel extends owl.Component {
|
|
@@ -30776,6 +30828,29 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30776
30828
|
const numberOfHeaders = hasHeaders ? 1 : 0;
|
|
30777
30829
|
this.updateNumberOfHeaders(numberOfHeaders);
|
|
30778
30830
|
}
|
|
30831
|
+
updateTableIsDynamic(isDynamic) {
|
|
30832
|
+
const newTableType = isDynamic ? "dynamic" : "forceStatic";
|
|
30833
|
+
if (newTableType === this.props.table.type) {
|
|
30834
|
+
return;
|
|
30835
|
+
}
|
|
30836
|
+
const uiTable = this.env.model.getters.getTable(getTableTopLeft(this.props.table));
|
|
30837
|
+
if (!uiTable) {
|
|
30838
|
+
return;
|
|
30839
|
+
}
|
|
30840
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30841
|
+
const result = this.env.model.dispatch("UPDATE_TABLE", {
|
|
30842
|
+
sheetId,
|
|
30843
|
+
zone: this.props.table.range.zone,
|
|
30844
|
+
newTableRange: uiTable.range.rangeData,
|
|
30845
|
+
tableType: newTableType,
|
|
30846
|
+
});
|
|
30847
|
+
const updatedTable = this.env.model.getters.getCoreTable(getTableTopLeft(this.props.table));
|
|
30848
|
+
if (result.isSuccessful && updatedTable) {
|
|
30849
|
+
const newTableRange = updatedTable.range;
|
|
30850
|
+
this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
|
|
30851
|
+
this.state.tableZoneErrors = [];
|
|
30852
|
+
}
|
|
30853
|
+
}
|
|
30779
30854
|
onChangeNumberOfHeaders(ev) {
|
|
30780
30855
|
const input = ev.target;
|
|
30781
30856
|
const numberOfHeaders = parseInt(input.value);
|
|
@@ -30799,35 +30874,59 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30799
30874
|
}
|
|
30800
30875
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30801
30876
|
this.state.tableXc = ranges[0];
|
|
30877
|
+
const newTableRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
|
|
30802
30878
|
this.state.tableZoneErrors = this.env.model.canDispatch("UPDATE_TABLE", {
|
|
30803
30879
|
sheetId,
|
|
30804
30880
|
zone: this.props.table.range.zone,
|
|
30805
30881
|
newTableRange: this.env.model.getters.getRangeDataFromXc(sheetId, this.state.tableXc),
|
|
30882
|
+
tableType: this.getNewTableType(newTableRange.zone),
|
|
30806
30883
|
}).reasons;
|
|
30807
30884
|
}
|
|
30808
30885
|
onRangeConfirmed() {
|
|
30809
30886
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30810
|
-
|
|
30887
|
+
let newRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
|
|
30888
|
+
if (getZoneArea(newRange.zone) === 1) {
|
|
30889
|
+
const extendedZone = this.env.model.getters.getContiguousZone(sheetId, newRange.zone);
|
|
30890
|
+
newRange = this.env.model.getters.getRangeFromZone(sheetId, extendedZone);
|
|
30891
|
+
}
|
|
30811
30892
|
const result = this.env.model.dispatch("UPDATE_TABLE", {
|
|
30812
30893
|
sheetId,
|
|
30813
30894
|
zone: this.props.table.range.zone,
|
|
30814
30895
|
newTableRange: newRange.rangeData,
|
|
30896
|
+
tableType: this.getNewTableType(newRange.zone),
|
|
30815
30897
|
});
|
|
30816
|
-
|
|
30817
|
-
|
|
30898
|
+
const position = { sheetId, col: newRange.zone.left, row: newRange.zone.top };
|
|
30899
|
+
const updatedTable = this.env.model.getters.getCoreTable(position);
|
|
30900
|
+
if (result.isSuccessful && updatedTable) {
|
|
30901
|
+
const newTopLeft = getTableTopLeft(updatedTable);
|
|
30818
30902
|
this.env.model.selection.selectZone({
|
|
30819
|
-
zone: positionToZone(
|
|
30820
|
-
cell:
|
|
30903
|
+
zone: positionToZone(newTopLeft),
|
|
30904
|
+
cell: newTopLeft,
|
|
30821
30905
|
});
|
|
30906
|
+
const newTableRange = updatedTable.range;
|
|
30907
|
+
this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
|
|
30908
|
+
}
|
|
30909
|
+
else {
|
|
30910
|
+
const oldTableRange = this.props.table.range;
|
|
30911
|
+
this.state.tableXc = this.env.model.getters.getRangeString(oldTableRange, sheetId);
|
|
30822
30912
|
}
|
|
30823
30913
|
this.state.tableZoneErrors = [];
|
|
30824
|
-
this.state.tableXc = result.isSuccessful
|
|
30825
|
-
? this.state.tableXc
|
|
30826
|
-
: this.env.model.getters.getRangeString(this.props.table.range, sheetId);
|
|
30827
30914
|
}
|
|
30828
30915
|
deleteTable() {
|
|
30829
30916
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30830
|
-
this.env.model.dispatch("REMOVE_TABLE", {
|
|
30917
|
+
this.env.model.dispatch("REMOVE_TABLE", {
|
|
30918
|
+
sheetId,
|
|
30919
|
+
target: [this.props.table.range.zone],
|
|
30920
|
+
});
|
|
30921
|
+
}
|
|
30922
|
+
getNewTableType(newTableZone) {
|
|
30923
|
+
if (this.props.table.type === "forceStatic") {
|
|
30924
|
+
return "forceStatic";
|
|
30925
|
+
}
|
|
30926
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30927
|
+
return this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [newTableZone])
|
|
30928
|
+
? "dynamic"
|
|
30929
|
+
: "static";
|
|
30831
30930
|
}
|
|
30832
30931
|
get tableConfig() {
|
|
30833
30932
|
return this.props.table.config;
|
|
@@ -30845,6 +30944,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30845
30944
|
get hasFilterCheckboxTooltip() {
|
|
30846
30945
|
return this.canHaveFilters ? undefined : TableTerms.Tooltips.filterWithoutHeader;
|
|
30847
30946
|
}
|
|
30947
|
+
get canBeDynamic() {
|
|
30948
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30949
|
+
return (this.props.table.type === "dynamic" ||
|
|
30950
|
+
this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [this.props.table.range.zone]));
|
|
30951
|
+
}
|
|
30952
|
+
get dynamicTableTooltip() {
|
|
30953
|
+
return TableTerms.Tooltips.isDynamic;
|
|
30954
|
+
}
|
|
30848
30955
|
}
|
|
30849
30956
|
|
|
30850
30957
|
const sidePanelRegistry = new Registry();
|
|
@@ -30907,11 +31014,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30907
31014
|
if (!table) {
|
|
30908
31015
|
return { isOpen: false };
|
|
30909
31016
|
}
|
|
30910
|
-
|
|
30911
|
-
|
|
30912
|
-
props: { table },
|
|
30913
|
-
key: table.id,
|
|
30914
|
-
};
|
|
31017
|
+
const coreTable = getters.getCoreTable(getTableTopLeft(table));
|
|
31018
|
+
return { isOpen: true, props: { table: coreTable }, key: table.id };
|
|
30915
31019
|
},
|
|
30916
31020
|
});
|
|
30917
31021
|
|
|
@@ -31856,9 +31960,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31856
31960
|
this.assistantState.allowCellSelectionBehind = false;
|
|
31857
31961
|
}, 2000);
|
|
31858
31962
|
}
|
|
31859
|
-
get formulaArgSeparator() {
|
|
31860
|
-
return this.env.model.getters.getLocale().formulaArgSeparator + " ";
|
|
31861
|
-
}
|
|
31862
31963
|
}
|
|
31863
31964
|
|
|
31864
31965
|
const functions$2 = functionRegistry.content;
|
|
@@ -32756,8 +32857,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
32756
32857
|
};
|
|
32757
32858
|
getFilterHeadersPositions() {
|
|
32758
32859
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
32759
|
-
|
|
32760
|
-
return headerPositions.map((position) => ({ sheetId, ...position }));
|
|
32860
|
+
return this.env.model.getters.getFilterHeaders(sheetId);
|
|
32761
32861
|
}
|
|
32762
32862
|
}
|
|
32763
32863
|
|
|
@@ -44826,22 +44926,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44826
44926
|
}
|
|
44827
44927
|
|
|
44828
44928
|
class TablePlugin extends CorePlugin {
|
|
44829
|
-
static getters = [
|
|
44830
|
-
"getFilter",
|
|
44831
|
-
"getFilters",
|
|
44832
|
-
"getTable",
|
|
44833
|
-
"getTables",
|
|
44834
|
-
"getTablesInZone",
|
|
44835
|
-
"getTablesOverlappingZones",
|
|
44836
|
-
"getFilterId",
|
|
44837
|
-
"getFilterHeaders",
|
|
44838
|
-
"isFilterHeader",
|
|
44839
|
-
];
|
|
44929
|
+
static getters = ["getCoreTable", "getCoreTables"];
|
|
44840
44930
|
tables = {};
|
|
44841
44931
|
adaptRanges(applyChange, sheetId) {
|
|
44842
44932
|
const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
|
|
44843
44933
|
for (const sheetId of sheetIds) {
|
|
44844
|
-
for (const table of this.
|
|
44934
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
44845
44935
|
this.applyRangeChangeOnTable(sheetId, table, applyChange);
|
|
44846
44936
|
}
|
|
44847
44937
|
}
|
|
@@ -44857,15 +44947,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44857
44947
|
? "TableOverlap" /* CommandResult.TableOverlap */
|
|
44858
44948
|
: "Success" /* CommandResult.Success */, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
|
|
44859
44949
|
case "UPDATE_TABLE":
|
|
44860
|
-
const updatedTable = this.
|
|
44950
|
+
const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
44861
44951
|
if (!updatedTable) {
|
|
44862
44952
|
return "TableNotFound" /* CommandResult.TableNotFound */;
|
|
44863
44953
|
}
|
|
44864
44954
|
return this.checkValidations(cmd, this.checkUpdatedTableZoneIsValid, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
|
|
44865
44955
|
case "ADD_MERGE":
|
|
44866
|
-
for (const
|
|
44867
|
-
|
|
44868
|
-
|
|
44956
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
44957
|
+
const tableZone = table.range.zone;
|
|
44958
|
+
for (const merge of cmd.target) {
|
|
44959
|
+
if (overlap(tableZone, merge)) {
|
|
44869
44960
|
return "MergeInTable" /* CommandResult.MergeInTable */;
|
|
44870
44961
|
}
|
|
44871
44962
|
}
|
|
@@ -44887,8 +44978,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44887
44978
|
}
|
|
44888
44979
|
case "DUPLICATE_SHEET": {
|
|
44889
44980
|
const newTables = {};
|
|
44890
|
-
for (const table of this.
|
|
44891
|
-
newTables[table.id] =
|
|
44981
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
44982
|
+
newTables[table.id] =
|
|
44983
|
+
table.type === "dynamic"
|
|
44984
|
+
? this.copyDynamicTableForSheet(cmd.sheetIdTo, table)
|
|
44985
|
+
: this.copyStaticTableForSheet(cmd.sheetIdTo, table);
|
|
44892
44986
|
}
|
|
44893
44987
|
this.history.update("tables", cmd.sheetIdTo, newTables);
|
|
44894
44988
|
break;
|
|
@@ -44899,14 +44993,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44899
44993
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
44900
44994
|
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
44901
44995
|
const id = this.uuidGenerator.uuidv4();
|
|
44902
|
-
const
|
|
44996
|
+
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
44997
|
+
const newTable = cmd.tableType === "dynamic"
|
|
44998
|
+
? this.createDynamicTable(id, union, config)
|
|
44999
|
+
: this.createStaticTable(id, cmd.tableType, union, config);
|
|
44903
45000
|
this.history.update("tables", cmd.sheetId, newTable.id, newTable);
|
|
44904
45001
|
break;
|
|
44905
45002
|
}
|
|
44906
45003
|
case "REMOVE_TABLE": {
|
|
44907
45004
|
const tables = {};
|
|
44908
|
-
for (const table of this.
|
|
44909
|
-
if (cmd.target.every((zone) => !intersection(
|
|
45005
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
45006
|
+
if (cmd.target.every((zone) => !intersection(table.range.zone, zone))) {
|
|
44910
45007
|
tables[table.id] = table;
|
|
44911
45008
|
}
|
|
44912
45009
|
}
|
|
@@ -44914,23 +45011,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44914
45011
|
break;
|
|
44915
45012
|
}
|
|
44916
45013
|
case "UPDATE_TABLE": {
|
|
44917
|
-
|
|
44918
|
-
if (table) {
|
|
44919
|
-
const newTableRange = cmd.newTableRange
|
|
44920
|
-
? this.getters.getRangeFromRangeData(cmd.newTableRange)
|
|
44921
|
-
: undefined;
|
|
44922
|
-
if (newTableRange) {
|
|
44923
|
-
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
|
|
44924
|
-
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
44925
|
-
}
|
|
44926
|
-
const newTable = this.updateTable(table, newTableRange, cmd.config);
|
|
44927
|
-
this.history.update("tables", cmd.sheetId, table.id, newTable);
|
|
44928
|
-
}
|
|
45014
|
+
this.updateTable(cmd);
|
|
44929
45015
|
break;
|
|
44930
45016
|
}
|
|
44931
45017
|
case "UPDATE_CELL": {
|
|
44932
45018
|
const sheetId = cmd.sheetId;
|
|
44933
|
-
for (const table of this.
|
|
45019
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
45020
|
+
if (table.type === "dynamic") {
|
|
45021
|
+
continue;
|
|
45022
|
+
}
|
|
44934
45023
|
const direction = this.canUpdateCellCmdExtendTable(cmd, table);
|
|
44935
45024
|
if (direction === "down") {
|
|
44936
45025
|
this.extendTableDown(sheetId, table);
|
|
@@ -44954,62 +45043,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44954
45043
|
}
|
|
44955
45044
|
}
|
|
44956
45045
|
}
|
|
44957
|
-
|
|
44958
|
-
return this.getTables(sheetId)
|
|
44959
|
-
.filter((table) => table.config.hasFilters)
|
|
44960
|
-
.map((table) => table.filters)
|
|
44961
|
-
.flat();
|
|
44962
|
-
}
|
|
44963
|
-
getTables(sheetId) {
|
|
45046
|
+
getCoreTables(sheetId) {
|
|
44964
45047
|
return this.tables[sheetId] ? Object.values(this.tables[sheetId]).filter(isDefined$1) : [];
|
|
44965
45048
|
}
|
|
44966
|
-
|
|
44967
|
-
|
|
44968
|
-
if (!table || !table.config.hasFilters) {
|
|
44969
|
-
return undefined;
|
|
44970
|
-
}
|
|
44971
|
-
return table.filters.find((filter) => filter.col === position.col);
|
|
44972
|
-
}
|
|
44973
|
-
getFilterId(position) {
|
|
44974
|
-
return this.getFilter(position)?.id;
|
|
44975
|
-
}
|
|
44976
|
-
getTable({ sheetId, col, row }) {
|
|
44977
|
-
return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
44978
|
-
}
|
|
44979
|
-
/** Get the filter tables that are fully inside the given zone */
|
|
44980
|
-
getTablesInZone(sheetId, zone) {
|
|
44981
|
-
return this.getTables(sheetId).filter((table) => isZoneInside(table.range.zone, zone));
|
|
45049
|
+
getCoreTable({ sheetId, col, row }) {
|
|
45050
|
+
return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
44982
45051
|
}
|
|
44983
45052
|
getTablesOverlappingZones(sheetId, zones) {
|
|
44984
|
-
return this.
|
|
44985
|
-
}
|
|
44986
|
-
getFilterHeaders(sheetId) {
|
|
44987
|
-
const headers = [];
|
|
44988
|
-
for (const table of this.getTables(sheetId)) {
|
|
44989
|
-
if (!table.config.hasFilters) {
|
|
44990
|
-
continue;
|
|
44991
|
-
}
|
|
44992
|
-
const zone = table.range.zone;
|
|
44993
|
-
const row = zone.top;
|
|
44994
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
44995
|
-
headers.push({ col, row });
|
|
44996
|
-
}
|
|
44997
|
-
}
|
|
44998
|
-
return headers;
|
|
44999
|
-
}
|
|
45000
|
-
isFilterHeader({ sheetId, col, row }) {
|
|
45001
|
-
const headers = this.getFilterHeaders(sheetId);
|
|
45002
|
-
return headers.some((header) => header.col === col && header.row === row);
|
|
45053
|
+
return this.getCoreTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
|
|
45003
45054
|
}
|
|
45004
45055
|
/** Extend a table down one row */
|
|
45005
45056
|
extendTableDown(sheetId, table) {
|
|
45006
45057
|
const newRange = this.getters.extendRange(table.range, "ROW", 1);
|
|
45007
|
-
this.history.update("tables", sheetId, table.id, this.
|
|
45058
|
+
this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
|
|
45008
45059
|
}
|
|
45009
45060
|
/** Extend a table right one col */
|
|
45010
45061
|
extendTableRight(sheetId, table) {
|
|
45011
45062
|
const newRange = this.getters.extendRange(table.range, "COL", 1);
|
|
45012
|
-
this.history.update("tables", sheetId, table.id, this.
|
|
45063
|
+
this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
|
|
45013
45064
|
}
|
|
45014
45065
|
/**
|
|
45015
45066
|
* Check if an UpdateCell command should cause the given table to be extended by one row or col.
|
|
@@ -45046,12 +45097,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45046
45097
|
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
45047
45098
|
if (cellContent ||
|
|
45048
45099
|
this.getters.isInMerge(cellPosition) ||
|
|
45049
|
-
this.
|
|
45100
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(position)]).length) {
|
|
45050
45101
|
return "none";
|
|
45051
45102
|
}
|
|
45052
45103
|
}
|
|
45053
45104
|
return direction;
|
|
45054
45105
|
}
|
|
45106
|
+
getTableFromZone(sheetId, zone) {
|
|
45107
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
45108
|
+
const tableZone = table.range.zone;
|
|
45109
|
+
// Only check top left to match dynamic tables
|
|
45110
|
+
if (tableZone.left === zone.left && tableZone.top === zone.top) {
|
|
45111
|
+
return table;
|
|
45112
|
+
}
|
|
45113
|
+
}
|
|
45114
|
+
return undefined;
|
|
45115
|
+
}
|
|
45055
45116
|
checkUpdatedTableZoneIsValid(cmd) {
|
|
45056
45117
|
if (!cmd.newTableRange) {
|
|
45057
45118
|
return "Success" /* CommandResult.Success */;
|
|
@@ -45061,7 +45122,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45061
45122
|
if (zoneIsInSheet !== "Success" /* CommandResult.Success */) {
|
|
45062
45123
|
return zoneIsInSheet;
|
|
45063
45124
|
}
|
|
45064
|
-
const
|
|
45125
|
+
const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
45126
|
+
if (!updatedTable) {
|
|
45127
|
+
return "TableNotFound" /* CommandResult.TableNotFound */;
|
|
45128
|
+
}
|
|
45129
|
+
const overlappingTables = this.getTablesOverlappingZones(cmd.sheetId, [newTableZone]).filter((table) => table.id !== updatedTable.id);
|
|
45065
45130
|
return overlappingTables.length ? "TableOverlap" /* CommandResult.TableOverlap */ : "Success" /* CommandResult.Success */;
|
|
45066
45131
|
}
|
|
45067
45132
|
checkTableConfigUpdateIsValid(config) {
|
|
@@ -45079,7 +45144,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45079
45144
|
}
|
|
45080
45145
|
return "Success" /* CommandResult.Success */;
|
|
45081
45146
|
}
|
|
45082
|
-
|
|
45147
|
+
createStaticTable(id, type, tableRange, config, filters) {
|
|
45083
45148
|
const zone = tableRange.zone;
|
|
45084
45149
|
if (!filters) {
|
|
45085
45150
|
filters = [];
|
|
@@ -45094,9 +45159,51 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45094
45159
|
range: tableRange,
|
|
45095
45160
|
filters,
|
|
45096
45161
|
config,
|
|
45162
|
+
type,
|
|
45163
|
+
};
|
|
45164
|
+
}
|
|
45165
|
+
createDynamicTable(id, tableRange, config) {
|
|
45166
|
+
const zone = zoneToTopLeft(tableRange.zone);
|
|
45167
|
+
return {
|
|
45168
|
+
id,
|
|
45169
|
+
range: this.getters.getRangeFromZone(tableRange.sheetId, zone),
|
|
45170
|
+
config,
|
|
45171
|
+
type: "dynamic",
|
|
45097
45172
|
};
|
|
45098
45173
|
}
|
|
45099
|
-
updateTable(
|
|
45174
|
+
updateTable(cmd) {
|
|
45175
|
+
const table = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
45176
|
+
if (!table) {
|
|
45177
|
+
return;
|
|
45178
|
+
}
|
|
45179
|
+
const newTableRange = cmd.newTableRange
|
|
45180
|
+
? this.getters.getRangeFromRangeData(cmd.newTableRange)
|
|
45181
|
+
: undefined;
|
|
45182
|
+
if (newTableRange) {
|
|
45183
|
+
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
|
|
45184
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
45185
|
+
}
|
|
45186
|
+
const range = newTableRange || table.range;
|
|
45187
|
+
const newConfig = this.updateTableConfig(cmd.config, table.config);
|
|
45188
|
+
const newTableType = cmd.tableType ?? table.type;
|
|
45189
|
+
if ((newTableType === "dynamic" && table.type !== "dynamic") ||
|
|
45190
|
+
(newTableType !== "dynamic" && table.type === "dynamic")) {
|
|
45191
|
+
const newTable = newTableType === "dynamic"
|
|
45192
|
+
? this.createDynamicTable(table.id, range, newConfig)
|
|
45193
|
+
: this.createStaticTable(table.id, newTableType, range, newConfig);
|
|
45194
|
+
this.history.update("tables", cmd.sheetId, table.id, newTable);
|
|
45195
|
+
}
|
|
45196
|
+
else {
|
|
45197
|
+
const updatedTable = table.type === "dynamic"
|
|
45198
|
+
? this.updateDynamicTable(table, range, newConfig)
|
|
45199
|
+
: this.updateStaticTable(table, range, newConfig, newTableType);
|
|
45200
|
+
this.history.update("tables", cmd.sheetId, table.id, updatedTable);
|
|
45201
|
+
}
|
|
45202
|
+
}
|
|
45203
|
+
updateStaticTable(table, newRange, configUpdate, newTableType = table.type) {
|
|
45204
|
+
if (newTableType === "dynamic") {
|
|
45205
|
+
throw new Error("Cannot use updateStaticTable to update a dynamic table");
|
|
45206
|
+
}
|
|
45100
45207
|
const tableRange = newRange ? newRange : table.range;
|
|
45101
45208
|
const tableZone = tableRange.zone;
|
|
45102
45209
|
const newConfig = this.updateTableConfig(configUpdate, table.config);
|
|
@@ -45117,8 +45224,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45117
45224
|
range: tableRange,
|
|
45118
45225
|
config,
|
|
45119
45226
|
filters: filters.length ? filters : table.filters,
|
|
45227
|
+
type: newTableType,
|
|
45120
45228
|
};
|
|
45121
45229
|
}
|
|
45230
|
+
updateDynamicTable(table, newRange, newConfig) {
|
|
45231
|
+
const range = newRange
|
|
45232
|
+
? this.getters.getRangeFromZone(newRange.sheetId, zoneToTopLeft(newRange.zone))
|
|
45233
|
+
: table.range;
|
|
45234
|
+
const config = newConfig ? newConfig : table.config;
|
|
45235
|
+
return { ...table, range, config };
|
|
45236
|
+
}
|
|
45122
45237
|
/**
|
|
45123
45238
|
* Update the old config of a table with the new partial config from an UpdateTable command.
|
|
45124
45239
|
*
|
|
@@ -45140,35 +45255,29 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45140
45255
|
}
|
|
45141
45256
|
createFilterFromZone(id, sheetId, zone, config) {
|
|
45142
45257
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
45143
|
-
return
|
|
45144
|
-
}
|
|
45145
|
-
createFilter(id, range, config) {
|
|
45146
|
-
const zone = range.zone;
|
|
45147
|
-
if (zone.left !== zone.right) {
|
|
45148
|
-
throw new Error("Can only define a filter on a single column");
|
|
45149
|
-
}
|
|
45150
|
-
const contentZone = getTableContentZone(zone, config);
|
|
45151
|
-
const filteredRange = contentZone
|
|
45152
|
-
? this.getters.getRangeFromZone(range.sheetId, contentZone)
|
|
45153
|
-
: undefined;
|
|
45154
|
-
return {
|
|
45155
|
-
id,
|
|
45156
|
-
rangeWithHeaders: range,
|
|
45157
|
-
col: zone.left,
|
|
45158
|
-
filteredRange,
|
|
45159
|
-
};
|
|
45258
|
+
return createFilter(id, range, config, this.getters.getRangeFromZone);
|
|
45160
45259
|
}
|
|
45161
|
-
|
|
45260
|
+
copyStaticTableForSheet(sheetId, table) {
|
|
45162
45261
|
const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
|
|
45163
45262
|
const newFilters = table.filters.map((filter) => {
|
|
45164
45263
|
const newFilterRange = this.getters.getRangeFromZone(sheetId, filter.rangeWithHeaders.zone);
|
|
45165
|
-
return
|
|
45264
|
+
return createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
|
|
45166
45265
|
});
|
|
45167
45266
|
return {
|
|
45168
45267
|
id: table.id,
|
|
45169
45268
|
range: newRange,
|
|
45170
45269
|
filters: newFilters,
|
|
45171
45270
|
config: deepCopy(table.config),
|
|
45271
|
+
type: table.type,
|
|
45272
|
+
};
|
|
45273
|
+
}
|
|
45274
|
+
copyDynamicTableForSheet(sheetId, table) {
|
|
45275
|
+
const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
|
|
45276
|
+
return {
|
|
45277
|
+
id: table.id,
|
|
45278
|
+
range: newRange,
|
|
45279
|
+
config: deepCopy(table.config),
|
|
45280
|
+
type: "dynamic",
|
|
45172
45281
|
};
|
|
45173
45282
|
}
|
|
45174
45283
|
applyRangeChangeOnTable(sheetId, table, applyChange) {
|
|
@@ -45183,6 +45292,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45183
45292
|
default:
|
|
45184
45293
|
newTableRange = tableRangeChange.range;
|
|
45185
45294
|
}
|
|
45295
|
+
if (table.type === "dynamic") {
|
|
45296
|
+
const newTable = this.updateDynamicTable(table, newTableRange);
|
|
45297
|
+
this.history.update("tables", sheetId, table.id, newTable);
|
|
45298
|
+
return;
|
|
45299
|
+
}
|
|
45186
45300
|
const filters = [];
|
|
45187
45301
|
for (const filter of table.filters) {
|
|
45188
45302
|
const filterRangeChange = applyChange(filter.rangeWithHeaders);
|
|
@@ -45194,7 +45308,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45194
45308
|
break;
|
|
45195
45309
|
default:
|
|
45196
45310
|
const newFilterRange = filterRangeChange.range;
|
|
45197
|
-
const newFilter =
|
|
45311
|
+
const newFilter = createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
|
|
45198
45312
|
filters.push(newFilter);
|
|
45199
45313
|
}
|
|
45200
45314
|
}
|
|
@@ -45209,7 +45323,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45209
45323
|
}
|
|
45210
45324
|
filters.sort((f1, f2) => f1.col - f2.col);
|
|
45211
45325
|
}
|
|
45212
|
-
const newTable = this.
|
|
45326
|
+
const newTable = this.createStaticTable(table.id, table.type, newTableRange, table.config, filters);
|
|
45213
45327
|
this.history.update("tables", sheetId, table.id, newTable);
|
|
45214
45328
|
}
|
|
45215
45329
|
// ---------------------------------------------------------------------------
|
|
@@ -45220,16 +45334,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
45220
45334
|
for (const tableData of sheet.tables || []) {
|
|
45221
45335
|
const uuid = this.uuidGenerator.uuidv4();
|
|
45222
45336
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
45223
|
-
const
|
|
45224
|
-
const
|
|
45337
|
+
const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
|
|
45338
|
+
const tableType = tableData.type || "static";
|
|
45339
|
+
const table = tableType === "dynamic"
|
|
45340
|
+
? this.createDynamicTable(uuid, range, tableConfig)
|
|
45341
|
+
: this.createStaticTable(uuid, tableType, range, tableConfig);
|
|
45225
45342
|
this.history.update("tables", sheet.id, table.id, table);
|
|
45226
45343
|
}
|
|
45227
45344
|
}
|
|
45228
45345
|
}
|
|
45229
45346
|
export(data) {
|
|
45230
45347
|
for (const sheet of data.sheets) {
|
|
45231
|
-
for (const table of this.
|
|
45232
|
-
const
|
|
45348
|
+
for (const table of this.getCoreTables(sheet.id)) {
|
|
45349
|
+
const range = zoneToXc(table.range.zone);
|
|
45350
|
+
const tableData = { range, type: table.type };
|
|
45233
45351
|
if (!deepEquals(table.config, DEFAULT_TABLE_CONFIG)) {
|
|
45234
45352
|
tableData.config = table.config;
|
|
45235
45353
|
}
|
|
@@ -46945,14 +47063,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46945
47063
|
if (!this.spreadingRelations.isArrayFormula(position)) {
|
|
46946
47064
|
return [];
|
|
46947
47065
|
}
|
|
46948
|
-
|
|
47066
|
+
if (this.evaluatedCells.get(position)?.type === CellValueType.error) {
|
|
47067
|
+
return [position];
|
|
47068
|
+
}
|
|
47069
|
+
const spreadPositions = Array.from(this.spreadingRelations.getArrayResultPositions(position));
|
|
47070
|
+
return [position, ...spreadPositions];
|
|
46949
47071
|
}
|
|
46950
47072
|
getEvaluatedPositions() {
|
|
46951
47073
|
return this.evaluatedCells.keys();
|
|
46952
47074
|
}
|
|
46953
47075
|
getArrayFormulaSpreadingOn(position) {
|
|
46954
47076
|
if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
|
|
46955
|
-
return undefined;
|
|
47077
|
+
return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
|
|
46956
47078
|
}
|
|
46957
47079
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
|
|
46958
47080
|
return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
|
|
@@ -47081,6 +47203,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47081
47203
|
if (!this.blockedArrayFormulas.has(position)) {
|
|
47082
47204
|
this.invalidateSpreading(position);
|
|
47083
47205
|
}
|
|
47206
|
+
this.spreadingRelations.removeNode(position);
|
|
47084
47207
|
const cell = this.getters.getCell(position);
|
|
47085
47208
|
if (cell === undefined) {
|
|
47086
47209
|
return EMPTY_CELL;
|
|
@@ -47191,7 +47314,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47191
47314
|
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
47192
47315
|
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
47193
47316
|
}
|
|
47194
|
-
this.spreadingRelations.removeNode(position);
|
|
47195
47317
|
}
|
|
47196
47318
|
// ----------------------------------------------------------
|
|
47197
47319
|
// COMMON FUNCTIONALITY
|
|
@@ -48289,6 +48411,181 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48289
48411
|
}
|
|
48290
48412
|
}
|
|
48291
48413
|
|
|
48414
|
+
class DynamicTablesPlugin extends UIPlugin {
|
|
48415
|
+
static getters = [
|
|
48416
|
+
"canCreateDynamicTableOnZones",
|
|
48417
|
+
"doesZonesContainFilter",
|
|
48418
|
+
"getFilter",
|
|
48419
|
+
"getFilters",
|
|
48420
|
+
"getTable",
|
|
48421
|
+
"getTables",
|
|
48422
|
+
"getTablesOverlappingZones",
|
|
48423
|
+
"getFilterId",
|
|
48424
|
+
"getFilterHeaders",
|
|
48425
|
+
"isFilterHeader",
|
|
48426
|
+
];
|
|
48427
|
+
tables = {};
|
|
48428
|
+
handle(cmd) {
|
|
48429
|
+
if (invalidateEvaluationCommands.has(cmd.type) ||
|
|
48430
|
+
(cmd.type === "UPDATE_CELL" && "content" in cmd) ||
|
|
48431
|
+
cmd.type === "EVALUATE_CELLS") {
|
|
48432
|
+
this.tables = {};
|
|
48433
|
+
return;
|
|
48434
|
+
}
|
|
48435
|
+
switch (cmd.type) {
|
|
48436
|
+
case "CREATE_TABLE":
|
|
48437
|
+
case "REMOVE_TABLE":
|
|
48438
|
+
case "UPDATE_TABLE":
|
|
48439
|
+
case "DELETE_CONTENT":
|
|
48440
|
+
this.tables = {};
|
|
48441
|
+
break;
|
|
48442
|
+
}
|
|
48443
|
+
}
|
|
48444
|
+
finalize() {
|
|
48445
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
48446
|
+
if (!this.tables[sheetId]) {
|
|
48447
|
+
this.tables[sheetId] = this.computeTables(sheetId);
|
|
48448
|
+
}
|
|
48449
|
+
}
|
|
48450
|
+
}
|
|
48451
|
+
computeTables(sheetId) {
|
|
48452
|
+
const tables = [];
|
|
48453
|
+
const coreTables = this.getters.getCoreTables(sheetId);
|
|
48454
|
+
// First we create the static tables, so we can use them to compute collision with dynamic tables
|
|
48455
|
+
for (const table of coreTables) {
|
|
48456
|
+
if (table.type === "dynamic")
|
|
48457
|
+
continue;
|
|
48458
|
+
tables.push(table);
|
|
48459
|
+
}
|
|
48460
|
+
const staticTables = [...tables];
|
|
48461
|
+
// Then we create the dynamic tables
|
|
48462
|
+
for (const coreTable of coreTables) {
|
|
48463
|
+
if (coreTable.type !== "dynamic")
|
|
48464
|
+
continue;
|
|
48465
|
+
const table = this.coreTableToTable(sheetId, coreTable);
|
|
48466
|
+
let tableZone = table.range.zone;
|
|
48467
|
+
// Reduce the zone to avoid collision with static tables. Per design, dynamic tables can't overlap with other
|
|
48468
|
+
// dynamic tables, because formulas cannot spread on the same area, so we don't need to check for that.
|
|
48469
|
+
for (const staticTable of staticTables) {
|
|
48470
|
+
if (overlap(tableZone, staticTable.range.zone)) {
|
|
48471
|
+
tableZone = { ...tableZone, right: staticTable.range.zone.left - 1 };
|
|
48472
|
+
}
|
|
48473
|
+
}
|
|
48474
|
+
tables.push({ ...table, range: this.getters.getRangeFromZone(sheetId, tableZone) });
|
|
48475
|
+
}
|
|
48476
|
+
return tables;
|
|
48477
|
+
}
|
|
48478
|
+
getFilters(sheetId) {
|
|
48479
|
+
return this.getTables(sheetId)
|
|
48480
|
+
.filter((table) => table.config.hasFilters)
|
|
48481
|
+
.map((table) => table.filters)
|
|
48482
|
+
.flat();
|
|
48483
|
+
}
|
|
48484
|
+
getTables(sheetId) {
|
|
48485
|
+
return this.tables[sheetId] || [];
|
|
48486
|
+
}
|
|
48487
|
+
getFilter(position) {
|
|
48488
|
+
const table = this.getTable(position);
|
|
48489
|
+
if (!table || !table.config.hasFilters) {
|
|
48490
|
+
return undefined;
|
|
48491
|
+
}
|
|
48492
|
+
return table.filters.find((filter) => filter.col === position.col);
|
|
48493
|
+
}
|
|
48494
|
+
getFilterId(position) {
|
|
48495
|
+
return this.getFilter(position)?.id;
|
|
48496
|
+
}
|
|
48497
|
+
getTable({ sheetId, col, row }) {
|
|
48498
|
+
return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
48499
|
+
}
|
|
48500
|
+
getTablesOverlappingZones(sheetId, zones) {
|
|
48501
|
+
return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
|
|
48502
|
+
}
|
|
48503
|
+
doesZonesContainFilter(sheetId, zones) {
|
|
48504
|
+
return this.getTablesOverlappingZones(sheetId, zones).some((table) => table.config.hasFilters);
|
|
48505
|
+
}
|
|
48506
|
+
getFilterHeaders(sheetId) {
|
|
48507
|
+
const headers = [];
|
|
48508
|
+
for (const table of this.getTables(sheetId)) {
|
|
48509
|
+
if (!table.config.hasFilters) {
|
|
48510
|
+
continue;
|
|
48511
|
+
}
|
|
48512
|
+
const zone = table.range.zone;
|
|
48513
|
+
const row = zone.top;
|
|
48514
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
48515
|
+
headers.push({ sheetId, col, row });
|
|
48516
|
+
}
|
|
48517
|
+
}
|
|
48518
|
+
return headers;
|
|
48519
|
+
}
|
|
48520
|
+
isFilterHeader({ sheetId, col, row }) {
|
|
48521
|
+
const headers = this.getFilterHeaders(sheetId);
|
|
48522
|
+
return headers.some((header) => header.col === col && header.row === row);
|
|
48523
|
+
}
|
|
48524
|
+
/**
|
|
48525
|
+
* Check if we can create a dynamic table on the given zones.
|
|
48526
|
+
* - The zones must be continuous
|
|
48527
|
+
* - The union of the zones must be either:
|
|
48528
|
+
* - A single cell that contains an array formula
|
|
48529
|
+
* - All the spread cells of a single array formula
|
|
48530
|
+
*/
|
|
48531
|
+
canCreateDynamicTableOnZones(sheetId, zones) {
|
|
48532
|
+
if (!areZonesContinuous(zones)) {
|
|
48533
|
+
return false;
|
|
48534
|
+
}
|
|
48535
|
+
const unionZone = union(...zones);
|
|
48536
|
+
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
48537
|
+
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
48538
|
+
if (!parentSpreadingCell) {
|
|
48539
|
+
return false;
|
|
48540
|
+
}
|
|
48541
|
+
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
48542
|
+
return true;
|
|
48543
|
+
}
|
|
48544
|
+
const spreadPositions = this.getters.getSpreadPositionsOf(parentSpreadingCell);
|
|
48545
|
+
return deepEquals(unionZone, unionPositionsToZone(spreadPositions));
|
|
48546
|
+
}
|
|
48547
|
+
coreTableToTable(sheetId, table) {
|
|
48548
|
+
if (table.type !== "dynamic") {
|
|
48549
|
+
return table;
|
|
48550
|
+
}
|
|
48551
|
+
const tableZone = table.range.zone;
|
|
48552
|
+
const tablePosition = { sheetId, col: tableZone.left, row: tableZone.top };
|
|
48553
|
+
const spreadPositions = this.getters.getSpreadPositionsOf(tablePosition);
|
|
48554
|
+
const zone = spreadPositions.length ? unionPositionsToZone(spreadPositions) : table.range.zone;
|
|
48555
|
+
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
48556
|
+
const filters = this.getDynamicTableFilters(sheetId, table, zone);
|
|
48557
|
+
return { id: table.id, range, filters, config: table.config };
|
|
48558
|
+
}
|
|
48559
|
+
getDynamicTableFilters(sheetId, table, tableZone) {
|
|
48560
|
+
const filters = [];
|
|
48561
|
+
const { top, bottom, left, right } = tableZone;
|
|
48562
|
+
for (let col = left; col <= right; col++) {
|
|
48563
|
+
const tableColIndex = col - left;
|
|
48564
|
+
const zone = { left: col, right: col, top, bottom };
|
|
48565
|
+
const filter = createFilter(this.getDynamicTableFilterId(table.id, tableColIndex), this.getters.getRangeFromZone(sheetId, zone), table.config, this.getters.getRangeFromZone);
|
|
48566
|
+
filters.push(filter);
|
|
48567
|
+
}
|
|
48568
|
+
return filters;
|
|
48569
|
+
}
|
|
48570
|
+
getDynamicTableFilterId(tableId, tableCol) {
|
|
48571
|
+
return tableId + "_" + tableCol;
|
|
48572
|
+
}
|
|
48573
|
+
exportForExcel(data) {
|
|
48574
|
+
for (const sheet of data.sheets) {
|
|
48575
|
+
for (const tableData of sheet.tables) {
|
|
48576
|
+
const zone = toZone(tableData.range);
|
|
48577
|
+
const topLeft = { sheetId: sheet.id, col: zone.left, row: zone.top };
|
|
48578
|
+
const coreTable = this.getters.getCoreTable(topLeft);
|
|
48579
|
+
const table = this.getTable(topLeft);
|
|
48580
|
+
if (coreTable?.type !== "dynamic" || !table) {
|
|
48581
|
+
continue;
|
|
48582
|
+
}
|
|
48583
|
+
tableData.range = zoneToXc(table.range.zone);
|
|
48584
|
+
}
|
|
48585
|
+
}
|
|
48586
|
+
}
|
|
48587
|
+
}
|
|
48588
|
+
|
|
48292
48589
|
class HeaderSizeUIPlugin extends UIPlugin {
|
|
48293
48590
|
static getters = ["getRowSize", "getHeaderSize"];
|
|
48294
48591
|
tallestCellInRow = {};
|
|
@@ -51336,10 +51633,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51336
51633
|
handle(cmd) {
|
|
51337
51634
|
switch (cmd.type) {
|
|
51338
51635
|
case "AUTOFILL_TABLE_COLUMN":
|
|
51339
|
-
const table = this.getters.
|
|
51636
|
+
const table = this.getters.getCoreTable(cmd);
|
|
51340
51637
|
const cell = this.getters.getCell(cmd);
|
|
51341
|
-
if (!table ||
|
|
51638
|
+
if (!table?.config.automaticAutofill || table.type === "dynamic" || !cell?.isFormula) {
|
|
51342
51639
|
return;
|
|
51640
|
+
}
|
|
51343
51641
|
const { col, row } = cmd;
|
|
51344
51642
|
const tableContentZone = getTableContentZone(table.range.zone, table.config);
|
|
51345
51643
|
if (tableContentZone && isInside(col, row, tableContentZone)) {
|
|
@@ -52068,9 +52366,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52068
52366
|
case "START":
|
|
52069
52367
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
52070
52368
|
this.filterValues[sheetId] = {};
|
|
52071
|
-
for (const filter of this.getters.getFilters(sheetId)) {
|
|
52072
|
-
this.filterValues[sheetId][filter.id] = [];
|
|
52073
|
-
}
|
|
52074
52369
|
}
|
|
52075
52370
|
break;
|
|
52076
52371
|
case "CREATE_SHEET":
|
|
@@ -52091,16 +52386,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52091
52386
|
this.updateHiddenRows();
|
|
52092
52387
|
break;
|
|
52093
52388
|
case "DUPLICATE_SHEET":
|
|
52094
|
-
|
|
52095
|
-
for (const newFilter of this.getters.getFilters(cmd.sheetIdTo)) {
|
|
52096
|
-
const zone = newFilter.rangeWithHeaders.zone;
|
|
52097
|
-
filterValues[newFilter.id] = this.getFilterHiddenValues({
|
|
52098
|
-
sheetId: cmd.sheetId,
|
|
52099
|
-
col: zone.left,
|
|
52100
|
-
row: zone.top,
|
|
52101
|
-
});
|
|
52102
|
-
}
|
|
52103
|
-
this.filterValues[cmd.sheetIdTo] = filterValues;
|
|
52389
|
+
this.filterValues[cmd.sheetIdTo] = deepCopy(this.filterValues[cmd.sheetId]);
|
|
52104
52390
|
break;
|
|
52105
52391
|
// If we don't handle DELETE_SHEET, on one hand we will have some residual data, on the other hand we keep the data
|
|
52106
52392
|
// on DELETE_SHEET followed by undo
|
|
@@ -54044,8 +54330,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54044
54330
|
.add("evaluation_chart", EvaluationChartPlugin)
|
|
54045
54331
|
.add("evaluation_cf", EvaluationConditionalFormatPlugin)
|
|
54046
54332
|
.add("row_size", HeaderSizeUIPlugin)
|
|
54047
|
-
.add("
|
|
54048
|
-
.add("
|
|
54333
|
+
.add("data_validation_ui", EvaluationDataValidationPlugin)
|
|
54334
|
+
.add("dynamic_tables", DynamicTablesPlugin)
|
|
54335
|
+
.add("custom_colors", CustomColorsPlugin);
|
|
54049
54336
|
|
|
54050
54337
|
const clickableCellRegistry = new Registry();
|
|
54051
54338
|
clickableCellRegistry.add("link", {
|
|
@@ -60176,9 +60463,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60176
60463
|
exports.tokenize = tokenize;
|
|
60177
60464
|
|
|
60178
60465
|
|
|
60179
|
-
__info__.version = "17.
|
|
60180
|
-
__info__.date = "2024-03-25T09:
|
|
60181
|
-
__info__.hash = "
|
|
60466
|
+
__info__.version = "17.3.0-alpha.1";
|
|
60467
|
+
__info__.date = "2024-03-25T09:43:36.072Z";
|
|
60468
|
+
__info__.hash = "4095c41";
|
|
60182
60469
|
|
|
60183
60470
|
|
|
60184
60471
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|