@odoo/o-spreadsheet 16.4.0-alpha.4 → 16.4.0-alpha.5

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.
@@ -751,12 +751,20 @@
751
751
  return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
752
752
  }
753
753
  function computeTextWidth(context, text, style) {
754
- context.save();
755
- context.font = computeTextFont(style);
756
- const textWidth = context.measureText(text).width;
757
- context.restore();
758
- return textWidth;
754
+ const font = computeTextFont(style);
755
+ if (!textWidthCache[font]) {
756
+ textWidthCache[font] = {};
757
+ }
758
+ if (textWidthCache[font][text] === undefined) {
759
+ context.save();
760
+ context.font = font;
761
+ const textWidth = context.measureText(text).width;
762
+ context.restore();
763
+ textWidthCache[font][text] = textWidth;
764
+ }
765
+ return textWidthCache[font][text];
759
766
  }
767
+ const textWidthCache = {};
760
768
  function fontSizeInPixels(fontSize) {
761
769
  return Math.round((fontSize * 96) / 72);
762
770
  }
@@ -1064,10 +1072,17 @@
1064
1072
  function toLowerCase(str) {
1065
1073
  return str ? str.toLowerCase() : "";
1066
1074
  }
1067
- function transpose2dArray(matrix) {
1075
+ function transpose2dArray(matrix, callback = (val) => val) {
1068
1076
  if (!matrix.length)
1069
- return matrix;
1070
- return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1077
+ return [];
1078
+ const transposed = Array(matrix[0].length);
1079
+ for (let i = 0; i < matrix[0].length; i++) {
1080
+ transposed[i] = Array(matrix.length);
1081
+ for (let j = 0; j < matrix.length; j++) {
1082
+ transposed[i][j] = callback(matrix[j][i]);
1083
+ }
1084
+ }
1085
+ return transposed;
1071
1086
  }
1072
1087
  /**
1073
1088
  * Equivalent to "\s" in regexp, minus the new lines characters
@@ -3705,6 +3720,290 @@
3705
3720
  return undefined;
3706
3721
  }
3707
3722
 
3723
+ var CellValueType;
3724
+ (function (CellValueType) {
3725
+ CellValueType["boolean"] = "boolean";
3726
+ CellValueType["number"] = "number";
3727
+ CellValueType["text"] = "text";
3728
+ CellValueType["empty"] = "empty";
3729
+ CellValueType["error"] = "error";
3730
+ })(CellValueType || (CellValueType = {}));
3731
+
3732
+ var ClipboardMIMEType;
3733
+ (function (ClipboardMIMEType) {
3734
+ ClipboardMIMEType["PlainText"] = "text/plain";
3735
+ ClipboardMIMEType["Html"] = "text/html";
3736
+ })(ClipboardMIMEType || (ClipboardMIMEType = {}));
3737
+
3738
+ function isSheetDependent(cmd) {
3739
+ return "sheetId" in cmd;
3740
+ }
3741
+ function isGridDependent(cmd) {
3742
+ return "dimension" in cmd && "sheetId" in cmd;
3743
+ }
3744
+ function isTargetDependent(cmd) {
3745
+ return "target" in cmd && "sheetId" in cmd;
3746
+ }
3747
+ function isRangeDependant(cmd) {
3748
+ return "ranges" in cmd;
3749
+ }
3750
+ function isPositionDependent(cmd) {
3751
+ return "col" in cmd && "row" in cmd && "sheetId" in cmd;
3752
+ }
3753
+ const invalidateEvaluationCommands = new Set([
3754
+ "RENAME_SHEET",
3755
+ "DELETE_SHEET",
3756
+ "CREATE_SHEET",
3757
+ "ADD_COLUMNS_ROWS",
3758
+ "REMOVE_COLUMNS_ROWS",
3759
+ "UNDO",
3760
+ "REDO",
3761
+ "ADD_MERGE",
3762
+ ]);
3763
+ const invalidateDependenciesCommands = new Set([
3764
+ ...invalidateEvaluationCommands,
3765
+ "MOVE_RANGES",
3766
+ ]);
3767
+ const invalidateCFEvaluationCommands = new Set([
3768
+ ...invalidateEvaluationCommands,
3769
+ "DUPLICATE_SHEET",
3770
+ "EVALUATE_CELLS",
3771
+ "ADD_CONDITIONAL_FORMAT",
3772
+ "REMOVE_CONDITIONAL_FORMAT",
3773
+ "MOVE_CONDITIONAL_FORMAT",
3774
+ ]);
3775
+ const readonlyAllowedCommands = new Set([
3776
+ "START",
3777
+ "ACTIVATE_SHEET",
3778
+ "COPY",
3779
+ "PREPARE_SELECTION_INPUT_EXPANSION",
3780
+ "STOP_SELECTION_INPUT",
3781
+ "RESIZE_SHEETVIEW",
3782
+ "SET_VIEWPORT_OFFSET",
3783
+ "SELECT_SEARCH_NEXT_MATCH",
3784
+ "SELECT_SEARCH_PREVIOUS_MATCH",
3785
+ "REFRESH_SEARCH",
3786
+ "UPDATE_SEARCH",
3787
+ "CLEAR_SEARCH",
3788
+ "EVALUATE_CELLS",
3789
+ "SET_CURRENT_CONTENT",
3790
+ "SET_FORMULA_VISIBILITY",
3791
+ "OPEN_CELL_POPOVER",
3792
+ "CLOSE_CELL_POPOVER",
3793
+ "UPDATE_FILTER",
3794
+ ]);
3795
+ const coreTypes = new Set([
3796
+ /** CELLS */
3797
+ "UPDATE_CELL",
3798
+ "UPDATE_CELL_POSITION",
3799
+ "CLEAR_CELL",
3800
+ "DELETE_CONTENT",
3801
+ /** GRID SHAPE */
3802
+ "ADD_COLUMNS_ROWS",
3803
+ "REMOVE_COLUMNS_ROWS",
3804
+ "RESIZE_COLUMNS_ROWS",
3805
+ "HIDE_COLUMNS_ROWS",
3806
+ "UNHIDE_COLUMNS_ROWS",
3807
+ "SET_GRID_LINES_VISIBILITY",
3808
+ "UNFREEZE_COLUMNS",
3809
+ "UNFREEZE_ROWS",
3810
+ "FREEZE_COLUMNS",
3811
+ "FREEZE_ROWS",
3812
+ "UNFREEZE_COLUMNS_ROWS",
3813
+ /** MERGE */
3814
+ "ADD_MERGE",
3815
+ "REMOVE_MERGE",
3816
+ /** SHEETS MANIPULATION */
3817
+ "CREATE_SHEET",
3818
+ "DELETE_SHEET",
3819
+ "DUPLICATE_SHEET",
3820
+ "MOVE_SHEET",
3821
+ "RENAME_SHEET",
3822
+ "HIDE_SHEET",
3823
+ "SHOW_SHEET",
3824
+ /** RANGES MANIPULATION */
3825
+ "MOVE_RANGES",
3826
+ /** CONDITIONAL FORMAT */
3827
+ "ADD_CONDITIONAL_FORMAT",
3828
+ "REMOVE_CONDITIONAL_FORMAT",
3829
+ "MOVE_CONDITIONAL_FORMAT",
3830
+ /** FIGURES */
3831
+ "CREATE_FIGURE",
3832
+ "DELETE_FIGURE",
3833
+ "UPDATE_FIGURE",
3834
+ /** FORMATTING */
3835
+ "SET_FORMATTING",
3836
+ "CLEAR_FORMATTING",
3837
+ "SET_BORDER",
3838
+ "SET_ZONE_BORDERS",
3839
+ /** CHART */
3840
+ "CREATE_CHART",
3841
+ "UPDATE_CHART",
3842
+ /** FILTERS */
3843
+ "CREATE_FILTER_TABLE",
3844
+ "REMOVE_FILTER_TABLE",
3845
+ /** IMAGE */
3846
+ "CREATE_IMAGE",
3847
+ ]);
3848
+ function isCoreCommand(cmd) {
3849
+ return coreTypes.has(cmd.type);
3850
+ }
3851
+ function canExecuteInReadonly(cmd) {
3852
+ return readonlyAllowedCommands.has(cmd.type);
3853
+ }
3854
+ /**
3855
+ * Holds the result of a command dispatch.
3856
+ * The command may have been successfully dispatched or cancelled
3857
+ * for one or more reasons.
3858
+ */
3859
+ class DispatchResult {
3860
+ reasons;
3861
+ constructor(results = []) {
3862
+ if (!Array.isArray(results)) {
3863
+ results = [results];
3864
+ }
3865
+ results = [...new Set(results)];
3866
+ this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
3867
+ }
3868
+ /**
3869
+ * Static helper which returns a successful DispatchResult
3870
+ */
3871
+ static get Success() {
3872
+ return new DispatchResult();
3873
+ }
3874
+ get isSuccessful() {
3875
+ return this.reasons.length === 0;
3876
+ }
3877
+ /**
3878
+ * Check if the dispatch has been cancelled because of
3879
+ * the given reason.
3880
+ */
3881
+ isCancelledBecause(reason) {
3882
+ return this.reasons.includes(reason);
3883
+ }
3884
+ }
3885
+ exports.CommandResult = void 0;
3886
+ (function (CommandResult) {
3887
+ CommandResult[CommandResult["Success"] = 0] = "Success";
3888
+ CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
3889
+ CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
3890
+ CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
3891
+ CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
3892
+ CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
3893
+ CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
3894
+ CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
3895
+ CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
3896
+ CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
3897
+ CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
3898
+ CommandResult[CommandResult["UnchangedSheetName"] = 11] = "UnchangedSheetName";
3899
+ CommandResult[CommandResult["DuplicatedSheetName"] = 12] = "DuplicatedSheetName";
3900
+ CommandResult[CommandResult["DuplicatedSheetId"] = 13] = "DuplicatedSheetId";
3901
+ CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 14] = "ForbiddenCharactersInSheetName";
3902
+ CommandResult[CommandResult["WrongSheetMove"] = 15] = "WrongSheetMove";
3903
+ CommandResult[CommandResult["WrongSheetPosition"] = 16] = "WrongSheetPosition";
3904
+ CommandResult[CommandResult["InvalidAnchorZone"] = 17] = "InvalidAnchorZone";
3905
+ CommandResult[CommandResult["SelectionOutOfBound"] = 18] = "SelectionOutOfBound";
3906
+ CommandResult[CommandResult["TargetOutOfSheet"] = 19] = "TargetOutOfSheet";
3907
+ CommandResult[CommandResult["WrongCutSelection"] = 20] = "WrongCutSelection";
3908
+ CommandResult[CommandResult["WrongPasteSelection"] = 21] = "WrongPasteSelection";
3909
+ CommandResult[CommandResult["WrongPasteOption"] = 22] = "WrongPasteOption";
3910
+ CommandResult[CommandResult["WrongFigurePasteOption"] = 23] = "WrongFigurePasteOption";
3911
+ CommandResult[CommandResult["EmptyClipboard"] = 24] = "EmptyClipboard";
3912
+ CommandResult[CommandResult["EmptyRange"] = 25] = "EmptyRange";
3913
+ CommandResult[CommandResult["InvalidRange"] = 26] = "InvalidRange";
3914
+ CommandResult[CommandResult["InvalidZones"] = 27] = "InvalidZones";
3915
+ CommandResult[CommandResult["InvalidSheetId"] = 28] = "InvalidSheetId";
3916
+ CommandResult[CommandResult["InvalidFigureId"] = 29] = "InvalidFigureId";
3917
+ CommandResult[CommandResult["InputAlreadyFocused"] = 30] = "InputAlreadyFocused";
3918
+ CommandResult[CommandResult["MaximumRangesReached"] = 31] = "MaximumRangesReached";
3919
+ CommandResult[CommandResult["InvalidChartDefinition"] = 32] = "InvalidChartDefinition";
3920
+ CommandResult[CommandResult["InvalidDataSet"] = 33] = "InvalidDataSet";
3921
+ CommandResult[CommandResult["InvalidLabelRange"] = 34] = "InvalidLabelRange";
3922
+ CommandResult[CommandResult["InvalidScorecardKeyValue"] = 35] = "InvalidScorecardKeyValue";
3923
+ CommandResult[CommandResult["InvalidScorecardBaseline"] = 36] = "InvalidScorecardBaseline";
3924
+ CommandResult[CommandResult["InvalidGaugeDataRange"] = 37] = "InvalidGaugeDataRange";
3925
+ CommandResult[CommandResult["EmptyGaugeRangeMin"] = 38] = "EmptyGaugeRangeMin";
3926
+ CommandResult[CommandResult["GaugeRangeMinNaN"] = 39] = "GaugeRangeMinNaN";
3927
+ CommandResult[CommandResult["EmptyGaugeRangeMax"] = 40] = "EmptyGaugeRangeMax";
3928
+ CommandResult[CommandResult["GaugeRangeMaxNaN"] = 41] = "GaugeRangeMaxNaN";
3929
+ CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 42] = "GaugeRangeMinBiggerThanRangeMax";
3930
+ CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 43] = "GaugeLowerInflectionPointNaN";
3931
+ CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 44] = "GaugeUpperInflectionPointNaN";
3932
+ CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 45] = "GaugeLowerBiggerThanUpper";
3933
+ CommandResult[CommandResult["InvalidAutofillSelection"] = 46] = "InvalidAutofillSelection";
3934
+ CommandResult[CommandResult["WrongComposerSelection"] = 47] = "WrongComposerSelection";
3935
+ CommandResult[CommandResult["MinBiggerThanMax"] = 48] = "MinBiggerThanMax";
3936
+ CommandResult[CommandResult["LowerBiggerThanUpper"] = 49] = "LowerBiggerThanUpper";
3937
+ CommandResult[CommandResult["MidBiggerThanMax"] = 50] = "MidBiggerThanMax";
3938
+ CommandResult[CommandResult["MinBiggerThanMid"] = 51] = "MinBiggerThanMid";
3939
+ CommandResult[CommandResult["FirstArgMissing"] = 52] = "FirstArgMissing";
3940
+ CommandResult[CommandResult["SecondArgMissing"] = 53] = "SecondArgMissing";
3941
+ CommandResult[CommandResult["MinNaN"] = 54] = "MinNaN";
3942
+ CommandResult[CommandResult["MidNaN"] = 55] = "MidNaN";
3943
+ CommandResult[CommandResult["MaxNaN"] = 56] = "MaxNaN";
3944
+ CommandResult[CommandResult["ValueUpperInflectionNaN"] = 57] = "ValueUpperInflectionNaN";
3945
+ CommandResult[CommandResult["ValueLowerInflectionNaN"] = 58] = "ValueLowerInflectionNaN";
3946
+ CommandResult[CommandResult["MinInvalidFormula"] = 59] = "MinInvalidFormula";
3947
+ CommandResult[CommandResult["MidInvalidFormula"] = 60] = "MidInvalidFormula";
3948
+ CommandResult[CommandResult["MaxInvalidFormula"] = 61] = "MaxInvalidFormula";
3949
+ CommandResult[CommandResult["ValueUpperInvalidFormula"] = 62] = "ValueUpperInvalidFormula";
3950
+ CommandResult[CommandResult["ValueLowerInvalidFormula"] = 63] = "ValueLowerInvalidFormula";
3951
+ CommandResult[CommandResult["InvalidSortZone"] = 64] = "InvalidSortZone";
3952
+ CommandResult[CommandResult["WaitingSessionConfirmation"] = 65] = "WaitingSessionConfirmation";
3953
+ CommandResult[CommandResult["MergeOverlap"] = 66] = "MergeOverlap";
3954
+ CommandResult[CommandResult["TooManyHiddenElements"] = 67] = "TooManyHiddenElements";
3955
+ CommandResult[CommandResult["Readonly"] = 68] = "Readonly";
3956
+ CommandResult[CommandResult["InvalidViewportSize"] = 69] = "InvalidViewportSize";
3957
+ CommandResult[CommandResult["InvalidScrollingDirection"] = 70] = "InvalidScrollingDirection";
3958
+ CommandResult[CommandResult["FigureDoesNotExist"] = 71] = "FigureDoesNotExist";
3959
+ CommandResult[CommandResult["InvalidConditionalFormatId"] = 72] = "InvalidConditionalFormatId";
3960
+ CommandResult[CommandResult["InvalidCellPopover"] = 73] = "InvalidCellPopover";
3961
+ CommandResult[CommandResult["EmptyTarget"] = 74] = "EmptyTarget";
3962
+ CommandResult[CommandResult["InvalidFreezeQuantity"] = 75] = "InvalidFreezeQuantity";
3963
+ CommandResult[CommandResult["FrozenPaneOverlap"] = 76] = "FrozenPaneOverlap";
3964
+ CommandResult[CommandResult["ValuesNotChanged"] = 77] = "ValuesNotChanged";
3965
+ CommandResult[CommandResult["InvalidFilterZone"] = 78] = "InvalidFilterZone";
3966
+ CommandResult[CommandResult["FilterOverlap"] = 79] = "FilterOverlap";
3967
+ CommandResult[CommandResult["FilterNotFound"] = 80] = "FilterNotFound";
3968
+ CommandResult[CommandResult["MergeInFilter"] = 81] = "MergeInFilter";
3969
+ CommandResult[CommandResult["NonContinuousTargets"] = 82] = "NonContinuousTargets";
3970
+ CommandResult[CommandResult["DuplicatedFigureId"] = 83] = "DuplicatedFigureId";
3971
+ CommandResult[CommandResult["InvalidSelectionStep"] = 84] = "InvalidSelectionStep";
3972
+ CommandResult[CommandResult["DuplicatedChartId"] = 85] = "DuplicatedChartId";
3973
+ CommandResult[CommandResult["ChartDoesNotExist"] = 86] = "ChartDoesNotExist";
3974
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 87] = "InvalidHeaderIndex";
3975
+ CommandResult[CommandResult["InvalidQuantity"] = 88] = "InvalidQuantity";
3976
+ CommandResult[CommandResult["MoreThanOneColumnSelected"] = 89] = "MoreThanOneColumnSelected";
3977
+ CommandResult[CommandResult["EmptySplitSeparator"] = 90] = "EmptySplitSeparator";
3978
+ CommandResult[CommandResult["SplitWillOverwriteContent"] = 91] = "SplitWillOverwriteContent";
3979
+ CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 92] = "NoSplitSeparatorInSelection";
3980
+ CommandResult[CommandResult["NoActiveSheet"] = 93] = "NoActiveSheet";
3981
+ })(exports.CommandResult || (exports.CommandResult = {}));
3982
+
3983
+ const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
3984
+ function isMatrix(x) {
3985
+ return Array.isArray(x) && Array.isArray(x[0]);
3986
+ }
3987
+ var DIRECTION;
3988
+ (function (DIRECTION) {
3989
+ DIRECTION["UP"] = "up";
3990
+ DIRECTION["DOWN"] = "down";
3991
+ DIRECTION["LEFT"] = "left";
3992
+ DIRECTION["RIGHT"] = "right";
3993
+ })(DIRECTION || (DIRECTION = {}));
3994
+
3995
+ var LAYERS;
3996
+ (function (LAYERS) {
3997
+ LAYERS[LAYERS["Background"] = 0] = "Background";
3998
+ LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
3999
+ LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
4000
+ LAYERS[LAYERS["Search"] = 3] = "Search";
4001
+ LAYERS[LAYERS["Chart"] = 4] = "Chart";
4002
+ LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4003
+ LAYERS[LAYERS["Selection"] = 6] = "Selection";
4004
+ LAYERS[LAYERS["Headers"] = 7] = "Headers";
4005
+ })(LAYERS || (LAYERS = {}));
4006
+
3708
4007
  // HELPERS
3709
4008
  const SORT_TYPES_ORDER = ["number", "string", "boolean", "undefined"];
3710
4009
  function assert(condition, message) {
@@ -3746,6 +4045,9 @@
3746
4045
  }
3747
4046
  return toNumber(value);
3748
4047
  }
4048
+ function toInteger(value) {
4049
+ return Math.trunc(toNumber(value));
4050
+ }
3749
4051
  function strictToInteger(value) {
3750
4052
  return Math.trunc(strictToNumber(value));
3751
4053
  }
@@ -3848,16 +4150,25 @@
3848
4150
  // -----------------------------------------------------------------------------
3849
4151
  // REDUCE FUNCTIONS
3850
4152
  // -----------------------------------------------------------------------------
