@trebco/treb 29.3.3 → 29.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,11 +37,12 @@
37
37
 
38
38
  import { EventSource } from 'treb-utils';
39
39
  import type { DataModel, ConditionalFormat, // MacroFunction, SerializedModel, SerializedNamedExpression,
40
- ViewModel } from 'treb-data-model';
40
+ ViewModel,
41
+ DataValidation} from 'treb-data-model';
41
42
 
42
43
  import type { Parser, UnitAddress} from 'treb-parser';
43
44
  import { type ExpressionUnit, IllegalSheetNameRegex, ParseCSV, DecimalMarkType } from 'treb-parser';
44
- import { Area, IsCellAddress, ValidationType, ValueType, DefaultTableSortOptions } from 'treb-base-types';
45
+ import { Area, IsCellAddress, ValueType, DefaultTableSortOptions } from 'treb-base-types';
45
46
  import type { ICellAddress, IArea, Cell, CellValue, CellStyle, Table, TableSortOptions, TableTheme, Complex, PatchOptions as PatchAreaOptions } from 'treb-base-types';
46
47
 
47
48
  import { Sheet, type SerializeOptions, type Annotation } from 'treb-data-model';
@@ -922,34 +923,54 @@ export class GridBase {
922
923
 
923
924
  protected SetValidationInternal(command: DataValidationCommand): void {
924
925
 
925
- let cell: Cell|undefined;
926
-
927
926
  const sheet = this.FindSheet(command.area);
928
-
929
- if (sheet) {
930
- cell = sheet.cells.GetCell(command.area, true);
927
+ if (!sheet) {
928
+ throw new Error('invalid sheet in set validation');
931
929
  }
932
930
 
933
- if (!cell) {
934
- throw new Error('invalid cell in set validation');
935
- }
931
+ const target = {start: command.area.start, end: command.area.end };
936
932
 
937
933
  if (command.range) {
934
+
935
+ sheet.AddValidation({
936
+ type: 'range',
937
+ error: !!command.error,
938
+ area: command.range,
939
+ target: [target],
940
+ });
941
+
942
+ /*
938
943
  cell.validation = {
939
944
  type: ValidationType.Range,
940
945
  area: command.range,
941
946
  error: !!command.error,
942
947
  };
948
+ */
949
+
943
950
  }
944
951
  else if (command.list) {
952
+
953
+ sheet.AddValidation({
954
+ type: 'list',
955
+ error: !!command.error,
956
+ list: JSON.parse(JSON.stringify(command.list)),
957
+ target: [target],
958
+ });
959
+
960
+ /*
945
961
  cell.validation = {
946
962
  type: ValidationType.List,
947
963
  list: JSON.parse(JSON.stringify(command.list)),
948
964
  error: !!command.error,
949
965
  }
966
+ */
967
+
950
968
  }
951
969
  else {
952
- cell.validation = undefined;
970
+ // cell.validation = undefined;
971
+
972
+ sheet.RemoveValidations(target);
973
+
953
974
  }
954
975
 
955
976
  }
@@ -2794,8 +2815,54 @@ export class GridBase {
2794
2815
  /**
2795
2816
  * patch sheet conditionals for insert/delete row/column operations.
2796
2817
  * some of them may be deleted.
2818
+ *
2819
+ * UPDATE: using this routine to also patch data validations
2797
2820
  */
2798
- protected PatchConditionals(options: PatchOptions) {
2821
+ protected PatchConditionalsAndValidations(options: PatchOptions) {
2822
+
2823
+ if (options.sheet.data_validation.length) {
2824
+
2825
+ const delete_list: Set<DataValidation> = new Set();
2826
+ for (const validation of options.sheet.data_validation) {
2827
+
2828
+ const targets: IArea[] = [];
2829
+ for (const area of validation.target) {
2830
+ const updated = Area.PatchArea(area, options);
2831
+ if (updated) {
2832
+ targets.push(updated);
2833
+ }
2834
+ }
2835
+
2836
+ if (targets.length > 0) {
2837
+
2838
+ validation.target = targets;
2839
+
2840
+ // format the range, if necessary
2841
+
2842
+ if (validation.type === 'range') {
2843
+ if (validation.area.start.sheet_id === options.sheet.id) {
2844
+ const updated = Area.PatchArea(validation.area, options);
2845
+ if (updated) {
2846
+ validation.area = updated;
2847
+ }
2848
+ else {
2849
+ delete_list.add(validation);
2850
+ }
2851
+ }
2852
+ }
2853
+
2854
+ }
2855
+ else {
2856
+ delete_list.add(validation);
2857
+ }
2858
+
2859
+ }
2860
+
2861
+ if (delete_list.size) {
2862
+ options.sheet.data_validation = options.sheet.data_validation.filter(test => !delete_list.has(test));
2863
+ }
2864
+
2865
+ }
2799
2866
 
2800
2867
  if (options.sheet.conditional_formats?.length) {
2801
2868
 
@@ -2869,7 +2936,7 @@ export class GridBase {
2869
2936
  }
2870
2937
 
2871
2938
  // conditionals
2872
- this.PatchConditionals({
2939
+ this.PatchConditionalsAndValidations({
2873
2940
  sheet: target_sheet,
2874
2941
  before_column: 0,
2875
2942
  column_count: 0,
@@ -3217,7 +3284,7 @@ export class GridBase {
3217
3284
  }
3218
3285
 
3219
3286
  // conditionals
3220
- this.PatchConditionals({
3287
+ this.PatchConditionalsAndValidations({
3221
3288
  sheet: target_sheet,
3222
3289
  before_column: command.before_column,
3223
3290
  column_count: command.count,
@@ -4029,8 +4096,8 @@ export class GridBase {
4029
4096
  // COEDITING: ok
4030
4097
 
4031
4098
  this.SetValidationInternal(command);
4032
- if (!command.area.sheet_id || command.area.sheet_id === this.active_sheet.id) {
4033
- flags.render_area = Area.Join(new Area(command.area), flags.render_area);
4099
+ if (!command.area.start.sheet_id || command.area.start.sheet_id === this.active_sheet.id) {
4100
+ flags.render_area = Area.Join(new Area(command.area.start, command.area.end), flags.render_area);
4034
4101
  }
4035
4102
  break;
4036
4103
 
@@ -225,7 +225,8 @@ export interface SetNameCommand {
225
225
 
226
226
  export interface DataValidationCommand {
227
227
  key: CommandKey.DataValidation;
228
- area: ICellAddress;
228
+ area: IArea;
229
+
229
230
  range?: IArea;
230
231
  list?: CellValue[];
231
232
  error?: boolean;
@@ -409,7 +409,7 @@ export class Parser {
409
409
  for (let i = 0; i < n; i++) {
410
410
  transposed[i] = [];
411
411
  for (let j = 0; j < m; j++) {
412
- transposed[i][j] = arr[j][i];
412
+ transposed[i][j] = arr[j] ? arr[j][i] : undefined;
413
413
  }
414
414
  }
415
415
 
@@ -2415,8 +2415,11 @@ export class Parser {
2415
2415
  if (!c) return null;
2416
2416
  position = c.position;
2417
2417
 
2418
+ // things that look like an address but have row 0 are legal
2419
+ // as names. so this should be a token if r === 0.
2420
+
2418
2421
  const r = this.ConsumeAddressRow(position);
2419
- if (!r) return null;
2422
+ if (!r) return null;
2420
2423
  position = r.position;
2421
2424
 
2422
2425
  const label = sheet ?
@@ -2460,7 +2463,11 @@ export class Parser {
2460
2463
 
2461
2464
  /**
2462
2465
  * consumes a row, possibly absolute ($). returns the numeric row
2463
- * (0-based) and metadata
2466
+ * (0-based) and metadata.
2467
+ *
2468
+ * note that something like "X0" is a legal token, because 0 is not
2469
+ * a valid row. but at the same time it can't have a $ in it. although
2470
+ * maybe "X$0" is a token but not a valid name? dunno
2464
2471
  */
2465
2472
  protected ConsumeAddressRow(position: number):
2466
2473
  {
@@ -2484,7 +2491,18 @@ export class Parser {
2484
2491
  else break;
2485
2492
  }
2486
2493
 
2487
- if (start === position) return false;
2494
+ if (start === position) {
2495
+ return false;
2496
+ }
2497
+
2498
+ // handle token X0. should ~maybe~ handle this only if !absolute
2499
+ // temp leaving this separate from the above test just so it's clear
2500
+ // what we are doing
2501
+
2502
+ if (value === 0) {
2503
+ return false;
2504
+ }
2505
+
2488
2506
  return { absolute, row: value - 1, position };
2489
2507
  }
2490
2508