@odoo/o-spreadsheet 14.0.1 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o_spreadsheet.cjs.js +31302 -0
- package/dist/o_spreadsheet.d.ts +6604 -0
- package/dist/o_spreadsheet.esm.js +31257 -0
- package/dist/o_spreadsheet.iife.js +31304 -0
- package/dist/o_spreadsheet.iife.min.js +3071 -0
- package/package.json +57 -15
- package/.eslintrc.json +0 -20
- package/.husky/post-checkout +0 -9
- package/.husky/pre-commit +0 -39
- package/.prettierignore +0 -1
- package/astToFormula.patch +0 -0
- package/demo/data.js +0 -255
- package/demo/index.html +0 -9
- package/demo/libs/Chart.bundle.js +0 -20755
- package/demo/main.js +0 -101
- package/doc/readme.md +0 -46
- package/rollup.config.js +0 -23
- package/src/base_plugin.ts +0 -102
- package/src/components/autofill.ts +0 -146
- package/src/components/bottom_bar.ts +0 -199
- package/src/components/color_picker.ts +0 -150
- package/src/components/composer/autocomplete_dropdown.ts +0 -135
- package/src/components/composer/composer.ts +0 -487
- package/src/components/composer/content_editable_helper.ts +0 -146
- package/src/components/figures/chart.ts +0 -70
- package/src/components/figures/container.ts +0 -268
- package/src/components/figures/text_figure.ts +0 -36
- package/src/components/grid.ts +0 -635
- package/src/components/helpers/dom_helpers.ts +0 -7
- package/src/components/helpers/drag_and_drop.ts +0 -17
- package/src/components/icons.ts +0 -36
- package/src/components/index.ts +0 -1
- package/src/components/menu.ts +0 -288
- package/src/components/overlay.ts +0 -457
- package/src/components/scrollbar.ts +0 -22
- package/src/components/selection_input.ts +0 -168
- package/src/components/side_panel/cell_is_rule_editor.ts +0 -169
- package/src/components/side_panel/chart_panel.ts +0 -104
- package/src/components/side_panel/color_scale_rule_editor.ts +0 -145
- package/src/components/side_panel/conditional_formatting.ts +0 -396
- package/src/components/side_panel/side_panel.ts +0 -127
- package/src/components/side_panel/translations_terms.ts +0 -45
- package/src/components/spreadsheet.ts +0 -198
- package/src/components/top_bar.ts +0 -535
- package/src/constants.ts +0 -26
- package/src/data.ts +0 -149
- package/src/fonts.ts +0 -41
- package/src/formulas/compiler.ts +0 -258
- package/src/formulas/composer_tokenizer.ts +0 -70
- package/src/formulas/index.ts +0 -15
- package/src/formulas/normalize.ts +0 -52
- package/src/formulas/parser.ts +0 -280
- package/src/formulas/range_tokenizer.ts +0 -97
- package/src/formulas/tokenizer.ts +0 -242
- package/src/functions/arguments.ts +0 -114
- package/src/functions/dates.ts +0 -302
- package/src/functions/helpers.ts +0 -592
- package/src/functions/index.ts +0 -52
- package/src/functions/module_database.ts +0 -282
- package/src/functions/module_date.ts +0 -743
- package/src/functions/module_info.ts +0 -69
- package/src/functions/module_logical.ts +0 -208
- package/src/functions/module_lookup.ts +0 -185
- package/src/functions/module_math.ts +0 -1252
- package/src/functions/module_operators.ts +0 -291
- package/src/functions/module_statistical.ts +0 -882
- package/src/functions/module_text.ts +0 -370
- package/src/helpers/color.ts +0 -30
- package/src/helpers/coordinates.ts +0 -71
- package/src/helpers/grid_manipulation.ts +0 -68
- package/src/helpers/index.ts +0 -7
- package/src/helpers/misc.ts +0 -76
- package/src/helpers/numbers.ts +0 -117
- package/src/helpers/uuid.ts +0 -19
- package/src/helpers/zones.ts +0 -263
- package/src/history.ts +0 -186
- package/src/index.ts +0 -84
- package/src/model.ts +0 -261
- package/src/plugins/autofill.ts +0 -412
- package/src/plugins/chart.ts +0 -404
- package/src/plugins/clipboard.ts +0 -461
- package/src/plugins/conditional_format.ts +0 -445
- package/src/plugins/core.ts +0 -1502
- package/src/plugins/edition.ts +0 -157
- package/src/plugins/evaluation.ts +0 -428
- package/src/plugins/figures.ts +0 -123
- package/src/plugins/formatting.ts +0 -630
- package/src/plugins/highlight.ts +0 -187
- package/src/plugins/index.ts +0 -32
- package/src/plugins/merge.ts +0 -524
- package/src/plugins/renderer.ts +0 -571
- package/src/plugins/selection.ts +0 -562
- package/src/plugins/selection_inputs.ts +0 -326
- package/src/registries/autofill_modifiers.ts +0 -76
- package/src/registries/autofill_rules.ts +0 -98
- package/src/registries/figure_registry.ts +0 -30
- package/src/registries/index.ts +0 -7
- package/src/registries/menu_items_registry.ts +0 -110
- package/src/registries/menus/cell_menu_registry.ts +0 -79
- package/src/registries/menus/col_menu_registry.ts +0 -63
- package/src/registries/menus/index.ts +0 -6
- package/src/registries/menus/menu_items_actions.ts +0 -425
- package/src/registries/menus/row_menu_registry.ts +0 -63
- package/src/registries/menus/sheet_menu_registry.ts +0 -75
- package/src/registries/menus/topbar_menu_registry.ts +0 -204
- package/src/registries/side_panel_registry.ts +0 -26
- package/src/registries/topbar_component_registry.ts +0 -12
- package/src/registry.ts +0 -51
- package/src/translation.ts +0 -44
- package/src/types/autofill.ts +0 -48
- package/src/types/chart.ts +0 -26
- package/src/types/commands.ts +0 -716
- package/src/types/conditional_formatting.ts +0 -124
- package/src/types/env.ts +0 -13
- package/src/types/functions.ts +0 -35
- package/src/types/getters.ts +0 -103
- package/src/types/index.ts +0 -20
- package/src/types/misc.ts +0 -143
- package/src/types/rendering.ts +0 -41
- package/src/types/workbook_data.ts +0 -62
- package/tests/__mocks__/uuid.ts +0 -7
- package/tests/canvas.mock.ts +0 -34
- package/tests/components/__mocks__/content_editable_helper.ts +0 -79
- package/tests/components/__mocks__/scrollbar.ts +0 -18
- package/tests/components/__snapshots__/autocomplete_dropdown_test.ts.snap +0 -29
- package/tests/components/__snapshots__/bottom_bar_test.ts.snap +0 -75
- package/tests/components/__snapshots__/context_menu_test.ts.snap +0 -88
- package/tests/components/__snapshots__/grid_test.ts.snap +0 -60
- package/tests/components/__snapshots__/spreadsheet_test.ts.snap +0 -455
- package/tests/components/__snapshots__/top_bar_test.ts.snap +0 -705
- package/tests/components/autocomplete_dropdown_test.ts +0 -315
- package/tests/components/autofill_test.ts +0 -167
- package/tests/components/bottom_bar_test.ts +0 -262
- package/tests/components/chart_side_panel_test.ts +0 -123
- package/tests/components/composer_test.ts +0 -400
- package/tests/components/context_menu_test.ts +0 -825
- package/tests/components/grid_manipulation_test.ts +0 -163
- package/tests/components/grid_test.ts +0 -581
- package/tests/components/overlay_test.ts +0 -541
- package/tests/components/selection_input_test.ts +0 -259
- package/tests/components/side_panel_test.ts +0 -148
- package/tests/components/spreadsheet_test.ts +0 -194
- package/tests/components/top_bar_test.ts +0 -427
- package/tests/data_test.ts +0 -175
- package/tests/dom_helper.ts +0 -42
- package/tests/formulas/__snapshots__/compiler_test.ts.snap +0 -302
- package/tests/formulas/compiler_test.ts +0 -266
- package/tests/formulas/composer_tokenizer_test.ts +0 -137
- package/tests/formulas/expressions_test.ts +0 -57
- package/tests/formulas/formulas_test.ts +0 -80
- package/tests/formulas/normalize_test.ts +0 -82
- package/tests/formulas/parser_test.ts +0 -224
- package/tests/formulas/range_tokenizer_test.ts +0 -187
- package/tests/formulas/tokenizer_test.ts +0 -164
- package/tests/functions/arguments_test.ts +0 -141
- package/tests/functions/dates_test.ts +0 -1081
- package/tests/functions/functions_test.ts +0 -53
- package/tests/functions/helper_test.ts +0 -98
- package/tests/functions/module_database_test.ts +0 -311
- package/tests/functions/module_date_test.ts +0 -941
- package/tests/functions/module_info_test.ts +0 -139
- package/tests/functions/module_logical_test.ts +0 -369
- package/tests/functions/module_lookup_test.ts +0 -541
- package/tests/functions/module_math_test.ts +0 -2482
- package/tests/functions/module_operators_test.ts +0 -955
- package/tests/functions/module_statistical_test.ts +0 -2014
- package/tests/functions/module_text_test.ts +0 -667
- package/tests/helpers/coordinates_test.ts +0 -25
- package/tests/helpers/misc_test.ts +0 -95
- package/tests/helpers/numbers_test.ts +0 -196
- package/tests/helpers/zones_test.ts +0 -97
- package/tests/helpers.ts +0 -384
- package/tests/menu_items_registry_test.ts +0 -540
- package/tests/model/plugins/__snapshots__/chart_test.ts.snap +0 -90
- package/tests/model/plugins/chart_test.ts +0 -562
- package/tests/model_test.ts +0 -82
- package/tests/plugins/__snapshots__/conditional_formatting_test.ts.snap +0 -131
- package/tests/plugins/__snapshots__/renderer_test.ts.snap +0 -371
- package/tests/plugins/autofill_test.ts +0 -457
- package/tests/plugins/borders_test.ts +0 -295
- package/tests/plugins/clipboard_test.ts +0 -1180
- package/tests/plugins/conditional_formatting_test.ts +0 -1253
- package/tests/plugins/core_test.ts +0 -614
- package/tests/plugins/edition_test.ts +0 -100
- package/tests/plugins/evaluation_async_test.ts +0 -332
- package/tests/plugins/evaluation_dates_test.ts +0 -79
- package/tests/plugins/evaluation_test.ts +0 -901
- package/tests/plugins/figures_test.ts +0 -327
- package/tests/plugins/formatting_test.ts +0 -391
- package/tests/plugins/grid_manipulation_test.ts +0 -1366
- package/tests/plugins/highlight_test.ts +0 -413
- package/tests/plugins/history_test.ts +0 -142
- package/tests/plugins/import_export_test.ts +0 -276
- package/tests/plugins/merges_test.ts +0 -490
- package/tests/plugins/navigation_test.ts +0 -181
- package/tests/plugins/plugins/evaluation_test.ts +0 -111
- package/tests/plugins/renderer_test.ts +0 -598
- package/tests/plugins/resizing_test.ts +0 -152
- package/tests/plugins/selection_input_test.ts +0 -409
- package/tests/plugins/selection_test.ts +0 -442
- package/tests/plugins/sheets_test.ts +0 -643
- package/tests/plugins/style_test.ts +0 -90
- package/tsconfig.json +0 -22
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { BasePlugin } from "../base_plugin";
|
|
2
|
-
import {
|
|
3
|
-
colorNumberString,
|
|
4
|
-
isInside,
|
|
5
|
-
recomputeZones,
|
|
6
|
-
toXC,
|
|
7
|
-
toZone,
|
|
8
|
-
updateAddColumns,
|
|
9
|
-
updateAddRows,
|
|
10
|
-
updateRemoveColumns,
|
|
11
|
-
updateRemoveRows,
|
|
12
|
-
} from "../helpers/index";
|
|
13
|
-
import { _lt } from "../translation";
|
|
14
|
-
import {
|
|
15
|
-
Cell,
|
|
16
|
-
CellIsRule,
|
|
17
|
-
ColorScaleRule,
|
|
18
|
-
Command,
|
|
19
|
-
ConditionalFormat,
|
|
20
|
-
Style,
|
|
21
|
-
WorkbookData,
|
|
22
|
-
Zone,
|
|
23
|
-
} from "../types/index";
|
|
24
|
-
|
|
25
|
-
// -----------------------------------------------------------------------------
|
|
26
|
-
// Constants
|
|
27
|
-
// -----------------------------------------------------------------------------
|
|
28
|
-
|
|
29
|
-
export class ConditionalFormatPlugin extends BasePlugin {
|
|
30
|
-
static getters = ["getConditionalFormats", "getConditionalStyle", "getRulesSelection"];
|
|
31
|
-
|
|
32
|
-
private isStale: boolean = true;
|
|
33
|
-
private cfRules: { [sheet: string]: ConditionalFormat[] } = {};
|
|
34
|
-
|
|
35
|
-
// stores the computed styles in the format of computedStyles.sheetName.cellXC = Style
|
|
36
|
-
private computedStyles: { [sheet: string]: { [cellXc: string]: Style } } = {};
|
|
37
|
-
|
|
38
|
-
// ---------------------------------------------------------------------------
|
|
39
|
-
// Command Handling
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
|
|
42
|
-
handle(cmd: Command) {
|
|
43
|
-
switch (cmd.type) {
|
|
44
|
-
case "ACTIVATE_SHEET":
|
|
45
|
-
const activeSheet = cmd.to;
|
|
46
|
-
this.computedStyles[activeSheet] = this.computedStyles[activeSheet] || {};
|
|
47
|
-
this.isStale = true;
|
|
48
|
-
break;
|
|
49
|
-
case "CREATE_SHEET":
|
|
50
|
-
this.cfRules[cmd.id] = [];
|
|
51
|
-
this.isStale = true;
|
|
52
|
-
break;
|
|
53
|
-
case "DUPLICATE_SHEET":
|
|
54
|
-
this.history.updateLocalState(["cfRules", cmd.id], this.cfRules[cmd.sheet].slice());
|
|
55
|
-
this.isStale = true;
|
|
56
|
-
break;
|
|
57
|
-
case "DELETE_SHEET":
|
|
58
|
-
const cfRules = Object.assign({}, this.cfRules);
|
|
59
|
-
delete cfRules[cmd.sheet];
|
|
60
|
-
this.history.updateLocalState(["cfRules"], cfRules);
|
|
61
|
-
this.isStale = true;
|
|
62
|
-
break;
|
|
63
|
-
case "ADD_CONDITIONAL_FORMAT":
|
|
64
|
-
this.addConditionalFormatting(cmd.cf, cmd.sheet);
|
|
65
|
-
this.isStale = true;
|
|
66
|
-
break;
|
|
67
|
-
case "REMOVE_CONDITIONAL_FORMAT":
|
|
68
|
-
this.removeConditionalFormatting(cmd.id, cmd.sheet);
|
|
69
|
-
this.isStale = true;
|
|
70
|
-
break;
|
|
71
|
-
case "REMOVE_COLUMNS":
|
|
72
|
-
this.adaptcfRules(cmd.sheet, (range: string) => updateRemoveColumns(range, cmd.columns));
|
|
73
|
-
this.isStale = true;
|
|
74
|
-
break;
|
|
75
|
-
case "REMOVE_ROWS":
|
|
76
|
-
this.adaptcfRules(cmd.sheet, (range: string) => updateRemoveRows(range, cmd.rows));
|
|
77
|
-
this.isStale = true;
|
|
78
|
-
break;
|
|
79
|
-
case "ADD_COLUMNS":
|
|
80
|
-
const column = cmd.position === "before" ? cmd.column : cmd.column + 1;
|
|
81
|
-
this.adaptcfRules(cmd.sheet, (range: string) =>
|
|
82
|
-
updateAddColumns(range, column, cmd.quantity)
|
|
83
|
-
);
|
|
84
|
-
this.isStale = true;
|
|
85
|
-
break;
|
|
86
|
-
case "AUTOFILL_CELL":
|
|
87
|
-
const sheet = this.getters.getActiveSheet();
|
|
88
|
-
const cfOrigin = this.getRulesByCell(toXC(cmd.originCol, cmd.originRow));
|
|
89
|
-
for (const cf of cfOrigin) {
|
|
90
|
-
this.adaptRules(sheet, cf, [toXC(cmd.col, cmd.row)], []);
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
case "ADD_ROWS":
|
|
94
|
-
const row = cmd.position === "before" ? cmd.row : cmd.row + 1;
|
|
95
|
-
this.adaptcfRules(cmd.sheet, (range: string) => updateAddRows(range, row, cmd.quantity));
|
|
96
|
-
this.isStale = true;
|
|
97
|
-
break;
|
|
98
|
-
case "PASTE_CELL":
|
|
99
|
-
if (!cmd.onlyValue) {
|
|
100
|
-
this.pasteCf(cmd.originCol, cmd.originRow, cmd.col, cmd.row, cmd.sheet, cmd.cut);
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
case "EVALUATE_CELLS":
|
|
104
|
-
case "UPDATE_CELL":
|
|
105
|
-
case "UNDO":
|
|
106
|
-
case "REDO":
|
|
107
|
-
this.isStale = true;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
finalize() {
|
|
113
|
-
if (this.isStale && this.currentMode !== "headless") {
|
|
114
|
-
this.computeStyles();
|
|
115
|
-
this.isStale = false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
import(data: WorkbookData) {
|
|
120
|
-
for (let sheet of data.sheets) {
|
|
121
|
-
this.cfRules[sheet.id] = sheet.conditionalFormats;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export(data: Partial<WorkbookData>) {
|
|
126
|
-
if (data.sheets) {
|
|
127
|
-
for (let sheet of data.sheets) {
|
|
128
|
-
if (this.cfRules[sheet.id]) {
|
|
129
|
-
sheet.conditionalFormats = this.cfRules[sheet.id];
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Getters
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Returns all the conditional format rules defined for the current sheet
|
|
141
|
-
*/
|
|
142
|
-
getConditionalFormats(): ConditionalFormat[] {
|
|
143
|
-
return this.cfRules[this.workbook.activeSheet.id];
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Returns the conditional style property for a given cell reference in the active sheet or
|
|
148
|
-
* undefined if this cell doesn't have a conditional style set.
|
|
149
|
-
*/
|
|
150
|
-
getConditionalStyle(xc: string): Style | undefined {
|
|
151
|
-
return (
|
|
152
|
-
this.computedStyles[this.workbook.activeSheet.id] &&
|
|
153
|
-
this.computedStyles[this.workbook.activeSheet.id][xc]
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
getRulesSelection(selection: [Zone]): string[] {
|
|
158
|
-
const ruleIds: Set<string> = new Set();
|
|
159
|
-
selection.forEach((zone) => {
|
|
160
|
-
const zoneRuleId = this.getRulesByZone(zone);
|
|
161
|
-
zoneRuleId.forEach((ruleId) => {
|
|
162
|
-
ruleIds.add(ruleId);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
return Array.from(ruleIds);
|
|
166
|
-
}
|
|
167
|
-
getRulesByZone(zone: Zone): Set<string> {
|
|
168
|
-
const ruleIds: Set<string> = new Set();
|
|
169
|
-
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
170
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
171
|
-
const cellRules = this.getRulesByCell(toXC(col, row));
|
|
172
|
-
cellRules.forEach((rule) => {
|
|
173
|
-
ruleIds.add(rule.id);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return ruleIds;
|
|
178
|
-
}
|
|
179
|
-
getRulesByCell(cellXc: string): Set<ConditionalFormat> {
|
|
180
|
-
const currentSheet = this.workbook.activeSheet.id;
|
|
181
|
-
const rulesId: Set<ConditionalFormat> = new Set();
|
|
182
|
-
for (let cf of this.cfRules[currentSheet]) {
|
|
183
|
-
for (let ref of cf.ranges) {
|
|
184
|
-
const zone: Zone = toZone(ref);
|
|
185
|
-
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
186
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
187
|
-
let xc = toXC(col, row);
|
|
188
|
-
if (cellXc == xc) {
|
|
189
|
-
rulesId.add(cf);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return rulesId;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// ---------------------------------------------------------------------------
|
|
199
|
-
// Private
|
|
200
|
-
// ---------------------------------------------------------------------------
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Add or replace a conditional format rule
|
|
204
|
-
*/
|
|
205
|
-
private addConditionalFormatting(cf: ConditionalFormat, sheet: string) {
|
|
206
|
-
const currentCF = this.cfRules[sheet].slice();
|
|
207
|
-
const replaceIndex = currentCF.findIndex((c) => c.id === cf.id);
|
|
208
|
-
|
|
209
|
-
if (replaceIndex > -1) {
|
|
210
|
-
currentCF.splice(replaceIndex, 1, cf);
|
|
211
|
-
} else {
|
|
212
|
-
currentCF.push(cf);
|
|
213
|
-
}
|
|
214
|
-
this.history.updateLocalState(["cfRules", sheet], currentCF);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Execute the complete color scale for the range of the conditional format for a 2 colors rule
|
|
219
|
-
*/
|
|
220
|
-
private applyColorScale(range: string, rule: ColorScaleRule): void {
|
|
221
|
-
const minValue = Number(this.getters.evaluateFormula(`=min(${range})`));
|
|
222
|
-
const maxValue = Number(this.getters.evaluateFormula(`=max(${range})`));
|
|
223
|
-
if (Number.isNaN(minValue) || Number.isNaN(maxValue)) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
const deltaValue = maxValue - minValue;
|
|
227
|
-
if (!deltaValue) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const deltaColorR = ((rule.minimum.color >> 16) % 256) - ((rule.maximum.color >> 16) % 256);
|
|
231
|
-
const deltaColorG = ((rule.minimum.color >> 8) % 256) - ((rule.maximum.color >> 8) % 256);
|
|
232
|
-
const deltaColorB = (rule.minimum.color % 256) - (rule.maximum.color % 256);
|
|
233
|
-
|
|
234
|
-
const colorDiffUnitR = deltaColorR / deltaValue;
|
|
235
|
-
const colorDiffUnitG = deltaColorG / deltaValue;
|
|
236
|
-
const colorDiffUnitB = deltaColorB / deltaValue;
|
|
237
|
-
const zone: Zone = toZone(range);
|
|
238
|
-
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
239
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
240
|
-
const cell = this.getters.getCell(col, row);
|
|
241
|
-
if (cell && !Number.isNaN(Number.parseFloat(cell.value))) {
|
|
242
|
-
const r = Math.round(
|
|
243
|
-
((rule.minimum.color >> 16) % 256) - colorDiffUnitR * (cell.value - minValue)
|
|
244
|
-
);
|
|
245
|
-
const g = Math.round(
|
|
246
|
-
((rule.minimum.color >> 8) % 256) - colorDiffUnitG * (cell.value - minValue)
|
|
247
|
-
);
|
|
248
|
-
const b = Math.round(
|
|
249
|
-
(rule.minimum.color % 256) - colorDiffUnitB * (cell.value - minValue)
|
|
250
|
-
);
|
|
251
|
-
const color = (r << 16) | (g << 8) | b;
|
|
252
|
-
this.computedStyles[this.workbook.activeSheet.id][cell.xc] =
|
|
253
|
-
this.computedStyles[this.workbook.activeSheet.id][cell.xc] || {};
|
|
254
|
-
this.computedStyles[this.workbook.activeSheet.id][cell.xc].fillColor =
|
|
255
|
-
"#" + colorNumberString(color);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Execute the predicate to know if a conditional formatting rule should be applied to a cell
|
|
263
|
-
*/
|
|
264
|
-
private rulePredicate: { CellIsRule: (cell: Cell, rule: CellIsRule) => boolean } = {
|
|
265
|
-
CellIsRule: (cell: Cell, rule: CellIsRule): boolean => {
|
|
266
|
-
switch (rule.operator) {
|
|
267
|
-
case "BeginsWith":
|
|
268
|
-
if (!cell && rule.values[0] === "") {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
return cell && cell.value.startsWith(rule.values[0]);
|
|
272
|
-
case "EndsWith":
|
|
273
|
-
if (!cell && rule.values[0] === "") {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
return cell && cell.value.endsWith(rule.values[0]);
|
|
277
|
-
case "Between":
|
|
278
|
-
return cell && cell.value >= rule.values[0] && cell.value <= rule.values[1];
|
|
279
|
-
case "NotBetween":
|
|
280
|
-
return !(cell && cell.value >= rule.values[0] && cell.value <= rule.values[1]);
|
|
281
|
-
case "ContainsText":
|
|
282
|
-
return cell && cell.value && cell.value.toString().indexOf(rule.values[0]) > -1;
|
|
283
|
-
case "NotContains":
|
|
284
|
-
return cell && cell.value && cell.value.toString().indexOf(rule.values[0]) == -1;
|
|
285
|
-
case "GreaterThan":
|
|
286
|
-
return cell && cell.value > rule.values[0];
|
|
287
|
-
case "GreaterThanOrEqual":
|
|
288
|
-
return cell && cell.value >= rule.values[0];
|
|
289
|
-
case "LessThan":
|
|
290
|
-
return cell && cell.value < rule.values[0];
|
|
291
|
-
case "LessThanOrEqual":
|
|
292
|
-
return cell && cell.value <= rule.values[0];
|
|
293
|
-
case "NotEqual":
|
|
294
|
-
if (!cell && rule.values[0] === "") {
|
|
295
|
-
return false;
|
|
296
|
-
}
|
|
297
|
-
return cell && cell.value != rule.values[0];
|
|
298
|
-
case "Equal":
|
|
299
|
-
if (!cell && rule.values[0] === "") {
|
|
300
|
-
return true;
|
|
301
|
-
}
|
|
302
|
-
return cell && cell.value == rule.values[0];
|
|
303
|
-
default:
|
|
304
|
-
console.warn(
|
|
305
|
-
_lt(
|
|
306
|
-
"Not implemented operator %s for kind of conditional formatting: %s",
|
|
307
|
-
rule.operator,
|
|
308
|
-
rule.type
|
|
309
|
-
)
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
return false;
|
|
313
|
-
},
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Compute the styles according to the conditional formatting.
|
|
318
|
-
* This computation must happen after the cell values are computed if they change
|
|
319
|
-
*
|
|
320
|
-
* This result of the computation will be in the state.cell[XC].conditionalStyle and will be the union of all the style
|
|
321
|
-
* properties of the rules applied (in order).
|
|
322
|
-
* So if a cell has multiple conditional formatting applied to it, and each affect a different value of the style,
|
|
323
|
-
* the resulting style will have the combination of all those values.
|
|
324
|
-
* If multiple conditional formatting use the same style value, they will be applied in order so that the last applied wins
|
|
325
|
-
*/
|
|
326
|
-
private computeStyles() {
|
|
327
|
-
const currentSheet = this.workbook.activeSheet.id;
|
|
328
|
-
this.computedStyles[currentSheet] = {};
|
|
329
|
-
for (let cf of this.cfRules[currentSheet]) {
|
|
330
|
-
try {
|
|
331
|
-
switch (cf.rule.type) {
|
|
332
|
-
case "ColorScaleRule":
|
|
333
|
-
for (let range of cf.ranges) {
|
|
334
|
-
this.applyColorScale(range, cf.rule);
|
|
335
|
-
}
|
|
336
|
-
break;
|
|
337
|
-
default:
|
|
338
|
-
for (let ref of cf.ranges) {
|
|
339
|
-
const zone: Zone = toZone(ref);
|
|
340
|
-
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
341
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
342
|
-
const pr = this.rulePredicate[cf.rule.type];
|
|
343
|
-
let cell = this.workbook.activeSheet.rows[row].cells[col];
|
|
344
|
-
let xc = toXC(col, row);
|
|
345
|
-
if (pr && pr(cell, cf.rule)) {
|
|
346
|
-
// we must combine all the properties of all the CF rules applied to the given cell
|
|
347
|
-
this.computedStyles[currentSheet][xc] = Object.assign(
|
|
348
|
-
this.computedStyles[currentSheet][xc] || {},
|
|
349
|
-
cf.rule.style
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
} catch (_) {
|
|
358
|
-
// we don't care about the errors within the evaluation of a rule
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
private adaptcfRules(sheet: string, updateCb: (range: string) => string | null) {
|
|
364
|
-
const currentCfs = this.cfRules[sheet];
|
|
365
|
-
const newCfs: ConditionalFormat[] = [];
|
|
366
|
-
for (let cf of currentCfs) {
|
|
367
|
-
const updatedRanges: string[] = [];
|
|
368
|
-
for (let range of cf.ranges) {
|
|
369
|
-
const updatedRange = updateCb(range);
|
|
370
|
-
if (updatedRange) {
|
|
371
|
-
updatedRanges.push(updatedRange);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
if (updatedRanges.length === 0) {
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
newCfs.push({ ...cf, ranges: updatedRanges });
|
|
378
|
-
}
|
|
379
|
-
this.history.updateLocalState(["cfRules", sheet], newCfs);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
private removeConditionalFormatting(id: string, sheet: string) {
|
|
383
|
-
const cfIndex = this.cfRules[sheet].findIndex((s) => s.id === id);
|
|
384
|
-
if (cfIndex !== -1) {
|
|
385
|
-
const currentCF = this.cfRules[sheet].slice();
|
|
386
|
-
currentCF.splice(cfIndex, 1);
|
|
387
|
-
this.history.updateLocalState(["cfRules", sheet], currentCF);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// ---------------------------------------------------------------------------
|
|
392
|
-
// Copy/Cut/Paste and Merge
|
|
393
|
-
// ---------------------------------------------------------------------------
|
|
394
|
-
private pasteCf(
|
|
395
|
-
originCol: number,
|
|
396
|
-
originRow: number,
|
|
397
|
-
col: number,
|
|
398
|
-
row: number,
|
|
399
|
-
originSheet: string,
|
|
400
|
-
cut?: boolean
|
|
401
|
-
) {
|
|
402
|
-
const xc = toXC(col, row);
|
|
403
|
-
for (let rule of this.cfRules[originSheet]) {
|
|
404
|
-
for (let range of rule.ranges) {
|
|
405
|
-
if (isInside(originCol, originRow, toZone(range))) {
|
|
406
|
-
const cf = rule;
|
|
407
|
-
const toRemoveRange: string[] = [];
|
|
408
|
-
if (cut) {
|
|
409
|
-
//remove from current rule
|
|
410
|
-
toRemoveRange.push(toXC(originCol, originRow));
|
|
411
|
-
}
|
|
412
|
-
if (originSheet === this.workbook.activeSheet.id) {
|
|
413
|
-
this.adaptRules(originSheet, cf, [xc], toRemoveRange);
|
|
414
|
-
} else {
|
|
415
|
-
this.adaptRules(this.workbook.activeSheet.id, cf, [xc], []);
|
|
416
|
-
this.adaptRules(originSheet, cf, [], toRemoveRange);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
private adaptRules(sheet: string, cf: ConditionalFormat, toAdd: string[], toRemove: string[]) {
|
|
424
|
-
if (toAdd.length === 0 && toRemove.length === 0) {
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
const replaceIndex = this.cfRules[sheet].findIndex((c) => c.id === cf.id);
|
|
428
|
-
let currentRanges: string[] = [];
|
|
429
|
-
if (replaceIndex > -1) {
|
|
430
|
-
currentRanges = this.cfRules[sheet][replaceIndex].ranges;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
currentRanges = currentRanges.concat(toAdd);
|
|
434
|
-
const newRange: string[] = recomputeZones(currentRanges, toRemove);
|
|
435
|
-
this.addConditionalFormatting(
|
|
436
|
-
{
|
|
437
|
-
id: cf.id,
|
|
438
|
-
rule: cf.rule,
|
|
439
|
-
stopIfTrue: cf.stopIfTrue,
|
|
440
|
-
ranges: newRange,
|
|
441
|
-
},
|
|
442
|
-
sheet
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
}
|