3851
- function reduceArgs(args, cellCb, dataCb, initialValue) {
4153
+ function reduceArgs(args, cellCb, dataCb, initialValue, dir = "rowFirst") {
3852
4154
  let val = initialValue;
3853
4155
  for (let arg of args) {
3854
4156
  if (Array.isArray(arg)) {
3855
4157
  // arg is ref to a Cell/Range
3856
- const lenRow = arg.length;
3857
- const lenCol = arg[0].length;
3858
- for (let y = 0; y < lenCol; y++) {
3859
- for (let x = 0; x < lenRow; x++) {
3860
- val = cellCb(val, arg[x][y]);
4158
+ const numberOfCols = arg.length;
4159
+ const numberOfRows = arg[0].length;
4160
+ if (dir === "rowFirst") {
4161
+ for (let row = 0; row < numberOfRows; row++) {
4162
+ for (let col = 0; col < numberOfCols; col++) {
4163
+ val = cellCb(val, arg[col][row]);
4164
+ }
4165
+ }
4166
+ }
4167
+ else {
4168
+ for (let col = 0; col < numberOfCols; col++) {
4169
+ for (let row = 0; row < numberOfRows; row++) {
4170
+ val = cellCb(val, arg[col][row]);
4171
+ }
3861
4172
  }
3862
4173
  }
3863
4174
  }
@@ -3868,8 +4179,8 @@
3868
4179
  }
3869
4180
  return val;
3870
4181
  }
3871
- function reduceAny(args, cb, initialValue) {
3872
- return reduceArgs(args, cb, cb, initialValue);
4182
+ function reduceAny(args, cb, initialValue, dir = "rowFirst") {
4183
+ return reduceArgs(args, cb, cb, initialValue, dir);
3873
4184
  }
3874
4185
  function reduceNumbers(args, cb, initialValue) {
3875
4186
  return reduceArgs(args, (acc, ArgValue) => {
@@ -4246,290 +4557,57 @@
4246
4557
  }
4247
4558
  }
4248
4559
  return typeOrder;
4249
- }
4250
-
4251
- var CellValueType;
4252
- (function (CellValueType) {
4253
- CellValueType["boolean"] = "boolean";
4254
- CellValueType["number"] = "number";
4255
- CellValueType["text"] = "text";
4256
- CellValueType["empty"] = "empty";
4257
- CellValueType["error"] = "error";
4258
- })(CellValueType || (CellValueType = {}));
4259
-
4260
- var ClipboardMIMEType;
4261
- (function (ClipboardMIMEType) {
4262
- ClipboardMIMEType["PlainText"] = "text/plain";
4263
- ClipboardMIMEType["Html"] = "text/html";
4264
- })(ClipboardMIMEType || (ClipboardMIMEType = {}));
4265
-
4266
- function isSheetDependent(cmd) {
4267
- return "sheetId" in cmd;
4268
- }
4269
- function isGridDependent(cmd) {
4270
- return "dimension" in cmd && "sheetId" in cmd;
4271
4560
  }
4272
- function isTargetDependent(cmd) {
4273
- return "target" in cmd && "sheetId" in cmd;
4274
- }
4275
- function isRangeDependant(cmd) {
4276
- return "ranges" in cmd;
4561
+ function matrixMap(matrix, fn) {
4562
+ let result = new Array(matrix.length);
4563
+ for (let i = 0; i < matrix.length; i++) {
4564
+ result[i] = new Array(matrix[i].length);
4565
+ for (let j = 0; j < matrix[i].length; j++) {
4566
+ result[i][j] = fn(matrix[i][j]);
4567
+ }
4568
+ }
4569
+ return result;
4277
4570
  }
4278
- function isPositionDependent(cmd) {
4279
- return "col" in cmd && "row" in cmd && "sheetId" in cmd;
4571
+ function toCellValueMatrix(values) {
4572
+ return matrixMap(values, toCellValue);
4280
4573
  }
4281
- const invalidateEvaluationCommands = new Set([
4282
- "RENAME_SHEET",
4283
- "DELETE_SHEET",
4284
- "CREATE_SHEET",
4285
- "ADD_COLUMNS_ROWS",
4286
- "REMOVE_COLUMNS_ROWS",
4287
- "UNDO",
4288
- "REDO",
4289
- "ADD_MERGE",
4290
- ]);
4291
- const invalidateDependenciesCommands = new Set([
4292
- ...invalidateEvaluationCommands,
4293
- "MOVE_RANGES",
4294
- ]);
4295
- const invalidateCFEvaluationCommands = new Set([
4296
- ...invalidateEvaluationCommands,
4297
- "DUPLICATE_SHEET",
4298
- "EVALUATE_CELLS",
4299
- "ADD_CONDITIONAL_FORMAT",
4300
- "REMOVE_CONDITIONAL_FORMAT",
4301
- "MOVE_CONDITIONAL_FORMAT",
4302
- ]);
4303
- const readonlyAllowedCommands = new Set([
4304
- "START",
4305
- "ACTIVATE_SHEET",
4306
- "COPY",
4307
- "PREPARE_SELECTION_INPUT_EXPANSION",
4308
- "STOP_SELECTION_INPUT",
4309
- "RESIZE_SHEETVIEW",
4310
- "SET_VIEWPORT_OFFSET",
4311
- "SELECT_SEARCH_NEXT_MATCH",
4312
- "SELECT_SEARCH_PREVIOUS_MATCH",
4313
- "REFRESH_SEARCH",
4314
- "UPDATE_SEARCH",
4315
- "CLEAR_SEARCH",
4316
- "EVALUATE_CELLS",
4317
- "SET_CURRENT_CONTENT",
4318
- "SET_FORMULA_VISIBILITY",
4319
- "OPEN_CELL_POPOVER",
4320
- "CLOSE_CELL_POPOVER",
4321
- "UPDATE_FILTER",
4322
- ]);
4323
- const coreTypes = new Set([
4324
- /** CELLS */
4325
- "UPDATE_CELL",
4326
- "UPDATE_CELL_POSITION",
4327
- "CLEAR_CELL",
4328
- "DELETE_CONTENT",
4329
- /** GRID SHAPE */
4330
- "ADD_COLUMNS_ROWS",
4331
- "REMOVE_COLUMNS_ROWS",
4332
- "RESIZE_COLUMNS_ROWS",
4333
- "HIDE_COLUMNS_ROWS",
4334
- "UNHIDE_COLUMNS_ROWS",
4335
- "SET_GRID_LINES_VISIBILITY",
4336
- "UNFREEZE_COLUMNS",
4337
- "UNFREEZE_ROWS",
4338
- "FREEZE_COLUMNS",
4339
- "FREEZE_ROWS",
4340
- "UNFREEZE_COLUMNS_ROWS",
4341
- /** MERGE */
4342
- "ADD_MERGE",
4343
- "REMOVE_MERGE",
4344
- /** SHEETS MANIPULATION */
4345
- "CREATE_SHEET",
4346
- "DELETE_SHEET",
4347
- "DUPLICATE_SHEET",
4348
- "MOVE_SHEET",
4349
- "RENAME_SHEET",
4350
- "HIDE_SHEET",
4351
- "SHOW_SHEET",
4352
- /** RANGES MANIPULATION */
4353
- "MOVE_RANGES",
4354
- /** CONDITIONAL FORMAT */
4355
- "ADD_CONDITIONAL_FORMAT",
4356
- "REMOVE_CONDITIONAL_FORMAT",
4357
- "MOVE_CONDITIONAL_FORMAT",
4358
- /** FIGURES */
4359
- "CREATE_FIGURE",
4360
- "DELETE_FIGURE",
4361
- "UPDATE_FIGURE",
4362
- /** FORMATTING */
4363
- "SET_FORMATTING",
4364
- "CLEAR_FORMATTING",
4365
- "SET_BORDER",
4366
- "SET_ZONE_BORDERS",
4367
- /** CHART */
4368
- "CREATE_CHART",
4369
- "UPDATE_CHART",
4370
- /** FILTERS */
4371
- "CREATE_FILTER_TABLE",
4372
- "REMOVE_FILTER_TABLE",
4373
- /** IMAGE */
4374
- "CREATE_IMAGE",
4375
- ]);
4376
- function isCoreCommand(cmd) {
4377
- return coreTypes.has(cmd.type);
4574
+ function toCellValue(value) {
4575
+ if (value === null || value === undefined)
4576
+ return 0;
4577
+ if (typeof value === "number")
4578
+ return value;
4579
+ if (typeof value === "string")
4580
+ return value;
4581
+ if (typeof value === "boolean")
4582
+ return value;
4583
+ return String(value);
4378
4584
  }
4379
- function canExecuteInReadonly(cmd) {
4380
- return readonlyAllowedCommands.has(cmd.type);
4585
+ function toMatrixArgValue(values) {
4586
+ if (isMatrix(values))
4587
+ return values;
4588
+ return [[values === null ? 0 : values]];
4381
4589
  }
4382
4590
  /**
4383
- * Holds the result of a command dispatch.
4384
- * The command may have been successfully dispatched or cancelled
4385
- * for one or more reasons.
4591
+ * Flatten an array of items, where each item can be a single value or a 2D array, and apply the
4592
+ * callback to each element.
4593
+ *
4594
+ * The 2D array are flattened row first.
4386
4595
  */
4387
- class DispatchResult {
4388
- reasons;
4389
- constructor(results = []) {
4390
- if (!Array.isArray(results)) {
4391
- results = [results];
4596
+ function flattenRowFirst(items, callback) {
4597
+ const flattened = [];
4598
+ for (const item of items) {
4599
+ if (!Array.isArray(item)) {
4600
+ flattened.push(callback(item));
4601
+ continue;
4602
+ }
4603
+ for (let row = 0; row < item[0].length; row++) {
4604
+ for (let col = 0; col < item.length; col++) {
4605
+ flattened.push(callback(item[col][row]));
4606
+ }
4392
4607
  }
4393
- results = [...new Set(results)];
4394
- this.reasons = results.filter((result) => result !== 0 /* CommandResult.Success */);
4395
- }
4396
- /**
4397
- * Static helper which returns a successful DispatchResult
4398
- */
4399
- static get Success() {
4400
- return new DispatchResult();
4401
- }
4402
- get isSuccessful() {
4403
- return this.reasons.length === 0;
4404
- }
4405
- /**
4406
- * Check if the dispatch has been cancelled because of
4407
- * the given reason.
4408
- */
4409
- isCancelledBecause(reason) {
4410
- return this.reasons.includes(reason);
4411
4608
  }
4412
- }
4413
- exports.CommandResult = void 0;
4414
- (function (CommandResult) {
4415
- CommandResult[CommandResult["Success"] = 0] = "Success";
4416
- CommandResult[CommandResult["CancelledForUnknownReason"] = 1] = "CancelledForUnknownReason";
4417
- CommandResult[CommandResult["WillRemoveExistingMerge"] = 2] = "WillRemoveExistingMerge";
4418
- CommandResult[CommandResult["MergeIsDestructive"] = 3] = "MergeIsDestructive";
4419
- CommandResult[CommandResult["CellIsMerged"] = 4] = "CellIsMerged";
4420
- CommandResult[CommandResult["InvalidTarget"] = 5] = "InvalidTarget";
4421
- CommandResult[CommandResult["EmptyUndoStack"] = 6] = "EmptyUndoStack";
4422
- CommandResult[CommandResult["EmptyRedoStack"] = 7] = "EmptyRedoStack";
4423
- CommandResult[CommandResult["NotEnoughElements"] = 8] = "NotEnoughElements";
4424
- CommandResult[CommandResult["NotEnoughSheets"] = 9] = "NotEnoughSheets";
4425
- CommandResult[CommandResult["MissingSheetName"] = 10] = "MissingSheetName";
4426
- CommandResult[CommandResult["DuplicatedSheetName"] = 11] = "DuplicatedSheetName";
4427
- CommandResult[CommandResult["DuplicatedSheetId"] = 12] = "DuplicatedSheetId";
4428
- CommandResult[CommandResult["ForbiddenCharactersInSheetName"] = 13] = "ForbiddenCharactersInSheetName";
4429
- CommandResult[CommandResult["WrongSheetMove"] = 14] = "WrongSheetMove";
4430
- CommandResult[CommandResult["WrongSheetPosition"] = 15] = "WrongSheetPosition";
4431
- CommandResult[CommandResult["InvalidAnchorZone"] = 16] = "InvalidAnchorZone";
4432
- CommandResult[CommandResult["SelectionOutOfBound"] = 17] = "SelectionOutOfBound";
4433
- CommandResult[CommandResult["TargetOutOfSheet"] = 18] = "TargetOutOfSheet";
4434
- CommandResult[CommandResult["WrongCutSelection"] = 19] = "WrongCutSelection";
4435
- CommandResult[CommandResult["WrongPasteSelection"] = 20] = "WrongPasteSelection";
4436
- CommandResult[CommandResult["WrongPasteOption"] = 21] = "WrongPasteOption";
4437
- CommandResult[CommandResult["WrongFigurePasteOption"] = 22] = "WrongFigurePasteOption";
4438
- CommandResult[CommandResult["EmptyClipboard"] = 23] = "EmptyClipboard";
4439
- CommandResult[CommandResult["EmptyRange"] = 24] = "EmptyRange";
4440
- CommandResult[CommandResult["InvalidRange"] = 25] = "InvalidRange";
4441
- CommandResult[CommandResult["InvalidZones"] = 26] = "InvalidZones";
4442
- CommandResult[CommandResult["InvalidSheetId"] = 27] = "InvalidSheetId";
4443
- CommandResult[CommandResult["InvalidFigureId"] = 28] = "InvalidFigureId";
4444
- CommandResult[CommandResult["InputAlreadyFocused"] = 29] = "InputAlreadyFocused";
4445
- CommandResult[CommandResult["MaximumRangesReached"] = 30] = "MaximumRangesReached";
4446
- CommandResult[CommandResult["InvalidChartDefinition"] = 31] = "InvalidChartDefinition";
4447
- CommandResult[CommandResult["InvalidDataSet"] = 32] = "InvalidDataSet";
4448
- CommandResult[CommandResult["InvalidLabelRange"] = 33] = "InvalidLabelRange";
4449
- CommandResult[CommandResult["InvalidScorecardKeyValue"] = 34] = "InvalidScorecardKeyValue";
4450
- CommandResult[CommandResult["InvalidScorecardBaseline"] = 35] = "InvalidScorecardBaseline";
4451
- CommandResult[CommandResult["InvalidGaugeDataRange"] = 36] = "InvalidGaugeDataRange";
4452
- CommandResult[CommandResult["EmptyGaugeRangeMin"] = 37] = "EmptyGaugeRangeMin";
4453
- CommandResult[CommandResult["GaugeRangeMinNaN"] = 38] = "GaugeRangeMinNaN";
4454
- CommandResult[CommandResult["EmptyGaugeRangeMax"] = 39] = "EmptyGaugeRangeMax";
4455
- CommandResult[CommandResult["GaugeRangeMaxNaN"] = 40] = "GaugeRangeMaxNaN";
4456
- CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 41] = "GaugeRangeMinBiggerThanRangeMax";
4457
- CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 42] = "GaugeLowerInflectionPointNaN";
4458
- CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 43] = "GaugeUpperInflectionPointNaN";
4459
- CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 44] = "GaugeLowerBiggerThanUpper";
4460
- CommandResult[CommandResult["InvalidAutofillSelection"] = 45] = "InvalidAutofillSelection";
4461
- CommandResult[CommandResult["WrongComposerSelection"] = 46] = "WrongComposerSelection";
4462
- CommandResult[CommandResult["MinBiggerThanMax"] = 47] = "MinBiggerThanMax";
4463
- CommandResult[CommandResult["LowerBiggerThanUpper"] = 48] = "LowerBiggerThanUpper";
4464
- CommandResult[CommandResult["MidBiggerThanMax"] = 49] = "MidBiggerThanMax";
4465
- CommandResult[CommandResult["MinBiggerThanMid"] = 50] = "MinBiggerThanMid";
4466
- CommandResult[CommandResult["FirstArgMissing"] = 51] = "FirstArgMissing";
4467
- CommandResult[CommandResult["SecondArgMissing"] = 52] = "SecondArgMissing";
4468
- CommandResult[CommandResult["MinNaN"] = 53] = "MinNaN";
4469
- CommandResult[CommandResult["MidNaN"] = 54] = "MidNaN";
4470
- CommandResult[CommandResult["MaxNaN"] = 55] = "MaxNaN";
4471
- CommandResult[CommandResult["ValueUpperInflectionNaN"] = 56] = "ValueUpperInflectionNaN";
4472
- CommandResult[CommandResult["ValueLowerInflectionNaN"] = 57] = "ValueLowerInflectionNaN";
4473
- CommandResult[CommandResult["MinInvalidFormula"] = 58] = "MinInvalidFormula";
4474
- CommandResult[CommandResult["MidInvalidFormula"] = 59] = "MidInvalidFormula";
4475
- CommandResult[CommandResult["MaxInvalidFormula"] = 60] = "MaxInvalidFormula";
4476
- CommandResult[CommandResult["ValueUpperInvalidFormula"] = 61] = "ValueUpperInvalidFormula";
4477
- CommandResult[CommandResult["ValueLowerInvalidFormula"] = 62] = "ValueLowerInvalidFormula";
4478
- CommandResult[CommandResult["InvalidSortZone"] = 63] = "InvalidSortZone";
4479
- CommandResult[CommandResult["WaitingSessionConfirmation"] = 64] = "WaitingSessionConfirmation";
4480
- CommandResult[CommandResult["MergeOverlap"] = 65] = "MergeOverlap";
4481
- CommandResult[CommandResult["TooManyHiddenElements"] = 66] = "TooManyHiddenElements";
4482
- CommandResult[CommandResult["Readonly"] = 67] = "Readonly";
4483
- CommandResult[CommandResult["InvalidViewportSize"] = 68] = "InvalidViewportSize";
4484
- CommandResult[CommandResult["InvalidScrollingDirection"] = 69] = "InvalidScrollingDirection";
4485
- CommandResult[CommandResult["FigureDoesNotExist"] = 70] = "FigureDoesNotExist";
4486
- CommandResult[CommandResult["InvalidConditionalFormatId"] = 71] = "InvalidConditionalFormatId";
4487
- CommandResult[CommandResult["InvalidCellPopover"] = 72] = "InvalidCellPopover";
4488
- CommandResult[CommandResult["EmptyTarget"] = 73] = "EmptyTarget";
4489
- CommandResult[CommandResult["InvalidFreezeQuantity"] = 74] = "InvalidFreezeQuantity";
4490
- CommandResult[CommandResult["FrozenPaneOverlap"] = 75] = "FrozenPaneOverlap";
4491
- CommandResult[CommandResult["ValuesNotChanged"] = 76] = "ValuesNotChanged";
4492
- CommandResult[CommandResult["InvalidFilterZone"] = 77] = "InvalidFilterZone";
4493
- CommandResult[CommandResult["FilterOverlap"] = 78] = "FilterOverlap";
4494
- CommandResult[CommandResult["FilterNotFound"] = 79] = "FilterNotFound";
4495
- CommandResult[CommandResult["MergeInFilter"] = 80] = "MergeInFilter";
4496
- CommandResult[CommandResult["NonContinuousTargets"] = 81] = "NonContinuousTargets";
4497
- CommandResult[CommandResult["DuplicatedFigureId"] = 82] = "DuplicatedFigureId";
4498
- CommandResult[CommandResult["InvalidSelectionStep"] = 83] = "InvalidSelectionStep";
4499
- CommandResult[CommandResult["DuplicatedChartId"] = 84] = "DuplicatedChartId";
4500
- CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4501
- CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4502
- CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4503
- CommandResult[CommandResult["MoreThanOneColumnSelected"] = 88] = "MoreThanOneColumnSelected";
4504
- CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
4505
- CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4506
- CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4507
- CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4508
- })(exports.CommandResult || (exports.CommandResult = {}));
4509
-
4510
- const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
4511
- function isMatrix(x) {
4512
- return Array.isArray(x) && Array.isArray(x[0]);
4513
- }
4514
- var DIRECTION;
4515
- (function (DIRECTION) {
4516
- DIRECTION["UP"] = "up";
4517
- DIRECTION["DOWN"] = "down";
4518
- DIRECTION["LEFT"] = "left";
4519
- DIRECTION["RIGHT"] = "right";
4520
- })(DIRECTION || (DIRECTION = {}));
4521
-
4522
- var LAYERS;
4523
- (function (LAYERS) {
4524
- LAYERS[LAYERS["Background"] = 0] = "Background";
4525
- LAYERS[LAYERS["Highlights"] = 1] = "Highlights";
4526
- LAYERS[LAYERS["Clipboard"] = 2] = "Clipboard";
4527
- LAYERS[LAYERS["Search"] = 3] = "Search";
4528
- LAYERS[LAYERS["Chart"] = 4] = "Chart";
4529
- LAYERS[LAYERS["Autofill"] = 5] = "Autofill";
4530
- LAYERS[LAYERS["Selection"] = 6] = "Selection";
4531
- LAYERS[LAYERS["Headers"] = 7] = "Headers";
4532
- })(LAYERS || (LAYERS = {}));
4609
+ return flattened;
4610
+ }
4533
4611
 
4534
4612
  function evaluateLiteral(content, format) {
4535
4613
  return createEvaluatedCell(parseLiteral(content || ""), format);
@@ -5110,10 +5188,10 @@
5110
5188
  this.state.selectedValue = value.string;
5111
5189
  }
5112
5190
  selectAll() {
5113
- this.state.values.forEach((value) => (value.checked = true));
5191
+ this.displayedValues.forEach((value) => (value.checked = true));
5114
5192
  }
5115
5193
  clearAll() {
5116
- this.state.values.forEach((value) => (value.checked = false));
5194
+ this.displayedValues.forEach((value) => (value.checked = false));
5117
5195
  }
5118
5196
  get filterTable() {
5119
5197
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -6576,11 +6654,11 @@
6576
6654
  if (definition.dataSets) {
6577
6655
  const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range)) !== undefined;
6578
6656
  if (invalidRanges) {
6579
- return 32 /* CommandResult.InvalidDataSet */;
6657
+ return 33 /* CommandResult.InvalidDataSet */;
6580
6658
  }
6581
6659
  const zones = definition.dataSets.map(toUnboundedZone);
6582
6660
  if (zones.some((zone) => zone.top !== zone.bottom && isFullRow(zone))) {
6583
- return 32 /* CommandResult.InvalidDataSet */;
6661
+ return 33 /* CommandResult.InvalidDataSet */;
6584
6662
  }
6585
6663
  }
6586
6664
  return 0 /* CommandResult.Success */;
@@ -6589,7 +6667,7 @@
6589
6667
  if (definition.labelRange) {
6590
6668
  const invalidLabels = !rangeReference.test(definition.labelRange || "");
6591
6669
  if (invalidLabels) {
6592
- return 33 /* CommandResult.InvalidLabelRange */;
6670
+ return 34 /* CommandResult.InvalidLabelRange */;
6593
6671
  }
6594
6672
  }
6595
6673
  return 0 /* CommandResult.Success */;
@@ -6675,24 +6753,24 @@
6675
6753
 
6676
6754
  const CfTerms = {
6677
6755
  Errors: {
6678
- [25 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6679
- [51 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6680
- [52 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6681
- [53 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6682
- [54 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6683
- [55 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6684
- [56 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6685
- [57 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6686
- [47 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6687
- [50 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6688
- [49 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6689
- [48 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6690
- [58 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6691
- [60 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6692
- [59 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6693
- [61 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6694
- [62 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6695
- [24 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6756
+ [26 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6757
+ [52 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6758
+ [53 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6759
+ [54 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6760
+ [55 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6761
+ [56 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6762
+ [57 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6763
+ [58 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6764
+ [48 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6765
+ [51 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6766
+ [50 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6767
+ [49 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6768
+ [59 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6769
+ [61 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6770
+ [60 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6771
+ [62 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6772
+ [63 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6773
+ [25 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6696
6774
  Unexpected: _lt("The rule is invalid for an unknown reason"),
6697
6775
  },
6698
6776
  ColorScale: _lt("Color scale"),
@@ -6719,20 +6797,20 @@
6719
6797
  Errors: {
6720
6798
  Unexpected: _lt("The chart definition is invalid for an unknown reason"),
6721
6799
  // BASIC CHART ERRORS (LINE | BAR | PIE)
6722
- [32 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6723
- [33 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6800
+ [33 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6801
+ [34 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6724
6802
  // SCORECARD CHART ERRORS
6725
- [34 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6726
- [35 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6803
+ [35 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6804
+ [36 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6727
6805
  // GAUGE CHART ERRORS
6728
- [36 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6729
- [37 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6730
- [38 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6731
- [39 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6732
- [40 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6733
- [41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6734
- [42 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6735
- [43 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6806
+ [37 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6807
+ [38 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6808
+ [39 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6809
+ [40 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6810
+ [41 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6811
+ [42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6812
+ [43 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6813
+ [44 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6736
6814
  },
6737
6815
  };
6738
6816
  const CustomCurrencyTerms = {
@@ -6742,9 +6820,9 @@
6742
6820
  const SplitToColumnsTerms = {
6743
6821
  Errors: {
6744
6822
  Unexpected: _lt("Cannot split the selection for an unknown reason"),
6745
- [91 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6746
- [88 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6747
- [90 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6823
+ [92 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6824
+ [89 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6825
+ [91 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6748
6826
  },
6749
6827
  };
6750
6828
 
@@ -7148,7 +7226,7 @@
7148
7226
 
7149
7227
  function isDataRangeValid(definition) {
7150
7228
  return definition.dataRange && !rangeReference.test(definition.dataRange)
7151
- ? 36 /* CommandResult.InvalidGaugeDataRange */
7229
+ ? 37 /* CommandResult.InvalidGaugeDataRange */
7152
7230
  : 0 /* CommandResult.Success */;
7153
7231
  }
7154
7232
  function checkRangeLimits(check, batchValidations) {
@@ -7180,7 +7258,7 @@
7180
7258
  function checkRangeMinBiggerThanRangeMax(definition) {
7181
7259
  if (definition.sectionRule) {
7182
7260
  if (Number(definition.sectionRule.rangeMin) >= Number(definition.sectionRule.rangeMax)) {
7183
- return 41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7261
+ return 42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7184
7262
  }
7185
7263
  }
7186
7264
  return 0 /* CommandResult.Success */;
@@ -7189,9 +7267,9 @@
7189
7267
  if (value === "") {
7190
7268
  switch (valueName) {
7191
7269
  case "rangeMin":
7192
- return 37 /* CommandResult.EmptyGaugeRangeMin */;
7270
+ return 38 /* CommandResult.EmptyGaugeRangeMin */;
7193
7271
  case "rangeMax":
7194
- return 39 /* CommandResult.EmptyGaugeRangeMax */;
7272
+ return 40 /* CommandResult.EmptyGaugeRangeMax */;
7195
7273
  }
7196
7274
  }
7197
7275
  return 0 /* CommandResult.Success */;
@@ -7200,13 +7278,13 @@
7200
7278
  if (isNaN(value)) {
7201
7279
  switch (valueName) {
7202
7280
  case "rangeMin":
7203
- return 38 /* CommandResult.GaugeRangeMinNaN */;
7281
+ return 39 /* CommandResult.GaugeRangeMinNaN */;
7204
7282
  case "rangeMax":
7205
- return 40 /* CommandResult.GaugeRangeMaxNaN */;
7283
+ return 41 /* CommandResult.GaugeRangeMaxNaN */;
7206
7284
  case "lowerInflectionPointValue":
7207
- return 42 /* CommandResult.GaugeLowerInflectionPointNaN */;
7285
+ return 43 /* CommandResult.GaugeLowerInflectionPointNaN */;
7208
7286
  case "upperInflectionPointValue":
7209
- return 43 /* CommandResult.GaugeUpperInflectionPointNaN */;
7287
+ return 44 /* CommandResult.GaugeUpperInflectionPointNaN */;
7210
7288
  }
7211
7289
  }
7212
7290
  return 0 /* CommandResult.Success */;
@@ -7982,12 +8060,12 @@
7982
8060
 
7983
8061
  function checkKeyValue(definition) {
7984
8062
  return definition.keyValue && !rangeReference.test(definition.keyValue)
7985
- ? 34 /* CommandResult.InvalidScorecardKeyValue */
8063
+ ? 35 /* CommandResult.InvalidScorecardKeyValue */
7986
8064
  : 0 /* CommandResult.Success */;
7987
8065
  }
7988
8066
  function checkBaseline(definition) {
7989
8067
  return definition.baseline && !rangeReference.test(definition.baseline)
7990
- ? 35 /* CommandResult.InvalidScorecardBaseline */
8068
+ ? 36 /* CommandResult.InvalidScorecardBaseline */
7991
8069
  : 0 /* CommandResult.Success */;
7992
8070
  }
7993
8071
  class ScorecardChart extends AbstractChart {
@@ -8487,13 +8565,22 @@
8487
8565
  ];
8488
8566
  }
8489
8567
 
8568
+ function interactiveCut(env) {
8569
+ const result = env.model.dispatch("CUT");
8570
+ if (!result.isSuccessful) {
8571
+ if (result.isCancelledBecause(20 /* CommandResult.WrongCutSelection */)) {
8572
+ env.raiseError(_lt("This operation is not allowed with multiple selections."));
8573
+ }
8574
+ }
8575
+ }
8576
+
8490
8577
  const AddMergeInteractiveContent = {
8491
8578
  MergeIsDestructive: _lt("Merging these cells will only preserve the top-leftmost value. Merge anyway?"),
8492
8579
  MergeInFilter: _lt("You can't merge cells inside of an existing filter."),
8493
8580
  };
8494
8581
  function interactiveAddMerge(env, sheetId, target) {
8495
8582
  const result = env.model.dispatch("ADD_MERGE", { sheetId, target });
8496
- if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8583
+ if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
8497
8584
  env.raiseError(AddMergeInteractiveContent.MergeInFilter);
8498
8585
  }
8499
8586
  else if (result.isCancelledBecause(3 /* CommandResult.MergeIsDestructive */)) {
@@ -8503,279 +8590,6 @@
8503
8590
  }
8504
8591
  }
8505
8592
 
8506
- /**
8507
- * Create a function used to create a Chart based on the definition
8508
- */
8509
- function chartFactory(getters) {
8510
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8511
- function createChart(id, definition, sheetId) {
8512
- const builder = builders.find((builder) => builder.match(definition.type));
8513
- if (!builder) {
8514
- throw new Error(`No builder for this chart: ${definition.type}`);
8515
- }
8516
- return builder.createChart(definition, sheetId, getters);
8517
- }
8518
- return createChart;
8519
- }
8520
- /**
8521
- * Create a function used to create a Chart Runtime based on the chart class
8522
- * instance
8523
- */
8524
- function chartRuntimeFactory(getters) {
8525
- const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8526
- function createRuntimeChart(chart) {
8527
- const builder = builders.find((builder) => builder.match(chart.type));
8528
- if (!builder) {
8529
- throw new Error("No runtime builder for this chart.");
8530
- }
8531
- return builder.getChartRuntime(chart, getters);
8532
- }
8533
- return createRuntimeChart;
8534
- }
8535
- /**
8536
- * Validate the chart definition given in arguments
8537
- */
8538
- function validateChartDefinition(validator, definition) {
8539
- const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8540
- if (!validators) {
8541
- throw new Error("Unknown chart type.");
8542
- }
8543
- return validators.validateChartDefinition(validator, definition);
8544
- }
8545
- /**
8546
- * Get a new chart definition transformed with the executed command. This
8547
- * functions will be called during operational transform process
8548
- */
8549
- function transformDefinition(definition, executed) {
8550
- const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8551
- if (!transformation) {
8552
- throw new Error("Unknown chart type.");
8553
- }
8554
- return transformation.transformDefinition(definition, executed);
8555
- }
8556
- /**
8557
- * Get an empty definition based on the given context and the given type
8558
- */
8559
- function getChartDefinitionFromContextCreation(context, type) {
8560
- const chartClass = chartRegistry.get(type);
8561
- return chartClass.getChartDefinitionFromContextCreation(context);
8562
- }
8563
- function getChartTypes() {
8564
- const result = {};
8565
- for (const key of chartRegistry.getKeys()) {
8566
- result[key] = chartRegistry.get(key).name;
8567
- }
8568
- return result;
8569
- }
8570
- /**
8571
- * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8572
- * use the best type of chart to display the data of the zone.
8573
- *
8574
- * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8575
- *
8576
- * The type of chart will be :
8577
- * - If the zone is a single non-empty cell, returns a scorecard
8578
- * - If the all the labels are numbers/date, returns a line chart
8579
- * - Else returns a bar chart
8580
- */
8581
- function getSmartChartDefinition(zone, getters) {
8582
- let dataSetZone = zone;
8583
- if (zone.left !== zone.right) {
8584
- dataSetZone = { ...zone, left: zone.left + 1 };
8585
- }
8586
- const dataSets = [zoneToXc(dataSetZone)];
8587
- const sheetId = getters.getActiveSheetId();
8588
- const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8589
- if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8590
- return {
8591
- type: "scorecard",
8592
- title: "",
8593
- background: topLeftCell.style?.fillColor || undefined,
8594
- keyValue: zoneToXc(zone),
8595
- baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8596
- baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8597
- baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8598
- };
8599
- }
8600
- let title = "";
8601
- const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8602
- ...dataSetZone,
8603
- bottom: dataSetZone.top,
8604
- });
8605
- const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8606
- if (dataSetsHaveTitle) {
8607
- const texts = cellsInFirstRow
8608
- .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8609
- .map((cell) => cell.formattedValue);
8610
- const lastElement = texts.splice(-1)[0];
8611
- title = texts.join(", ");
8612
- if (lastElement) {
8613
- title += (title ? " " + _t("and") + " " : "") + lastElement;
8614
- }
8615
- }
8616
- let labelRangeXc;
8617
- if (zone.left !== zone.right) {
8618
- labelRangeXc = zoneToXc({
8619
- ...zone,
8620
- right: zone.left,
8621
- });
8622
- }
8623
- // Only display legend for several datasets.
8624
- const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8625
- const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8626
- if (canChartParseLabels(labelRange, getters)) {
8627
- return {
8628
- title,
8629
- dataSets,
8630
- labelsAsText: false,
8631
- stacked: false,
8632
- aggregated: false,
8633
- labelRange: labelRangeXc,
8634
- type: "line",
8635
- dataSetsHaveTitle,
8636
- verticalAxisPosition: "left",
8637
- legendPosition: newLegendPos,
8638
- };
8639
- }
8640
- return {
8641
- title,
8642
- dataSets,
8643
- labelRange: labelRangeXc,
8644
- type: "bar",
8645
- stacked: false,
8646
- aggregated: false,
8647
- dataSetsHaveTitle,
8648
- verticalAxisPosition: "left",
8649
- legendPosition: newLegendPos,
8650
- };
8651
- }
8652
-
8653
- const SORT_TYPES = [
8654
- CellValueType.number,
8655
- CellValueType.error,
8656
- CellValueType.text,
8657
- CellValueType.boolean,
8658
- ];
8659
- function sortCells(cells, sortDirection, emptyCellAsZero) {
8660
- const cellsWithIndex = cells.map((cell, index) => ({
8661
- index,
8662
- type: cell.type,
8663
- value: cell.value,
8664
- }));
8665
- let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
8666
- let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
8667
- if (emptyCellAsZero) {
8668
- nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
8669
- emptyCells = [];
8670
- }
8671
- const inverse = sortDirection === "descending" ? -1 : 1;
8672
- return nonEmptyCells
8673
- .sort((left, right) => {
8674
- let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
8675
- if (typeOrder === 0) {
8676
- if (left.type === CellValueType.text || left.type === CellValueType.error) {
8677
- typeOrder = left.value.localeCompare(right.value);
8678
- }
8679
- else
8680
- typeOrder = left.value - right.value;
8681
- }
8682
- return inverse * typeOrder;
8683
- })
8684
- .concat(emptyCells);
8685
- }
8686
- function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
8687
- let result = DispatchResult.Success;
8688
- //several columns => bypass the contiguity check
8689
- let multiColumns = zone.right > zone.left;
8690
- if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
8691
- multiColumns = false;
8692
- let table;
8693
- for (let row = zone.top; row <= zone.bottom; row++) {
8694
- table = [];
8695
- for (let col = zone.left; col <= zone.right; col++) {
8696
- let merge = env.model.getters.getMerge({ sheetId, col, row });
8697
- if (merge && !table.includes(merge.id.toString())) {
8698
- table.push(merge.id.toString());
8699
- }
8700
- }
8701
- if (table.length >= 2) {
8702
- multiColumns = true;
8703
- break;
8704
- }
8705
- }
8706
- }
8707
- const { col, row } = anchor;
8708
- if (multiColumns) {
8709
- result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
8710
- }
8711
- else {
8712
- // check contiguity
8713
- const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
8714
- if (isEqual(contiguousZone, zone)) {
8715
- // merge as it is
8716
- result = env.model.dispatch("SORT_CELLS", {
8717
- sheetId,
8718
- col,
8719
- row,
8720
- zone,
8721
- sortDirection,
8722
- });
8723
- }
8724
- else {
8725
- env.askConfirmation(_lt("We found data next to your selection. Since this data was not selected, it will not be sorted. Do you want to extend your selection?"), () => {
8726
- zone = contiguousZone;
8727
- result = env.model.dispatch("SORT_CELLS", {
8728
- sheetId,
8729
- col,
8730
- row,
8731
- zone,
8732
- sortDirection,
8733
- });
8734
- }, () => {
8735
- result = env.model.dispatch("SORT_CELLS", {
8736
- sheetId,
8737
- col,
8738
- row,
8739
- zone,
8740
- sortDirection,
8741
- });
8742
- });
8743
- }
8744
- }
8745
- if (result.isCancelledBecause(63 /* CommandResult.InvalidSortZone */)) {
8746
- const { col, row } = anchor;
8747
- env.model.selection.selectZone({ cell: { col, row }, zone });
8748
- env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
8749
- }
8750
- }
8751
-
8752
- function interactiveCut(env) {
8753
- const result = env.model.dispatch("CUT");
8754
- if (!result.isSuccessful) {
8755
- if (result.isCancelledBecause(19 /* CommandResult.WrongCutSelection */)) {
8756
- env.raiseError(_lt("This operation is not allowed with multiple selections."));
8757
- }
8758
- }
8759
- }
8760
-
8761
- const AddFilterInteractiveContent = {
8762
- filterOverlap: _lt("You cannot create overlapping filters."),
8763
- nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
8764
- mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
8765
- };
8766
- function interactiveAddFilter(env, sheetId, target) {
8767
- const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
8768
- if (result.isCancelledBecause(78 /* CommandResult.FilterOverlap */)) {
8769
- env.raiseError(AddFilterInteractiveContent.filterOverlap);
8770
- }
8771
- else if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8772
- env.raiseError(AddFilterInteractiveContent.mergeInFilter);
8773
- }
8774
- else if (result.isCancelledBecause(81 /* CommandResult.NonContinuousTargets */)) {
8775
- env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
8776
- }
8777
- }
8778
-
8779
8593
  const PasteInteractiveContent = {
8780
8594
  wrongPasteSelection: _lt("This operation is not allowed with multiple selections."),
8781
8595
  willRemoveExistingMerge: _lt("This operation is not possible due to a merge. Please remove the merges first than try again."),
@@ -8784,16 +8598,16 @@
8784
8598
  };
8785
8599
  function handlePasteResult(env, result) {
8786
8600
  if (!result.isSuccessful) {
8787
- if (result.reasons.includes(20 /* CommandResult.WrongPasteSelection */)) {
8601
+ if (result.reasons.includes(21 /* CommandResult.WrongPasteSelection */)) {
8788
8602
  env.raiseError(PasteInteractiveContent.wrongPasteSelection);
8789
8603
  }
8790
8604
  else if (result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
8791
8605
  env.raiseError(PasteInteractiveContent.willRemoveExistingMerge);
8792
8606
  }
8793
- else if (result.reasons.includes(22 /* CommandResult.WrongFigurePasteOption */)) {
8607
+ else if (result.reasons.includes(23 /* CommandResult.WrongFigurePasteOption */)) {
8794
8608
  env.raiseError(PasteInteractiveContent.wrongFigurePasteOption);
8795
8609
  }
8796
- else if (result.reasons.includes(75 /* CommandResult.FrozenPaneOverlap */)) {
8610
+ else if (result.reasons.includes(76 /* CommandResult.FrozenPaneOverlap */)) {
8797
8611
  env.raiseError(PasteInteractiveContent.frozenPaneOverlap);
8798
8612
  }
8799
8613
  }
@@ -8802,34 +8616,161 @@
8802
8616
  const result = env.model.dispatch("PASTE", { target, pasteOption });
8803
8617
  handlePasteResult(env, result);
8804
8618
  }
8805
- function interactivePasteFromOS(env, target, text) {
8806
- const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text });
8619
+ function interactivePasteFromOS(env, target, text, pasteOption) {
8620
+ const result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", { target, text, pasteOption });
8807
8621
  handlePasteResult(env, result);
8808
8622
  }
8809
8623
 
8810
- //------------------------------------------------------------------------------
8811
- // Helpers
8812
- //------------------------------------------------------------------------------
8813
- function getColumnsNumber(env) {
8814
- const activeCols = env.model.getters.getActiveCols();
8815
- if (activeCols.size) {
8816
- return activeCols.size;
8624
+ /**
8625
+ * Create a function used to create a Chart based on the definition
8626
+ */
8627
+ function chartFactory(getters) {
8628
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8629
+ function createChart(id, definition, sheetId) {
8630
+ const builder = builders.find((builder) => builder.match(definition.type));
8631
+ if (!builder) {
8632
+ throw new Error(`No builder for this chart: ${definition.type}`);
8633
+ }
8634
+ return builder.createChart(definition, sheetId, getters);
8817
8635
  }
8818
- else {
8819
- const zone = env.model.getters.getSelectedZones()[0];
8820
- return zone.right - zone.left + 1;
8636
+ return createChart;
8637
+ }
8638
+ /**
8639
+ * Create a function used to create a Chart Runtime based on the chart class
8640
+ * instance
8641
+ */
8642
+ function chartRuntimeFactory(getters) {
8643
+ const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
8644
+ function createRuntimeChart(chart) {
8645
+ const builder = builders.find((builder) => builder.match(chart.type));
8646
+ if (!builder) {
8647
+ throw new Error("No runtime builder for this chart.");
8648
+ }
8649
+ return builder.getChartRuntime(chart, getters);
8821
8650
  }
8651
+ return createRuntimeChart;
8822
8652
  }
8823
- function getRowsNumber(env) {
8824
- const activeRows = env.model.getters.getActiveRows();
8825
- if (activeRows.size) {
8826
- return activeRows.size;
8653
+ /**
8654
+ * Validate the chart definition given in arguments
8655
+ */
8656
+ function validateChartDefinition(validator, definition) {
8657
+ const validators = chartRegistry.getAll().find((validator) => validator.match(definition.type));
8658
+ if (!validators) {
8659
+ throw new Error("Unknown chart type.");
8827
8660
  }
8828
- else {
8829
- const zone = env.model.getters.getSelectedZones()[0];
8830
- return zone.bottom - zone.top + 1;
8661
+ return validators.validateChartDefinition(validator, definition);
8662
+ }
8663
+ /**
8664
+ * Get a new chart definition transformed with the executed command. This
8665
+ * functions will be called during operational transform process
8666
+ */
8667
+ function transformDefinition(definition, executed) {
8668
+ const transformation = chartRegistry.getAll().find((factory) => factory.match(definition.type));
8669
+ if (!transformation) {
8670
+ throw new Error("Unknown chart type.");
8671
+ }
8672
+ return transformation.transformDefinition(definition, executed);
8673
+ }
8674
+ /**
8675
+ * Get an empty definition based on the given context and the given type
8676
+ */
8677
+ function getChartDefinitionFromContextCreation(context, type) {
8678
+ const chartClass = chartRegistry.get(type);
8679
+ return chartClass.getChartDefinitionFromContextCreation(context);
8680
+ }
8681
+ function getChartTypes() {
8682
+ const result = {};
8683
+ for (const key of chartRegistry.getKeys()) {
8684
+ result[key] = chartRegistry.get(key).name;
8831
8685
  }
8686
+ return result;
8832
8687
  }
8688
+ /**
8689
+ * Return a "smart" chart definition in the given zone. The definition is "smart" because it will
8690
+ * use the best type of chart to display the data of the zone.
8691
+ *
8692
+ * It will also try to find labels and datasets in the range, and try to find title for the datasets.
8693
+ *
8694
+ * The type of chart will be :
8695
+ * - If the zone is a single non-empty cell, returns a scorecard
8696
+ * - If the all the labels are numbers/date, returns a line chart
8697
+ * - Else returns a bar chart
8698
+ */
8699
+ function getSmartChartDefinition(zone, getters) {
8700
+ let dataSetZone = zone;
8701
+ if (zone.left !== zone.right) {
8702
+ dataSetZone = { ...zone, left: zone.left + 1 };
8703
+ }
8704
+ const dataSets = [zoneToXc(dataSetZone)];
8705
+ const sheetId = getters.getActiveSheetId();
8706
+ const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
8707
+ if (getZoneArea(zone) === 1 && topLeftCell?.content) {
8708
+ return {
8709
+ type: "scorecard",
8710
+ title: "",
8711
+ background: topLeftCell.style?.fillColor || undefined,
8712
+ keyValue: zoneToXc(zone),
8713
+ baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
8714
+ baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
8715
+ baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
8716
+ };
8717
+ }
8718
+ let title = "";
8719
+ const cellsInFirstRow = getters.getEvaluatedCellsInZone(sheetId, {
8720
+ ...dataSetZone,
8721
+ bottom: dataSetZone.top,
8722
+ });
8723
+ const dataSetsHaveTitle = !!cellsInFirstRow.find((cell) => cell.type !== CellValueType.empty && cell.type !== CellValueType.number);
8724
+ if (dataSetsHaveTitle) {
8725
+ const texts = cellsInFirstRow
8726
+ .filter((cell) => cell.type !== CellValueType.error && cell.type !== CellValueType.empty)
8727
+ .map((cell) => cell.formattedValue);
8728
+ const lastElement = texts.splice(-1)[0];
8729
+ title = texts.join(", ");
8730
+ if (lastElement) {
8731
+ title += (title ? " " + _t("and") + " " : "") + lastElement;
8732
+ }
8733
+ }
8734
+ let labelRangeXc;
8735
+ if (zone.left !== zone.right) {
8736
+ labelRangeXc = zoneToXc({
8737
+ ...zone,
8738
+ right: zone.left,
8739
+ });
8740
+ }
8741
+ // Only display legend for several datasets.
8742
+ const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
8743
+ const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
8744
+ if (canChartParseLabels(labelRange, getters)) {
8745
+ return {
8746
+ title,
8747
+ dataSets,
8748
+ labelsAsText: false,
8749
+ stacked: false,
8750
+ aggregated: false,
8751
+ labelRange: labelRangeXc,
8752
+ type: "line",
8753
+ dataSetsHaveTitle,
8754
+ verticalAxisPosition: "left",
8755
+ legendPosition: newLegendPos,
8756
+ };
8757
+ }
8758
+ return {
8759
+ title,
8760
+ dataSets,
8761
+ labelRange: labelRangeXc,
8762
+ type: "bar",
8763
+ stacked: false,
8764
+ aggregated: false,
8765
+ dataSetsHaveTitle,
8766
+ verticalAxisPosition: "left",
8767
+ legendPosition: newLegendPos,
8768
+ };
8769
+ }
8770
+
8771
+ //------------------------------------------------------------------------------
8772
+ // Helpers
8773
+ //------------------------------------------------------------------------------
8833
8774
  function setFormatter(env, format) {
8834
8775
  env.model.dispatch("SET_FORMATTING", {
8835
8776
  sheetId: env.model.getters.getActiveSheetId(),
@@ -8847,16 +8788,6 @@
8847
8788
  //------------------------------------------------------------------------------
8848
8789
  // Simple actions
8849
8790
  //------------------------------------------------------------------------------
8850
- const UNDO_ACTION = (env) => env.model.dispatch("REQUEST_UNDO");
8851
- const REDO_ACTION = (env) => env.model.dispatch("REQUEST_REDO");
8852
- const COPY_ACTION = async (env) => {
8853
- env.model.dispatch("COPY");
8854
- await env.clipboard.write(env.model.getters.getClipboardContent());
8855
- };
8856
- const CUT_ACTION = async (env) => {
8857
- interactiveCut(env);
8858
- await env.clipboard.write(env.model.getters.getClipboardContent());
8859
- };
8860
8791
  const PASTE_ACTION = async (env) => paste$1(env);
8861
8792
  const PASTE_VALUE_ACTION = async (env) => paste$1(env, "onlyValue");
8862
8793
  async function paste$1(env, pasteOption) {
@@ -8866,11 +8797,14 @@
8866
8797
  case "ok":
8867
8798
  const target = env.model.getters.getSelectedZones();
8868
8799
  if (osClipboard && osClipboard.content !== spreadsheetClipboard) {
8869
- interactivePasteFromOS(env, target, osClipboard.content);
8800
+ interactivePasteFromOS(env, target, osClipboard.content, pasteOption);
8870
8801
  }
8871
8802
  else {
8872
8803
  interactivePaste(env, target, pasteOption);
8873
8804
  }
8805
+ if (env.model.getters.isCutOperation() && pasteOption !== "onlyValue") {
8806
+ await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
8807
+ }
8874
8808
  break;
8875
8809
  case "notImplemented":
8876
8810
  env.raiseError(_lt("Pasting from the context menu is not supported in this browser. Use keyboard shortcuts ctrl+c / ctrl+v instead."));
@@ -8880,22 +8814,7 @@
8880
8814
  break;
8881
8815
  }
8882
8816
  }
8883
- const PASTE_FORMAT_ACTION = (env) => interactivePaste(env, env.model.getters.getSelectedZones(), "onlyFormat");
8884
- const DELETE_CONTENT_ACTION = (env) => env.model.dispatch("DELETE_CONTENT", {
8885
- sheetId: env.model.getters.getActiveSheetId(),
8886
- target: env.model.getters.getSelectedZones(),
8887
- });
8888
- const SET_FORMULA_VISIBILITY_ACTION = (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() });
8889
- const SET_GRID_LINES_VISIBILITY_ACTION = (env) => {
8890
- const sheetId = env.model.getters.getActiveSheetId();
8891
- env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
8892
- sheetId,
8893
- areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
8894
- });
8895
- };
8896
- const IS_NOT_CUT_OPERATION = (env) => {
8897
- return !env.model.getters.isCutOperation();
8898
- };
8817
+ const PASTE_FORMAT_ACTION = (env) => paste$1(env, "onlyFormat");
8899
8818
  //------------------------------------------------------------------------------
8900
8819
  // Grid manipulations
8901
8820
  //------------------------------------------------------------------------------
@@ -9037,48 +8956,6 @@
9037
8956
  const selectedCols = env.model.getters.getElementsFromSelection("COL");
9038
8957
  return env.model.getters.canRemoveHeaders(sheetId, "COL", selectedCols);
9039
8958
  };
9040
- const INSERT_CELL_SHIFT_DOWN = (env) => {
9041
- const zone = env.model.getters.getSelectedZone();
9042
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
9043
- handlePasteResult(env, result);
9044
- };
9045
- const INSERT_CELL_SHIFT_RIGHT = (env) => {
9046
- const zone = env.model.getters.getSelectedZone();
9047
- const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
9048
- handlePasteResult(env, result);
9049
- };
9050
- const DELETE_CELL_SHIFT_UP = (env) => {
9051
- const zone = env.model.getters.getSelectedZone();
9052
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9053
- handlePasteResult(env, result);
9054
- };
9055
- const DELETE_CELL_SHIFT_LEFT = (env) => {
9056
- const zone = env.model.getters.getSelectedZone();
9057
- const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9058
- handlePasteResult(env, result);
9059
- };
9060
- const MENU_INSERT_ROWS_NAME = (env) => {
9061
- const number = getRowsNumber(env);
9062
- return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
9063
- };
9064
- const MENU_INSERT_ROWS_BEFORE_NAME = (env) => {
9065
- const number = getRowsNumber(env);
9066
- if (number === 1) {
9067
- return _lt("Row above");
9068
- }
9069
- return _lt("%s Rows above", number.toString());
9070
- };
9071
- const ROW_INSERT_ROWS_BEFORE_NAME = (env) => {
9072
- const number = getRowsNumber(env);
9073
- return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
9074
- };
9075
- const CELL_INSERT_ROWS_BEFORE_NAME = (env) => {
9076
- const number = getRowsNumber(env);
9077
- if (number === 1) {
9078
- return _lt("Insert row");
9079
- }
9080
- return _lt("Insert %s rows", number.toString());
9081
- };
9082
8959
  const INSERT_ROWS_BEFORE_ACTION = (env) => {
9083
8960
  const activeRows = env.model.getters.getActiveRows();
9084
8961
  let row;
@@ -9100,17 +8977,6 @@
9100
8977
  dimension: "ROW",
9101
8978
  });
9102
8979
  };
9103
- const MENU_INSERT_ROWS_AFTER_NAME = (env) => {
9104
- const number = getRowsNumber(env);
9105
- if (number === 1) {
9106
- return _lt("Row below");
9107
- }
9108
- return _lt("%s Rows below", number.toString());
9109
- };
9110
- const ROW_INSERT_ROWS_AFTER_NAME = (env) => {
9111
- const number = getRowsNumber(env);
9112
- return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
9113
- };
9114
8980
  const INSERT_ROWS_AFTER_ACTION = (env) => {
9115
8981
  const activeRows = env.model.getters.getActiveRows();
9116
8982
  let row;
@@ -9132,30 +8998,6 @@
9132
8998
  dimension: "ROW",
9133
8999
  });
9134
9000
  };
9135
- const MENU_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9136
- const number = getColumnsNumber(env);
9137
- if (number === 1) {
9138
- return _lt("Column left");
9139
- }
9140
- return _lt("%s Columns left", number.toString());
9141
- };
9142
- const MENU_INSERT_COLUMNS_NAME = (env) => {
9143
- const number = getColumnsNumber(env);
9144
- return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
9145
- };
9146
- const COLUMN_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9147
- const number = getColumnsNumber(env);
9148
- return number === 1
9149
- ? _lt("Insert column left")
9150
- : _lt("Insert %s columns left", number.toString());
9151
- };
9152
- const CELL_INSERT_COLUMNS_BEFORE_NAME = (env) => {
9153
- const number = getColumnsNumber(env);
9154
- if (number === 1) {
9155
- return _lt("Insert column");
9156
- }
9157
- return _lt("Insert %s columns", number.toString());
9158
- };
9159
9001
  const INSERT_COLUMNS_BEFORE_ACTION = (env) => {
9160
9002
  const activeCols = env.model.getters.getActiveCols();
9161
9003
  let column;
@@ -9177,19 +9019,6 @@
9177
9019
  quantity,
9178
9020
  });
9179
9021
  };
9180
- const MENU_INSERT_COLUMNS_AFTER_NAME = (env) => {
9181
- const number = getColumnsNumber(env);
9182
- if (number === 1) {
9183
- return _lt("Column right");
9184
- }
9185
- return _lt("%s Columns right", number.toString());
9186
- };
9187
- const COLUMN_INSERT_COLUMNS_AFTER_NAME = (env) => {
9188
- const number = getColumnsNumber(env);
9189
- return number === 1
9190
- ? _lt("Insert column right")
9191
- : _lt("Insert %s columns right", number.toString());
9192
- };
9193
9022
  const INSERT_COLUMNS_AFTER_ACTION = (env) => {
9194
9023
  const activeCols = env.model.getters.getActiveCols();
9195
9024
  let column;
@@ -9225,30 +9054,6 @@
9225
9054
  return _lt("Hide columns");
9226
9055
  }
9227
9056
  };
9228
- const HIDE_COLUMNS_ACTION = (env) => {
9229
- const columns = env.model.getters.getElementsFromSelection("COL");
9230
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9231
- sheetId: env.model.getters.getActiveSheetId(),
9232
- dimension: "COL",
9233
- elements: columns,
9234
- });
9235
- };
9236
- const UNHIDE_ALL_COLUMNS_ACTION = (env) => {
9237
- const sheetId = env.model.getters.getActiveSheetId();
9238
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9239
- sheetId,
9240
- dimension: "COL",
9241
- elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
9242
- });
9243
- };
9244
- const UNHIDE_COLUMNS_ACTION = (env) => {
9245
- const columns = env.model.getters.getElementsFromSelection("COL");
9246
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9247
- sheetId: env.model.getters.getActiveSheetId(),
9248
- dimension: "COL",
9249
- elements: columns,
9250
- });
9251
- };
9252
9057
  const HIDE_ROWS_NAME = (env) => {
9253
9058
  const rows = env.model.getters.getElementsFromSelection("ROW");
9254
9059
  let first = rows[0];
@@ -9263,40 +9068,6 @@
9263
9068
  return _lt("Hide rows");
9264
9069
  }
9265
9070
  };
9266
- const HIDE_ROWS_ACTION = (env) => {
9267
- const rows = env.model.getters.getElementsFromSelection("ROW");
9268
- env.model.dispatch("HIDE_COLUMNS_ROWS", {
9269
- sheetId: env.model.getters.getActiveSheetId(),
9270
- dimension: "ROW",
9271
- elements: rows,
9272
- });
9273
- };
9274
- const UNHIDE_ALL_ROWS_ACTION = (env) => {
9275
- const sheetId = env.model.getters.getActiveSheetId();
9276
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9277
- sheetId,
9278
- dimension: "ROW",
9279
- elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
9280
- });
9281
- };
9282
- const UNHIDE_ROWS_ACTION = (env) => {
9283
- const columns = env.model.getters.getElementsFromSelection("ROW");
9284
- env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
9285
- sheetId: env.model.getters.getActiveSheetId(),
9286
- dimension: "ROW",
9287
- elements: columns,
9288
- });
9289
- };
9290
- //------------------------------------------------------------------------------
9291
- // Sheets
9292
- //------------------------------------------------------------------------------
9293
- const CREATE_SHEET_ACTION = (env) => {
9294
- const activeSheetId = env.model.getters.getActiveSheetId();
9295
- const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
9296
- const sheetId = env.model.uuidGenerator.uuidv4();
9297
- env.model.dispatch("CREATE_SHEET", { sheetId, position });
9298
- env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
9299
- };
9300
9071
  //------------------------------------------------------------------------------
9301
9072
  // Charts
9302
9073
  //------------------------------------------------------------------------------
@@ -9355,37 +9126,13 @@
9355
9126
  //------------------------------------------------------------------------------
9356
9127
  // Style/Format
9357
9128
  //------------------------------------------------------------------------------
9358
- const FORMAT_AUTOMATIC_ACTION = (env) => setFormatter(env, "");
9359
- const FORMAT_NUMBER_ACTION = (env) => setFormatter(env, "#,##0.00");
9360
9129
  const FORMAT_PERCENT_ACTION = (env) => setFormatter(env, "0.00%");
9361
- const FORMAT_CURRENCY_ACTION = (env) => setFormatter(env, "[$$]#,##0.00");
9362
- const FORMAT_CURRENCY_ROUNDED_ACTION = (env) => setFormatter(env, "[$$]#,##0");
9363
- const FORMAT_DATE_ACTION = (env) => setFormatter(env, "m/d/yyyy");
9364
- const FORMAT_TIME_ACTION = (env) => setFormatter(env, "hh:mm:ss a");
9365
- const FORMAT_DATE_TIME_ACTION = (env) => setFormatter(env, "m/d/yyyy hh:mm:ss");
9366
- const FORMAT_DURATION_ACTION = (env) => setFormatter(env, "hhhh:mm:ss");
9367
- const FORMAT_BOLD_ACTION = (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold });
9368
- const FORMAT_ITALIC_ACTION = (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic });
9369
- const FORMAT_STRIKETHROUGH_ACTION = (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough });
9370
- const FORMAT_UNDERLINE_ACTION = (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline });
9371
- const FORMAT_CLEARFORMAT_ACTION = (env) => {
9372
- env.model.dispatch("CLEAR_FORMATTING", {
9373
- sheetId: env.model.getters.getActiveSheetId(),
9374
- target: env.model.getters.getSelectedZones(),
9375
- });
9376
- };
9377
9130
  //------------------------------------------------------------------------------
9378
9131
  // Side panel
9379
9132
  //------------------------------------------------------------------------------
9380
9133
  const OPEN_CF_SIDEPANEL_ACTION = (env) => {
9381
9134
  env.openSidePanel("ConditionalFormatting", { selection: env.model.getters.getSelectedZones() });
9382
9135
  };
9383
- const OPEN_FAR_SIDEPANEL_ACTION = (env) => {
9384
- env.openSidePanel("FindAndReplace", {});
9385
- };
9386
- const OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION = (env) => {
9387
- env.openSidePanel("CustomCurrency", {});
9388
- };
9389
9136
  const INSERT_LINK = (env) => {
9390
9137
  let { col, row } = env.model.getters.getActivePosition();
9391
9138
  env.model.dispatch("OPEN_CELL_POPOVER", { col, row, popoverType: "LinkEditor" });
@@ -9393,40 +9140,14 @@
9393
9140
  //------------------------------------------------------------------------------
9394
9141
  // Filters action
9395
9142
  //------------------------------------------------------------------------------
9396
- const FILTERS_CREATE_FILTER_TABLE = (env) => {
9397
- const sheetId = env.model.getters.getActiveSheetId();
9398
- const selection = env.model.getters.getSelection().zones;
9399
- interactiveAddFilter(env, sheetId, selection);
9400
- };
9401
- const FILTERS_REMOVE_FILTER_TABLE = (env) => {
9402
- const sheetId = env.model.getters.getActiveSheetId();
9403
- env.model.dispatch("REMOVE_FILTER_TABLE", {
9404
- sheetId,
9405
- target: env.model.getters.getSelectedZones(),
9406
- });
9407
- };
9408
9143
  const SELECTION_CONTAINS_FILTER = (env) => {
9409
9144
  const sheetId = env.model.getters.getActiveSheetId();
9410
9145
  const selectedZones = env.model.getters.getSelectedZones();
9411
9146
  return env.model.getters.doesZonesContainFilter(sheetId, selectedZones);
9412
9147
  };
9413
- const SELECTION_IS_CONTINUOUS = (env) => {
9414
- const selectedZones = env.model.getters.getSelectedZones();
9415
- return areZonesContinuous(...selectedZones);
9416
- };
9417
9148
  //------------------------------------------------------------------------------
9418
9149
  // Sorting action
9419
9150
  //------------------------------------------------------------------------------
9420
- const SORT_CELLS_ASCENDING = (env) => {
9421
- const { anchor, zones } = env.model.getters.getSelection();
9422
- const sheetId = env.model.getters.getActiveSheetId();
9423
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
9424
- };
9425
- const SORT_CELLS_DESCENDING = (env) => {
9426
- const { anchor, zones } = env.model.getters.getSelection();
9427
- const sheetId = env.model.getters.getActiveSheetId();
9428
- interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
9429
- };
9430
9151
  const IS_ONLY_ONE_RANGE = (env) => {
9431
9152
  return env.model.getters.getSelectedZones().length === 1;
9432
9153
  };
@@ -9434,14 +9155,14 @@
9434
9155
  const undo = {
9435
9156
  name: _lt("Undo"),
9436
9157
  description: "Ctrl+Z",
9437
- execute: UNDO_ACTION,
9158
+ execute: (env) => env.model.dispatch("REQUEST_UNDO"),
9438
9159
  isEnabled: (env) => env.model.getters.canUndo(),
9439
9160
  icon: "o-spreadsheet-Icon.UNDO",
9440
9161
  };
9441
9162
  const redo = {
9442
9163
  name: _lt("Redo"),
9443
9164
  description: "Ctrl+Y",
9444
- execute: REDO_ACTION,
9165
+ execute: (env) => env.model.dispatch("REQUEST_REDO"),
9445
9166
  isEnabled: (env) => env.model.getters.canRedo(),
9446
9167
  icon: "o-spreadsheet-Icon.REDO",
9447
9168
  };
@@ -9449,13 +9170,19 @@
9449
9170
  name: _lt("Copy"),
9450
9171
  description: "Ctrl+C",
9451
9172
  isReadonlyAllowed: true,
9452
- execute: COPY_ACTION,
9173
+ execute: async (env) => {
9174
+ env.model.dispatch("COPY");
9175
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9176
+ },
9453
9177
  icon: "o-spreadsheet-Icon.COPY",
9454
9178
  };
9455
9179
  const cut = {
9456
9180
  name: _lt("Cut"),
9457
9181
  description: "Ctrl+X",
9458
- execute: CUT_ACTION,
9182
+ execute: async (env) => {
9183
+ interactiveCut(env);
9184
+ await env.clipboard.write(env.model.getters.getClipboardContent());
9185
+ },
9459
9186
  icon: "o-spreadsheet-Icon.CUT",
9460
9187
  };
9461
9188
  const paste = {
@@ -9466,7 +9193,9 @@
9466
9193
  };
9467
9194
  const pasteSpecial = {
9468
9195
  name: _lt("Paste special"),
9469
- isVisible: IS_NOT_CUT_OPERATION,
9196
+ isVisible: (env) => {
9197
+ return !env.model.getters.isCutOperation();
9198
+ },
9470
9199
  icon: "o-spreadsheet-Icon.PASTE",
9471
9200
  };
9472
9201
  const pasteSpecialValue = {
@@ -9482,12 +9211,17 @@
9482
9211
  name: _lt("Find and replace"),
9483
9212
  description: "Ctrl+H",
9484
9213
  isReadonlyAllowed: true,
9485
- execute: OPEN_FAR_SIDEPANEL_ACTION,
9214
+ execute: (env) => {
9215
+ env.openSidePanel("FindAndReplace", {});
9216
+ },
9486
9217
  icon: "o-spreadsheet-Icon.FIND_AND_REPLACE",
9487
9218
  };
9488
9219
  const deleteValues = {
9489
9220
  name: _lt("Delete values"),
9490
- execute: DELETE_CONTENT_ACTION,
9221
+ execute: (env) => env.model.dispatch("DELETE_CONTENT", {
9222
+ sheetId: env.model.getters.getActiveSheetId(),
9223
+ target: env.model.getters.getSelectedZones(),
9224
+ }),
9491
9225
  };
9492
9226
  const deleteRows = {
9493
9227
  name: REMOVE_ROWS_NAME,
@@ -9521,11 +9255,19 @@
9521
9255
  };
9522
9256
  const deleteCellShiftUp = {
9523
9257
  name: _lt("Delete cell and shift up"),
9524
- execute: DELETE_CELL_SHIFT_UP,
9258
+ execute: (env) => {
9259
+ const zone = env.model.getters.getSelectedZone();
9260
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" });
9261
+ handlePasteResult(env, result);
9262
+ },
9525
9263
  };
9526
9264
  const deleteCellShiftLeft = {
9527
9265
  name: _lt("Delete cell and shift left"),
9528
- execute: DELETE_CELL_SHIFT_LEFT,
9266
+ execute: (env) => {
9267
+ const zone = env.model.getters.getSelectedZone();
9268
+ const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" });
9269
+ handlePasteResult(env, result);
9270
+ },
9529
9271
  };
9530
9272
  const mergeCells = {
9531
9273
  name: _lt("Merge cells"),
@@ -9610,9 +9352,9 @@
9610
9352
  "META",
9611
9353
  ];
9612
9354
  function arg(definition, description = "") {
9613
- return makeArg(`${definition} ${description}`);
9355
+ return makeArg(definition, description);
9614
9356
  }
9615
- function makeArg(str) {
9357
+ function makeArg(str, description) {
9616
9358
  let parts = str.match(ARG_REGEXP);
9617
9359
  let name = parts[1].trim();
9618
9360
  let types = [];
@@ -9642,7 +9384,6 @@
9642
9384
  defaultValue = param.trim().slice(8);
9643
9385
  }
9644
9386
  }
9645
- let description = parts[3].trim();
9646
9387
  const result = {
9647
9388
  name,
9648
9389
  description,
@@ -9756,6 +9497,740 @@
9756
9497
  }
9757
9498
  }
9758
9499
 
9500
+ function assertSingleColOrRow(errorStr, arg) {
9501
+ assert(() => arg.length === 1 || arg[0].length === 1, errorStr);
9502
+ }
9503
+ function assertSameDimensions(errorStr, ...args) {
9504
+ if (args.every(isMatrix)) {
9505
+ const cols = args[0].length;
9506
+ const rows = args[0][0].length;
9507
+ for (const arg of args) {
9508
+ assert(() => arg.length === cols && arg[0].length === rows, errorStr);
9509
+ }
9510
+ return;
9511
+ }
9512
+ if (args.some((arg) => Array.isArray(arg) && (arg.length !== 1 || arg[0].length !== 1))) {
9513
+ throw new Error(errorStr);
9514
+ }
9515
+ }
9516
+ function assertPositive(errorStr, arg) {
9517
+ assert(() => arg > 0, errorStr);
9518
+ }
9519
+ function assertSquareMatrix(errorStr, arg) {
9520
+ assert(() => arg.length === arg[0].length, errorStr);
9521
+ }
9522
+ function isNumberMatrix(arg) {
9523
+ return arg.every((row) => row.every((val) => typeof val === "number"));
9524
+ }
9525
+
9526
+ function getUnitMatrix(n) {
9527
+ const matrix = Array(n);
9528
+ for (let i = 0; i < n; i++) {
9529
+ matrix[i] = Array(n).fill(0);
9530
+ matrix[i][i] = 1;
9531
+ }
9532
+ return matrix;
9533
+ }
9534
+ /**
9535
+ * Invert a matrix and compute its determinant using Gaussian Elimination.
9536
+ *
9537
+ * The Matrix should be a square matrix, and should be indexed [col][row] instead of the
9538
+ * standard mathematical indexing [row][col].
9539
+ */
9540
+ function invertMatrix(M) {
9541
+ // Use Gaussian Elimination to calculate the inverse:
9542
+ // (1) 'augment' the matrix (left) by the identity (on the right)
9543
+ // (2) Turn the matrix on the left into the identity using elementary row operations
9544
+ // (3) The matrix on the right becomes the inverse (was the identity matrix)
9545
+ //
9546
+ // There are 3 elementary row operations:
9547
+ // (a) Swap 2 rows. This multiply the determinant by -1.
9548
+ // (b) Multiply a row by a scalar. This multiply the determinant by that scalar.
9549
+ // (c) Add to a row a multiple of another row. This does not change the determinant.
9550
+ if (M.length !== M[0].length) {
9551
+ throw new Error(`Function [[FUNCTION_NAME]] invert matrix error, only square matrices are invertible`);
9552
+ }
9553
+ let determinant = 1;
9554
+ const dim = M.length;
9555
+ const I = getUnitMatrix(dim);
9556
+ const C = M.map((row) => row.slice());
9557
+ // Perform elementary row operations
9558
+ for (let pivot = 0; pivot < dim; pivot++) {
9559
+ let diagonalElement = C[pivot][pivot];
9560
+ // if we have a 0 on the diagonal we'll need to swap with a lower row
9561
+ if (diagonalElement == 0) {
9562
+ //look through every row below the i'th row
9563
+ for (let row = pivot + 1; row < dim; row++) {
9564
+ //if the ii'th row has a non-0 in the i'th col, swap it with that row
9565
+ if (C[pivot][row] != 0) {
9566
+ swapMatrixRows(C, pivot, row);
9567
+ swapMatrixRows(I, pivot, row);
9568
+ determinant *= -1;
9569
+ break;
9570
+ }
9571
+ }
9572
+ diagonalElement = C[pivot][pivot];
9573
+ //if it's still 0, matrix isn't invertible
9574
+ if (diagonalElement === 0) {
9575
+ return { determinant: 0 };
9576
+ }
9577
+ }
9578
+ // Scale this row down by e (so we have a 1 on the diagonal)
9579
+ for (let col = 0; col < dim; col++) {
9580
+ C[col][pivot] = C[col][pivot] / diagonalElement;
9581
+ I[col][pivot] = I[col][pivot] / diagonalElement;
9582
+ }
9583
+ determinant *= diagonalElement;
9584
+ // Subtract a multiple of the current row from ALL of
9585
+ // the other rows so that there will be 0's in this column in the
9586
+ // rows above and below this one
9587
+ for (let row = 0; row < dim; row++) {
9588
+ if (row == pivot) {
9589
+ continue;
9590
+ }
9591
+ // We want to change this element to 0
9592
+ const e = C[pivot][row];
9593
+ // Subtract (the row above(or below) scaled by e) from (the
9594
+ // current row) but start at the i'th column and assume all the
9595
+ // stuff left of diagonal is 0 (which it should be if we made this
9596
+ // algorithm correctly)
9597
+ for (let col = 0; col < dim; col++) {
9598
+ C[col][row] -= e * C[col][pivot];
9599
+ I[col][row] -= e * I[col][pivot];
9600
+ }
9601
+ }
9602
+ }
9603
+ // We've done all operations, C should be the identity matrix I should be the inverse
9604
+ return { inverted: I, determinant };
9605
+ }
9606
+ function swapMatrixRows(matrix, row1, row2) {
9607
+ for (let i = 0; i < matrix.length; i++) {
9608
+ const tmp = matrix[i][row1];
9609
+ matrix[i][row1] = matrix[i][row2];
9610
+ matrix[i][row2] = tmp;
9611
+ }
9612
+ }
9613
+ /**
9614
+ * Matrix multiplication of 2 matrices.
9615
+ * ex: matrix1 : n x l, matrix2 : m x n => result : m x l
9616
+ *
9617
+ * Note: we use indexing [col][row] instead of the standard mathematical notation [row][col]
9618
+ */
9619
+ function multiplyMatrices(matrix1, matrix2) {
9620
+ if (matrix1.length !== matrix2[0].length) {
9621
+ throw new Error(_lt("Cannot multiply matrices : incompatible matrices size."));
9622
+ }
9623
+ const rowsM1 = matrix1[0].length;
9624
+ const colsM2 = matrix2.length;
9625
+ const n = matrix1.length;
9626
+ const result = Array(colsM2);
9627
+ for (let col = 0; col < colsM2; col++) {
9628
+ result[col] = Array(rowsM1);
9629
+ for (let row = 0; row < rowsM1; row++) {
9630
+ let sum = 0;
9631
+ for (let k = 0; k < n; k++) {
9632
+ sum += matrix1[k][row] * matrix2[col][k];
9633
+ }
9634
+ result[col][row] = sum;
9635
+ }
9636
+ }
9637
+ return result;
9638
+ }
9639
+
9640
+ // -----------------------------------------------------------------------------
9641
+ // ARRAY_CONSTRAIN
9642
+ // -----------------------------------------------------------------------------
9643
+ const ARRAY_CONSTRAIN = {
9644
+ description: _lt("Returns a result array constrained to a specific width and height."),
9645
+ args: [
9646
+ arg("input_range (any, range<any>)", _lt("The range to constrain.")),
9647
+ arg("rows (number)", _lt("The number of rows in the constrained array.")),
9648
+ arg("columns (number)", _lt("The number of columns in the constrained array.")),
9649
+ ],
9650
+ returns: ["RANGE<ANY>"],
9651
+ //TODO computeFormat
9652
+ compute: function (array, rows, columns) {
9653
+ const _array = toMatrixArgValue(array);
9654
+ const _rowsArg = toInteger(rows);
9655
+ const _columnsArg = toInteger(columns);
9656
+ assertPositive(_lt("The rows argument (%s) must be strictly positive.", _rowsArg.toString()), _rowsArg);
9657
+ assertPositive(_lt("The columns argument (%s) must be strictly positive.", _rowsArg.toString()), _columnsArg);
9658
+ const _rows = Math.min(_rowsArg, _array[0].length);
9659
+ const _columns = Math.min(_columnsArg, _array.length);
9660
+ const result = Array(_columns);
9661
+ for (let col = 0; col < _columns; col++) {
9662
+ result[col] = Array(_rows);
9663
+ for (let row = 0; row < _rows; row++) {
9664
+ result[col][row] = toCellValue(_array[col][row]);
9665
+ }
9666
+ }
9667
+ return result;
9668
+ },
9669
+ isExported: false,
9670
+ };
9671
+ // -----------------------------------------------------------------------------
9672
+ // CHOOSECOLS
9673
+ // -----------------------------------------------------------------------------
9674
+ const CHOOSECOLS = {
9675
+ description: _lt("Creates a new array from the selected columns in the existing range."),
9676
+ args: [
9677
+ arg("array (any, range<any>)", _lt("The array that contains the columns to be returned.")),
9678
+ arg("col_num (number, range<number>)", _lt("The first column index of the columns to be returned.")),
9679
+ arg("col_num2 (number, range<number>, repeating)", _lt("The columns indexes of the columns to be returned.")),
9680
+ ],
9681
+ returns: ["RANGE<ANY>"],
9682
+ //TODO computeFormat
9683
+ compute: function (array, ...columns) {
9684
+ const _array = toMatrixArgValue(array);
9685
+ const _columns = flattenRowFirst(columns, toInteger);
9686
+ assert(() => _columns.every((col) => col > 0 && col <= _array.length), _lt("The columns arguments must be between 1 and %s (got %s).", _array.length.toString(), (_columns.find((col) => col <= 0 || col > _array.length) || 0).toString()));
9687
+ const result = Array(_columns.length);
9688
+ for (let i = 0; i < _columns.length; i++) {
9689
+ const colIndex = _columns[i] - 1; // -1 because columns arguments are 1-indexed
9690
+ result[i] = _array[colIndex];
9691
+ }
9692
+ return toCellValueMatrix(result);
9693
+ },
9694
+ isExported: true,
9695
+ };
9696
+ // -----------------------------------------------------------------------------
9697
+ // CHOOSEROWS
9698
+ // -----------------------------------------------------------------------------
9699
+ const CHOOSEROWS = {
9700
+ description: _lt("Creates a new array from the selected rows in the existing range."),
9701
+ args: [
9702
+ arg("array (any, range<any>)", _lt("The array that contains the rows to be returned.")),
9703
+ arg("row_num (number, range<number>)", _lt("The first row index of the rows to be returned.")),
9704
+ arg("row_num2 (number, range<number>, repeating)", _lt("The rows indexes of the rows to be returned.")),
9705
+ ],
9706
+ returns: ["RANGE<ANY>"],
9707
+ //TODO computeFormat
9708
+ compute: function (array, ...rows) {
9709
+ const _array = toMatrixArgValue(array);
9710
+ const _rows = flattenRowFirst(rows, toInteger);
9711
+ assert(() => _rows.every((row) => row > 0 && row <= _array[0].length), _lt("The rows arguments must be between 1 and %s (got %s).", _array[0].length.toString(), (_rows.find((row) => row <= 0 || row > _array[0].length) || 0).toString()));
9712
+ const result = Array(_array.length);
9713
+ for (let col = 0; col < _array.length; col++) {
9714
+ result[col] = Array(_rows.length);
9715
+ for (let row = 0; row < _rows.length; row++) {
9716
+ const rowIndex = _rows[row] - 1; // -1 because rows arguments are 1-indexed
9717
+ result[col][row] = toCellValue(_array[col][rowIndex]);
9718
+ }
9719
+ }
9720
+ return result;
9721
+ },
9722
+ isExported: true,
9723
+ };
9724
+ // -----------------------------------------------------------------------------
9725
+ // EXPAND
9726
+ // -----------------------------------------------------------------------------
9727
+ const EXPAND = {
9728
+ description: _lt("Expands or pads an array to specified row and column dimensions."),
9729
+ args: [
9730
+ arg("array (any, range<any>)", _lt("The array to expand.")),
9731
+ arg("rows (number)", _lt("The number of rows in the expanded array. If missing, rows will not be expanded.")),
9732
+ arg("columns (number, optional)", _lt("The number of columns in the expanded array. If missing, columns will not be expanded.")),
9733
+ arg("pad_with (any, default=0)", _lt("The value with which to pad.")), // @compatibility: on Excel, pad with #N/A
9734
+ ],
9735
+ returns: ["RANGE<ANY>"],
9736
+ //TODO computeFormat
9737
+ compute: function (array, rows, columns, padWith = 0) {
9738
+ const _array = toMatrixArgValue(array);
9739
+ const _rows = toInteger(rows);
9740
+ const _columns = columns !== undefined ? toInteger(columns) : _array.length;
9741
+ const _padWith = padWith !== undefined && padWith !== null ? padWith : 0; // TODO : Replace with #N/A errors once it's supported
9742
+ assert(() => _rows >= _array[0].length, _lt("The rows arguments (%s) must be greater or equal than the number of rows of the array.", _rows.toString()));
9743
+ assert(() => _columns >= _array.length, _lt("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _columns.toString()));
9744
+ const result = [];
9745
+ for (let col = 0; col < _columns; col++) {
9746
+ result[col] = [];
9747
+ for (let row = 0; row < _rows; row++) {
9748
+ if (col >= _array.length || row >= _array[col].length) {
9749
+ result[col][row] = _padWith;
9750
+ }
9751
+ else {
9752
+ result[col][row] = _array[col][row] ?? 0;
9753
+ }
9754
+ }
9755
+ }
9756
+ return result;
9757
+ },
9758
+ isExported: true,
9759
+ };
9760
+ // -----------------------------------------------------------------------------
9761
+ // FLATTEN
9762
+ // -----------------------------------------------------------------------------
9763
+ const FLATTEN = {
9764
+ description: _lt("Flattens all the values from one or more ranges into a single column."),
9765
+ args: [
9766
+ arg("range (any, range<any>)", _lt("The first range to flatten.")),
9767
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to flatten.")),
9768
+ ],
9769
+ returns: ["RANGE<ANY>"],
9770
+ compute: function (...ranges) {
9771
+ return [flattenRowFirst(ranges, toCellValue)];
9772
+ },
9773
+ isExported: false,
9774
+ };
9775
+ // -----------------------------------------------------------------------------
9776
+ // FREQUENCY
9777
+ // -----------------------------------------------------------------------------
9778
+ const FREQUENCY = {
9779
+ description: _lt("Calculates the frequency distribution of a range."),
9780
+ args: [
9781
+ arg("data (range<number>)", _lt("The array of ranges containing the values to be counted.")),
9782
+ arg("classes (number, range<number>)", _lt("The range containing the set of classes.")),
9783
+ ],
9784
+ returns: ["RANGE<NUMBER>"],
9785
+ compute: function (data, classes) {
9786
+ const _data = flattenRowFirst([data], (val) => val).filter((val) => typeof val === "number");
9787
+ const _classes = flattenRowFirst([classes], (val) => val).filter((val) => typeof val === "number");
9788
+ /**
9789
+ * Returns the frequency distribution of the data in the classes, ie. the number of elements in the range
9790
+ * between each classes.
9791
+ *
9792
+ * For example:
9793
+ * - data = [1, 3, 2, 5, 4]
9794
+ * - classes = [3, 5, 1]
9795
+ *
9796
+ * The result will be:
9797
+ * - 2 ==> number of elements 1 > el >= 3
9798
+ * - 2 ==> number of elements 3 > el >= 5
9799
+ * - 1 ==> number of elements <= 1
9800
+ * - 0 ==> number of elements > 5
9801
+ *
9802
+ * @compatibility: GSheet sort the input classes. We do the implemntation of Excel, where we kee the classes unsorted.
9803
+ */
9804
+ const sortedClasses = _classes
9805
+ .map((value, index) => ({ initialIndex: index, value, count: 0 }))
9806
+ .sort((a, b) => a.value - b.value);
9807
+ sortedClasses.push({ initialIndex: sortedClasses.length, value: Infinity, count: 0 });
9808
+ const sortedData = _data.sort((a, b) => a - b);
9809
+ let index = 0;
9810
+ for (const val of sortedData) {
9811
+ while (val > sortedClasses[index].value && index < sortedClasses.length - 1) {
9812
+ index++;
9813
+ }
9814
+ sortedClasses[index].count++;
9815
+ }
9816
+ const result = sortedClasses
9817
+ .sort((a, b) => a.initialIndex - b.initialIndex)
9818
+ .map((val) => val.count);
9819
+ return [result];
9820
+ },
9821
+ isExported: true,
9822
+ };
9823
+ // -----------------------------------------------------------------------------
9824
+ // HSTACK
9825
+ // -----------------------------------------------------------------------------
9826
+ const HSTACK = {
9827
+ description: _lt("Appends ranges horizontally and in sequence to return a larger array."),
9828
+ args: [
9829
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
9830
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
9831
+ ],
9832
+ returns: ["RANGE<ANY>"],
9833
+ //TODO computeFormat
9834
+ compute: function (...ranges) {
9835
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
9836
+ const nRows = Math.max(..._ranges.map((range) => range[0].length));
9837
+ const colArray = [];
9838
+ for (const range of _ranges) {
9839
+ for (const col of range) {
9840
+ //TODO: fill with #N/A for unavailable values instead of zeroes
9841
+ const paddedCol = Array(nRows).fill(0);
9842
+ for (let i = 0; i < col.length; i++) {
9843
+ paddedCol[i] = toCellValue(col[i]);
9844
+ }
9845
+ colArray.push(paddedCol);
9846
+ }
9847
+ }
9848
+ return colArray;
9849
+ },
9850
+ isExported: true,
9851
+ };
9852
+ // -----------------------------------------------------------------------------
9853
+ // MDETERM
9854
+ // -----------------------------------------------------------------------------
9855
+ const MDETERM = {
9856
+ description: _lt("Returns the matrix determinant of a square matrix."),
9857
+ args: [
9858
+ arg("square_matrix (number, range<number>)", _lt("An range with an equal number of rows and columns representing a matrix whose determinant will be calculated.")),
9859
+ ],
9860
+ returns: ["NUMBER"],
9861
+ compute: function (matrix) {
9862
+ const _matrix = toMatrixArgValue(matrix);
9863
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9864
+ if (!isNumberMatrix(_matrix)) {
9865
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9866
+ }
9867
+ const { determinant } = invertMatrix(_matrix);
9868
+ return determinant;
9869
+ },
9870
+ isExported: true,
9871
+ };
9872
+ // -----------------------------------------------------------------------------
9873
+ // MINVERSE
9874
+ // -----------------------------------------------------------------------------
9875
+ const MINVERSE = {
9876
+ description: _lt("Returns the multiplicative inverse of a square matrix."),
9877
+ args: [
9878
+ arg("square_matrix (number, range<number>)", _lt("An range with an equal number of rows and columns representing a matrix whose multiplicative inverse will be calculated.")),
9879
+ ],
9880
+ returns: ["RANGE<NUMBER>"],
9881
+ compute: function (matrix) {
9882
+ const _matrix = toMatrixArgValue(matrix);
9883
+ assertSquareMatrix(_lt("The argument square_matrix must have the same number of columns and rows."), _matrix);
9884
+ if (!isNumberMatrix(_matrix)) {
9885
+ throw new Error(_lt("The argument square_matrix must be a matrix of numbers."));
9886
+ }
9887
+ const { inverted } = invertMatrix(_matrix);
9888
+ if (!inverted) {
9889
+ throw new Error(_lt("The matrix is not invertible."));
9890
+ }
9891
+ return inverted;
9892
+ },
9893
+ isExported: true,
9894
+ };
9895
+ // -----------------------------------------------------------------------------
9896
+ // MMULT
9897
+ // -----------------------------------------------------------------------------
9898
+ const MMULT = {
9899
+ description: _lt("Calculates the matrix product of two matrices."),
9900
+ args: [
9901
+ arg("matrix1 (number, range<number>)", _lt("The first matrix in the matrix multiplication operation.")),
9902
+ arg("matrix2 (number, range<number>)", _lt("The second matrix in the matrix multiplication operation.")),
9903
+ ],
9904
+ returns: ["RANGE<NUMBER>"],
9905
+ compute: function (matrix1, matrix2) {
9906
+ const _matrix1 = toMatrixArgValue(matrix1);
9907
+ const _matrix2 = toMatrixArgValue(matrix2);
9908
+ assert(() => _matrix1.length === _matrix2[0].length, _lt("In [[FUNCTION_NAME]], the number of columns of the first matrix (%s) must be equal to the \
9909
+ number of rows of the second matrix (%s).", _matrix1.length.toString(), _matrix2[0].length.toString()));
9910
+ if (!isNumberMatrix(_matrix1) || !isNumberMatrix(_matrix2)) {
9911
+ throw new Error(_lt("The arguments matrix1 and matrix2 must be matrices of numbers."));
9912
+ }
9913
+ return multiplyMatrices(_matrix1, _matrix2);
9914
+ },
9915
+ isExported: true,
9916
+ };
9917
+ // -----------------------------------------------------------------------------
9918
+ // SUMPRODUCT
9919
+ // -----------------------------------------------------------------------------
9920
+ const SUMPRODUCT = {
9921
+ description: _lt("Calculates the sum of the products of corresponding entries in equal-sized ranges."),
9922
+ args: [
9923
+ arg("range1 (number, range<number>)", _lt("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
9924
+ arg("range2 (number, range<number>, repeating)", _lt("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
9925
+ ],
9926
+ returns: ["NUMBER"],
9927
+ compute: function (...args) {
9928
+ assertSameDimensions(_lt("All the ranges must have the same dimensions."), ...args);
9929
+ const _args = args.map(toMatrixArgValue);
9930
+ let result = 0;
9931
+ for (let i = 0; i < _args[0].length; i++) {
9932
+ for (let j = 0; j < _args[0][i].length; j++) {
9933
+ if (!_args.every((range) => typeof range[i][j] === "number")) {
9934
+ continue;
9935
+ }
9936
+ let product = 1;
9937
+ for (const range of _args) {
9938
+ product *= toNumber(range[i][j]);
9939
+ }
9940
+ result += product;
9941
+ }
9942
+ }
9943
+ return result;
9944
+ },
9945
+ isExported: true,
9946
+ };
9947
+ // -----------------------------------------------------------------------------
9948
+ // SUMX2MY2
9949
+ // -----------------------------------------------------------------------------
9950
+ /**
9951
+ * Return the sum of the callback applied to each pair of values in the two arrays.
9952
+ *
9953
+ * Ignore the pairs X,Y where one of the value isn't a number. Throw an error if no pair of numbers is found.
9954
+ */
9955
+ function getSumXAndY(arrayX, arrayY, cb) {
9956
+ assertSameDimensions("The arguments array_x and array_y must have the same dimensions.", arrayX, arrayY);
9957
+ const _arrayX = toMatrixArgValue(arrayX);
9958
+ const _arrayY = toMatrixArgValue(arrayY);
9959
+ let validPairFound = false;
9960
+ let result = 0;
9961
+ for (const i in _arrayX) {
9962
+ for (const j in _arrayX[i]) {
9963
+ const arrayXValue = _arrayX[i][j];
9964
+ const arrayYValue = _arrayY[i][j];
9965
+ if (typeof arrayXValue !== "number" || typeof arrayYValue !== "number") {
9966
+ continue;
9967
+ }
9968
+ validPairFound = true;
9969
+ result += cb(arrayXValue, arrayYValue);
9970
+ }
9971
+ }
9972
+ if (!validPairFound) {
9973
+ throw new Error("The arguments array_x and array_y must contain at least one pair of numbers.");
9974
+ }
9975
+ return result;
9976
+ }
9977
+ const SUMX2MY2 = {
9978
+ description: _lt("Calculates the sum of the difference of the squares of the values in two array."),
9979
+ args: [
9980
+ arg("array_x (number, range<number>)", _lt("The array or range of values whose squares will be reduced by the squares of corresponding entries in array_y and added together.")),
9981
+ arg("array_y (number, range<number>)", _lt("The array or range of values whose squares will be subtracted from the squares of corresponding entries in array_x and added together.")),
9982
+ ],
9983
+ returns: ["NUMBER"],
9984
+ compute: function (arrayX, arrayY) {
9985
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 - y ** 2);
9986
+ },
9987
+ isExported: true,
9988
+ };
9989
+ // -----------------------------------------------------------------------------
9990
+ // SUMX2PY2
9991
+ // -----------------------------------------------------------------------------
9992
+ const SUMX2PY2 = {
9993
+ description: _lt("Calculates the sum of the sum of the squares of the values in two array."),
9994
+ args: [
9995
+ arg("array_x (number, range<number>)", _lt("The array or range of values whose squares will be added to the squares of corresponding entries in array_y and added together.")),
9996
+ arg("array_y (number, range<number>)", _lt("The array or range of values whose squares will be added to the squares of corresponding entries in array_x and added together.")),
9997
+ ],
9998
+ returns: ["NUMBER"],
9999
+ compute: function (arrayX, arrayY) {
10000
+ return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 + y ** 2);
10001
+ },
10002
+ isExported: true,
10003
+ };
10004
+ // -----------------------------------------------------------------------------
10005
+ // SUMXMY2
10006
+ // -----------------------------------------------------------------------------
10007
+ const SUMXMY2 = {
10008
+ description: _lt("Calculates the sum of squares of the differences of values in two array."),
10009
+ args: [
10010
+ arg("array_x (number, range<number>)", _lt("The array or range of values that will be reduced by corresponding entries in array_y, squared, and added together.")),
10011
+ arg("array_y (number, range<number>)", _lt("The array or range of values that will be subtracted from corresponding entries in array_x, the result squared, and all such results added together.")),
10012
+ ],
10013
+ returns: ["NUMBER"],
10014
+ compute: function (arrayX, arrayY) {
10015
+ return getSumXAndY(arrayX, arrayY, (x, y) => (x - y) ** 2);
10016
+ },
10017
+ isExported: true,
10018
+ };
10019
+ // -----------------------------------------------------------------------------
10020
+ // TOCOL
10021
+ // -----------------------------------------------------------------------------
10022
+ const TO_COL_ROW_DEFAULT_IGNORE = 0;
10023
+ const TO_COL_ROW_DEFAULT_SCAN = false;
10024
+ const TO_COL_ROW_ARGS = [
10025
+ arg("array (any, range<any>)", _lt("The array which will be transformed.")),
10026
+ arg(`ignore (number, default=${TO_COL_ROW_DEFAULT_IGNORE})`, _lt("The control to ignore blanks and errors. 0 (default) is to keep all values, 1 is to ignore blanks, 2 is to ignore errors, and 3 is to ignore blanks and errors.")),
10027
+ arg(`scan_by_column (number, default=${TO_COL_ROW_DEFAULT_SCAN})`, _lt("Whether the array should be scanned by column. True scans the array by column and false (default) \
10028
+ scans the array by row.")),
10029
+ ];
10030
+ const TOCOL = {
10031
+ description: _lt("Transforms a range of cells into a single column."),
10032
+ args: TO_COL_ROW_ARGS,
10033
+ returns: ["RANGE<ANY>"],
10034
+ //TODO compute format
10035
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10036
+ const _array = toMatrixArgValue(array);
10037
+ const _ignore = toInteger(ignore);
10038
+ const _scanByColumn = toBoolean(scanByColumn);
10039
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10040
+ const mappedFn = (acc, item) => {
10041
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10042
+ // the array w/o crashing
10043
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10044
+ return acc;
10045
+ }
10046
+ acc.push(toCellValue(item));
10047
+ return acc;
10048
+ };
10049
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10050
+ if (result.length === 0) {
10051
+ throw new NotAvailableError(_lt("No results for the given arguments of TOCOL."));
10052
+ }
10053
+ return [result];
10054
+ },
10055
+ isExported: true,
10056
+ };
10057
+ // -----------------------------------------------------------------------------
10058
+ // TOROW
10059
+ // -----------------------------------------------------------------------------
10060
+ const TOROW = {
10061
+ description: _lt("Transforms a range of cells into a single row."),
10062
+ args: TO_COL_ROW_ARGS,
10063
+ returns: ["RANGE<ANY>"],
10064
+ //TODO compute format
10065
+ compute: function (array, ignore = TO_COL_ROW_DEFAULT_IGNORE, scanByColumn = TO_COL_ROW_DEFAULT_SCAN) {
10066
+ const _array = toMatrixArgValue(array);
10067
+ const _ignore = toInteger(ignore);
10068
+ const _scanByColumn = toBoolean(scanByColumn);
10069
+ assert(() => _ignore >= 0 && _ignore <= 3, _lt("Argument ignore must be between 0 and 3"));
10070
+ const mappedFn = (acc, item) => {
10071
+ // TODO : implement ignore value 2 (ignore error) & 3 (ignore blanks and errors) once we can have errors in
10072
+ // the array w/o crashing
10073
+ if ((_ignore === 1 || _ignore === 3) && (item === undefined || item === null)) {
10074
+ return acc;
10075
+ }
10076
+ acc.push([toCellValue(item)]);
10077
+ return acc;
10078
+ };
10079
+ const result = reduceAny([_array], mappedFn, [], _scanByColumn ? "colFirst" : "rowFirst");
10080
+ if (result.length === 0 || result[0].length === 0) {
10081
+ throw new NotAvailableError(_lt("No results for the given arguments of TOROW."));
10082
+ }
10083
+ return result;
10084
+ },
10085
+ isExported: true,
10086
+ };
10087
+ // -----------------------------------------------------------------------------
10088
+ // TRANSPOSE
10089
+ // -----------------------------------------------------------------------------
10090
+ const TRANSPOSE = {
10091
+ description: _lt("Transposes the rows and columns of a range."),
10092
+ args: [arg("range (any, range<any>)", _lt("The range to be transposed."))],
10093
+ returns: ["RANGE<ANY>"],
10094
+ computeFormat: (values) => {
10095
+ if (!values.format) {
10096
+ return undefined;
10097
+ }
10098
+ if (!isMatrix(values.format)) {
10099
+ return values.format;
10100
+ }
10101
+ return transpose2dArray(values.format);
10102
+ },
10103
+ compute: function (values) {
10104
+ const _values = toMatrixArgValue(values);
10105
+ return transpose2dArray(_values, toCellValue);
10106
+ },
10107
+ isExported: true,
10108
+ };
10109
+ // -----------------------------------------------------------------------------
10110
+ // VSTACK
10111
+ // -----------------------------------------------------------------------------
10112
+ const VSTACK = {
10113
+ description: _lt("Appends ranges vertically and in sequence to return a larger array."),
10114
+ args: [
10115
+ arg("range1 (any, range<any>)", _lt("The first range to be appended.")),
10116
+ arg("range2 (any, range<any>, repeating)", _lt("Additional ranges to add to range1.")),
10117
+ ],
10118
+ returns: ["RANGE<ANY>"],
10119
+ //TODO computeFormat
10120
+ compute: function (...ranges) {
10121
+ const _ranges = ranges.map((range) => toMatrixArgValue(range));
10122
+ const nCols = Math.max(..._ranges.map((range) => range.length));
10123
+ const nRows = _ranges.reduce((acc, range) => acc + range[0].length, 0);
10124
+ const result = Array(nCols)
10125
+ .fill([])
10126
+ .map(() => Array(nRows).fill(0)); // TODO fill with #N/A
10127
+ let currentRow = 0;
10128
+ for (const range of _ranges) {
10129
+ for (let col = 0; col < range.length; col++) {
10130
+ for (let row = 0; row < range[col].length; row++) {
10131
+ result[col][currentRow + row] = toCellValue(range[col][row]);
10132
+ }
10133
+ }
10134
+ currentRow += range[0].length;
10135
+ }
10136
+ return result;
10137
+ },
10138
+ isExported: true,
10139
+ };
10140
+ // -----------------------------------------------------------------------------
10141
+ // WRAPCOLS
10142
+ // -----------------------------------------------------------------------------
10143
+ const WRAPCOLS = {
10144
+ description: _lt("Wraps the provided row or column of cells by columns after a specified number of elements to form a new array."),
10145
+ args: [
10146
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10147
+ arg("wrap_count (number)", _lt("The maximum number of cells for each column, rounded down to the nearest whole number.")),
10148
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10149
+ _lt("The value with which to fill the extra cells in the range.")),
10150
+ ],
10151
+ returns: ["RANGE<ANY>"],
10152
+ //TODO computeFormat
10153
+ compute: function (range, wrapCount, padWith = 0) {
10154
+ const _range = toMatrixArgValue(range);
10155
+ const nOfRows = toInteger(wrapCount);
10156
+ const _padWith = padWith === null ? 0 : padWith;
10157
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10158
+ const values = _range.flat();
10159
+ const nOfCols = Math.ceil(values.length / nOfRows);
10160
+ const result = Array(nOfCols);
10161
+ for (let col = 0; col < nOfCols; col++) {
10162
+ result[col] = Array(nOfRows).fill(_padWith);
10163
+ for (let row = 0; row < nOfRows; row++) {
10164
+ const index = col * nOfRows + row;
10165
+ if (index < values.length) {
10166
+ result[col][row] = toCellValue(values[index]);
10167
+ }
10168
+ }
10169
+ }
10170
+ return result;
10171
+ },
10172
+ isExported: true,
10173
+ };
10174
+ // -----------------------------------------------------------------------------
10175
+ // WRAPROWS
10176
+ // -----------------------------------------------------------------------------
10177
+ const WRAPROWS = {
10178
+ description: _lt("Wraps the provided row or column of cells by rows after a specified number of elements to form a new array."),
10179
+ args: [
10180
+ arg("range (any, range<any>)", _lt("The range to wrap.")),
10181
+ arg("wrap_count (number)", _lt("The maximum number of cells for each row, rounded down to the nearest whole number.")),
10182
+ arg("pad_with (any, default=0)", // TODO : replace with #N/A
10183
+ _lt("The value with which to fill the extra cells in the range.")),
10184
+ ],
10185
+ returns: ["RANGE<ANY>"],
10186
+ //TODO computeFormat
10187
+ compute: function (range, wrapCount, padWith = 0) {
10188
+ const _range = toMatrixArgValue(range);
10189
+ const nOfCols = toInteger(wrapCount);
10190
+ const _padWith = padWith === null ? 0 : padWith;
10191
+ assertSingleColOrRow(_lt("Argument range must be a single row or column."), _range);
10192
+ const values = _range.flat();
10193
+ const nOfRows = Math.ceil(values.length / nOfCols);
10194
+ const result = Array(nOfCols)
10195
+ .fill([])
10196
+ .map(() => Array(nOfRows).fill(_padWith));
10197
+ for (let row = 0; row < nOfRows; row++) {
10198
+ for (let col = 0; col < nOfCols; col++) {
10199
+ const index = row * nOfCols + col;
10200
+ if (index < values.length) {
10201
+ result[col][row] = toCellValue(values[index]);
10202
+ }
10203
+ }
10204
+ }
10205
+ return result;
10206
+ },
10207
+ isExported: true,
10208
+ };
10209
+
10210
+ var array = /*#__PURE__*/Object.freeze({
10211
+ __proto__: null,
10212
+ ARRAY_CONSTRAIN: ARRAY_CONSTRAIN,
10213
+ CHOOSECOLS: CHOOSECOLS,
10214
+ CHOOSEROWS: CHOOSEROWS,
10215
+ EXPAND: EXPAND,
10216
+ FLATTEN: FLATTEN,
10217
+ FREQUENCY: FREQUENCY,
10218
+ HSTACK: HSTACK,
10219
+ MDETERM: MDETERM,
10220
+ MINVERSE: MINVERSE,
10221
+ MMULT: MMULT,
10222
+ SUMPRODUCT: SUMPRODUCT,
10223
+ SUMX2MY2: SUMX2MY2,
10224
+ SUMX2PY2: SUMX2PY2,
10225
+ SUMXMY2: SUMXMY2,
10226
+ TOCOL: TOCOL,
10227
+ TOROW: TOROW,
10228
+ TRANSPOSE: TRANSPOSE,
10229
+ VSTACK: VSTACK,
10230
+ WRAPCOLS: WRAPCOLS,
10231
+ WRAPROWS: WRAPROWS
10232
+ });
10233
+
9759
10234
  // -----------------------------------------------------------------------------
9760
10235
  // FORMAT.LARGE.NUMBER
9761
10236
  // -----------------------------------------------------------------------------
@@ -10411,6 +10886,22 @@
10411
10886
  isExported: true,
10412
10887
  };
10413
10888
  // -----------------------------------------------------------------------------
10889
+ // MUNIT
10890
+ // -----------------------------------------------------------------------------
10891
+ const MUNIT = {
10892
+ description: _lt("Returns a n x n unit matrix, where n is the input dimension."),
10893
+ args: [
10894
+ arg("dimension (number)", _lt("An integer specifying the dimension size of the unit matrix. It must be positive.")),
10895
+ ],
10896
+ returns: ["RANGE<NUMBER>"],
10897
+ compute: function (n) {
10898
+ const _n = toInteger(n);
10899
+ assertPositive(_lt("The argument dimension must be positive"), _n);
10900
+ return getUnitMatrix(_n);
10901
+ },
10902
+ isExported: true,
10903
+ };
10904
+ // -----------------------------------------------------------------------------
10414
10905
  // ODD
10415
10906
  // -----------------------------------------------------------------------------
10416
10907
  const ODD = {
@@ -10509,6 +11000,47 @@
10509
11000
  isExported: true,
10510
11001
  };
10511
11002
  // -----------------------------------------------------------------------------
11003
+ // RANDARRAY
11004
+ // -----------------------------------------------------------------------------
11005
+ const RANDARRAY = {
11006
+ description: _lt("Returns a grid of random numbers between 0 inclusive and 1 exclusive."),
11007
+ args: [
11008
+ arg("rows (number, default=1)", _lt("The number of rows to be returned.")),
11009
+ arg("columns (number, default=1)", _lt("The number of columns to be returned.")),
11010
+ arg("min (number, default=0)", _lt("The minimum number you would like returned.")),
11011
+ arg("max (number, default=1)", _lt("The maximum number you would like returned.")),
11012
+ arg("whole_number (number, default=FALSE)", _lt("Return a whole number or a decimal value.")),
11013
+ ],
11014
+ returns: ["RANGE<NUMBER>"],
11015
+ compute: function (rows = 1, columns = 1, min = 0, max = 1, whole_number = false) {
11016
+ const _cols = toInteger(columns);
11017
+ const _rows = toInteger(rows);
11018
+ const _min = toNumber(min);
11019
+ const _max = toNumber(max);
11020
+ const _whole_number = toBoolean(whole_number);
11021
+ assertPositive(_lt("The number columns (%s) must be positive.", _cols.toString()), _cols);
11022
+ assertPositive(_lt("The number rows (%s) must be positive.", _rows.toString()), _rows);
11023
+ assert(() => _min <= _max, _lt("The maximum (%s) must be greater than or equal to the minimum (%s).", _max.toString(), _min.toString()));
11024
+ if (_whole_number) {
11025
+ assert(() => Number.isInteger(_min) && Number.isInteger(_max), _lt("The maximum (%s) and minimum (%s) must be integers when whole_number is TRUE.", _max.toString(), _min.toString()));
11026
+ }
11027
+ const result = Array(_cols);
11028
+ for (let col = 0; col < _cols; col++) {
11029
+ result[col] = Array(_rows);
11030
+ for (let row = 0; row < _rows; row++) {
11031
+ if (!_whole_number) {
11032
+ result[col][row] = _min + Math.random() * (_max - _min);
11033
+ }
11034
+ else {
11035
+ result[col][row] = Math.floor(Math.random() * (_max - _min + 1) + _min);
11036
+ }
11037
+ }
11038
+ }
11039
+ return result;
11040
+ },
11041
+ isExported: true,
11042
+ };
11043
+ // -----------------------------------------------------------------------------
10512
11044
  // RANDBETWEEN
10513
11045
  // -----------------------------------------------------------------------------
10514
11046
  const RANDBETWEEN = {
@@ -10838,11 +11370,13 @@
10838
11370
  ISODD: ISODD,
10839
11371
  LN: LN,
10840
11372
  MOD: MOD,
11373
+ MUNIT: MUNIT,
10841
11374
  ODD: ODD,
10842
11375
  PI: PI,
10843
11376
  POWER: POWER,
10844
11377
  PRODUCT: PRODUCT,
10845
11378
  RAND: RAND,
11379
+ RANDARRAY: RANDARRAY,
10846
11380
  RANDBETWEEN: RANDBETWEEN,
10847
11381
  ROUND: ROUND,
10848
11382
  ROUNDDOWN: ROUNDDOWN,
@@ -12869,6 +13403,89 @@
12869
13403
  DELTA: DELTA
12870
13404
  });
12871
13405
 
13406
+ // -----------------------------------------------------------------------------
13407
+ // FILTER
13408
+ // -----------------------------------------------------------------------------
13409
+ const FILTER = {
13410
+ description: _lt("Returns a filtered version of the source range, returning only rows or columns that meet the specified conditions."),
13411
+ // TODO modify args description when vectorization on formulas is available
13412
+ args: [
13413
+ arg("range (any, range<any>)", _lt("The data to be filtered.")),
13414
+ arg("condition1 (boolean, range<boolean>)", _lt("A column or row containing true or false values corresponding to the first column or row of range.")),
13415
+ arg("condition2 (boolean, range<boolean>, repeating)", _lt("Additional column or row containing true or false values.")),
13416
+ ],
13417
+ returns: ["RANGE<ANY>"],
13418
+ //TODO computeFormat
13419
+ compute: function (range, ...conditions) {
13420
+ let _range = toMatrixArgValue(range);
13421
+ const _conditionsMatrices = conditions.map((cond) => toMatrixArgValue(cond));
13422
+ _conditionsMatrices.map((c) => assertSingleColOrRow(_lt("The arguments condition must be a single column or row."), c));
13423
+ assertSameDimensions(_lt("The arguments conditions must have the same dimensions."), ..._conditionsMatrices);
13424
+ const _conditions = _conditionsMatrices.map((c) => c.flat());
13425
+ const mode = _conditionsMatrices[0].length === 1 ? "row" : "col";
13426
+ _range = mode === "row" ? transpose2dArray(_range) : _range;
13427
+ assert(() => _conditions.every((cond) => cond.length === _range.length), _lt(`FILTER has mismatched sizes on the range and conditions.`));
13428
+ const results = [];
13429
+ for (let i = 0; i < _range.length; i++) {
13430
+ const row = _range[i];
13431
+ if (_conditions.every((c) => c[i])) {
13432
+ results.push(row);
13433
+ }
13434
+ }
13435
+ if (!results.length) {
13436
+ throw new NotAvailableError(_lt("No match found in FILTER evaluation"));
13437
+ }
13438
+ return toCellValueMatrix(mode === "row" ? transpose2dArray(results) : results);
13439
+ },
13440
+ isExported: true,
13441
+ };
13442
+ // -----------------------------------------------------------------------------
13443
+ // UNIQUE
13444
+ // -----------------------------------------------------------------------------
13445
+ const UNIQUE = {
13446
+ description: _lt("Unique rows in the provided source range."),
13447
+ args: [
13448
+ arg("range (any, range<any>)", _lt("The data to filter by unique entries.")),
13449
+ arg("by_column (boolean, default=FALSE)", _lt("Whether to filter the data by columns or by rows.")),
13450
+ arg("exactly_once (boolean, default=FALSE)", _lt("Whether to return only entries with no duplicates.")),
13451
+ ],
13452
+ returns: ["RANGE<NUMBER>"],
13453
+ // TODO computeFormat
13454
+ compute: function (range, byColumn, exactlyOnce) {
13455
+ if (!isMatrix(range)) {
13456
+ return toCellValue(range);
13457
+ }
13458
+ const _byColumn = toBoolean(byColumn) || false;
13459
+ const _exactlyOnce = toBoolean(exactlyOnce) || false;
13460
+ if (!_byColumn)
13461
+ range = transpose2dArray(range);
13462
+ const map = new Map();
13463
+ for (const row of range) {
13464
+ const key = JSON.stringify(row);
13465
+ const occurrence = map.get(key);
13466
+ if (!occurrence) {
13467
+ map.set(key, { val: row, count: 1 });
13468
+ }
13469
+ else {
13470
+ occurrence.count++;
13471
+ }
13472
+ }
13473
+ const results = _exactlyOnce
13474
+ ? [...map.values()].filter((v) => v.count === 1).map((v) => v.val)
13475
+ : [...map.values()].map((v) => v.val);
13476
+ if (!results.length)
13477
+ throw new Error(_lt("No unique values found"));
13478
+ return toCellValueMatrix(_byColumn ? results : transpose2dArray(results));
13479
+ },
13480
+ isExported: true,
13481
+ };
13482
+
13483
+ var filter = /*#__PURE__*/Object.freeze({
13484
+ __proto__: null,
13485
+ FILTER: FILTER,
13486
+ UNIQUE: UNIQUE
13487
+ });
13488
+
12872
13489
  /** Assert maturity date > settlement date */
12873
13490
  function assertMaturityAndSettlementDatesAreValid(settlement, maturity) {
12874
13491
  assert(() => settlement < maturity, _lt("The maturity (%s) must be strictly greater than the settlement (%s).", maturity.toString(), settlement.toString()));
@@ -15564,13 +16181,16 @@
15564
16181
  const _searchMode = Math.trunc(toNumber(searchMode));
15565
16182
  const _searchKey = normalizeValue(searchKey);
15566
16183
  assert(() => lookupRange.length === 1 || lookupRange[0].length === 1, _lt("lookup_range should be either a single row or single column."));
15567
- assert(() => returnRange.length === 1 || returnRange[0].length === 1, _lt("return_range should be either a single row or single column."));
15568
- assert(() => returnRange.length === lookupRange.length &&
15569
- returnRange[0].length === lookupRange[0].length, _lt("return_range should have the same dimensions as lookup_range."));
15570
16184
  assert(() => [-1, 1, -2, 2].includes(_searchMode), _lt("searchMode should be a value in [-1, 1, -2, 2]."));
15571
16185
  assert(() => [-1, 0, 1].includes(_matchMode), _lt("matchMode should be a value in [-1, 0, 1]."));
15572
- const getElement = lookupRange.length === 1 ? getNormalizedValueFromColumnRange : getNormalizedValueFromRowRange;
15573
- const rangeLen = lookupRange.length === 1 ? lookupRange[0].length : lookupRange.length;
16186
+ const lookupDirection = lookupRange.length === 1 ? "col" : "row";
16187
+ assert(() => lookupDirection === "col"
16188
+ ? returnRange[0].length === lookupRange[0].length
16189
+ : returnRange.length === lookupRange.length, _lt("return_range should have the same dimensions as lookup_range."));
16190
+ const getElement = lookupDirection === "col"
16191
+ ? getNormalizedValueFromColumnRange
16192
+ : getNormalizedValueFromRowRange;
16193
+ const rangeLen = lookupDirection === "col" ? lookupRange[0].length : lookupRange.length;
15574
16194
  const mode = _matchMode === 0 ? "strict" : _matchMode === 1 ? "nextGreater" : "nextSmaller";
15575
16195
  const reverseSearch = _searchMode === -1;
15576
16196
  let index;
@@ -15582,7 +16202,7 @@
15582
16202
  index = linearSearch(lookupRange, _searchKey, mode, rangeLen, getElement, reverseSearch);
15583
16203
  }
15584
16204
  if (index !== -1) {
15585
- return (lookupRange.length === 1 ? returnRange[0][index] : returnRange[index][0]);
16205
+ return toCellValueMatrix(lookupDirection === "col" ? returnRange.map((col) => [col[index]]) : [returnRange[index]]);
15586
16206
  }
15587
16207
  const _defaultValue = defaultValue?.();
15588
16208
  assertAvailable(_defaultValue, searchKey);
@@ -16123,6 +16743,36 @@
16123
16743
  isExported: true,
16124
16744
  };
16125
16745
  // -----------------------------------------------------------------------------
16746
+ // SPLIT
16747
+ // -----------------------------------------------------------------------------
16748
+ const SPLIT_DEFAULT_SPLIT_BY_EACH = true;
16749
+ const SPLIT_DEFAULT_REMOVE_EMPTY_TEXT = true;
16750
+ const SPLIT = {
16751
+ description: _lt("Split text by specific character delimiter(s)."),
16752
+ args: [
16753
+ arg("text (string)", _lt("The text to divide.")),
16754
+ arg("delimiter (string)", _lt("The character or characters to use to split text.")),
16755
+ arg(`split_by_each (boolean, default=${SPLIT_DEFAULT_SPLIT_BY_EACH}})`, _lt("Whether or not to divide text around each character contained in delimiter.")),
16756
+ arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _lt("Whether or not to remove empty text messages from the split results. The default behavior is to treat \
16757
+ consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters.")),
16758
+ ],
16759
+ returns: ["RANGE<STRING>"],
16760
+ compute: function (text, delimiter, splitByEach = SPLIT_DEFAULT_SPLIT_BY_EACH, removeEmptyText = SPLIT_DEFAULT_REMOVE_EMPTY_TEXT) {
16761
+ const _text = toString(text);
16762
+ const _delimiter = escapeRegExp(toString(delimiter));
16763
+ const _splitByEach = toBoolean(splitByEach);
16764
+ const _removeEmptyText = toBoolean(removeEmptyText);
16765
+ assert(() => _delimiter.length > 0, _lt("The _delimiter (%s) must be not be empty.", _delimiter));
16766
+ const regex = _splitByEach ? new RegExp(`[${_delimiter}]`, "g") : new RegExp(_delimiter, "g");
16767
+ let result = _text.split(regex);
16768
+ if (_removeEmptyText) {
16769
+ result = result.filter((text) => text !== "");
16770
+ }
16771
+ return transpose2dArray([result]);
16772
+ },
16773
+ isExported: true,
16774
+ };
16775
+ // -----------------------------------------------------------------------------
16126
16776
  // SUBSTITUTE
16127
16777
  // -----------------------------------------------------------------------------
16128
16778
  const SUBSTITUTE = {
@@ -16231,6 +16881,7 @@
16231
16881
  REPLACE: REPLACE,
16232
16882
  RIGHT: RIGHT,
16233
16883
  SEARCH: SEARCH,
16884
+ SPLIT: SPLIT,
16234
16885
  SUBSTITUTE: SUBSTITUTE,
16235
16886
  TEXTJOIN: TEXTJOIN,
16236
16887
  TRIM: TRIM,
@@ -16264,8 +16915,10 @@
16264
16915
  });
16265
16916
 
16266
16917
  const categories = [
16918
+ { name: _lt("Array"), functions: array },
16267
16919
  { name: _lt("Database"), functions: database },
16268
16920
  { name: _lt("Date"), functions: date },
16921
+ { name: _lt("Filter"), functions: filter },
16269
16922
  { name: _lt("Financial"), functions: financial },
16270
16923
  { name: _lt("Info"), functions: info },
16271
16924
  { name: _lt("Lookup"), functions: lookup },
@@ -16338,14 +16991,20 @@
16338
16991
  }
16339
16992
 
16340
16993
  const insertRow = {
16341
- name: MENU_INSERT_ROWS_NAME,
16994
+ name: (env) => {
16995
+ const number = getRowsNumber(env);
16996
+ return number === 1 ? _lt("Insert row") : _lt("Insert %s rows", number.toString());
16997
+ },
16342
16998
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16343
16999
  IS_ONLY_ONE_RANGE(env) &&
16344
17000
  env.model.getters.getActiveCols().size === 0,
16345
17001
  icon: "o-spreadsheet-Icon.INSERT_ROW",
16346
17002
  };
16347
17003
  const rowInsertRowBefore = {
16348
- name: ROW_INSERT_ROWS_BEFORE_NAME,
17004
+ name: (env) => {
17005
+ const number = getRowsNumber(env);
17006
+ return number === 1 ? _lt("Insert row above") : _lt("Insert %s rows above", number.toString());
17007
+ },
16349
17008
  execute: INSERT_ROWS_BEFORE_ACTION,
16350
17009
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16351
17010
  IS_ONLY_ONE_RANGE(env) &&
@@ -16354,17 +17013,32 @@
16354
17013
  };
16355
17014
  const topBarInsertRowsBefore = {
16356
17015
  ...rowInsertRowBefore,
16357
- name: MENU_INSERT_ROWS_BEFORE_NAME,
17016
+ name: (env) => {
17017
+ const number = getRowsNumber(env);
17018
+ if (number === 1) {
17019
+ return _lt("Row above");
17020
+ }
17021
+ return _lt("%s Rows above", number.toString());
17022
+ },
16358
17023
  };
16359
17024
  const cellInsertRowsBefore = {
16360
17025
  ...rowInsertRowBefore,
16361
- name: CELL_INSERT_ROWS_BEFORE_NAME,
17026
+ name: (env) => {
17027
+ const number = getRowsNumber(env);
17028
+ if (number === 1) {
17029
+ return _lt("Insert row");
17030
+ }
17031
+ return _lt("Insert %s rows", number.toString());
17032
+ },
16362
17033
  isVisible: IS_ONLY_ONE_RANGE,
16363
17034
  icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
16364
17035
  };
16365
17036
  const rowInsertRowsAfter = {
16366
17037
  execute: INSERT_ROWS_AFTER_ACTION,
16367
- name: ROW_INSERT_ROWS_AFTER_NAME,
17038
+ name: (env) => {
17039
+ const number = getRowsNumber(env);
17040
+ return number === 1 ? _lt("Insert row below") : _lt("Insert %s rows below", number.toString());
17041
+ },
16368
17042
  isVisible: (env) => isConsecutive(env.model.getters.getActiveRows()) &&
16369
17043
  IS_ONLY_ONE_RANGE(env) &&
16370
17044
  env.model.getters.getActiveCols().size === 0,
@@ -16372,17 +17046,31 @@
16372
17046
  };
16373
17047
  const topBarInsertRowsAfter = {
16374
17048
  ...rowInsertRowsAfter,
16375
- name: MENU_INSERT_ROWS_AFTER_NAME,
17049
+ name: (env) => {
17050
+ const number = getRowsNumber(env);
17051
+ if (number === 1) {
17052
+ return _lt("Row below");
17053
+ }
17054
+ return _lt("%s Rows below", number.toString());
17055
+ },
16376
17056
  };
16377
17057
  const insertCol = {
16378
- name: MENU_INSERT_COLUMNS_NAME,
17058
+ name: (env) => {
17059
+ const number = getColumnsNumber(env);
17060
+ return number === 1 ? _lt("Insert column") : _lt("Insert %s columns", number.toString());
17061
+ },
16379
17062
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16380
17063
  IS_ONLY_ONE_RANGE(env) &&
16381
17064
  env.model.getters.getActiveRows().size === 0,
16382
17065
  icon: "o-spreadsheet-Icon.INSERT_COL",
16383
17066
  };
16384
17067
  const colInsertColsBefore = {
16385
- name: COLUMN_INSERT_COLUMNS_BEFORE_NAME,
17068
+ name: (env) => {
17069
+ const number = getColumnsNumber(env);
17070
+ return number === 1
17071
+ ? _lt("Insert column left")
17072
+ : _lt("Insert %s columns left", number.toString());
17073
+ },
16386
17074
  execute: INSERT_COLUMNS_BEFORE_ACTION,
16387
17075
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16388
17076
  IS_ONLY_ONE_RANGE(env) &&
@@ -16391,16 +17079,33 @@
16391
17079
  };
16392
17080
  const topBarInsertColsBefore = {
16393
17081
  ...colInsertColsBefore,
16394
- name: MENU_INSERT_COLUMNS_BEFORE_NAME,
17082
+ name: (env) => {
17083
+ const number = getColumnsNumber(env);
17084
+ if (number === 1) {
17085
+ return _lt("Column left");
17086
+ }
17087
+ return _lt("%s Columns left", number.toString());
17088
+ },
16395
17089
  };
16396
17090
  const cellInsertColsBefore = {
16397
17091
  ...colInsertColsBefore,
16398
- name: CELL_INSERT_COLUMNS_BEFORE_NAME,
17092
+ name: (env) => {
17093
+ const number = getColumnsNumber(env);
17094
+ if (number === 1) {
17095
+ return _lt("Insert column");
17096
+ }
17097
+ return _lt("Insert %s columns", number.toString());
17098
+ },
16399
17099
  isVisible: IS_ONLY_ONE_RANGE,
16400
17100
  icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
16401
17101
  };
16402
17102
  const colInsertColsAfter = {
16403
- name: COLUMN_INSERT_COLUMNS_AFTER_NAME,
17103
+ name: (env) => {
17104
+ const number = getColumnsNumber(env);
17105
+ return number === 1
17106
+ ? _lt("Insert column right")
17107
+ : _lt("Insert %s columns right", number.toString());
17108
+ },
16404
17109
  execute: INSERT_COLUMNS_AFTER_ACTION,
16405
17110
  isVisible: (env) => isConsecutive(env.model.getters.getActiveCols()) &&
16406
17111
  IS_ONLY_ONE_RANGE(env) &&
@@ -16409,7 +17114,13 @@
16409
17114
  };
16410
17115
  const topBarInsertColsAfter = {
16411
17116
  ...colInsertColsAfter,
16412
- name: MENU_INSERT_COLUMNS_AFTER_NAME,
17117
+ name: (env) => {
17118
+ const number = getColumnsNumber(env);
17119
+ if (number === 1) {
17120
+ return _lt("Column right");
17121
+ }
17122
+ return _lt("%s Columns right", number.toString());
17123
+ },
16413
17124
  execute: INSERT_COLUMNS_AFTER_ACTION,
16414
17125
  };
16415
17126
  const insertCell = {
@@ -16421,13 +17132,21 @@
16421
17132
  };
16422
17133
  const insertCellShiftDown = {
16423
17134
  name: _lt("Insert cells and shift down"),
16424
- execute: INSERT_CELL_SHIFT_DOWN,
17135
+ execute: (env) => {
17136
+ const zone = env.model.getters.getSelectedZone();
17137
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" });
17138
+ handlePasteResult(env, result);
17139
+ },
16425
17140
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16426
17141
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN",
16427
17142
  };
16428
17143
  const insertCellShiftRight = {
16429
17144
  name: _lt("Insert cells and shift right"),
16430
- execute: INSERT_CELL_SHIFT_RIGHT,
17145
+ execute: (env) => {
17146
+ const zone = env.model.getters.getSelectedZone();
17147
+ const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" });
17148
+ handlePasteResult(env, result);
17149
+ },
16431
17150
  isVisible: (env) => env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0,
16432
17151
  icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT",
16433
17152
  };
@@ -16493,7 +17212,13 @@
16493
17212
  };
16494
17213
  const insertSheet = {
16495
17214
  name: _lt("Insert sheet"),
16496
- execute: CREATE_SHEET_ACTION,
17215
+ execute: (env) => {
17216
+ const activeSheetId = env.model.getters.getActiveSheetId();
17217
+ const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
17218
+ const sheetId = env.model.uuidGenerator.uuidv4();
17219
+ env.model.dispatch("CREATE_SHEET", { sheetId, position });
17220
+ env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
17221
+ },
16497
17222
  icon: "o-spreadsheet-Icon.INSERT_SHEET",
16498
17223
  };
16499
17224
  function createFormulaFunctions(fnNames) {
@@ -16504,6 +17229,26 @@
16504
17229
  execute: (env) => env.startCellEdition(`=${fnName}(`),
16505
17230
  };
16506
17231
  });
17232
+ }
17233
+ function getRowsNumber(env) {
17234
+ const activeRows = env.model.getters.getActiveRows();
17235
+ if (activeRows.size) {
17236
+ return activeRows.size;
17237
+ }
17238
+ else {
17239
+ const zone = env.model.getters.getSelectedZones()[0];
17240
+ return zone.bottom - zone.top + 1;
17241
+ }
17242
+ }
17243
+ function getColumnsNumber(env) {
17244
+ const activeCols = env.model.getters.getActiveCols();
17245
+ if (activeCols.size) {
17246
+ return activeCols.size;
17247
+ }
17248
+ else {
17249
+ const zone = env.model.getters.getSelectedZones()[0];
17250
+ return zone.right - zone.left + 1;
17251
+ }
16507
17252
  }
16508
17253
 
16509
17254
  //------------------------------------------------------------------------------
@@ -16594,6 +17339,123 @@
16594
17339
  separator: true,
16595
17340
  });
16596
17341
 
17342
+ const SORT_TYPES = [
17343
+ CellValueType.number,
17344
+ CellValueType.error,
17345
+ CellValueType.text,
17346
+ CellValueType.boolean,
17347
+ ];
17348
+ function sortCells(cells, sortDirection, emptyCellAsZero) {
17349
+ const cellsWithIndex = cells.map((cell, index) => ({
17350
+ index,
17351
+ type: cell.type,
17352
+ value: cell.value,
17353
+ }));
17354
+ let emptyCells = cellsWithIndex.filter((x) => x.type === CellValueType.empty);
17355
+ let nonEmptyCells = cellsWithIndex.filter((x) => x.type !== CellValueType.empty);
17356
+ if (emptyCellAsZero) {
17357
+ nonEmptyCells.push(...emptyCells.map((emptyCell) => ({ ...emptyCell, type: CellValueType.number, value: 0 })));
17358
+ emptyCells = [];
17359
+ }
17360
+ const inverse = sortDirection === "descending" ? -1 : 1;
17361
+ return nonEmptyCells
17362
+ .sort((left, right) => {
17363
+ let typeOrder = SORT_TYPES.indexOf(left.type) - SORT_TYPES.indexOf(right.type);
17364
+ if (typeOrder === 0) {
17365
+ if (left.type === CellValueType.text || left.type === CellValueType.error) {
17366
+ typeOrder = left.value.localeCompare(right.value);
17367
+ }
17368
+ else
17369
+ typeOrder = left.value - right.value;
17370
+ }
17371
+ return inverse * typeOrder;
17372
+ })
17373
+ .concat(emptyCells);
17374
+ }
17375
+ function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
17376
+ let result = DispatchResult.Success;
17377
+ //several columns => bypass the contiguity check
17378
+ let multiColumns = zone.right > zone.left;
17379
+ if (env.model.getters.doesIntersectMerge(sheetId, zone)) {
17380
+ multiColumns = false;
17381
+ let table;
17382
+ for (let row = zone.top; row <= zone.bottom; row++) {
17383
+ table = [];
17384
+ for (let col = zone.left; col <= zone.right; col++) {
17385
+ let merge = env.model.getters.getMerge({ sheetId, col, row });
17386
+ if (merge && !table.includes(merge.id.toString())) {
17387
+ table.push(merge.id.toString());
17388
+ }
17389
+ }
17390
+ if (table.length >= 2) {
17391
+ multiColumns = true;
17392
+ break;
17393
+ }
17394
+ }
17395
+ }
17396
+ const { col, row } = anchor;
17397
+ if (multiColumns) {
17398
+ result = env.model.dispatch("SORT_CELLS", { sheetId, col, row, zone, sortDirection });
17399
+ }
17400
+ else {
17401
+ // check contiguity
17402
+ const contiguousZone = env.model.getters.getContiguousZone(sheetId, zone);
17403
+ if (isEqual(contiguousZone, zone)) {
17404
+ // merge as it is
17405
+ result = env.model.dispatch("SORT_CELLS", {
17406
+ sheetId,
17407
+ col,
17408
+ row,
17409
+ zone,
17410
+ sortDirection,
17411
+ });
17412
+ }
17413
+ else {
17414
+ env.askConfirmation(_lt("We found data next to your selection. Since this data was not selected, it will not be sorted. Do you want to extend your selection?"), () => {
17415
+ zone = contiguousZone;
17416
+ result = env.model.dispatch("SORT_CELLS", {
17417
+ sheetId,
17418
+ col,
17419
+ row,
17420
+ zone,
17421
+ sortDirection,
17422
+ });
17423
+ }, () => {
17424
+ result = env.model.dispatch("SORT_CELLS", {
17425
+ sheetId,
17426
+ col,
17427
+ row,
17428
+ zone,
17429
+ sortDirection,
17430
+ });
17431
+ });
17432
+ }
17433
+ }
17434
+ if (result.isCancelledBecause(64 /* CommandResult.InvalidSortZone */)) {
17435
+ const { col, row } = anchor;
17436
+ env.model.selection.selectZone({ cell: { col, row }, zone });
17437
+ env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
17438
+ }
17439
+ }
17440
+
17441
+ const AddFilterInteractiveContent = {
17442
+ filterOverlap: _lt("You cannot create overlapping filters."),
17443
+ nonContinuousTargets: _lt("A filter can only be created on a continuous selection."),
17444
+ mergeInFilter: _lt("You can't create a filter over a range that contains a merge."),
17445
+ };
17446
+ function interactiveAddFilter(env, sheetId, target) {
17447
+ const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
17448
+ if (result.isCancelledBecause(79 /* CommandResult.FilterOverlap */)) {
17449
+ env.raiseError(AddFilterInteractiveContent.filterOverlap);
17450
+ }
17451
+ else if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
17452
+ env.raiseError(AddFilterInteractiveContent.mergeInFilter);
17453
+ }
17454
+ else if (result.isCancelledBecause(82 /* CommandResult.NonContinuousTargets */)) {
17455
+ env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
17456
+ }
17457
+ }
17458
+
16597
17459
  const sortRange = {
16598
17460
  name: _lt("Sort range"),
16599
17461
  isVisible: IS_ONLY_ONE_RANGE,
@@ -16601,24 +17463,45 @@
16601
17463
  };
16602
17464
  const sortAscending = {
16603
17465
  name: _lt("Ascending (A ⟶ Z)"),
16604
- execute: SORT_CELLS_ASCENDING,
17466
+ execute: (env) => {
17467
+ const { anchor, zones } = env.model.getters.getSelection();
17468
+ const sheetId = env.model.getters.getActiveSheetId();
17469
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "ascending");
17470
+ },
16605
17471
  icon: "o-spreadsheet-Icon.SORT_ASCENDING",
16606
17472
  };
16607
17473
  const sortDescending = {
16608
17474
  name: _lt("Descending (Z ⟶ A)"),
16609
- execute: SORT_CELLS_DESCENDING,
17475
+ execute: (env) => {
17476
+ const { anchor, zones } = env.model.getters.getSelection();
17477
+ const sheetId = env.model.getters.getActiveSheetId();
17478
+ interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "descending");
17479
+ },
16610
17480
  icon: "o-spreadsheet-Icon.SORT_DESCENDING",
16611
17481
  };
16612
17482
  const addDataFilter = {
16613
17483
  name: _lt("Create filter"),
16614
- execute: FILTERS_CREATE_FILTER_TABLE,
17484
+ execute: (env) => {
17485
+ const sheetId = env.model.getters.getActiveSheetId();
17486
+ const selection = env.model.getters.getSelection().zones;
17487
+ interactiveAddFilter(env, sheetId, selection);
17488
+ },
16615
17489
  isVisible: (env) => !SELECTION_CONTAINS_FILTER(env),
16616
- isEnabled: (env) => SELECTION_IS_CONTINUOUS(env),
17490
+ isEnabled: (env) => {
17491
+ const selectedZones = env.model.getters.getSelectedZones();
17492
+ return areZonesContinuous(...selectedZones);
17493
+ },
16617
17494
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16618
17495
  };
16619
17496
  const removeDataFilter = {
16620
17497
  name: _lt("Remove filter"),
16621
- execute: FILTERS_REMOVE_FILTER_TABLE,
17498
+ execute: (env) => {
17499
+ const sheetId = env.model.getters.getActiveSheetId();
17500
+ env.model.dispatch("REMOVE_FILTER_TABLE", {
17501
+ sheetId,
17502
+ target: env.model.getters.getSelectedZones(),
17503
+ });
17504
+ },
16622
17505
  isVisible: SELECTION_CONTAINS_FILTER,
16623
17506
  icon: "o-spreadsheet-Icon.MENU_FILTER_ICON",
16624
17507
  };
@@ -16632,13 +17515,13 @@
16632
17515
 
16633
17516
  const formatNumberAutomatic = {
16634
17517
  name: _lt("Automatic"),
16635
- execute: FORMAT_AUTOMATIC_ACTION,
17518
+ execute: (env) => setFormatter(env, ""),
16636
17519
  isActive: (env) => isAutomaticFormatSelected(env),
16637
17520
  };
16638
17521
  const formatNumberNumber = {
16639
17522
  name: _lt("Number"),
16640
17523
  description: "1,000.12",
16641
- execute: FORMAT_NUMBER_ACTION,
17524
+ execute: (env) => setFormatter(env, "#,##0.00"),
16642
17525
  isActive: (env) => isFormatSelected(env, "#,##0.00"),
16643
17526
  };
16644
17527
  const formatPercent = {
@@ -16655,42 +17538,42 @@
16655
17538
  const formatNumberCurrency = {
16656
17539
  name: _lt("Currency"),
16657
17540
  description: "$1,000.12",
16658
- execute: FORMAT_CURRENCY_ACTION,
17541
+ execute: (env) => setFormatter(env, "[$$]#,##0.00"),
16659
17542
  isActive: (env) => isFormatSelected(env, "[$$]#,##0.00"),
16660
17543
  };
16661
17544
  const formatNumberCurrencyRounded = {
16662
17545
  name: _lt("Currency rounded"),
16663
17546
  description: "$1,000",
16664
- execute: FORMAT_CURRENCY_ROUNDED_ACTION,
17547
+ execute: (env) => setFormatter(env, "[$$]#,##0"),
16665
17548
  isActive: (env) => isFormatSelected(env, "[$$]#,##0"),
16666
17549
  };
16667
17550
  const formatCustomCurrency = {
16668
17551
  name: _lt("Custom currency"),
16669
17552
  isVisible: (env) => env.loadCurrencies !== undefined,
16670
- execute: OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION,
17553
+ execute: (env) => env.openSidePanel("CustomCurrency", {}),
16671
17554
  };
16672
17555
  const formatNumberDate = {
16673
17556
  name: _lt("Date"),
16674
17557
  description: "9/26/2008",
16675
- execute: FORMAT_DATE_ACTION,
17558
+ execute: (env) => setFormatter(env, "m/d/yyyy"),
16676
17559
  isActive: (env) => isFormatSelected(env, "m/d/yyyy"),
16677
17560
  };
16678
17561
  const formatNumberTime = {
16679
17562
  name: _lt("Time"),
16680
17563
  description: "10:43:00 PM",
16681
- execute: FORMAT_TIME_ACTION,
17564
+ execute: (env) => setFormatter(env, "hh:mm:ss a"),
16682
17565
  isActive: (env) => isFormatSelected(env, "hh:mm:ss a"),
16683
17566
  };
16684
17567
  const formatNumberDateTime = {
16685
17568
  name: _lt("Date time"),
16686
17569
  description: "9/26/2008 22:43:00",
16687
- execute: FORMAT_DATE_TIME_ACTION,
17570
+ execute: (env) => setFormatter(env, "m/d/yyyy hh:mm:ss"),
16688
17571
  isActive: (env) => isFormatSelected(env, "m/d/yyyy hh:mm:ss"),
16689
17572
  };
16690
17573
  const formatNumberDuration = {
16691
17574
  name: _lt("Duration"),
16692
17575
  description: "27:51:38",
16693
- execute: FORMAT_DURATION_ACTION,
17576
+ execute: (env) => setFormatter(env, "hhhh:mm:ss"),
16694
17577
  isActive: (env) => isFormatSelected(env, "hhhh:mm:ss"),
16695
17578
  };
16696
17579
  const incraseDecimalPlaces = {
@@ -16714,27 +17597,27 @@
16714
17597
  const formatBold = {
16715
17598
  name: _lt("Bold"),
16716
17599
  description: "Ctrl+B",
16717
- execute: FORMAT_BOLD_ACTION,
17600
+ execute: (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold }),
16718
17601
  icon: "o-spreadsheet-Icon.BOLD",
16719
17602
  isActive: (env) => !!env.model.getters.getCurrentStyle().bold,
16720
17603
  };
16721
17604
  const formatItalic = {
16722
17605
  name: _lt("Italic"),
16723
17606
  description: "Ctrl+I",
16724
- execute: FORMAT_ITALIC_ACTION,
17607
+ execute: (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic }),
16725
17608
  icon: "o-spreadsheet-Icon.ITALIC",
16726
17609
  isActive: (env) => !!env.model.getters.getCurrentStyle().italic,
16727
17610
  };
16728
17611
  const formatUnderline = {
16729
17612
  name: _lt("Underline"),
16730
17613
  description: "Ctrl+U",
16731
- execute: FORMAT_UNDERLINE_ACTION,
17614
+ execute: (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline }),
16732
17615
  icon: "o-spreadsheet-Icon.UNDERLINE",
16733
17616
  isActive: (env) => !!env.model.getters.getCurrentStyle().underline,
16734
17617
  };
16735
17618
  const formatStrikethrough = {
16736
17619
  name: _lt("Strikethrough"),
16737
- execute: FORMAT_STRIKETHROUGH_ACTION,
17620
+ execute: (env) => setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough }),
16738
17621
  icon: "o-spreadsheet-Icon.STRIKE",
16739
17622
  isActive: (env) => !!env.model.getters.getCurrentStyle().strikethrough,
16740
17623
  };
@@ -16840,7 +17723,10 @@
16840
17723
  const clearFormat = {
16841
17724
  name: _lt("Clear formatting"),
16842
17725
  description: "Ctrl+<",
16843
- execute: FORMAT_CLEARFORMAT_ACTION,
17726
+ execute: (env) => env.model.dispatch("CLEAR_FORMATTING", {
17727
+ sheetId: env.model.getters.getActiveSheetId(),
17728
+ target: env.model.getters.getSelectedZones(),
17729
+ }),
16844
17730
  icon: "o-spreadsheet-Icon.CLEAR_FORMAT",
16845
17731
  };
16846
17732
  function fontSizeMenuBuilder() {
@@ -16919,20 +17805,34 @@
16919
17805
  const sheetId = env.model.getters.getActiveSheetId();
16920
17806
  const cmd = dimension === "COL" ? "FREEZE_COLUMNS" : "FREEZE_ROWS";
16921
17807
  const result = env.model.dispatch(cmd, { sheetId, quantity: base });
16922
- if (result.isCancelledBecause(65 /* CommandResult.MergeOverlap */)) {
17808
+ if (result.isCancelledBecause(66 /* CommandResult.MergeOverlap */)) {
16923
17809
  env.raiseError(MergeErrorMessage);
16924
17810
  }
16925
17811
  }
16926
17812
 
16927
17813
  const hideCols = {
16928
17814
  name: HIDE_COLUMNS_NAME,
16929
- execute: HIDE_COLUMNS_ACTION,
17815
+ execute: (env) => {
17816
+ const columns = env.model.getters.getElementsFromSelection("COL");
17817
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17818
+ sheetId: env.model.getters.getActiveSheetId(),
17819
+ dimension: "COL",
17820
+ elements: columns,
17821
+ });
17822
+ },
16930
17823
  isVisible: NOT_ALL_VISIBLE_COLS_SELECTED,
16931
17824
  icon: "o-spreadsheet-Icon.HIDE_COL",
16932
17825
  };
16933
17826
  const unhideCols = {
16934
17827
  name: _lt("Unhide columns"),
16935
- execute: UNHIDE_COLUMNS_ACTION,
17828
+ execute: (env) => {
17829
+ const columns = env.model.getters.getElementsFromSelection("COL");
17830
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17831
+ sheetId: env.model.getters.getActiveSheetId(),
17832
+ dimension: "COL",
17833
+ elements: columns,
17834
+ });
17835
+ },
16936
17836
  isVisible: (env) => {
16937
17837
  const hiddenCols = env.model.getters
16938
17838
  .getHiddenColsGroups(env.model.getters.getActiveSheetId())
@@ -16943,18 +17843,39 @@
16943
17843
  };
16944
17844
  const unhideAllCols = {
16945
17845
  name: _lt("Unhide all columns"),
16946
- execute: UNHIDE_ALL_COLUMNS_ACTION,
17846
+ execute: (env) => {
17847
+ const sheetId = env.model.getters.getActiveSheetId();
17848
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17849
+ sheetId,
17850
+ dimension: "COL",
17851
+ elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()),
17852
+ });
17853
+ },
16947
17854
  isVisible: (env) => env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0,
16948
17855
  };
16949
17856
  const hideRows = {
16950
17857
  name: HIDE_ROWS_NAME,
16951
- execute: HIDE_ROWS_ACTION,
17858
+ execute: (env) => {
17859
+ const rows = env.model.getters.getElementsFromSelection("ROW");
17860
+ env.model.dispatch("HIDE_COLUMNS_ROWS", {
17861
+ sheetId: env.model.getters.getActiveSheetId(),
17862
+ dimension: "ROW",
17863
+ elements: rows,
17864
+ });
17865
+ },
16952
17866
  isVisible: NOT_ALL_VISIBLE_ROWS_SELECTED,
16953
17867
  icon: "o-spreadsheet-Icon.HIDE_ROW",
16954
17868
  };
16955
17869
  const unhideRows = {
16956
17870
  name: _lt("Unhide rows"),
16957
- execute: UNHIDE_ROWS_ACTION,
17871
+ execute: (env) => {
17872
+ const columns = env.model.getters.getElementsFromSelection("ROW");
17873
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17874
+ sheetId: env.model.getters.getActiveSheetId(),
17875
+ dimension: "ROW",
17876
+ elements: columns,
17877
+ });
17878
+ },
16958
17879
  isVisible: (env) => {
16959
17880
  const hiddenRows = env.model.getters
16960
17881
  .getHiddenRowsGroups(env.model.getters.getActiveSheetId())
@@ -16965,7 +17886,14 @@
16965
17886
  };
16966
17887
  const unhideAllRows = {
16967
17888
  name: _lt("Unhide all rows"),
16968
- execute: UNHIDE_ALL_ROWS_ACTION,
17889
+ execute: (env) => {
17890
+ const sheetId = env.model.getters.getActiveSheetId();
17891
+ env.model.dispatch("UNHIDE_COLUMNS_ROWS", {
17892
+ sheetId,
17893
+ dimension: "ROW",
17894
+ elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()),
17895
+ });
17896
+ },
16969
17897
  isVisible: (env) => env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0,
16970
17898
  };
16971
17899
  const unFreezePane = {
@@ -17039,12 +17967,18 @@
17039
17967
  name: (env) => env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId())
17040
17968
  ? _lt("Hide gridlines")
17041
17969
  : _lt("Show gridlines"),
17042
- execute: SET_GRID_LINES_VISIBILITY_ACTION,
17970
+ execute: (env) => {
17971
+ const sheetId = env.model.getters.getActiveSheetId();
17972
+ env.model.dispatch("SET_GRID_LINES_VISIBILITY", {
17973
+ sheetId,
17974
+ areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId),
17975
+ });
17976
+ },
17043
17977
  icon: "o-spreadsheet-Icon.SHOW_HIDE_GRID",
17044
17978
  };
17045
17979
  const viewFormulas = {
17046
17980
  name: (env) => env.model.getters.shouldShowFormulas() ? _lt("Hide formulas") : _lt("Show formulas"),
17047
- execute: SET_FORMULA_VISIBILITY_ACTION,
17981
+ execute: (env) => env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() }),
17048
17982
  isReadonlyAllowed: true,
17049
17983
  icon: "o-spreadsheet-Icon.SHOW_HIDE_FORMULA",
17050
17984
  };
@@ -18008,10 +18942,10 @@
18008
18942
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18009
18943
  }
18010
18944
  get isDatasetInvalid() {
18011
- return !!this.state.datasetDispatchResult?.isCancelledBecause(32 /* CommandResult.InvalidDataSet */);
18945
+ return !!this.state.datasetDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidDataSet */);
18012
18946
  }
18013
18947
  get isLabelInvalid() {
18014
- return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
18948
+ return !!this.state.labelsDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidLabelRange */);
18015
18949
  }
18016
18950
  onUpdateDataSetsHaveTitle(ev) {
18017
18951
  this.props.updateChart(this.props.figureId, {
@@ -18642,12 +19576,14 @@
18642
19576
  static template = "o-spreadsheet-LineBarPieDesignPanel";
18643
19577
  static components = { ColorPickerWidget };
18644
19578
  state = owl.useState({
19579
+ title: "",
18645
19580
  fillColorTool: false,
18646
19581
  });
18647
19582
  onClick(ev) {
18648
19583
  this.state.fillColorTool = false;
18649
19584
  }
18650
19585
  setup() {
19586
+ this.state.title = _t(this.props.definition.title);
18651
19587
  owl.useExternalListener(window, "click", this.onClick);
18652
19588
  }
18653
19589
  toggleColorPicker() {
@@ -18658,9 +19594,9 @@
18658
19594
  background: color,
18659
19595
  });
18660
19596
  }
18661
- updateTitle(ev) {
19597
+ updateTitle() {
18662
19598
  this.props.updateChart(this.props.figureId, {
18663
- title: ev.target.value,
19599
+ title: this.state.title,
18664
19600
  });
18665
19601
  }
18666
19602
  updateSelect(attr, ev) {
@@ -18692,7 +19628,7 @@
18692
19628
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18693
19629
  }
18694
19630
  get isDataRangeInvalid() {
18695
- return !!this.state.dataRangeDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidGaugeDataRange */);
19631
+ return !!this.state.dataRangeDispatchResult?.isCancelledBecause(37 /* CommandResult.InvalidGaugeDataRange */);
18696
19632
  }
18697
19633
  onDataRangeChanged(ranges) {
18698
19634
  this.dataRange = ranges[0];
@@ -18751,11 +19687,13 @@
18751
19687
  static template = "o-spreadsheet-GaugeChartDesignPanel";
18752
19688
  static components = { ColorPickerWidget, SidePanelErrors };
18753
19689
  state = owl.useState({
19690
+ title: "",
18754
19691
  openedMenu: undefined,
18755
19692
  sectionRuleDispatchResult: undefined,
18756
19693
  sectionRule: deepCopy(this.props.definition.sectionRule),
18757
19694
  });
18758
19695
  setup() {
19696
+ this.state.title = _t(this.props.definition.title);
18759
19697
  owl.useExternalListener(window, "click", this.closeMenus);
18760
19698
  }
18761
19699
  get designErrorMessages() {
@@ -18768,31 +19706,31 @@
18768
19706
  background: color,
18769
19707
  });
18770
19708
  }
18771
- updateTitle(ev) {
19709
+ updateTitle() {
18772
19710
  this.props.updateChart(this.props.figureId, {
18773
- title: ev.target.value,
19711
+ title: this.state.title,
18774
19712
  });
18775
19713
  }
18776
19714
  isRangeMinInvalid() {
18777
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(37 /* CommandResult.EmptyGaugeRangeMin */) ||
18778
- this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.GaugeRangeMinNaN */) ||
18779
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19715
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.EmptyGaugeRangeMin */) ||
19716
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.GaugeRangeMinNaN */) ||
19717
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18780
19718
  }
18781
19719
  isRangeMaxInvalid() {
18782
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.EmptyGaugeRangeMax */) ||
18783
- this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.GaugeRangeMaxNaN */) ||
18784
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
19720
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.EmptyGaugeRangeMax */) ||
19721
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMaxNaN */) ||
19722
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18785
19723
  }
18786
19724
  // ---------------------------------------------------------------------------
18787
19725
  // COLOR_SECTION_TEMPLATE
18788
19726
  // ---------------------------------------------------------------------------
18789
19727
  get isLowerInflectionPointInvalid() {
18790
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
18791
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19728
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
19729
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18792
19730
  }
18793
19731
  get isUpperInflectionPointInvalid() {
18794
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
18795
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
19732
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
19733
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18796
19734
  }
18797
19735
  updateSectionColor(target, color) {
18798
19736
  const sectionRule = deepCopy(this.state.sectionRule);
@@ -18875,10 +19813,10 @@
18875
19813
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18876
19814
  }
18877
19815
  get isKeyValueInvalid() {
18878
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidScorecardKeyValue */);
19816
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardKeyValue */);
18879
19817
  }
18880
19818
  get isBaselineInvalid() {
18881
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardBaseline */);
19819
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidScorecardBaseline */);
18882
19820
  }
18883
19821
  onKeyValueRangeChanged(ranges) {
18884
19822
  this.keyValue = ranges[0];
@@ -18923,14 +19861,16 @@
18923
19861
  static template = "o-spreadsheet-ScorecardChartDesignPanel";
18924
19862
  static components = { ColorPickerWidget };
18925
19863
  state = owl.useState({
19864
+ title: "",
18926
19865
  openedColorPicker: undefined,
18927
19866
  });
18928
19867
  setup() {
19868
+ this.state.title = _t(this.props.definition.title);
18929
19869
  owl.useExternalListener(window, "click", this.closeMenus);
18930
19870
  }
18931
- updateTitle(ev) {
19871
+ updateTitle() {
18932
19872
  this.props.updateChart(this.props.figureId, {
18933
- title: ev.target.value,
19873
+ title: this.state.title,
18934
19874
  });
18935
19875
  }
18936
19876
  updateBaselineDescr(ev) {
@@ -19552,7 +20492,7 @@
19552
20492
  return this.env.model.getters.getConditionalFormats(this.env.model.getters.getActiveSheetId());
19553
20493
  }
19554
20494
  get isRangeValid() {
19555
- return this.state.errors.includes(24 /* CommandResult.EmptyRange */);
20495
+ return this.state.errors.includes(25 /* CommandResult.EmptyRange */);
19556
20496
  }
19557
20497
  errorMessage(error) {
19558
20498
  return CfTerms.Errors[error] || CfTerms.Errors.Unexpected;
@@ -19611,7 +20551,7 @@
19611
20551
  if (this.state.currentCF) {
19612
20552
  const invalidRanges = this.state.currentCF.ranges.some((xc) => !xc.match(rangeReference));
19613
20553
  if (invalidRanges) {
19614
- this.state.errors = [25 /* CommandResult.InvalidRange */];
20554
+ this.state.errors = [26 /* CommandResult.InvalidRange */];
19615
20555
  return;
19616
20556
  }
19617
20557
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -19766,10 +20706,10 @@
19766
20706
  * Cell Is Rule
19767
20707
  ****************************************************************************/
19768
20708
  get isValue1Invalid() {
19769
- return !!this.state.errors?.includes(51 /* CommandResult.FirstArgMissing */);
20709
+ return !!this.state.errors?.includes(52 /* CommandResult.FirstArgMissing */);
19770
20710
  }
19771
20711
  get isValue2Invalid() {
19772
- return !!this.state.errors?.includes(52 /* CommandResult.SecondArgMissing */);
20712
+ return !!this.state.errors?.includes(53 /* CommandResult.SecondArgMissing */);
19773
20713
  }
19774
20714
  toggleStyle(tool) {
19775
20715
  const style = this.state.rules.cellIs.style;
@@ -19786,17 +20726,17 @@
19786
20726
  isValueInvalid(threshold) {
19787
20727
  switch (threshold) {
19788
20728
  case "minimum":
19789
- return (this.state.errors.includes(58 /* CommandResult.MinInvalidFormula */) ||
19790
- this.state.errors.includes(50 /* CommandResult.MinBiggerThanMid */) ||
19791
- this.state.errors.includes(47 /* CommandResult.MinBiggerThanMax */) ||
19792
- this.state.errors.includes(53 /* CommandResult.MinNaN */));
20729
+ return (this.state.errors.includes(59 /* CommandResult.MinInvalidFormula */) ||
20730
+ this.state.errors.includes(51 /* CommandResult.MinBiggerThanMid */) ||
20731
+ this.state.errors.includes(48 /* CommandResult.MinBiggerThanMax */) ||
20732
+ this.state.errors.includes(54 /* CommandResult.MinNaN */));
19793
20733
  case "midpoint":
19794
- return (this.state.errors.includes(59 /* CommandResult.MidInvalidFormula */) ||
19795
- this.state.errors.includes(54 /* CommandResult.MidNaN */) ||
19796
- this.state.errors.includes(49 /* CommandResult.MidBiggerThanMax */));
20734
+ return (this.state.errors.includes(60 /* CommandResult.MidInvalidFormula */) ||
20735
+ this.state.errors.includes(55 /* CommandResult.MidNaN */) ||
20736
+ this.state.errors.includes(50 /* CommandResult.MidBiggerThanMax */));
19797
20737
  case "maximum":
19798
- return (this.state.errors.includes(60 /* CommandResult.MaxInvalidFormula */) ||
19799
- this.state.errors.includes(55 /* CommandResult.MaxNaN */));
20738
+ return (this.state.errors.includes(61 /* CommandResult.MaxInvalidFormula */) ||
20739
+ this.state.errors.includes(56 /* CommandResult.MaxNaN */));
19800
20740
  default:
19801
20741
  return false;
19802
20742
  }
@@ -19844,13 +20784,13 @@
19844
20784
  isInflectionPointInvalid(inflectionPoint) {
19845
20785
  switch (inflectionPoint) {
19846
20786
  case "lowerInflectionPoint":
19847
- return (this.state.errors.includes(57 /* CommandResult.ValueLowerInflectionNaN */) ||
19848
- this.state.errors.includes(62 /* CommandResult.ValueLowerInvalidFormula */) ||
19849
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20787
+ return (this.state.errors.includes(58 /* CommandResult.ValueLowerInflectionNaN */) ||
20788
+ this.state.errors.includes(63 /* CommandResult.ValueLowerInvalidFormula */) ||
20789
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19850
20790
  case "upperInflectionPoint":
19851
- return (this.state.errors.includes(56 /* CommandResult.ValueUpperInflectionNaN */) ||
19852
- this.state.errors.includes(61 /* CommandResult.ValueUpperInvalidFormula */) ||
19853
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
20791
+ return (this.state.errors.includes(57 /* CommandResult.ValueUpperInflectionNaN */) ||
20792
+ this.state.errors.includes(62 /* CommandResult.ValueUpperInvalidFormula */) ||
20793
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19854
20794
  default:
19855
20795
  return true;
19856
20796
  }
@@ -20160,7 +21100,7 @@
20160
21100
  };
20161
21101
  function interactiveSplitToColumns(env, separator, addNewColumns) {
20162
21102
  let result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", { separator, addNewColumns });
20163
- if (result.isCancelledBecause(90 /* CommandResult.SplitWillOverwriteContent */)) {
21103
+ if (result.isCancelledBecause(91 /* CommandResult.SplitWillOverwriteContent */)) {
20164
21104
  env.askConfirmation(SplitToColumnsInteractiveContent.SplitIsDestructive, () => {
20165
21105
  result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", {
20166
21106
  separator,
@@ -20224,8 +21164,8 @@
20224
21164
  const errors = new Set();
20225
21165
  for (const reason of cancelledReasons) {
20226
21166
  switch (reason) {
20227
- case 90 /* CommandResult.SplitWillOverwriteContent */:
20228
- case 89 /* CommandResult.EmptySplitSeparator */:
21167
+ case 91 /* CommandResult.SplitWillOverwriteContent */:
21168
+ case 90 /* CommandResult.EmptySplitSeparator */:
20229
21169
  break;
20230
21170
  default:
20231
21171
  errors.add(SplitToColumnsTerms.Errors[reason] || SplitToColumnsTerms.Errors.Unexpected);
@@ -20240,8 +21180,8 @@
20240
21180
  addNewColumns: this.state.addNewColumns,
20241
21181
  force: false,
20242
21182
  }).reasons;
20243
- if (cancelledReasons.includes(90 /* CommandResult.SplitWillOverwriteContent */)) {
20244
- warnings.push(SplitToColumnsTerms.Errors[90 /* CommandResult.SplitWillOverwriteContent */]);
21183
+ if (cancelledReasons.includes(91 /* CommandResult.SplitWillOverwriteContent */)) {
21184
+ warnings.push(SplitToColumnsTerms.Errors[91 /* CommandResult.SplitWillOverwriteContent */]);
20245
21185
  }
20246
21186
  return warnings;
20247
21187
  }
@@ -20894,6 +21834,13 @@
20894
21834
  const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
20895
21835
  element?.scrollIntoView({ block: "nearest" });
20896
21836
  }
21837
+ /**
21838
+ * remove the current selection of the user
21839
+ * */
21840
+ removeSelection() {
21841
+ let selection = window.getSelection();
21842
+ selection.removeAllRanges();
21843
+ }
20897
21844
  removeAll() {
20898
21845
  if (this.el) {
20899
21846
  while (this.el.firstChild) {
@@ -21380,6 +22327,21 @@
21380
22327
  this.autoCompleteState.values = values.slice(0, 10);
21381
22328
  this.autoCompleteState.selectedIndex = 0;
21382
22329
  }
22330
+ /**
22331
+ * This is required to ensure the content helper selection is
22332
+ * properly updated on "onclick" events. Depending on the browser,
22333
+ * the callback onClick from the composer will be executed before
22334
+ * the selection was updated in the dom, which means we capture an
22335
+ * wrong selection which is then forced upon the content helper on
22336
+ * patchContent.
22337
+ */
22338
+ onMousedown(ev) {
22339
+ if (ev.button > 0) {
22340
+ // not main button, probably a context menu
22341
+ return;
22342
+ }
22343
+ this.contentHelper.removeSelection();
22344
+ }
21383
22345
  onClick() {
21384
22346
  if (this.env.model.getters.isReadonly()) {
21385
22347
  return;
@@ -21392,6 +22354,29 @@
21392
22354
  this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
21393
22355
  this.processTokenAtCursor();
21394
22356
  }
22357
+ onDblClick() {
22358
+ if (this.env.model.getters.isReadonly()) {
22359
+ return;
22360
+ }
22361
+ const composerContent = this.env.model.getters.getCurrentContent();
22362
+ const isValidFormula = composerContent.startsWith("=");
22363
+ if (isValidFormula) {
22364
+ const tokens = this.env.model.getters.getCurrentTokens();
22365
+ const currentSelection = this.contentHelper.getCurrentSelection();
22366
+ if (currentSelection.start === currentSelection.end)
22367
+ return;
22368
+ const currentSelectedText = composerContent.substring(currentSelection.start, currentSelection.end);
22369
+ const token = tokens.filter((token) => token.value.includes(currentSelectedText) &&
22370
+ token.start <= currentSelection.start &&
22371
+ token.end >= currentSelection.end)[0];
22372
+ if (token.type === "REFERENCE") {
22373
+ this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", {
22374
+ start: token.start,
22375
+ end: token.end,
22376
+ });
22377
+ }
22378
+ }
22379
+ }
21395
22380
  // ---------------------------------------------------------------------------
21396
22381
  // Private
21397
22382
  // ---------------------------------------------------------------------------
@@ -21420,7 +22405,7 @@
21420
22405
  */
21421
22406
  getContentLines() {
21422
22407
  let value = this.env.model.getters.getCurrentContent();
21423
- const isValidFormula = value.startsWith("=") && this.env.model.getters.getCurrentTokens().length > 0;
22408
+ const isValidFormula = value.startsWith("=");
21424
22409
  if (value === "") {
21425
22410
  return [];
21426
22411
  }
@@ -24129,7 +25114,7 @@
24129
25114
  }
24130
25115
  ev.preventDefault();
24131
25116
  }
24132
- paste(ev) {
25117
+ async paste(ev) {
24133
25118
  if (!this.gridEl.contains(document.activeElement)) {
24134
25119
  return;
24135
25120
  }
@@ -24149,6 +25134,9 @@
24149
25134
  else {
24150
25135
  interactivePasteFromOS(this.env, target, content);
24151
25136
  }
25137
+ if (this.env.model.getters.isCutOperation()) {
25138
+ await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
25139
+ }
24152
25140
  }
24153
25141
  }
24154
25142
  displayWarningCopyPasteNotSupported() {
@@ -30088,9 +31076,9 @@
30088
31076
  checkCellOutOfSheet(sheetId, col, row) {
30089
31077
  const sheet = this.getters.tryGetSheet(sheetId);
30090
31078
  if (!sheet)
30091
- return 27 /* CommandResult.InvalidSheetId */;
31079
+ return 28 /* CommandResult.InvalidSheetId */;
30092
31080
  const sheetZone = this.getters.getSheetZone(sheetId);
30093
- return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
31081
+ return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 19 /* CommandResult.TargetOutOfSheet */;
30094
31082
  }
30095
31083
  }
30096
31084
  class FormulaCellWithDependencies {
@@ -30313,13 +31301,13 @@
30313
31301
  }
30314
31302
  checkChartDuplicate(cmd) {
30315
31303
  return this.getters.getFigureSheetId(cmd.id)
30316
- ? 84 /* CommandResult.DuplicatedChartId */
31304
+ ? 85 /* CommandResult.DuplicatedChartId */
30317
31305
  : 0 /* CommandResult.Success */;
30318
31306
  }
30319
31307
  checkChartExists(cmd) {
30320
31308
  return this.getters.getFigureSheetId(cmd.id)
30321
31309
  ? 0 /* CommandResult.Success */
30322
- : 85 /* CommandResult.ChartDoesNotExist */;
31310
+ : 86 /* CommandResult.ChartDoesNotExist */;
30323
31311
  }
30324
31312
  }
30325
31313
 
@@ -30528,18 +31516,18 @@
30528
31516
  }
30529
31517
  checkValidReordering(cfId, direction, sheetId) {
30530
31518
  if (!this.cfRules[sheetId])
30531
- return 27 /* CommandResult.InvalidSheetId */;
31519
+ return 28 /* CommandResult.InvalidSheetId */;
30532
31520
  const ruleIndex = this.cfRules[sheetId].findIndex((cf) => cf.id === cfId);
30533
31521
  if (ruleIndex === -1)
30534
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31522
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30535
31523
  const cfIndex2 = direction === "up" ? ruleIndex - 1 : ruleIndex + 1;
30536
31524
  if (cfIndex2 < 0 || cfIndex2 >= this.cfRules[sheetId].length) {
30537
- return 71 /* CommandResult.InvalidConditionalFormatId */;
31525
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30538
31526
  }
30539
31527
  return 0 /* CommandResult.Success */;
30540
31528
  }
30541
31529
  checkEmptyRange(cmd) {
30542
- return cmd.ranges.length ? 0 /* CommandResult.Success */ : 24 /* CommandResult.EmptyRange */;
31530
+ return cmd.ranges.length ? 0 /* CommandResult.Success */ : 25 /* CommandResult.EmptyRange */;
30543
31531
  }
30544
31532
  checkCFRule(cmd) {
30545
31533
  const rule = cmd.cf.rule;
@@ -30575,10 +31563,10 @@
30575
31563
  const errors = [];
30576
31564
  const isEmpty = (value) => value === undefined || value === "";
30577
31565
  if (expectedNumber >= 1 && isEmpty(rule.values[0])) {
30578
- errors.push(51 /* CommandResult.FirstArgMissing */);
31566
+ errors.push(52 /* CommandResult.FirstArgMissing */);
30579
31567
  }
30580
31568
  if (expectedNumber >= 2 && isEmpty(rule.values[1])) {
30581
- errors.push(52 /* CommandResult.SecondArgMissing */);
31569
+ errors.push(53 /* CommandResult.SecondArgMissing */);
30582
31570
  }
30583
31571
  return errors.length ? errors : 0 /* CommandResult.Success */;
30584
31572
  }
@@ -30590,15 +31578,15 @@
30590
31578
  (threshold.value === "" || isNaN(threshold.value))) {
30591
31579
  switch (thresholdName) {
30592
31580
  case "min":
30593
- return 53 /* CommandResult.MinNaN */;
31581
+ return 54 /* CommandResult.MinNaN */;
30594
31582
  case "max":
30595
- return 55 /* CommandResult.MaxNaN */;
31583
+ return 56 /* CommandResult.MaxNaN */;
30596
31584
  case "mid":
30597
- return 54 /* CommandResult.MidNaN */;
31585
+ return 55 /* CommandResult.MidNaN */;
30598
31586
  case "upperInflectionPoint":
30599
- return 56 /* CommandResult.ValueUpperInflectionNaN */;
31587
+ return 57 /* CommandResult.ValueUpperInflectionNaN */;
30600
31588
  case "lowerInflectionPoint":
30601
- return 57 /* CommandResult.ValueLowerInflectionNaN */;
31589
+ return 58 /* CommandResult.ValueLowerInflectionNaN */;
30602
31590
  }
30603
31591
  }
30604
31592
  return 0 /* CommandResult.Success */;
@@ -30612,15 +31600,15 @@
30612
31600
  catch (error) {
30613
31601
  switch (thresholdName) {
30614
31602
  case "min":
30615
- return 58 /* CommandResult.MinInvalidFormula */;
31603
+ return 59 /* CommandResult.MinInvalidFormula */;
30616
31604
  case "max":
30617
- return 60 /* CommandResult.MaxInvalidFormula */;
31605
+ return 61 /* CommandResult.MaxInvalidFormula */;
30618
31606
  case "mid":
30619
- return 59 /* CommandResult.MidInvalidFormula */;
31607
+ return 60 /* CommandResult.MidInvalidFormula */;
30620
31608
  case "upperInflectionPoint":
30621
- return 61 /* CommandResult.ValueUpperInvalidFormula */;
31609
+ return 62 /* CommandResult.ValueUpperInvalidFormula */;
30622
31610
  case "lowerInflectionPoint":
30623
- return 62 /* CommandResult.ValueLowerInvalidFormula */;
31611
+ return 63 /* CommandResult.ValueLowerInvalidFormula */;
30624
31612
  }
30625
31613
  }
30626
31614
  return 0 /* CommandResult.Success */;
@@ -30637,7 +31625,7 @@
30637
31625
  if (["number", "percentage", "percentile"].includes(rule.lowerInflectionPoint.type) &&
30638
31626
  rule.lowerInflectionPoint.type === rule.upperInflectionPoint.type &&
30639
31627
  Number(minValue) > Number(maxValue)) {
30640
- return 48 /* CommandResult.LowerBiggerThanUpper */;
31628
+ return 49 /* CommandResult.LowerBiggerThanUpper */;
30641
31629
  }
30642
31630
  return 0 /* CommandResult.Success */;
30643
31631
  }
@@ -30647,7 +31635,7 @@
30647
31635
  if (["number", "percentage", "percentile"].includes(rule.minimum.type) &&
30648
31636
  rule.minimum.type === rule.maximum.type &&
30649
31637
  stringToNumber(minValue) >= stringToNumber(maxValue)) {
30650
- return 47 /* CommandResult.MinBiggerThanMax */;
31638
+ return 48 /* CommandResult.MinBiggerThanMax */;
30651
31639
  }
30652
31640
  return 0 /* CommandResult.Success */;
30653
31641
  }
@@ -30658,7 +31646,7 @@
30658
31646
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30659
31647
  rule.midpoint.type === rule.maximum.type &&
30660
31648
  stringToNumber(midValue) >= stringToNumber(maxValue)) {
30661
- return 49 /* CommandResult.MidBiggerThanMax */;
31649
+ return 50 /* CommandResult.MidBiggerThanMax */;
30662
31650
  }
30663
31651
  return 0 /* CommandResult.Success */;
30664
31652
  }
@@ -30669,7 +31657,7 @@
30669
31657
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30670
31658
  rule.minimum.type === rule.midpoint.type &&
30671
31659
  stringToNumber(minValue) >= stringToNumber(midValue)) {
30672
- return 50 /* CommandResult.MinBiggerThanMid */;
31660
+ return 51 /* CommandResult.MinBiggerThanMid */;
30673
31661
  }
30674
31662
  return 0 /* CommandResult.Success */;
30675
31663
  }
@@ -30799,13 +31787,13 @@
30799
31787
  }
30800
31788
  checkFigureExists(sheetId, figureId) {
30801
31789
  if (this.figures[sheetId]?.[figureId] === undefined) {
30802
- return 70 /* CommandResult.FigureDoesNotExist */;
31790
+ return 71 /* CommandResult.FigureDoesNotExist */;
30803
31791
  }
30804
31792
  return 0 /* CommandResult.Success */;
30805
31793
  }
30806
31794
  checkFigureDuplicate(figureId) {
30807
31795
  if (Object.values(this.figures).find((sheet) => sheet?.[figureId])) {
30808
- return 82 /* CommandResult.DuplicatedFigureId */;
31796
+ return 83 /* CommandResult.DuplicatedFigureId */;
30809
31797
  }
30810
31798
  return 0 /* CommandResult.Success */;
30811
31799
  }
@@ -30917,12 +31905,12 @@
30917
31905
  switch (cmd.type) {
30918
31906
  case "CREATE_FILTER_TABLE":
30919
31907
  if (!areZonesContinuous(...cmd.target)) {
30920
- return 81 /* CommandResult.NonContinuousTargets */;
31908
+ return 82 /* CommandResult.NonContinuousTargets */;
30921
31909
  }
30922
31910
  const zone = union(...cmd.target);
30923
31911
  const checkFilterOverlap = () => {
30924
31912
  if (this.getFilterTables(cmd.sheetId).some((filter) => overlap(filter.zone, zone))) {
30925
- return 78 /* CommandResult.FilterOverlap */;
31913
+ return 79 /* CommandResult.FilterOverlap */;
30926
31914
  }
30927
31915
  return 0 /* CommandResult.Success */;
30928
31916
  };
@@ -30930,7 +31918,7 @@
30930
31918
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, zone);
30931
31919
  for (let merge of mergesInTarget) {
30932
31920
  if (overlap(zone, merge)) {
30933
- return 80 /* CommandResult.MergeInFilter */;
31921
+ return 81 /* CommandResult.MergeInFilter */;
30934
31922
  }
30935
31923
  }
30936
31924
  return 0 /* CommandResult.Success */;
@@ -30940,7 +31928,7 @@
30940
31928
  for (let merge of cmd.target) {
30941
31929
  for (let filterTable of this.getFilterTables(cmd.sheetId)) {
30942
31930
  if (overlap(filterTable.zone, merge)) {
30943
- return 80 /* CommandResult.MergeInFilter */;
31931
+ return 81 /* CommandResult.MergeInFilter */;
30944
31932
  }
30945
31933
  }
30946
31934
  }
@@ -30959,7 +31947,14 @@
30959
31947
  this.history.update("tables", filterTables);
30960
31948
  break;
30961
31949
  case "DUPLICATE_SHEET":
30962
- this.history.update("tables", cmd.sheetIdTo, deepCopy(this.tables[cmd.sheetId]));
31950
+ const tables = {};
31951
+ for (const filterTable of Object.values(this.tables[cmd.sheetId] || {})) {
31952
+ if (filterTable) {
31953
+ const newFilterTable = deepCopy(filterTable);
31954
+ tables[newFilterTable.id] = newFilterTable;
31955
+ }
31956
+ }
31957
+ this.history.update("tables", cmd.sheetIdTo, tables);
30963
31958
  break;
30964
31959
  case "ADD_COLUMNS_ROWS":
30965
31960
  this.onAddColumnsRows(cmd);
@@ -31411,7 +32406,7 @@
31411
32406
  switch (cmd.type) {
31412
32407
  case "HIDE_COLUMNS_ROWS": {
31413
32408
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31414
- return 27 /* CommandResult.InvalidSheetId */;
32409
+ return 28 /* CommandResult.InvalidSheetId */;
31415
32410
  }
31416
32411
  const hiddenGroup = cmd.dimension === "COL"
31417
32412
  ? this.getHiddenColsGroups(cmd.sheetId)
@@ -31421,10 +32416,10 @@
31421
32416
  : this.getters.getNumberRows(cmd.sheetId);
31422
32417
  const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
31423
32418
  if (hiddenElements.size >= elements) {
31424
- return 66 /* CommandResult.TooManyHiddenElements */;
32419
+ return 67 /* CommandResult.TooManyHiddenElements */;
31425
32420
  }
31426
32421
  else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31427
- return 86 /* CommandResult.InvalidHeaderIndex */;
32422
+ return 87 /* CommandResult.InvalidHeaderIndex */;
31428
32423
  }
31429
32424
  else {
31430
32425
  return 0 /* CommandResult.Success */;
@@ -31432,7 +32427,7 @@
31432
32427
  }
31433
32428
  case "REMOVE_COLUMNS_ROWS":
31434
32429
  if (!this.getters.tryGetSheet(cmd.sheetId)) {
31435
- return 27 /* CommandResult.InvalidSheetId */;
32430
+ return 28 /* CommandResult.InvalidSheetId */;
31436
32431
  }
31437
32432
  if (!this.canRemoveHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
31438
32433
  return 8 /* CommandResult.NotEnoughElements */;
@@ -31600,7 +32595,7 @@
31600
32595
  switch (cmd.type) {
31601
32596
  case "CREATE_IMAGE":
31602
32597
  if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
31603
- return 28 /* CommandResult.InvalidFigureId */;
32598
+ return 29 /* CommandResult.InvalidFigureId */;
31604
32599
  }
31605
32600
  return 0 /* CommandResult.Success */;
31606
32601
  default:
@@ -31988,7 +32983,7 @@
31988
32983
  for (const zone of target) {
31989
32984
  for (const zone2 of target) {
31990
32985
  if (zone !== zone2 && overlap(zone, zone2)) {
31991
- return 65 /* CommandResult.MergeOverlap */;
32986
+ return 66 /* CommandResult.MergeOverlap */;
31992
32987
  }
31993
32988
  }
31994
32989
  }
@@ -32002,7 +32997,7 @@
32002
32997
  for (const zone of target) {
32003
32998
  if ((zone.left < xSplit && zone.right >= xSplit) ||
32004
32999
  (zone.top < ySplit && zone.bottom >= ySplit)) {
32005
- return 75 /* CommandResult.FrozenPaneOverlap */;
33000
+ return 76 /* CommandResult.FrozenPaneOverlap */;
32006
33001
  }
32007
33002
  }
32008
33003
  return 0 /* CommandResult.Success */;
@@ -32196,7 +33191,7 @@
32196
33191
  // ---------------------------------------------------------------------------
32197
33192
  allowDispatch(cmd) {
32198
33193
  if (cmd.type === "MOVE_RANGES") {
32199
- return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 26 /* CommandResult.InvalidZones */;
33194
+ return cmd.target.length === 1 ? 0 /* CommandResult.Success */ : 27 /* CommandResult.InvalidZones */;
32200
33195
  }
32201
33196
  return 0 /* CommandResult.Success */;
32202
33197
  }
@@ -32621,7 +33616,7 @@
32621
33616
  return 0 /* CommandResult.Success */;
32622
33617
  }
32623
33618
  catch (e) {
32624
- return 14 /* CommandResult.WrongSheetMove */;
33619
+ return 15 /* CommandResult.WrongSheetMove */;
32625
33620
  }
32626
33621
  case "RENAME_SHEET":
32627
33622
  return this.isRenameAllowed(cmd);
@@ -32634,10 +33629,10 @@
32634
33629
  ? this.getNumberCols(cmd.sheetId)
32635
33630
  : this.getNumberRows(cmd.sheetId);
32636
33631
  if (cmd.base < 0 || cmd.base > elements) {
32637
- return 86 /* CommandResult.InvalidHeaderIndex */;
33632
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32638
33633
  }
32639
33634
  else if (cmd.quantity <= 0) {
32640
- return 87 /* CommandResult.InvalidQuantity */;
33635
+ return 88 /* CommandResult.InvalidQuantity */;
32641
33636
  }
32642
33637
  return 0 /* CommandResult.Success */;
32643
33638
  case "REMOVE_COLUMNS_ROWS": {
@@ -32645,7 +33640,7 @@
32645
33640
  ? this.getNumberCols(cmd.sheetId)
32646
33641
  : this.getNumberRows(cmd.sheetId);
32647
33642
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
32648
- return 86 /* CommandResult.InvalidHeaderIndex */;
33643
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32649
33644
  }
32650
33645
  else {
32651
33646
  return 0 /* CommandResult.Success */;
@@ -32972,12 +33967,12 @@
32972
33967
  */
32973
33968
  checkZonesExistInSheet(sheetId, zones) {
32974
33969
  if (!zones.every(isZoneValid))
32975
- return 25 /* CommandResult.InvalidRange */;
33970
+ return 26 /* CommandResult.InvalidRange */;
32976
33971
  if (zones.length) {
32977
33972
  const sheetZone = this.getSheetZone(sheetId);
32978
33973
  return zones.every((zone) => isZoneInside(zone, sheetZone))
32979
33974
  ? 0 /* CommandResult.Success */
32980
- : 18 /* CommandResult.TargetOutOfSheet */;
33975
+ : 19 /* CommandResult.TargetOutOfSheet */;
32981
33976
  }
32982
33977
  return 0 /* CommandResult.Success */;
32983
33978
  }
@@ -33084,38 +34079,42 @@
33084
34079
  throw new Error(_lt("There is not enough visible sheets"));
33085
34080
  }
33086
34081
  checkSheetName(cmd) {
34082
+ const originalSheetName = this.getters.tryGetSheetName(cmd.sheetId);
34083
+ if (originalSheetName !== undefined && cmd.name === originalSheetName) {
34084
+ return 11 /* CommandResult.UnchangedSheetName */;
34085
+ }
33087
34086
  const { orderedSheetIds, sheets } = this;
33088
34087
  const name = cmd.name && cmd.name.trim().toLowerCase();
33089
- if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name)) {
33090
- return 11 /* CommandResult.DuplicatedSheetName */;
34088
+ if (orderedSheetIds.find((id) => sheets[id]?.name.toLowerCase() === name && id !== cmd.sheetId)) {
34089
+ return 12 /* CommandResult.DuplicatedSheetName */;
33091
34090
  }
33092
34091
  if (FORBIDDEN_IN_EXCEL_REGEX.test(name)) {
33093
- return 13 /* CommandResult.ForbiddenCharactersInSheetName */;
34092
+ return 14 /* CommandResult.ForbiddenCharactersInSheetName */;
33094
34093
  }
33095
34094
  return 0 /* CommandResult.Success */;
33096
34095
  }
33097
34096
  checkSheetPosition(cmd) {
33098
34097
  const { orderedSheetIds } = this;
33099
34098
  if (cmd.position > orderedSheetIds.length || cmd.position < 0) {
33100
- return 15 /* CommandResult.WrongSheetPosition */;
34099
+ return 16 /* CommandResult.WrongSheetPosition */;
33101
34100
  }
33102
34101
  return 0 /* CommandResult.Success */;
33103
34102
  }
33104
34103
  checkRowFreezeQuantity(cmd) {
33105
34104
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberRows(cmd.sheetId)
33106
34105
  ? 0 /* CommandResult.Success */
33107
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34106
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33108
34107
  }
33109
34108
  checkColFreezeQuantity(cmd) {
33110
34109
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberCols(cmd.sheetId)
33111
34110
  ? 0 /* CommandResult.Success */
33112
- : 74 /* CommandResult.InvalidFreezeQuantity */;
34111
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
33113
34112
  }
33114
34113
  checkRowFreezeOverlapMerge(cmd) {
33115
34114
  const merges = this.getters.getMerges(cmd.sheetId);
33116
34115
  for (let merge of merges) {
33117
34116
  if (merge.top < cmd.quantity && cmd.quantity <= merge.bottom) {
33118
- return 65 /* CommandResult.MergeOverlap */;
34117
+ return 66 /* CommandResult.MergeOverlap */;
33119
34118
  }
33120
34119
  }
33121
34120
  return 0 /* CommandResult.Success */;
@@ -33124,7 +34123,7 @@
33124
34123
  const merges = this.getters.getMerges(cmd.sheetId);
33125
34124
  for (let merge of merges) {
33126
34125
  if (merge.left < cmd.quantity && cmd.quantity <= merge.right) {
33127
- return 65 /* CommandResult.MergeOverlap */;
34126
+ return 66 /* CommandResult.MergeOverlap */;
33128
34127
  }
33129
34128
  }
33130
34129
  return 0 /* CommandResult.Success */;
@@ -33140,8 +34139,8 @@
33140
34139
  const oldName = sheet.name;
33141
34140
  this.history.update("sheets", sheet.id, "name", name.trim());
33142
34141
  const sheetIdsMapName = Object.assign({}, this.sheetIdsMapName);
33143
- sheetIdsMapName[name] = sheet.id;
33144
34142
  delete sheetIdsMapName[oldName];
34143
+ sheetIdsMapName[name] = sheet.id;
33145
34144
  this.history.update("sheetIdsMapName", sheetIdsMapName);
33146
34145
  }
33147
34146
  hideSheet(sheetId) {
@@ -33435,10 +34434,10 @@
33435
34434
  */
33436
34435
  checkSheetExists(cmd) {
33437
34436
  if (cmd.type !== "CREATE_SHEET" && "sheetId" in cmd && this.sheets[cmd.sheetId] === undefined) {
33438
- return 27 /* CommandResult.InvalidSheetId */;
34437
+ return 28 /* CommandResult.InvalidSheetId */;
33439
34438
  }
33440
34439
  else if (cmd.type === "CREATE_SHEET" && this.sheets[cmd.sheetId] !== undefined) {
33441
- return 12 /* CommandResult.DuplicatedSheetId */;
34440
+ return 13 /* CommandResult.DuplicatedSheetId */;
33442
34441
  }
33443
34442
  return 0 /* CommandResult.Success */;
33444
34443
  }
@@ -34999,7 +35998,7 @@
34999
35998
  if (this.lastCellSelected.col !== undefined && this.lastCellSelected.row !== undefined) {
35000
35999
  return 0 /* CommandResult.Success */;
35001
36000
  }
35002
- return 45 /* CommandResult.InvalidAutofillSelection */;
36001
+ return 46 /* CommandResult.InvalidAutofillSelection */;
35003
36002
  case "AUTOFILL_AUTO":
35004
36003
  const zone = this.getters.getSelectedZone();
35005
36004
  return zone.top === zone.bottom
@@ -35616,7 +36615,7 @@
35616
36615
  cellPopoverRegistry.get(cmd.popoverType);
35617
36616
  }
35618
36617
  catch (error) {
35619
- return 72 /* CommandResult.InvalidCellPopover */;
36618
+ return 73 /* CommandResult.InvalidCellPopover */;
35620
36619
  }
35621
36620
  return 0 /* CommandResult.Success */;
35622
36621
  default:
@@ -37746,12 +38745,12 @@
37746
38745
  case "ADD_RANGE":
37747
38746
  case "ADD_EMPTY_RANGE":
37748
38747
  if (this.inputHasSingleRange && this.ranges.length === 1) {
37749
- return 30 /* CommandResult.MaximumRangesReached */;
38748
+ return 31 /* CommandResult.MaximumRangesReached */;
37750
38749
  }
37751
38750
  break;
37752
38751
  case "CHANGE_RANGE":
37753
38752
  if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
37754
- return 30 /* CommandResult.MaximumRangesReached */;
38753
+ return 31 /* CommandResult.MaximumRangesReached */;
37755
38754
  }
37756
38755
  break;
37757
38756
  }
@@ -37980,7 +38979,7 @@
37980
38979
  case "FOCUS_RANGE":
37981
38980
  const index = this.currentInput?.getIndex(cmd.rangeId);
37982
38981
  if (this.focusedInputId === cmd.id && this.currentInput?.focusedRangeIndex === index) {
37983
- return 29 /* CommandResult.InputAlreadyFocused */;
38982
+ return 30 /* CommandResult.InputAlreadyFocused */;
37984
38983
  }
37985
38984
  break;
37986
38985
  }
@@ -38112,7 +39111,7 @@
38112
39111
  /*Test the presence of single cells*/
38113
39112
  const singleCells = positions(zone).some(({ col, row }) => !this.getters.isInMerge({ sheetId, col, row }));
38114
39113
  if (singleCells) {
38115
- return 63 /* CommandResult.InvalidSortZone */;
39114
+ return 64 /* CommandResult.InvalidSortZone */;
38116
39115
  }
38117
39116
  return 0 /* CommandResult.Success */;
38118
39117
  }
@@ -38131,7 +39130,7 @@
38131
39130
  ];
38132
39131
  return widthCurrent === widthFirst && heightCurrent === heightFirst;
38133
39132
  })) {
38134
- return 63 /* CommandResult.InvalidSortZone */;
39133
+ return 64 /* CommandResult.InvalidSortZone */;
38135
39134
  }
38136
39135
  return 0 /* CommandResult.Success */;
38137
39136
  }
@@ -38624,7 +39623,7 @@
38624
39623
  */
38625
39624
  checkSheetExists(cmd) {
38626
39625
  if ("sheetId" in cmd && this.getters.tryGetSheet(cmd.sheetId) === undefined) {
38627
- return 27 /* CommandResult.InvalidSheetId */;
39626
+ return 28 /* CommandResult.InvalidSheetId */;
38628
39627
  }
38629
39628
  return 0 /* CommandResult.Success */;
38630
39629
  }
@@ -38636,7 +39635,7 @@
38636
39635
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
38637
39636
  const zones = this.getters.getCommandZones(cmd);
38638
39637
  if (!sheetId && zones.length > 0) {
38639
- return 92 /* CommandResult.NoActiveSheet */;
39638
+ return 93 /* CommandResult.NoActiveSheet */;
38640
39639
  }
38641
39640
  if (sheetId && zones.length > 0) {
38642
39641
  return this.getters.checkZonesExistInSheet(sheetId, zones);
@@ -39118,13 +40117,13 @@
39118
40117
  }
39119
40118
  checkSingleColSelected() {
39120
40119
  if (!this.getters.isSingleColSelected()) {
39121
- return 88 /* CommandResult.MoreThanOneColumnSelected */;
40120
+ return 89 /* CommandResult.MoreThanOneColumnSelected */;
39122
40121
  }
39123
40122
  return 0 /* CommandResult.Success */;
39124
40123
  }
39125
40124
  checkNonEmptySelector(cmd) {
39126
40125
  if (cmd.separator === "") {
39127
- return 89 /* CommandResult.EmptySplitSeparator */;
40126
+ return 90 /* CommandResult.EmptySplitSeparator */;
39128
40127
  }
39129
40128
  return 0 /* CommandResult.Success */;
39130
40129
  }
@@ -39135,7 +40134,7 @@
39135
40134
  const selection = this.getters.getSelectedZones()[0];
39136
40135
  const splitted = this.getSplittedCols(selection, cmd.separator);
39137
40136
  if (this.willSplittedColsOverwriteContent(selection, splitted)) {
39138
- return 90 /* CommandResult.SplitWillOverwriteContent */;
40137
+ return 91 /* CommandResult.SplitWillOverwriteContent */;
39139
40138
  }
39140
40139
  return 0 /* CommandResult.Success */;
39141
40140
  }
@@ -39146,7 +40145,7 @@
39146
40145
  return 0 /* CommandResult.Success */;
39147
40146
  }
39148
40147
  }
39149
- return 91 /* CommandResult.NoSplitSeparatorInSelection */;
40148
+ return 92 /* CommandResult.NoSplitSeparatorInSelection */;
39150
40149
  }
39151
40150
  }
39152
40151
 
@@ -39261,7 +40260,7 @@
39261
40260
  }
