@trebco/treb 28.17.5 → 29.1.2

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.
Files changed (87) hide show
  1. package/dist/treb-spreadsheet-light.mjs +12 -12
  2. package/dist/treb-spreadsheet.mjs +12 -12
  3. package/dist/treb.d.ts +121 -82
  4. package/eslint.config.js +21 -0
  5. package/package.json +6 -6
  6. package/treb-base-types/src/area.ts +4 -2
  7. package/treb-base-types/src/cell.ts +1 -1
  8. package/treb-base-types/src/cells.ts +16 -7
  9. package/treb-base-types/src/dom-utilities.ts +4 -2
  10. package/treb-base-types/src/import.ts +2 -2
  11. package/treb-base-types/src/rectangle.ts +5 -5
  12. package/treb-base-types/src/union.ts +6 -1
  13. package/treb-base-types/src/value-type.ts +1 -1
  14. package/treb-calculator/src/calculator.ts +114 -165
  15. package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -2
  16. package/treb-calculator/src/dag/graph.ts +3 -3
  17. package/treb-calculator/src/dag/spreadsheet_vertex.ts +2 -2
  18. package/treb-calculator/src/dag/state_leaf_vertex.ts +2 -4
  19. package/treb-calculator/src/descriptors.ts +28 -2
  20. package/treb-calculator/src/expression-calculator.ts +25 -34
  21. package/treb-calculator/src/function-error.ts +2 -2
  22. package/treb-calculator/src/function-library.ts +16 -0
  23. package/treb-calculator/src/functions/base-functions.ts +185 -211
  24. package/treb-calculator/src/functions/checkbox.ts +0 -1
  25. package/treb-calculator/src/functions/complex-functions.ts +49 -47
  26. package/treb-calculator/src/functions/finance-functions.ts +10 -10
  27. package/treb-calculator/src/functions/function-utilities.ts +26 -0
  28. package/treb-calculator/src/functions/information-functions.ts +21 -41
  29. package/treb-calculator/src/functions/matrix-functions.ts +8 -1
  30. package/treb-calculator/src/functions/sparkline.ts +6 -4
  31. package/treb-calculator/src/functions/statistics-functions.ts +21 -17
  32. package/treb-calculator/src/functions/text-functions.ts +14 -13
  33. package/treb-calculator/src/primitives.ts +48 -37
  34. package/treb-calculator/src/utilities.ts +117 -134
  35. package/treb-charts/src/chart-functions.ts +3 -3
  36. package/treb-charts/src/chart-types.ts +42 -1
  37. package/treb-charts/src/chart-utils.ts +155 -113
  38. package/treb-charts/src/chart.ts +6 -5
  39. package/treb-charts/src/default-chart-renderer.ts +6 -5
  40. package/treb-charts/src/renderer.ts +12 -11
  41. package/treb-charts/src/util.ts +25 -36
  42. package/treb-data-model/package.json +5 -0
  43. package/{treb-grid/src/types → treb-data-model/src}/annotation.ts +2 -2
  44. package/{treb-grid/src/types → treb-data-model/src}/conditional_format.ts +20 -0
  45. package/{treb-grid/src/types → treb-data-model/src}/data_model.ts +231 -133
  46. package/treb-data-model/src/index.ts +45 -0
  47. package/{treb-grid/src/types/named_range.ts → treb-data-model/src/named.ts} +459 -376
  48. package/{treb-grid/src/types → treb-data-model/src}/sheet.ts +13 -5
  49. package/treb-data-model/src/sheet_collection.ts +114 -0
  50. package/{treb-grid/src/types → treb-data-model/src}/sheet_types.ts +6 -3
  51. package/treb-embed/modern.tsconfig.json +1 -0
  52. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +2 -2
  53. package/treb-embed/src/embedded-spreadsheet.ts +125 -270
  54. package/treb-embed/src/selection-state.ts +1 -1
  55. package/treb-embed/src/toolbar-message.ts +1 -1
  56. package/treb-embed/src/types.ts +13 -5
  57. package/treb-export/src/export-worker/export-worker.ts +22 -7
  58. package/treb-export/src/export2.ts +110 -41
  59. package/treb-export/src/import2.ts +6 -5
  60. package/treb-export/src/workbook2.ts +31 -13
  61. package/treb-export/src/xml-utils.ts +5 -1
  62. package/treb-format/src/format.ts +8 -6
  63. package/treb-grid/src/editors/autocomplete.ts +2 -2
  64. package/treb-grid/src/editors/autocomplete_matcher.ts +57 -19
  65. package/treb-grid/src/editors/editor.ts +27 -25
  66. package/treb-grid/src/editors/formula_bar.ts +5 -5
  67. package/treb-grid/src/editors/overlay_editor.ts +1 -2
  68. package/treb-grid/src/index.ts +0 -11
  69. package/treb-grid/src/layout/base_layout.ts +20 -8
  70. package/treb-grid/src/layout/grid_layout.ts +2 -2
  71. package/treb-grid/src/layout/mock-layout.ts +5 -6
  72. package/treb-grid/src/render/selection-renderer.ts +2 -3
  73. package/treb-grid/src/render/tile_renderer.ts +1 -1
  74. package/treb-grid/src/types/grid.ts +95 -66
  75. package/treb-grid/src/types/grid_base.ts +76 -60
  76. package/treb-grid/src/types/grid_command.ts +3 -2
  77. package/treb-grid/src/types/grid_events.ts +12 -6
  78. package/treb-grid/src/types/tab_bar.ts +1 -2
  79. package/treb-parser/src/parser-types.ts +2 -1
  80. package/treb-parser/src/parser.ts +7 -5
  81. package/treb-utils/src/event_source.ts +1 -1
  82. package/treb-utils/src/serialize_html.ts +31 -6
  83. package/.eslintignore +0 -8
  84. package/.eslintrc.cjs +0 -168
  85. package/treb-grid/src/layout/rectangle_cache.ts +0 -86
  86. /package/{treb-grid/src/types → treb-data-model/src}/serialize_options.ts +0 -0
  87. /package/{treb-grid/src/types/grid_selection.ts → treb-data-model/src/sheet_selection.ts} +0 -0
