@trebco/treb 27.7.6 → 27.9.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/treb-spreadsheet.mjs +14 -14
- package/dist/treb.d.ts +21 -21
- package/notes/conditional-fomratring.md +29 -0
- package/package.json +1 -1
- package/treb-base-types/src/area.ts +181 -0
- package/treb-base-types/src/evaluate-options.ts +21 -0
- package/treb-base-types/src/gradient.ts +97 -0
- package/treb-base-types/src/import.ts +2 -1
- package/treb-base-types/src/index.ts +2 -0
- package/treb-calculator/src/calculator.ts +190 -28
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +97 -0
- package/treb-calculator/src/dag/graph.ts +10 -22
- package/treb-calculator/src/dag/{leaf_vertex.ts → state_leaf_vertex.ts} +3 -3
- package/treb-calculator/src/descriptors.ts +10 -3
- package/treb-calculator/src/expression-calculator.ts +1 -1
- package/treb-calculator/src/function-library.ts +25 -22
- package/treb-calculator/src/functions/base-functions.ts +166 -5
- package/treb-calculator/src/index.ts +6 -6
- package/treb-calculator/src/notifier-types.ts +1 -1
- package/treb-calculator/src/utilities.ts +2 -2
- package/treb-charts/src/util.ts +2 -2
- package/treb-embed/src/embedded-spreadsheet.ts +352 -41
- package/treb-export/src/export-worker/export-worker.ts +0 -13
- package/treb-export/src/export2.ts +187 -2
- package/treb-export/src/import2.ts +169 -4
- package/treb-export/src/workbook-style2.ts +56 -8
- package/treb-export/src/workbook2.ts +10 -1
- package/treb-grid/src/index.ts +2 -1
- package/treb-grid/src/layout/base_layout.ts +23 -15
- package/treb-grid/src/render/tile_renderer.ts +2 -1
- package/treb-grid/src/types/conditional_format.ts +168 -0
- package/treb-grid/src/types/grid.ts +5 -6
- package/treb-grid/src/types/grid_base.ts +186 -33
- package/treb-grid/src/types/sheet.ts +330 -26
- package/treb-grid/src/types/sheet_types.ts +4 -0
- /package/{README-shadow-DOM.md → notes/shadow-DOM.md} +0 -0
|
@@ -42,6 +42,7 @@ import type { SerializeOptions } from './serialize_options';
|
|
|
42
42
|
import type { GridSelection } from './grid_selection';
|
|
43
43
|
import { CreateSelection } from './grid_selection';
|
|
44
44
|
import { Annotation } from './annotation';
|
|
45
|
+
import type { ConditionalFormatList } from './conditional_format';
|
|
45
46
|
|
|
46
47
|
// --- constants --------------------------------------------------------------
|
|
47
48
|
|
|
@@ -147,10 +148,21 @@ export class Sheet {
|
|
|
147
148
|
|
|
148
149
|
protected _image: HTMLImageElement|undefined = undefined;
|
|
149
150
|
|
|
151
|
+
/**
|
|
152
|
+
* set this flag when we need to update conditional formats even
|
|
153
|
+
* if they are not dirty (generally when one is deleted)
|
|
154
|
+
*/
|
|
155
|
+
public flush_conditional_formats = false;
|
|
156
|
+
|
|
150
157
|
public get image(): HTMLImageElement|undefined {
|
|
151
158
|
return this._image;
|
|
152
159
|
}
|
|
153
160
|
|
|
161
|
+
/**
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
public conditional_formats: ConditionalFormatList = [];
|
|
165
|
+
|
|
154
166
|
/**
|
|
155
167
|
* @internal
|
|
156
168
|
*
|
|
@@ -228,6 +240,21 @@ export class Sheet {
|
|
|
228
240
|
|
|
229
241
|
private cell_style: CellStyle[][] = [];
|
|
230
242
|
|
|
243
|
+
/**
|
|
244
|
+
* applied conditional formats are stored them in this array;
|
|
245
|
+
* they will be stacked on top of cell style when rendering.
|
|
246
|
+
* conditional formats have top priority. [FIXME: what about tables?]
|
|
247
|
+
*/
|
|
248
|
+
private conditional_format_cache: CellStyle[][][] = [];
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* this is a list of cells we formatted on the last pass, so we can
|
|
252
|
+
* compare when applying conditional formats .
|
|
253
|
+
*
|
|
254
|
+
* update: using areas
|
|
255
|
+
*/
|
|
256
|
+
private conditional_format_checklist: IArea[] = [];
|
|
257
|
+
|
|
231
258
|
// --- accessors ------------------------------------------------------------
|
|
232
259
|
|
|
233
260
|
// public get column_header_count() { return this.column_header_count_; }
|
|
@@ -352,6 +379,10 @@ export class Sheet {
|
|
|
352
379
|
sheet.default_row_height = source.default_row_height;
|
|
353
380
|
}
|
|
354
381
|
|
|
382
|
+
if (source.conditional_formats) {
|
|
383
|
+
sheet.conditional_formats = source.conditional_formats;
|
|
384
|
+
}
|
|
385
|
+
|
|
355
386
|
// persist ID, name
|
|
356
387
|
|
|
357
388
|
if (source.id) {
|
|
@@ -1010,7 +1041,7 @@ export class Sheet {
|
|
|
1010
1041
|
|
|
1011
1042
|
// testing
|
|
1012
1043
|
// const underlying = this.CompositeStyleForCell(address, false);
|
|
1013
|
-
const underlying = this.CompositeStyleForCell(address, false, false);
|
|
1044
|
+
const underlying = this.CompositeStyleForCell(address, false, false, undefined, false);
|
|
1014
1045
|
|
|
1015
1046
|
const merged = Style.Composite([
|
|
1016
1047
|
this.default_style_properties,
|
|
@@ -1048,7 +1079,8 @@ export class Sheet {
|
|
|
1048
1079
|
this.cell_style[column][row] = composite; // merged;
|
|
1049
1080
|
|
|
1050
1081
|
// targeted flush
|
|
1051
|
-
this.CellData(address).FlushStyle();
|
|
1082
|
+
// this.CellData(address).FlushStyle();
|
|
1083
|
+
this.BleedFlush({start: address, end: address});
|
|
1052
1084
|
|
|
1053
1085
|
}
|
|
1054
1086
|
|
|
@@ -1332,7 +1364,7 @@ export class Sheet {
|
|
|
1332
1364
|
* @param address
|
|
1333
1365
|
*/
|
|
1334
1366
|
public GetCopyStyle(address: ICellAddress): CellStyle {
|
|
1335
|
-
return this.CompositeStyleForCell(address, true, false);
|
|
1367
|
+
return this.CompositeStyleForCell(address, true, false, undefined, false);
|
|
1336
1368
|
}
|
|
1337
1369
|
|
|
1338
1370
|
/**
|
|
@@ -2069,6 +2101,8 @@ export class Sheet {
|
|
|
2069
2101
|
* this is a new GetCellStyle function, used for external access
|
|
2070
2102
|
* to style (for API access). there was an old GetCellStyle function
|
|
2071
2103
|
* for rendering, but that's been removed (control+F for info).
|
|
2104
|
+
*
|
|
2105
|
+
* Q: does this include conditional formatting? (...)
|
|
2072
2106
|
*/
|
|
2073
2107
|
public GetCellStyle(area: ICellAddress|IArea, apply_theme = false): CellStyle|CellStyle[][] {
|
|
2074
2108
|
|
|
@@ -2558,6 +2592,13 @@ export class Sheet {
|
|
|
2558
2592
|
|
|
2559
2593
|
const cell_styles = this.CompressCellStyles(cell_reference_map);
|
|
2560
2594
|
|
|
2595
|
+
// if we serialize this when it has Area values (instead of IArea) it
|
|
2596
|
+
// will export incorrectly. is that an issue anywhere else? (...)
|
|
2597
|
+
|
|
2598
|
+
const conditional_formats = this.conditional_formats.length ?
|
|
2599
|
+
JSON.parse(JSON.stringify(this.conditional_formats.map(format => ({...format, internal: undefined })))) :
|
|
2600
|
+
undefined;
|
|
2601
|
+
|
|
2561
2602
|
const result: SerializedSheet = {
|
|
2562
2603
|
|
|
2563
2604
|
// not used atm, but in the event we need to gate
|
|
@@ -2580,6 +2621,8 @@ export class Sheet {
|
|
|
2580
2621
|
row_style,
|
|
2581
2622
|
column_style,
|
|
2582
2623
|
|
|
2624
|
+
conditional_formats,
|
|
2625
|
+
|
|
2583
2626
|
row_pattern: row_pattern.length ? row_pattern : undefined,
|
|
2584
2627
|
|
|
2585
2628
|
// why are these serialized? (...) export!
|
|
@@ -2763,6 +2806,10 @@ export class Sheet {
|
|
|
2763
2806
|
this.annotations.push(new Annotation(annotation));
|
|
2764
2807
|
}
|
|
2765
2808
|
|
|
2809
|
+
for (const format of data.conditional_formats || []) {
|
|
2810
|
+
this.conditional_formats.push(format);
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2766
2813
|
if (data.hidden) {
|
|
2767
2814
|
this.visible = false;
|
|
2768
2815
|
}
|
|
@@ -2976,28 +3023,6 @@ export class Sheet {
|
|
|
2976
3023
|
|
|
2977
3024
|
}
|
|
2978
3025
|
|
|
2979
|
-
/* *
|
|
2980
|
-
* styles are applied as a stack,
|
|
2981
|
-
*
|
|
2982
|
-
* sheet
|
|
2983
|
-
* row pattern
|
|
2984
|
-
* row
|
|
2985
|
-
* column
|
|
2986
|
-
* cell
|
|
2987
|
-
*
|
|
2988
|
-
* there are some cases where we wind up with overridden but matching
|
|
2989
|
-
* styles that are duplicative. they can be removed, although it's not
|
|
2990
|
-
* necessarily useful to do it in real time -- we can do it on load/save
|
|
2991
|
-
* or perhaps on idle.
|
|
2992
|
-
*
|
|
2993
|
-
* /
|
|
2994
|
-
private FlattenStyles() {
|
|
2995
|
-
|
|
2996
|
-
this.CompositeStyleForCell
|
|
2997
|
-
|
|
2998
|
-
}
|
|
2999
|
-
*/
|
|
3000
|
-
|
|
3001
3026
|
/**
|
|
3002
3027
|
* updates column properties. reverse-overrides cells (@see UpdateSheetStyle).
|
|
3003
3028
|
*/
|
|
@@ -3049,6 +3074,276 @@ export class Sheet {
|
|
|
3049
3074
|
|
|
3050
3075
|
}
|
|
3051
3076
|
|
|
3077
|
+
/* *
|
|
3078
|
+
* flush the cache and the checklist. flush cell styles at the same
|
|
3079
|
+
* time. this should be called when adding/removing a conditional format.
|
|
3080
|
+
* optionally apply active formats again.
|
|
3081
|
+
*
|
|
3082
|
+
* is this actually necessary? what's the use case? (...)
|
|
3083
|
+
*
|
|
3084
|
+
* /
|
|
3085
|
+
public FlushConditionalFormats(reapply = false) {
|
|
3086
|
+
|
|
3087
|
+
for (const [row, column] of this.conditional_format_checklist) {
|
|
3088
|
+
this.CellData({row, column}).FlushStyle();
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
this.conditional_format_checklist = [];
|
|
3092
|
+
this.conditional_format_cache = [];
|
|
3093
|
+
|
|
3094
|
+
if (reapply) {
|
|
3095
|
+
this.ApplyConditionalFormats();
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
}
|
|
3099
|
+
*/
|
|
3100
|
+
|
|
3101
|
+
public BleedFlush(area: IArea) {
|
|
3102
|
+
|
|
3103
|
+
let rows = [Math.max(0, area.start.row - 1), area.end.row + 1];
|
|
3104
|
+
let cols = [Math.max(0, area.start.column - 1), area.end.column + 1];
|
|
3105
|
+
|
|
3106
|
+
for (let row = rows[0]; row <= rows[1]; row++) {
|
|
3107
|
+
for (let column = cols[0]; column <= cols[1]; column++) {
|
|
3108
|
+
// const cell = this.cells.EnsureCell({row, column});
|
|
3109
|
+
this.cells.GetCell({row, column}, false)?.FlushStyle();
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
public FlushConditionalFormats() {
|
|
3116
|
+
this.flush_conditional_formats = true;
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
/**
|
|
3120
|
+
* this version combines flushing the cache with building it, using
|
|
3121
|
+
* the application flag in the format objects.
|
|
3122
|
+
*
|
|
3123
|
+
* this function was set up to support comparing the two lists and
|
|
3124
|
+
* only flushing style if necessary; but that turns out to be so
|
|
3125
|
+
* much additional work that I'm not sure it's preferable to just
|
|
3126
|
+
* repaint. need to test.
|
|
3127
|
+
*
|
|
3128
|
+
* ...we're also probably looping unecessarily. since we're using
|
|
3129
|
+
* those leaf nodes we can probably check if the state changed, and
|
|
3130
|
+
* it not, skip the loop pass. I think we'd need to identify or map
|
|
3131
|
+
* the applications though (meaning use a stack that matches the list
|
|
3132
|
+
* of formats). or you could even recheck everything if one of them
|
|
3133
|
+
* changed, you'd still probably save a lot in cases where nothing
|
|
3134
|
+
* changed.
|
|
3135
|
+
*
|
|
3136
|
+
*/
|
|
3137
|
+
public ApplyConditionalFormats() {
|
|
3138
|
+
|
|
3139
|
+
// we're not doing any pruning at the moment, so this is doing
|
|
3140
|
+
// a lot of unecessary looping -- we could start with one big
|
|
3141
|
+
// global check
|
|
3142
|
+
|
|
3143
|
+
// ...we need to account for the case where a format is removed,
|
|
3144
|
+
// in that case we will need to update. flag?
|
|
3145
|
+
|
|
3146
|
+
let updated = this.flush_conditional_formats; // maybe required
|
|
3147
|
+
|
|
3148
|
+
for (const format of this.conditional_formats) {
|
|
3149
|
+
if (format.internal?.vertex?.updated) {
|
|
3150
|
+
updated = true;
|
|
3151
|
+
break;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
if (!updated) {
|
|
3156
|
+
|
|
3157
|
+
// console.info('no updates');
|
|
3158
|
+
|
|
3159
|
+
// that should save 90% of the calculation, we'll still do
|
|
3160
|
+
// unecessary work but it's a step in the right direction.
|
|
3161
|
+
|
|
3162
|
+
// note that this flag doesn't necessarily indicate anything
|
|
3163
|
+
// has changed -- it will get set if you do a global recalc,
|
|
3164
|
+
// because that marks everything as dirty. still a good step
|
|
3165
|
+
// though.
|
|
3166
|
+
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3170
|
+
this.flush_conditional_formats = false; // unset
|
|
3171
|
+
|
|
3172
|
+
const temp: CellStyle[][][] = [];
|
|
3173
|
+
const checklist: IArea[] = [...this.conditional_format_checklist];
|
|
3174
|
+
|
|
3175
|
+
this.conditional_format_checklist = []; // flush
|
|
3176
|
+
|
|
3177
|
+
for (const format of this.conditional_formats) {
|
|
3178
|
+
|
|
3179
|
+
if (format.internal?.vertex?.updated) {
|
|
3180
|
+
|
|
3181
|
+
// console.info('updated');
|
|
3182
|
+
|
|
3183
|
+
format.internal.vertex.updated = false;
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
// NOTE: if you go backwards, then you can short-circuit if a format
|
|
3187
|
+
// is already set. except then if you want to support "stop" rules,
|
|
3188
|
+
// that won't work.
|
|
3189
|
+
//
|
|
3190
|
+
// although you might still want to go backwards as it's easier to
|
|
3191
|
+
// apply stop rules in reverse (why? because if you are going backwards,
|
|
3192
|
+
// you can just drop everything on the stack when you see a
|
|
3193
|
+
// stop rule. if you go forwards, you need some sort of indicator
|
|
3194
|
+
// or flag).
|
|
3195
|
+
|
|
3196
|
+
if (format.type === 'gradient') {
|
|
3197
|
+
const area = JSON.parse(JSON.stringify(format.area));
|
|
3198
|
+
const result = format.internal?.vertex?.result;
|
|
3199
|
+
|
|
3200
|
+
if (result && format.internal?.gradient) {
|
|
3201
|
+
const property: 'fill'|'text' = format.property ?? 'fill';
|
|
3202
|
+
|
|
3203
|
+
if (result.type === ValueType.array) {
|
|
3204
|
+
for (let row = area.start.row; row <= area.end.row; row++) {
|
|
3205
|
+
for (let column = area.start.column; column <= area.end.column; column++) {
|
|
3206
|
+
const value = result.value[column - area.start.column][row - area.start.row];
|
|
3207
|
+
if (value.type === ValueType.number) {
|
|
3208
|
+
if (!temp[row]) { temp[row] = []; }
|
|
3209
|
+
if (!temp[row][column] ) { temp[row][column] = []; }
|
|
3210
|
+
const color = format.internal.gradient.Interpolate(value.value);
|
|
3211
|
+
temp[row][column].push({ [property]: color});
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
else if (result.type === ValueType.number) {
|
|
3217
|
+
const color = format.internal.gradient.Interpolate(result.value);
|
|
3218
|
+
for (let row = area.start.row; row <= area.end.row; row++) {
|
|
3219
|
+
if (!temp[row]) { temp[row] = []; }
|
|
3220
|
+
for (let column = area.start.column; column <= area.end.column; column++) {
|
|
3221
|
+
if (!temp[row][column] ) { temp[row][column] = []; }
|
|
3222
|
+
temp[row][column].push({ [property]: color});
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
checklist.push(area);
|
|
3228
|
+
this.conditional_format_checklist.push(area);
|
|
3229
|
+
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
else {
|
|
3233
|
+
|
|
3234
|
+
// handle types expression, cell-match and duplicate-values
|
|
3235
|
+
|
|
3236
|
+
const area = JSON.parse(JSON.stringify(format.area));
|
|
3237
|
+
const result = format.internal?.vertex?.result;
|
|
3238
|
+
|
|
3239
|
+
if (result) {
|
|
3240
|
+
|
|
3241
|
+
if (result.type === ValueType.array) {
|
|
3242
|
+
for (let row = area.start.row; row <= area.end.row; row++) {
|
|
3243
|
+
for (let column = area.start.column; column <= area.end.column; column++) {
|
|
3244
|
+
const value = result.value[column - area.start.column][row - area.start.row];
|
|
3245
|
+
if ((value.type === ValueType.boolean || value.type === ValueType.number) && !!value.value) {
|
|
3246
|
+
if (!temp[row]) { temp[row] = []; }
|
|
3247
|
+
if (!temp[row][column] ) { temp[row][column] = []; }
|
|
3248
|
+
temp[row][column].push(format.style);
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
else {
|
|
3254
|
+
if (result.type === ValueType.boolean || result.type === ValueType.number) {
|
|
3255
|
+
if(!!result.value) {
|
|
3256
|
+
for (let row = area.start.row; row <= area.end.row; row++) {
|
|
3257
|
+
if (!temp[row]) { temp[row] = []; }
|
|
3258
|
+
for (let column = area.start.column; column <= area.end.column; column++) {
|
|
3259
|
+
if (!temp[row][column] ) { temp[row][column] = []; }
|
|
3260
|
+
temp[row][column].push(format.style);
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
checklist.push(area);
|
|
3268
|
+
this.conditional_format_checklist.push(area);
|
|
3269
|
+
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
for (const area of checklist) {
|
|
3277
|
+
this.BleedFlush(area);
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
this.conditional_format_cache = temp;
|
|
3281
|
+
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
/*
|
|
3285
|
+
public ApplyConditionalFormats() {
|
|
3286
|
+
|
|
3287
|
+
this.FlushConditionalFormatCache();
|
|
3288
|
+
|
|
3289
|
+
for (const entry of this.conditional_formats) {
|
|
3290
|
+
|
|
3291
|
+
console.info({entry});
|
|
3292
|
+
|
|
3293
|
+
if (entry.applied) {
|
|
3294
|
+
this.ApplyConditionalFormatCache(entry);
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
public FlushConditionalFormatCache() {
|
|
3301
|
+
|
|
3302
|
+
// FIXME: need to flush any styles that are set, unless they match;
|
|
3303
|
+
// perhaps we should use an alternate cache so we can compare? TODO/FIXME
|
|
3304
|
+
|
|
3305
|
+
for (const [row, row_data] of this.conditional_format_cache.entries()) {
|
|
3306
|
+
if (row_data) {
|
|
3307
|
+
for (const [column, column_data] of row_data.entries()) {
|
|
3308
|
+
if (column_data) {
|
|
3309
|
+
|
|
3310
|
+
this.CellData({row, column}).FlushStyle();
|
|
3311
|
+
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
this.conditional_format_cache = [];
|
|
3318
|
+
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
public ApplyConditionalFormatCache(format: ConditionalFormat) {
|
|
3322
|
+
|
|
3323
|
+
for (let row = format.area.start.row; row <= format.area.end.row; row++ ) {
|
|
3324
|
+
for (let column = format.area.start.column; column <= format.area.end.column; column++ ) {
|
|
3325
|
+
if (!this.conditional_format_cache[row]) {
|
|
3326
|
+
this.conditional_format_cache[row] = [];
|
|
3327
|
+
}
|
|
3328
|
+
if (!this.conditional_format_cache[row][column]) {
|
|
3329
|
+
this.conditional_format_cache[row][column] = [];
|
|
3330
|
+
}
|
|
3331
|
+
this.conditional_format_cache[row][column].push(format.style);
|
|
3332
|
+
this.CellData({row, column}).FlushStyle();
|
|
3333
|
+
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
|
|
3337
|
+
}
|
|
3338
|
+
*/
|
|
3339
|
+
|
|
3340
|
+
private ConditionalFormatForCell(address: ICellAddress): CellStyle[] {
|
|
3341
|
+
if (this.conditional_format_cache[address.row]) {
|
|
3342
|
+
return this.conditional_format_cache[address.row][address.column] || [];
|
|
3343
|
+
}
|
|
3344
|
+
return [];
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3052
3347
|
/**
|
|
3053
3348
|
* generates the composite style for the given cell. this
|
|
3054
3349
|
* should only be used to generate a cache of styles (Q: really? PERF?)
|
|
@@ -3057,7 +3352,12 @@ export class Sheet {
|
|
|
3057
3352
|
* want to check what happens if the cell style is not applied; if nothing
|
|
3058
3353
|
* happens, then we can drop the cell style (or the property in the style).
|
|
3059
3354
|
*/
|
|
3060
|
-
private CompositeStyleForCell(
|
|
3355
|
+
private CompositeStyleForCell(
|
|
3356
|
+
address: ICellAddress,
|
|
3357
|
+
apply_cell_style = true,
|
|
3358
|
+
apply_row_pattern = true,
|
|
3359
|
+
apply_default = true,
|
|
3360
|
+
apply_conditional = true, ) {
|
|
3061
3361
|
|
|
3062
3362
|
const { row, column } = address;
|
|
3063
3363
|
const stack: CellStyle[] = [];
|
|
@@ -3085,6 +3385,10 @@ export class Sheet {
|
|
|
3085
3385
|
stack.push(this.cell_style[column][row]);
|
|
3086
3386
|
}
|
|
3087
3387
|
|
|
3388
|
+
if (apply_conditional) {
|
|
3389
|
+
stack.push(...this.ConditionalFormatForCell(address));
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3088
3392
|
return Style.Composite(stack);
|
|
3089
3393
|
}
|
|
3090
3394
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import type { IArea, SerializedCellData, Style, CellStyle } from 'treb-base-types';
|
|
23
23
|
import type { Annotation, AnnotationData } from './annotation';
|
|
24
24
|
import type { GridSelection, SerializedGridSelection } from './grid_selection';
|
|
25
|
+
import type { ConditionalFormatList } from './conditional_format';
|
|
25
26
|
|
|
26
27
|
export interface UpdateHints {
|
|
27
28
|
data?: boolean;
|
|
@@ -68,6 +69,9 @@ export interface SerializedSheet {
|
|
|
68
69
|
*/
|
|
69
70
|
cell_styles: CellStyleRecord[]; // Array<{row: number; column: number; ref: number, rows?: number}>;
|
|
70
71
|
|
|
72
|
+
/** @internal */
|
|
73
|
+
conditional_formats?: ConditionalFormatList;
|
|
74
|
+
|
|
71
75
|
/**
|
|
72
76
|
* @deprecated use `styles` instead
|
|
73
77
|
*/
|
|
File without changes
|