39262
40261
  isCutAllowed(target) {
39263
40262
  if (target.length !== 1) {
39264
- return 19 /* CommandResult.WrongCutSelection */;
40263
+ return 20 /* CommandResult.WrongCutSelection */;
39265
40264
  }
39266
40265
  return 0 /* CommandResult.Success */;
39267
40266
  }
@@ -39269,13 +40268,13 @@
39269
40268
  const sheetId = this.getters.getActiveSheetId();
39270
40269
  if (this.operation === "CUT" && clipboardOption?.pasteOption !== undefined) {
39271
40270
  // cannot paste only format or only value if the previous operation is a CUT
39272
- return 21 /* CommandResult.WrongPasteOption */;
40271
+ return 22 /* CommandResult.WrongPasteOption */;
39273
40272
  }
39274
40273
  if (target.length > 1) {
39275
40274
  // cannot paste if we have a clipped zone larger than a cell and multiple
39276
40275
  // zones selected
39277
40276
  if (this.cells.length > 1 || this.cells[0].length > 1) {
39278
- return 20 /* CommandResult.WrongPasteSelection */;
40277
+ return 21 /* CommandResult.WrongPasteSelection */;
39279
40278
  }
39280
40279
  }
39281
40280
  const clipboardHeight = this.cells.length;