@@ -19,6 +19,7 @@
19
19
  *
20
20
  */
21
21
 
22
+ // import type { UnionValue } from 'treb-base-types';
22
23
  import type { RangeScale} from 'treb-utils';
23
24
  import { Scale } from 'treb-utils';
24
25
 
@@ -39,40 +40,7 @@ export class Util {
39
40
  * suggestion -- we try to get as close as possible.
40
41
  */
41
42
  public static Scale(min: number, max: number, count = 6.5, limit_count?: boolean, discrete?: boolean): RangeScale {
42
-
43
- /*
44
- const range = max - min;
45
- const log10 = // Math.log10(range);
46
- Math.log(range) / Math.log(10); // just avoid the problem
47
-
48
- const scale = Math.floor(Math.abs(log10)) * (log10 < 0 ? -1 : 1) - 1;
49
- const steps = [.1, .25, .5, 1, 2.5, 5, 10, 25, 100];
50
-
51
- let step = -1;
52
- let delta = 0;
53
-
54
- for (const x of steps) {
55
- const test_step = x * Math.pow(10, scale);
56
- const test_min = Math.floor(min / test_step) * test_step;
57
- const test_max = Math.ceil(max / test_step) * test_step;
58
- const test_count = (test_max - test_min) / test_step;
59
- const test_delta = Math.abs(test_count - count);
60
-
61
- if (step < 0 || test_delta < delta){
62
- delta = test_delta;
63
- step = test_step;
64
- }
65
- else if (step >= 0 && test_delta > delta) break;
66
- }
67
-
68
- min = Math.floor(min / step) * step;
69
- max = Math.ceil(max / step) * step;
70
- count = Math.round((max - min) / step); // accounts for fp errors
71
-
72
- return { scale, step, count, min, max };
73
- */
74
43
  return Scale(min, max, count, limit_count, discrete);
75
-
76
44
  }
77
45
 
78
46
  public static Range(data: Array<number|undefined>) {
@@ -95,13 +63,13 @@ export class Util {
95
63
  return range * (value - scale.min) / (scale.max - scale.min);
96
64
  }
97
65
 
98
- /**
66
+ /* *
99
67
  * flatten. we support holes in data, which means undefined values
100
68
  * in arrays, but don't push an empty value at the top level (if
101
69
  * that makes sense).
102
70
  *
103
- * @param args
104
- */
71
+ * @deprecated
72
+ * /
105
73
  public static Flatten(args: any) {
106
74
  let flat: any[] = [];
107
75
  if (Array.isArray(args)) {
@@ -119,5 +87,26 @@ export class Util {
119
87
  }
120
88
  return flat;
121
89
  }
90
+ */
91
+
92
+ public static Flatten<T>(args?: T|T[]|T[][]) {
93
+ let flat: T[] = [];
94
+ if (Array.isArray(args)) {
95
+ for (const element of args) {
96
+ if (Array.isArray(element)) {
97
+ flat = flat.concat(this.Flatten(element));
98
+ }
99
+ else {
100
+ flat.push(element);
101
+ }
102
+ }
103
+ }
104
+ else if (typeof args !== 'undefined') {
105
+ flat.push(args);
106
+ }
107
+ return flat;
108
+ }
122
109
 
123
110
  }
111
+
112
+
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "treb-data-model",
3
+ "version": "16.1.10",
4
+ "main": "src/index.ts"
5
+ }
@@ -194,7 +194,7 @@ export interface AnnotationTextBoxData extends AnnotationDataBase {
194
194
  }[],
195
195
  }[];