@@ -39293,7 +40292,7 @@
39293
40292
  for (const zone of this.getPasteZones(target)) {
39294
40293
  if ((zone.left < xSplit && zone.right >= xSplit) ||
39295
40294
  (zone.top < ySplit && zone.bottom >= ySplit)) {
39296
- return 75 /* CommandResult.FrozenPaneOverlap */;
40295
+ return 76 /* CommandResult.FrozenPaneOverlap */;
39297
40296
  }
39298
40297
  }
39299
40298
  return 0 /* CommandResult.Success */;
@@ -39361,6 +40360,13 @@
39361
40360
  });
39362
40361
  }
39363
40362
  this.pasteCopiedTables(target);
40363
+ this.cells.forEach((row) => {
40364
+ row.forEach((c) => {
40365
+ if (c.cell) {
40366
+ c.cell = undefined;
40367
+ }
40368
+ });
40369
+ });
39364
40370
  }
39365
40371
  /**
39366
40372
  * The clipped zone is copied as many times as it fits in the target.
@@ -39593,7 +40599,9 @@
39593
40599
  return (this.cells
39594
40600
  .map((cells) => {
39595
40601
  return cells
39596
- .map((c) => c.cell ? this.getters.getCellText(c.position, this.getters.shouldShowFormulas()) : "")
40602
+ .map((c) => this.getters.shouldShowFormulas() && c.cell?.isFormula
40603
+ ? c.cell?.content || ""
40604
+ : c.evaluatedCell?.formattedValue || "")
39597
40605
  .join("\t");
39598
40606
  })
39599
40607
  .join("\n") || "\t");
@@ -39724,10 +40732,10 @@
39724
40732
  }
39725
40733
  isPasteAllowed(target, option) {
39726
40734
  if (target.length === 0) {
39727
- return 73 /* CommandResult.EmptyTarget */;
40735
+ return 74 /* CommandResult.EmptyTarget */;
39728
40736
  }
39729
40737
  if (option?.pasteOption !== undefined) {
39730
- return 22 /* CommandResult.WrongFigurePasteOption */;
40738
+ return 23 /* CommandResult.WrongFigurePasteOption */;
39731
40739
  }
39732
40740
  return 0 /* CommandResult.Success */;
39733
40741
  }
@@ -39829,7 +40837,10 @@
39829
40837
  }
39830
40838
  return 0 /* CommandResult.Success */;
39831
40839
  }
39832
- paste(target) {
40840
+ paste(target, clipboardOption) {
40841
+ if (clipboardOption?.pasteOption === "onlyFormat") {
40842
+ return;
40843
+ }
39833
40844
  const values = this.values;
39834
40845
  const pasteZone = this.getPasteZone(target);
39835
40846
  const { left: activeCol, top: activeRow } = pasteZone;
@@ -39890,6 +40901,7 @@
39890
40901
  state;
39891
40902
  lastPasteState;
39892
40903
  _isPaintingFormat = false;
40904
+ originSheetId;
39893
40905
  // ---------------------------------------------------------------------------
39894
40906
  // Command Handling
39895
40907
  // ---------------------------------------------------------------------------
@@ -39901,13 +40913,13 @@
39901
40913
  return state.isCutAllowed(zones);
39902
40914
  case "PASTE":
39903
40915
  if (!this.state) {
39904
- return 23 /* CommandResult.EmptyClipboard */;
40916
+ return 24 /* CommandResult.EmptyClipboard */;
39905
40917
  }
39906
40918
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39907
40919
  return this.state.isPasteAllowed(cmd.target, { pasteOption });
39908
40920
  case "PASTE_FROM_OS_CLIPBOARD": {
39909
40921
  const state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
39910
- return state.isPasteAllowed(cmd.target);
40922
+ return state.isPasteAllowed(cmd.target, { pasteOption: cmd.pasteOption });
39911
40923
  }
39912
40924
  case "INSERT_CELL": {
39913
40925
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
@@ -39929,6 +40941,7 @@
39929
40941
  const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
39930
40942
  this.state = this.getClipboardState(zones, cmd.type);
39931
40943
  this.status = "visible";
40944
+ this.originSheetId = this.getters.getActiveSheetId();
39932
40945
  break;
39933
40946
  case "PASTE":
39934
40947
  if (!this.state) {
@@ -39937,9 +40950,6 @@
39937
40950
  const pasteOption = cmd.pasteOption || (this._isPaintingFormat ? "onlyFormat" : undefined);
39938
40951
  this._isPaintingFormat = false;
39939
40952
  this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
39940
- if (this.state.operation === "CUT") {
39941
- this.state = undefined;
39942
- }
39943
40953
  this.lastPasteState = this.state;
39944
40954
  this.status = "invisible";
39945
40955
  break;
@@ -39994,7 +41004,7 @@
39994
41004
  }
39995
41005
  case "PASTE_FROM_OS_CLIPBOARD":
39996
41006
  this.state = new ClipboardOsState(cmd.text, this.getters, this.dispatch, this.selection);
39997
- this.state.paste(cmd.target);
41007
+ this.state.paste(cmd.target, { pasteOption: cmd.pasteOption });
39998
41008
  this.lastPasteState = this.state;
39999
41009
  this.status = "invisible";
40000
41010
  break;
@@ -40013,6 +41023,15 @@
40013
41023
  this.status = "visible";
40014
41024
  break;
40015
41025
  }
41026
+ case "DELETE_SHEET":
41027
+ if (this.state?.operation !== "CUT") {
41028
+ return;
41029
+ }
41030
+ if (this.originSheetId === cmd.sheetId) {
41031
+ this.state = undefined;
41032
+ this.status = "invisible";
41033
+ }
41034
+ break;
40016
41035
  default:
40017
41036
  if (isCoreCommand(cmd)) {
40018
41037
  this.status = "invisible";
@@ -40471,7 +41490,7 @@
40471
41490
  validateSelection(length, start, end) {
40472
41491
  return start >= 0 && start <= length && end >= 0 && end <= length
40473
41492
  ? 0 /* CommandResult.Success */
40474
- : 46 /* CommandResult.WrongComposerSelection */;
41493
+ : 47 /* CommandResult.WrongComposerSelection */;
40475
41494
  }
40476
41495
  onColumnsRemoved(cmd) {
40477
41496
  if (cmd.elements.includes(this.col) && this.mode !== "inactive") {
@@ -40847,7 +41866,7 @@
40847
41866
  switch (cmd.type) {
40848
41867
  case "UPDATE_FILTER":
40849
41868
  if (!this.getters.getFilterId(cmd)) {
40850
- return 79 /* CommandResult.FilterNotFound */;
41869
+ return 80 /* CommandResult.FilterNotFound */;
40851
41870
  }
40852
41871
  break;
40853
41872
  }
@@ -40988,6 +42007,7 @@
40988
42007
  }
40989
42008
  exportForExcel(data) {
40990
42009
  for (const sheetData of data.sheets) {
42010
+ const sheetId = sheetData.id;
40991
42011
  for (const tableData of sheetData.filterTables) {
40992
42012
  const tableZone = toZone(tableData.range);
40993
42013
  const filters = [];
@@ -41003,20 +42023,20 @@
41003
42023
  if (!filter)
41004
42024
  continue;
41005
42025
  const valuesInFilterZone = filter.filteredZone
41006
- ? positions(filter.filteredZone)
41007
- .map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId: sheetData.id, col, row }))
41008
- .filter((cell) => cell.type !== CellValueType.empty)
41009
- .map((cell) => cell.formattedValue)
42026
+ ? positions(filter.filteredZone).map((position) => this.getters.getEvaluatedCell({ sheetId, ...position }).formattedValue)
41010
42027
  : [];
41011
- // In xlsx, filtered values = values that are displayed, not values that are hidden
41012
- const xlsxFilteredValues = valuesInFilterZone.filter((val) => !filteredValues.includes(val));
41013
- filters.push({ colId: i, filteredValues: [...new Set(xlsxFilteredValues)] });
41014
- // In xlsx, filter header should ALWAYS be a string and should be unique
41015
- const headerPosition = {
41016
- col: filter.col,
41017
- row: filter.zoneWithHeaders.top,
41018
- sheetId: sheetData.id,
41019
- };
42028
+ if (filteredValues.length) {
42029
+ const xlsxDisplayedValues = valuesInFilterZone
42030
+ .filter((val) => val)
42031
+ .filter((val) => !filteredValues.includes(val));
42032
+ filters.push({
42033
+ colId: i,
42034
+ displayedValues: [...new Set(xlsxDisplayedValues)],
42035
+ displayBlanks: !filteredValues.includes("") && valuesInFilterZone.some((val) => !val),
42036
+ });
42037
+ }
42038
+ // In xlsx, filter header should ALWAYS be a string and should be unique in the table
42039
+ const headerPosition = { col: filter.col, row: filter.zoneWithHeaders.top, sheetId };
41020
42040
  const headerString = this.getters.getEvaluatedCell(headerPosition).formattedValue;
41021
42041
  const headerName = this.getUniqueColNameForExcel(i, headerString, headerNames);
41022
42042
  headerNames.push(headerName);
@@ -41135,7 +42155,7 @@
41135
42155
  break;
41136
42156
  }
41137
42157
  catch (error) {
41138
- return 27 /* CommandResult.InvalidSheetId */;
42158
+ return 28 /* CommandResult.InvalidSheetId */;
41139
42159
  }
41140
42160
  case "MOVE_COLUMNS_ROWS":
41141
42161
  return this.isMoveElementAllowed(cmd);
@@ -42438,7 +43458,7 @@
42438
43458
  }
42439
43459
  checkPositiveDimension(cmd) {
42440
43460
  if (cmd.width < 0 || cmd.height < 0) {
42441
- return 68 /* CommandResult.InvalidViewportSize */;
43461
+ return 69 /* CommandResult.InvalidViewportSize */;
42442
43462
  }
42443
43463
  return 0 /* CommandResult.Success */;
42444
43464
  }
@@ -42448,7 +43468,7 @@
42448
43468
  cmd.gridOffsetY === this.gridOffsetY &&
42449
43469
  cmd.width === width &&
42450
43470
  cmd.height === height) {
42451
- return 76 /* CommandResult.ValuesNotChanged */;
43471
+ return 77 /* CommandResult.ValuesNotChanged */;
42452
43472
  }
42453
43473
  return 0 /* CommandResult.Success */;
42454
43474
  }