196
196
  };
197
- };
197
+ }
198
198
 
199
199
  export interface AnnotationExternalData extends AnnotationDataBase {
200
200
  type: 'external';
@@ -230,7 +230,7 @@ export class Annotation {
230
230
  public scaled_rect?: Rectangle;
231
231
 
232
232
  /** also opaque data, but not serialized. */
233
- public temp: any = {};
233
+ public temp: unknown = {};
234
234
 
235
235
  public view: ViewData[] = [];
236
236
 
@@ -1,3 +1,23 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2024 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
1
21
 
2
22
  import type { CellStyle, EvaluateOptions, IArea, Color, Gradient, GradientStop, UnionValue } from 'treb-base-types';
3
23
 
@@ -20,11 +20,13 @@
20
20
  */
21
21
 
22
22
  import type { Sheet } from './sheet';
23
+ import { SheetCollection } from './sheet_collection';
23
24
  import type { IArea, ICellAddress, Table, CellStyle } from 'treb-base-types';
24
25
  import type { SerializedSheet } from './sheet_types';
25
- import { NamedRangeCollection } from './named_range';
26
- import { type ExpressionUnit, type UnitAddress, type UnitStructuredReference, type UnitRange, Parser, QuotedSheetNameRegex } from 'treb-parser';
26
+ import { type ExpressionUnit, type UnitAddress, type UnitStructuredReference, type UnitRange, Parser, QuotedSheetNameRegex, DecimalMarkType, ArgumentSeparatorType } from 'treb-parser';
27
27
  import { Area, IsCellAddress, Style } from 'treb-base-types';
28
+ import type { CompositeNamed, SerializedNamed } from './named';
29
+ import { NamedRangeManager } from './named';
28
30
 
29
31
  export interface ConnectedElementType {
30
32
  formula: string;
@@ -49,173 +51,255 @@ export interface MacroFunction extends SerializedMacroFunction {
49
51
  }
50
52
 
51
53
  /**
52
- * we spend a lot of time looking up sheets by name, or id, or
53
- * sometimes index. it makes sense to have a class that can
54
- * support all of these, ideally without looping.
55
- *
56
- * we just have to make sure that no one is assigning to the
57
- * array, or we'll lose track.
58
- *
59
- * also there are some operations -- rename, in particular -- that
60
- * require updating indexes.
61
- *
62
- *
63
- * FIXME: new file (1 class per file)
54
+ * FIXME: this should move out of the grid module, grid should be focused on view
64
55
  */
65
- export class SheetCollection {
56
+ export class DataModel {
57
+
58
+ public readonly parser: Parser = new Parser();
59
+
60
+ /** document metadata */
61
+ public document_name?: string;
66
62
 
67
63
  /**
68
- * returns a read-only copy of the list. useful for indexing or
69
- * functional-style calls. it's not actually read-only, but it's a
70
- * copy, so changes will be ignored.
64
+ * document metadata. this is opaque to everyone except the user, so
65
+ * we're intentionally leaving it as unknown except where users have
66
+ * direct access (embedded spreadsheet).
71
67
  */
72
- public get list() {
73
- return this.sheets_.slice(0);
74
- }
68
+ public user_data?: unknown;
75
69
 
76
70
  /**
77
- * length of list
71
+ *
78
72
  */
79
- public get length() {
80
- return this.sheets_.length;
81
- }
73
+ public readonly sheets = new SheetCollection();
82
74
 
83
- /** map of (normalized) name -> sheet */
84
- protected names: Map<string, Sheet> = new Map();
75
+ /** new composite collection (TODO: add macro functions too?) */
76
+ public readonly named = new NamedRangeManager();
85
77
 
86
- /** map of id -> sheet */
87
- protected ids: Map<number, Sheet> = new Map();
78
+ /** macro functions are functions written in spreadsheet language */
79
+ public readonly macro_functions: Map<string, MacroFunction> = new Map();
88
80
 
89
- /** the actual list */
90
- private sheets_: Sheet[] = [];
81
+ /** index for views */
82
+ public view_count = 0;
91
83
 
92
84
  /**
93
- * remove any existing sheets and add the passed list. updates indexes.
85
+ * base style properties moved to model, so we can have a single
86
+ * and consistent reference.
94
87
  */
95
- public Assign(sheets: Sheet[]) {
96
- this.sheets_ = [...sheets];
97
- this.UpdateIndexes();
98
- }
88
+ public theme_style_properties: CellStyle = JSON.parse(JSON.stringify(Style.DefaultProperties));
99
89
 
100
- /**
101
- * add a new sheet to the end of the list (push). updates indexes.
90
+ /**
91
+ * tables are global, because we need to reference them by name; and they
92
+ * need unique names, so we need to keep track of names. name matching is
93
+ * icase so we lc the names before inserting.
102
94
  */
103
- public Add(sheet: Sheet) {
104
- this.sheets_.push(sheet);
105
- this.UpdateIndexes();
106
- }
95
+ public tables: Map<string, Table> = new Map();
107
96
 
108
97
  /**
109
- * wrapper for array splice. updates indexes.
98
+ * we're wrapping up the get name method so we can check for a sheet
99
+ * name -- we have the list of sheet names. we could pass that to the
100
+ * name list manager but it's easier for us to intercept the call.
101
+ * I thought about wrapping up more API functions here, but that seems
102
+ * unecessary atm.
110
103
  */
111
- public Splice(insert_index: number, delete_count: number, ...items: Sheet[]) {
112
- this.sheets_.splice(insert_index, delete_count, ...items);
113
- this.UpdateIndexes();
114
- }
115
-
116
- /**
117
- * so our new strategy is to add lookup methods first -- then
118
- * we can fix the underlying storage implementation.
119
- *
120
- * NOTE we normalize strings here so you do not need to do it (don't)
121
- */
122
- public Find(id: string|number): Sheet|undefined {
104
+ public GetName(name: string, scope: number) {
105
+
106
+ // helpfully this is not a legal character in names or sheets, so
107
+ // we don't need a full parser to handle the split. watch out for
108
+ // quoted sheet names.
123
109
 
124
- // console.info('get', typeof id);
110
+ const parts = name.split(/!/);
125
111
 
126
- if (typeof id === 'string') {
127
- return this.names.get(id.toLocaleUpperCase());
112
+ if (parts.length === 1) {
113
+ return this.named.Get_(name, scope);
128
114
  }
129
- else {
130
- return this.ids.get(id);
115
+
116
+ let sheet_name = parts[0];
117
+
118
+ // can we just test with indexes? surely faster
119
+
120
+ if (/^'.*?'$/.test(sheet_name)) {
121
+ sheet_name = sheet_name.substring(1, sheet_name.length - 1);
131
122
  }
123
+
124
+ const sheet = this.sheets.ID(sheet_name);
125
+ return this.named.Get_(parts[1], sheet || 0, true); // require scope in this case
132
126
 
133
- return undefined;
134
- }
135
127
 
136
- /** get name for sheet with given id */
137
- public Name(id: number): string|undefined {
138
- return this.ids.get(id)?.name || undefined;
139
128
  }
140
129
 
141
- /** get ID for sheet with given name */
142
- public ID(name: string): number|undefined {
143
- return this.names.get(name.toLocaleUpperCase())?.id || undefined;
130
+ /**
131
+ * from import, we get ranges and expressions in the same format. we
132
+ * need to check if something is a range -- if so, it will just be
133
+ * a single address or range. in that case store it as a named range.
134
+ */
135
+ public UnserializeComposite(names: CompositeNamed[], active_sheet?: Sheet) {
136
+
137
+ this.parser.Save();
138
+ this.parser.SetLocaleSettings(DecimalMarkType.Period, ArgumentSeparatorType.Comma);
139
+
140
+ const sorted = names.map(named => {
141
+ const parse_result = this.parser.Parse(named.expression);
142
+ if (parse_result.expression) {
143
+ if (parse_result.expression.type === 'address' || parse_result.expression.type === 'range') {
144
+ return {
145
+ ...named,
146
+ expression: undefined,
147
+ area: parse_result.expression.type === 'address' ? {
148
+ start: parse_result.expression,
149
+ end: parse_result.expression,
150
+ } : parse_result.expression,
151
+ } as SerializedNamed;
152
+ }
153
+ return {
154
+ ...named
155
+ } as SerializedNamed;
156
+ }
157
+ return undefined;
158
+ }).filter((test): test is SerializedNamed => !!test);
159
+
160
+ this.parser.Restore();
161
+ this.UnserializeNames(sorted, active_sheet);
162
+
144
163
  }
145
164
 
146
- /** not sure why this is private, makes it a little more complicated */
147
- public UpdateIndexes(): void {
165
+ public UnserializeNames(names: SerializedNamed[], active_sheet?: Sheet) {
166
+
167
+ for (const entry of names) {
168
+
169
+ const scope = (typeof entry.scope === 'string') ? this.sheets.ID(entry.scope) : undefined;
170
+
171
+ if (entry.expression) {
172
+
173
+ const parse_result = this.parser.Parse(entry.expression);
174
+
175
+ if (parse_result.valid && parse_result.expression) {
176
+ this.parser.Walk(parse_result.expression, unit => {
177
+ if (unit.type === 'address' || unit.type === 'range') {
178
+ if (unit.type === 'range') {
179
+ unit = unit.start;
180
+ }
181
+ if (!unit.sheet_id) {
182
+ if (unit.sheet) {
183
+ unit.sheet_id = this.sheets.ID(unit.sheet);
184
+ }
185
+ }
186
+ if (!unit.sheet_id) {
187
+ unit.sheet_id = active_sheet?.id;
188
+ }
189
+ return false; // don't continue in ranges
190
+ }
191
+ return true;
192
+ });
193
+
194
+ this.named.SetNamedExpression(entry.name, parse_result.expression, scope);
195
+
196
+ }
197
+
198
+ }
199
+ else if (entry.area) {
200
+ if (entry.area.start.sheet) {
148
201
 
149
- this.names.clear();
150
- this.ids.clear();
202
+ const area = new Area({
203
+ ...entry.area.start,
204
+ sheet_id: this.sheets.ID(entry.area.start.sheet),
205
+ }, entry.area.end);
151
206
 
152
- for (const sheet of this.sheets_) {
153
- const uc = sheet.name.toLocaleUpperCase();
154
- this.names.set(uc, sheet);
155
- this.ids.set(sheet.id, sheet);
207
+ if (area.start.sheet_id) {
208
+ this.named.SetNamedRange(entry.name, area, scope);
209
+ }
210
+ else {
211
+ console.warn("missing sheet ID?", entry.area.start.sheet);
212
+ }
213
+ }
214
+ else {
215
+ console.warn("missing sheet name?");
216
+ }
217
+ }
156
218
  }
157
219
 
158
220
  }
159
221
 
222
+ /**
223
+ * serialize names. ranges are easy, but make sure there's a sheet name
224
+ * in each address (and remove the ID). expressions are a little more
225
+ * complicated.
226
+ */
227
+ public SerializeNames(active_sheet?: Sheet): SerializedNamed[] {
228
+ const list: SerializedNamed[] = [];
160
229
 
161
- }
230
+ for (const entry of this.named.list) {
162
231
 
163
- /**
164
- * FIXME: this should move out of the grid module, grid should be focused on view
165
- */
166
- export class DataModel {
232
+ const named: SerializedNamed = {
233
+ name: entry.name,
234
+ // scope: entry.scope,
235
+ };
167
236
 
168
- public readonly parser: Parser = new Parser();
237
+ if (entry.scope) {
238
+ named.scope = this.sheets.Name(entry.scope);
239
+ }
169
240
 
170
- /** document metadata */
171
- public document_name?: string;
241
+ if (entry.type === 'expression') {
172
242
 
173
- /** document metadata */
174
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
- public user_data?: any;
243
+ this.parser.Walk(entry.expression, unit => {
244
+ if (unit.type === 'address' || unit.type === 'range') {
176
245
 
177
- /**
178
- * list of sheets. we _should_ index these by ID, so we
179
- * don't have to look up. FIXME/TODO
180
- */
181
- // public sheets: Sheet[] = [];
246
+ const test = unit.type === 'range' ? unit.start : unit;
247
+ test.absolute_column = test.absolute_row = true;
182
248
 
183
- /**
184
- * this prevents assignment, but not push/pop/splice (baby steps)
185
- */
186
- // public get sheets(): Sheet[] {
187
- // return this._sheets;
188
- //}
189
- public readonly sheets = new SheetCollection();
249
+ if (!test.sheet) {
250
+ if (test.sheet_id) {
251
+ test.sheet = this.sheets.Name(test.sheet_id);
252
+ }
253
+ if (!test.sheet) {
254
+ test.sheet = active_sheet?.name;
255
+ }
256
+ }
190
257
 
191
- /** named ranges are document-scope, we don't support sheet-scope names */
192
- public readonly named_ranges = new NamedRangeCollection;
258
+ if (unit.type === 'range') {
259
+ unit.end.absolute_column = unit.end.absolute_row = true;
260
+ }
193
261
 
194
- /** macro functions are functions written in spreadsheet language */
195
- // public macro_functions: Record<string, MacroFunction> = {};
196
- public readonly macro_functions: Map<string, MacroFunction> = new Map();
262
+ return false;
263
+ }
264
+ /*
197
265
 
198
- /**
199
- * new, for parametric. these might move to a different construct.
200
- */
201
- //public named_expressions: Record<string, ExpressionUnit> = {};
202
- public readonly named_expressions: Map<string, ExpressionUnit> = new Map();
266
+ // if we do the function export thing, we need to call that here
267
+ // (exporting functions to fix missing arguments or add decorators).
268
+ // we're not doing that, at least not yet.
203
269
 
204
- /** index for views */
205
- public view_count = 0;
270
+ else if (unit.type === 'call' && options.export_functions) {
271
+ // ...
272
+ }
273
+ */
274
+ return true;
275
+ });
206
276
 
207
- /**
208
- * base style properties moved to model, so we can have a single
209
- * and consistent reference.
210
- */
211
- public theme_style_properties: CellStyle = JSON.parse(JSON.stringify(Style.DefaultProperties));
277
+ named.expression = this.parser.Render(entry.expression, { missing: '' });
212
278
 
213
- /**
214
- * tables are global, because we need to reference them by name; and they
215
- * need unique names, so we need to keep track of names. name matching is
216
- * icase so we lc the names before inserting.
217
- */
218
- public tables: Map<string, Table> = new Map();
279
+ }
280
+ else {
281
+ named.area = {
282
+ start: {
283
+ ...entry.area.start,
284
+ sheet: this.sheets.Name(entry.area.start.sheet_id || 0) || '',
285
+ sheet_id: undefined, // in favor of name
286
+ absolute_column: true,
287
+ absolute_row: true,
288
+ },
289
+ end: {
290
+ ...entry.area.end,
291
+ absolute_column: true,
292
+ absolute_row: true,
293
+ },
294
+ };
295
+ }
296
+
297
+ list.push(named);
298
+
299
+ }
300
+
301
+ return list;
302
+ }
219
303
 
220
304
  /**
221
305
  * putting this here temporarily. it should probably move into a table
@@ -332,7 +416,7 @@ export class DataModel {
332
416
  * @param address
333
417
  * @param active_sheet
334
418
  */
335
- public AddressToLabel(address: ICellAddress|IArea, active_sheet?: Sheet) {
419
+ public AddressToLabel(address: ICellAddress|IArea) {
336
420
 
337
421
  const start = IsCellAddress(address) ? address : address.start;
338
422
  const parts = IsCellAddress(address) ?
@@ -369,15 +453,6 @@ export class DataModel {
369
453
  return true;
370
454
  }
371
455
 
372
- /*
373
- const lc = target.sheet.toLowerCase();
374
- for (const sheet of this.model.sheets.list) {
375
- if (sheet.name.toLowerCase() === lc) {
376
- target.sheet_id = sheet.id;
377
- return true;
378
- }
379
- }
380
- */
381
456
  }
382
457
  else if (context?.sheet_id) {
383
458
  target.sheet_id = context.sheet_id;
@@ -435,12 +510,20 @@ export class DataModel {
435
510
  }
436
511
  else if (parse_result.expression && parse_result.expression.type === 'identifier') {
437
512
 
513
+ const named = this.GetName(parse_result.expression.name, active_sheet.id);
514
+ if (named?.type === 'range') {
515
+ return named.area;
516
+ }
517
+
518
+ /*
438
519
  // is named range guaranteed to have a sheet ID? (I think yes...)
439
520
 
440
521
  const named_range = this.named_ranges.Get(parse_result.expression.name);
441
522
  if (named_range) {
442
523
  return named_range;
443
524
  }
525
+ */
526
+
444
527
  }
445
528
 
446
529
  return { row: 0, column: 0 }; // default for string types -- broken
@@ -479,6 +562,9 @@ export class DataModel {
479
562
 
480
563
  }
481
564
 
565
+ /**
566
+ * @internal
567
+ */
482
568
  export interface ViewModel {
483
569
  active_sheet: Sheet;
484
570
  view_index: number;
@@ -492,9 +578,21 @@ export interface SerializedNamedExpression {
492
578
  export interface SerializedModel {
493
579
  sheet_data: SerializedSheet[];
494
580
  active_sheet: number;
581
+
582
+ /** @deprecated */
495
583
  named_ranges?: Record<string, IArea>;
584
+
585
+ /** @deprecated */
586
+ named_expressions?: SerializedNamedExpression[];
587
+
588
+ /**
589
+ * new type for consolidated named ranges & expressions. the old
590
+ * types are retained for backwards compatibility on import but we won't
591
+ * export them anymore.
592
+ */
593
+ named?: SerializedNamed[];
594
+
496
595
  macro_functions?: MacroFunction[];
497
596
  tables?: Table[];
498
- named_expressions?: SerializedNamedExpression[];
499
597
  decimal_mark?: ','|'.';
500
598
  }
@@ -0,0 +1,45 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2024 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ export { DataModel } from './data_model';
23
+
24
+ export type {
25
+ MacroFunction,
26
+ ConnectedElementType,
27
+ SerializedNamedExpression,
28
+ SerializedModel,
29
+ ViewModel,
30
+ SerializedMacroFunction,
31
+ } from './data_model';
32
+
33
+ export type { SerializedNamed, CompositeNamed } from './named';
34
+
35
+ export { Sheet } from './sheet';
36
+ export type { SerializedSheet, FreezePane, LegacySerializedSheet } from './sheet_types';
37
+ export * from './conditional_format';
38
+ export type { GridSelection } from './sheet_selection';
39
+ export type { SerializeOptions } from './serialize_options';
40
+
41
+ export { Annotation } from './annotation';
42
+ export type { ViewData as AnnotationViewData } from './annotation';
43
+ export type { AnnotationData, AnnotationType } from './annotation';
44
+
45
+