@@ -42456,7 +43476,7 @@
42456
43476
  const pane = this.getMainInternalViewport(this.getters.getActiveSheetId());
42457
43477
  if ((!pane.canScrollHorizontally && offsetX > 0) ||
42458
43478
  (!pane.canScrollVertically && offsetY > 0)) {
42459
- return 69 /* CommandResult.InvalidScrollingDirection */;
43479
+ return 70 /* CommandResult.InvalidScrollingDirection */;
42460
43480
  }
42461
43481
  return 0 /* CommandResult.Success */;
42462
43482
  }
@@ -42883,17 +43903,14 @@
42883
43903
  };
42884
43904
 
42885
43905
  function interactiveRenameSheet(env, sheetId, name, errorCallback) {
42886
- const originalSheetName = env.model.getters.getSheetName(sheetId);
42887
- if (name === null || name === originalSheetName)
42888
- return;
42889
43906
  const result = env.model.dispatch("RENAME_SHEET", { sheetId, name });
42890
43907
  if (result.reasons.includes(10 /* CommandResult.MissingSheetName */)) {
42891
43908
  env.raiseError(_lt("The sheet name cannot be empty."), errorCallback);
42892
43909
  }
42893
- else if (result.reasons.includes(11 /* CommandResult.DuplicatedSheetName */)) {
43910
+ else if (result.reasons.includes(12 /* CommandResult.DuplicatedSheetName */)) {
42894
43911
  env.raiseError(_lt("A sheet with the name %s already exists. Please select another name.", name), errorCallback);
42895
43912
  }
42896
- else if (result.reasons.includes(13 /* CommandResult.ForbiddenCharactersInSheetName */)) {
43913
+ else if (result.reasons.includes(14 /* CommandResult.ForbiddenCharactersInSheetName */)) {
42897
43914
  env.raiseError(_lt("Some used characters are not allowed in a sheet name (Forbidden characters are %s).", FORBIDDEN_SHEET_CHARS.join(" ")), errorCallback);
42898
43915
  }
42899
43916
  }
@@ -44222,11 +45239,9 @@
44222
45239
  onComposerContentFocused: Function,
44223
45240
  };
44224
45241
 
44225
- // -----------------------------------------------------------------------------
44226
- // TopBar
44227
- // -----------------------------------------------------------------------------
44228
45242
  css /* scss */ `
44229
45243
  .o-font-size-editor {
45244
+ height: calc(100% - 4px);
44230
45245
  input.o-font-size {
44231
45246
  outline-color: ${SELECTION_BORDER_COLOR};
44232
45247
  height: 20px;
@@ -44239,13 +45254,13 @@
44239
45254
  input::-webkit-inner-spin-button {
44240
45255
  -webkit-appearance: none;
44241
45256
  }
44242
-
44243
- .o-text-options > div {
44244
- line-height: 26px;
44245
- padding: 3px 12px;
44246
- &:hover {
44247
- background-color: rgba(0, 0, 0, 0.08);
44248
- }
45257
+ }
45258
+ .o-text-options > div {
45259
+ cursor: pointer;
45260
+ line-height: 26px;
45261
+ padding: 3px 12px;
45262
+ &:hover {
45263
+ background-color: rgba(0, 0, 0, 0.08);
44249
45264
  }
44250
45265
  }
44251
45266
  `;
@@ -44310,6 +45325,7 @@
44310
45325
  FontSizeEditor.props = {
44311
45326
  onToggle: Function,
44312
45327
  dropdownStyle: String,
45328
+ class: String,
44313
45329
  };
44314
45330
 
44315
45331
  // -----------------------------------------------------------------------------
@@ -45882,7 +46898,7 @@
45882
46898
  */
45883
46899
  moveAnchorCell(direction, step = 1) {
45884
46900
  if (step !== "end" && step <= 0) {
45885
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46901
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45886
46902
  }
45887
46903
  const { col, row } = this.getNextAvailablePosition(direction, step);
45888
46904
  return this.selectCell(col, row);
@@ -45928,7 +46944,7 @@
45928
46944
  */
45929
46945
  resizeAnchorZone(direction, step = 1) {
45930
46946
  if (step !== "end" && step <= 0) {
45931
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
46947
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45932
46948
  }
45933
46949
  const sheetId = this.getters.getActiveSheetId();
45934
46950
  const anchor = this.anchor;
@@ -46122,20 +47138,20 @@
46122
47138
  checkAnchorZone(anchor) {
46123
47139
  const { cell, zone } = anchor;
46124
47140
  if (!isInside(cell.col, cell.row, zone)) {
46125
- return 16 /* CommandResult.InvalidAnchorZone */;
47141
+ return 17 /* CommandResult.InvalidAnchorZone */;
46126
47142
  }
46127
47143
  const { left, right, top, bottom } = zone;
46128
47144
  const sheetId = this.getters.getActiveSheetId();
46129
47145
  const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
46130
47146
  const refRow = this.getters.findVisibleHeader(sheetId, "ROW", top, bottom);
46131
47147
  if (refRow === undefined || refCol === undefined) {
46132
- return 17 /* CommandResult.SelectionOutOfBound */;
47148
+ return 18 /* CommandResult.SelectionOutOfBound */;
46133
47149
  }
46134
47150
  return 0 /* CommandResult.Success */;
46135
47151
  }
46136
47152
  checkAnchorZoneOrThrow(anchor) {
46137
47153
  const result = this.checkAnchorZone(anchor);
46138
- if (result === 16 /* CommandResult.InvalidAnchorZone */) {
47154
+ if (result === 17 /* CommandResult.InvalidAnchorZone */) {
46139
47155
  throw new Error(_t("The provided anchor is invalid. The cell must be part of the zone."));
46140
47156
  }
46141
47157
  }
@@ -47478,15 +48494,10 @@
47478
48494
  `;
47479
48495
  }
47480
48496
  function addFilterColumns(table) {
47481
- const tableZone = toZone(table.range);
47482
48497
  const columns = [];
47483
- for (const i of range(0, zoneToDimension(tableZone).numberOfCols)) {
47484
- const filter = table.filters[i];
47485
- if (!filter || !filter.filteredValues.length) {
47486
- continue;
47487
- }
48498
+ for (const filter of table.filters) {
47488
48499
  const colXml = escapeXml /*xml*/ `
47489
- <filterColumn ${formatAttributes([["colId", i]])}>
48500
+ <filterColumn ${formatAttributes([["colId", filter.colId]])}>
47490
48501
  ${addFilter(filter)}
47491
48502
  </filterColumn>
47492
48503
  `;
@@ -47495,9 +48506,10 @@
47495
48506
  return columns;
47496
48507
  }
47497
48508
  function addFilter(filter) {
47498
- const filterValues = filter.filteredValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48509
+ const filterValues = filter.displayedValues.map((val) => escapeXml /*xml*/ `<filter ${formatAttributes([["val", val]])}/>`);
48510
+ const filterAttributes = filter.displayBlanks ? [["blank", 1]] : [];
47499
48511
  return escapeXml /*xml*/ `
47500
- <filters>
48512
+ <filters ${formatAttributes(filterAttributes)}>
47501
48513
  ${joinXmlNodes(filterValues)}
47502
48514
  </filters>
47503
48515
  `;
@@ -47616,8 +48628,13 @@
47616
48628
  const sheetId = parseSheetUrl(url);
47617
48629
  const sheet = data.sheets.find((sheet) => sheet.id === sheetId);
47618
48630
  const location = sheet ? `${sheet.name}!A1` : INCORRECT_RANGE_STRING;
48631
+ const hyperlinkAttributes = [
48632
+ ["display", label],
48633
+ ["location", location],
48634
+ ["ref", xc],
48635
+ ];
47619
48636
  linkNodes.push(escapeXml /*xml*/ `
47620
- <hyperlink display="${label}" location="${location}" ref="${xc}"/>
48637
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47621
48638
  `);
47622
48639
  }
47623
48640
  else {
@@ -47626,8 +48643,12 @@
47626
48643
  type: XLSX_RELATION_TYPE.hyperlink,
47627
48644
  targetMode: "External",
47628
48645
  });
48646
+ const hyperlinkAttributes = [
48647
+ ["r:id", linkRelId],
48648
+ ["ref", xc],
48649
+ ];
47629
48650
  linkNodes.push(escapeXml /*xml*/ `
47630
- <hyperlink r:id="${linkRelId}" ref="${xc}"/>
48651
+ <hyperlink ${formatAttributes(hyperlinkAttributes)}/>
47631
48652
  `);
47632
48653
  }
47633
48654
  }
@@ -48251,10 +49272,10 @@
48251
49272
  const command = createCommand(type, payload);
48252
49273
  let status = this.status;
48253
49274
  if (this.getters.isReadonly() && !canExecuteInReadonly(command)) {
48254
- return new DispatchResult(67 /* CommandResult.Readonly */);
49275
+ return new DispatchResult(68 /* CommandResult.Readonly */);
48255
49276
  }
48256
49277
  if (!this.session.canApplyOptimisticUpdate()) {
48257
- return new DispatchResult(64 /* CommandResult.WaitingSessionConfirmation */);
49278
+ return new DispatchResult(65 /* CommandResult.WaitingSessionConfirmation */);
48258
49279
  }
48259
49280
  switch (status) {
48260
49281
  case 0 /* Status.Ready */:
@@ -48537,9 +49558,9 @@
48537
49558
  Object.defineProperty(exports, '__esModule', { value: true });
48538
49559
 
48539
49560
 
48540
- __info__.version = '16.4.0-alpha.4';
48541
- __info__.date = '2023-06-12T13:55:29.711Z';
48542
- __info__.hash = '251a52e';
49561
+ __info__.version = '16.4.0-alpha.5';
49562
+ __info__.date = '2023-06-26T14:35:24.001Z';
49563
+ __info__.hash = '3b0b6f1';
48543
49564
 
48544
49565
 
48545
49566
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);