@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.
- package/dist/treb-spreadsheet-light.mjs +12 -12
- package/dist/treb-spreadsheet.mjs +12 -12
- package/dist/treb.d.ts +121 -82
- package/eslint.config.js +21 -0
- package/package.json +6 -6
- package/treb-base-types/src/area.ts +4 -2
- package/treb-base-types/src/cell.ts +1 -1
- package/treb-base-types/src/cells.ts +16 -7
- package/treb-base-types/src/dom-utilities.ts +4 -2
- package/treb-base-types/src/import.ts +2 -2
- package/treb-base-types/src/rectangle.ts +5 -5
- package/treb-base-types/src/union.ts +6 -1
- package/treb-base-types/src/value-type.ts +1 -1
- package/treb-calculator/src/calculator.ts +114 -165
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -2
- package/treb-calculator/src/dag/graph.ts +3 -3
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +2 -2
- package/treb-calculator/src/dag/state_leaf_vertex.ts +2 -4
- package/treb-calculator/src/descriptors.ts +28 -2
- package/treb-calculator/src/expression-calculator.ts +25 -34
- package/treb-calculator/src/function-error.ts +2 -2
- package/treb-calculator/src/function-library.ts +16 -0
- package/treb-calculator/src/functions/base-functions.ts +185 -211
- package/treb-calculator/src/functions/checkbox.ts +0 -1
- package/treb-calculator/src/functions/complex-functions.ts +49 -47
- package/treb-calculator/src/functions/finance-functions.ts +10 -10
- package/treb-calculator/src/functions/function-utilities.ts +26 -0
- package/treb-calculator/src/functions/information-functions.ts +21 -41
- package/treb-calculator/src/functions/matrix-functions.ts +8 -1
- package/treb-calculator/src/functions/sparkline.ts +6 -4
- package/treb-calculator/src/functions/statistics-functions.ts +21 -17
- package/treb-calculator/src/functions/text-functions.ts +14 -13
- package/treb-calculator/src/primitives.ts +48 -37
- package/treb-calculator/src/utilities.ts +117 -134
- package/treb-charts/src/chart-functions.ts +3 -3
- package/treb-charts/src/chart-types.ts +42 -1
- package/treb-charts/src/chart-utils.ts +155 -113
- package/treb-charts/src/chart.ts +6 -5
- package/treb-charts/src/default-chart-renderer.ts +6 -5
- package/treb-charts/src/renderer.ts +12 -11
- package/treb-charts/src/util.ts +25 -36
- package/treb-data-model/package.json +5 -0
- package/{treb-grid/src/types → treb-data-model/src}/annotation.ts +2 -2
- package/{treb-grid/src/types → treb-data-model/src}/conditional_format.ts +20 -0
- package/{treb-grid/src/types → treb-data-model/src}/data_model.ts +231 -133
- package/treb-data-model/src/index.ts +45 -0
- package/{treb-grid/src/types/named_range.ts → treb-data-model/src/named.ts} +459 -376
- package/{treb-grid/src/types → treb-data-model/src}/sheet.ts +13 -5
- package/treb-data-model/src/sheet_collection.ts +114 -0
- package/{treb-grid/src/types → treb-data-model/src}/sheet_types.ts +6 -3
- package/treb-embed/modern.tsconfig.json +1 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +2 -2
- package/treb-embed/src/embedded-spreadsheet.ts +125 -270
- package/treb-embed/src/selection-state.ts +1 -1
- package/treb-embed/src/toolbar-message.ts +1 -1
- package/treb-embed/src/types.ts +13 -5
- package/treb-export/src/export-worker/export-worker.ts +22 -7
- package/treb-export/src/export2.ts +110 -41
- package/treb-export/src/import2.ts +6 -5
- package/treb-export/src/workbook2.ts +31 -13
- package/treb-export/src/xml-utils.ts +5 -1
- package/treb-format/src/format.ts +8 -6
- package/treb-grid/src/editors/autocomplete.ts +2 -2
- package/treb-grid/src/editors/autocomplete_matcher.ts +57 -19
- package/treb-grid/src/editors/editor.ts +27 -25
- package/treb-grid/src/editors/formula_bar.ts +5 -5
- package/treb-grid/src/editors/overlay_editor.ts +1 -2
- package/treb-grid/src/index.ts +0 -11
- package/treb-grid/src/layout/base_layout.ts +20 -8
- package/treb-grid/src/layout/grid_layout.ts +2 -2
- package/treb-grid/src/layout/mock-layout.ts +5 -6
- package/treb-grid/src/render/selection-renderer.ts +2 -3
- package/treb-grid/src/render/tile_renderer.ts +1 -1
- package/treb-grid/src/types/grid.ts +95 -66
- package/treb-grid/src/types/grid_base.ts +76 -60
- package/treb-grid/src/types/grid_command.ts +3 -2
- package/treb-grid/src/types/grid_events.ts +12 -6
- package/treb-grid/src/types/tab_bar.ts +1 -2
- package/treb-parser/src/parser-types.ts +2 -1
- package/treb-parser/src/parser.ts +7 -5
- package/treb-utils/src/event_source.ts +1 -1
- package/treb-utils/src/serialize_html.ts +31 -6
- package/.eslintignore +0 -8
- package/.eslintrc.cjs +0 -168
- package/treb-grid/src/layout/rectangle_cache.ts +0 -86
- /package/{treb-grid/src/types → treb-data-model/src}/serialize_options.ts +0 -0
- /package/{treb-grid/src/types/grid_selection.ts → treb-data-model/src/sheet_selection.ts} +0 -0
|
@@ -25,49 +25,58 @@
|
|
|
25
25
|
/// <reference path="./content-types.d.ts" />
|
|
26
26
|
|
|
27
27
|
import type {
|
|
28
|
-
GridEvent,
|
|
29
|
-
SerializedModel, FreezePane, SerializedSheet,
|
|
28
|
+
GridEvent,
|
|
30
29
|
SheetChangeEvent, GridOptions,
|
|
31
|
-
|
|
32
|
-
AnnotationViewData,
|
|
33
|
-
AnnotationType,
|
|
30
|
+
CellEvent, FunctionDescriptor,
|
|
34
31
|
ExternalEditorConfig,
|
|
35
|
-
ConditionalFormatDuplicateValuesOptions,
|
|
36
|
-
ConditionalFormatDuplicateValues,
|
|
37
|
-
ConditionalFormatGradientOptions,
|
|
38
|
-
ConditionalFormat,
|
|
39
|
-
ConditionalFormatGradient,
|
|
40
|
-
ConditionalFormatExpression,
|
|
41
|
-
StandardGradient,
|
|
42
|
-
CondifionalFormatExpressionOptions,
|
|
43
|
-
ConditionalFormatCellMatchOptions,
|
|
44
|
-
ConditionalFormatCellMatch,
|
|
45
|
-
MacroFunction,
|
|
46
|
-
SerializedNamedExpression,
|
|
47
32
|
} from 'treb-grid';
|
|
48
33
|
|
|
34
|
+
import { DataModel, Sheet, StandardGradientsList } from 'treb-data-model';
|
|
35
|
+
import type {
|
|
36
|
+
SerializeOptions,
|
|
37
|
+
Annotation,
|
|
38
|
+
AnnotationViewData,
|
|
39
|
+
AnnotationType,
|
|
40
|
+
MacroFunction,
|
|
41
|
+
GridSelection,
|
|
42
|
+
ConnectedElementType,
|
|
43
|
+
SerializedModel,
|
|
44
|
+
SerializedSheet,
|
|
45
|
+
FreezePane,
|
|
46
|
+
ConditionalFormatDuplicateValuesOptions,
|
|
47
|
+
ConditionalFormatGradientOptions,
|
|
48
|
+
ConditionalFormat,
|
|
49
|
+
ConditionalFormatGradient,
|
|
50
|
+
ConditionalFormatExpression,
|
|
51
|
+
StandardGradient,
|
|
52
|
+
CondifionalFormatExpressionOptions,
|
|
53
|
+
ConditionalFormatCellMatchOptions,
|
|
54
|
+
ConditionalFormatCellMatch,
|
|
55
|
+
|
|
56
|
+
} from 'treb-data-model';
|
|
57
|
+
|
|
58
|
+
|
|
49
59
|
import {
|
|
50
|
-
|
|
51
|
-
StandardGradientsList,
|
|
60
|
+
Grid, BorderConstants, ErrorCode, UA,
|
|
52
61
|
} from 'treb-grid';
|
|
53
62
|
|
|
54
63
|
import {
|
|
55
64
|
Parser, DecimalMarkType,
|
|
56
65
|
ArgumentSeparatorType, QuotedSheetNameRegex } from 'treb-parser';
|
|
57
66
|
|
|
58
|
-
import { Calculator
|
|
67
|
+
import { Calculator } from 'treb-calculator';
|
|
59
68
|
|
|
60
69
|
import type {
|
|
61
70
|
ICellAddress,
|
|
62
71
|
EvaluateOptions,
|
|
63
72
|
IArea, CellValue, Point,
|
|
64
73
|
Complex, ExtendedUnion, IRectangle,
|
|
65
|
-
AddressReference, RangeReference, TableSortOptions, Table, TableTheme,
|
|
74
|
+
AddressReference, RangeReference, TableSortOptions, Table, TableTheme,
|
|
66
75
|
} from 'treb-base-types';
|
|
67
76
|
|
|
68
77
|
import {
|
|
69
78
|
IsArea, ThemeColorTable, ComplexToString, Rectangle, IsComplex, type CellStyle,
|
|
70
|
-
Localization, Style, type Color, ThemeColor2, IsCellAddress, Area, IsFlatData, IsFlatDataArray, Gradient,
|
|
79
|
+
Localization, Style, type Color, ThemeColor2, IsCellAddress, Area, IsFlatData, IsFlatDataArray, Gradient, DOMContext,
|
|
71
80
|
} from 'treb-base-types';
|
|
72
81
|
|
|
73
82
|
import { EventSource, ValidateURI } from 'treb-utils';
|
|
@@ -90,7 +99,6 @@ import { Chart, ChartFunctions } from 'treb-charts';
|
|
|
90
99
|
import type { SetRangeOptions } from 'treb-grid';
|
|
91
100
|
|
|
92
101
|
import type { StateLeafVertex } from 'treb-calculator';
|
|
93
|
-
import type { ConnectedElementType } from 'treb-grid';
|
|
94
102
|
|
|
95
103
|
|
|
96
104
|
// --- worker ------------------------------------------------------------------
|
|
@@ -496,7 +504,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
496
504
|
* parameter you can set when creating the spreadsheet.
|
|
497
505
|
*/
|
|
498
506
|
public get user_data(): USER_DATA_TYPE|undefined {
|
|
499
|
-
return this.grid.model.user_data;
|
|
507
|
+
return this.grid.model.user_data as USER_DATA_TYPE;
|
|
500
508
|
}
|
|
501
509
|
|
|
502
510
|
/**
|
|
@@ -693,7 +701,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
693
701
|
|
|
694
702
|
if (this.options.local_storage && !options.model ) {
|
|
695
703
|
|
|
696
|
-
window.addEventListener('visibilitychange',
|
|
704
|
+
window.addEventListener('visibilitychange', () => {
|
|
697
705
|
if (document.visibilityState === 'hidden') {
|
|
698
706
|
if (this.options.local_storage && this.dirty) {
|
|
699
707
|
this.SaveLocalStorage(this.options.local_storage);
|
|
@@ -784,7 +792,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
784
792
|
}
|
|
785
793
|
|
|
786
794
|
if (options.model) {
|
|
787
|
-
this.model = options.model.model;
|
|
795
|
+
this.model = options.model.model as DataModel;
|
|
788
796
|
this.calculator = options.model.calculator; // as CalcType;
|
|
789
797
|
this.DOM = options.model.DOM;
|
|
790
798
|
}
|
|
@@ -946,7 +954,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
946
954
|
|
|
947
955
|
case 'style':
|
|
948
956
|
this.DocumentChange();
|
|
949
|
-
this.UpdateDocumentStyles(
|
|
957
|
+
this.UpdateDocumentStyles();
|
|
950
958
|
this.UpdateSelectionStyle();
|
|
951
959
|
break;
|
|
952
960
|
|
|
@@ -1297,7 +1305,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
1297
1305
|
if (event.type === 'structure') {
|
|
1298
1306
|
this.grid.EnsureActiveSheet();
|
|
1299
1307
|
this.grid.UpdateLayout();
|
|
1300
|
-
(this.grid as any).tab_bar?.Update();
|
|
1308
|
+
// (this.grid as any).tab_bar?.Update();
|
|
1309
|
+
this.grid.UpdateTabBar();
|
|
1301
1310
|
}
|
|
1302
1311
|
});
|
|
1303
1312
|
|
|
@@ -1315,7 +1324,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
1315
1324
|
if (event.type === 'structure') {
|
|
1316
1325
|
view.grid.EnsureActiveSheet();
|
|
1317
1326
|
view.grid.UpdateLayout();
|
|
1318
|
-
(view.grid as any).tab_bar?.Update();
|
|
1327
|
+
// (view.grid as any).tab_bar?.Update();
|
|
1328
|
+
view.grid.UpdateTabBar();
|
|
1319
1329
|
}
|
|
1320
1330
|
});
|
|
1321
1331
|
|
|
@@ -2235,7 +2245,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2235
2245
|
const element = this.model.connected_elements.get(id);
|
|
2236
2246
|
if (element) {
|
|
2237
2247
|
element.formula = formula;
|
|
2238
|
-
|
|
2248
|
+
|
|
2249
|
+
const internal = (element.internal) as { vertex: StateLeafVertex, state: unknown };
|
|
2239
2250
|
|
|
2240
2251
|
if (internal?.state) {
|
|
2241
2252
|
internal.state = undefined;
|
|
@@ -2262,8 +2273,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2262
2273
|
|
|
2263
2274
|
// FIXME: merge w/ insert annotation?
|
|
2264
2275
|
|
|
2265
|
-
|
|
2266
|
-
|
|
2276
|
+
const r1c1 = options?.r1c1 || false;
|
|
2277
|
+
const argument_separator = options?.argument_separator || this.parser.argument_separator; // default to current
|
|
2267
2278
|
|
|
2268
2279
|
this.parser.Save();
|
|
2269
2280
|
this.parser.flags.r1c1 = r1c1;
|
|
@@ -2776,7 +2787,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2776
2787
|
}
|
|
2777
2788
|
|
|
2778
2789
|
if (!this.export_worker) {
|
|
2779
|
-
this.export_worker = await this.LoadWorker(
|
|
2790
|
+
this.export_worker = await this.LoadWorker();
|
|
2780
2791
|
}
|
|
2781
2792
|
|
|
2782
2793
|
return new Promise<Blob>((resolve, reject) => {
|
|
@@ -3295,7 +3306,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
3295
3306
|
}
|
|
3296
3307
|
|
|
3297
3308
|
if (text && filename) {
|
|
3298
|
-
const blob = new Blob([text
|
|
3309
|
+
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
|
|
3299
3310
|
this.SaveAs(blob, filename);
|
|
3300
3311
|
}
|
|
3301
3312
|
|
|
@@ -3927,37 +3938,6 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
3927
3938
|
|
|
3928
3939
|
return this.calculator.Unresolve(ref, this.grid.active_sheet, qualified, named);
|
|
3929
3940
|
|
|
3930
|
-
/*
|
|
3931
|
-
let range = '';
|
|
3932
|
-
const area = IsCellAddress(ref) ? new Area(ref) : new Area(ref.start, ref.end);
|
|
3933
|
-
|
|
3934
|
-
if (named) {
|
|
3935
|
-
const named_range = this.model.named_ranges.MatchSelection(area);
|
|
3936
|
-
if (named_range) {
|
|
3937
|
-
return named_range;
|
|
3938
|
-
}
|
|
3939
|
-
}
|
|
3940
|
-
|
|
3941
|
-
if (area.count > 1) {
|
|
3942
|
-
range = Area.CellAddressToLabel(area.start) + ':' + Area.CellAddressToLabel(area.end);
|
|
3943
|
-
}
|
|
3944
|
-
else {
|
|
3945
|
-
range = Area.CellAddressToLabel(area.start);
|
|
3946
|
-
}
|
|
3947
|
-
|
|
3948
|
-
if (!qualified) {
|
|
3949
|
-
return range;
|
|
3950
|
-
}
|
|
3951
|
-
|
|
3952
|
-
// is there a function to resolve sheet? actually, don't we know that
|
|
3953
|
-
// the active selection must be on the active sheet? (...)
|
|
3954
|
-
|
|
3955
|
-
const sheet_id = area.start.sheet_id || this.grid.active_sheet.id;
|
|
3956
|
-
const sheet_name = this.calculator.ResolveSheetName(sheet_id, true);
|
|
3957
|
-
|
|
3958
|
-
return sheet_name ? sheet_name + '!' + range : range;
|
|
3959
|
-
*/
|
|
3960
|
-
|
|
3961
3941
|
}
|
|
3962
3942
|
|
|
3963
3943
|
/**
|
|
@@ -4162,8 +4142,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4162
4142
|
|
|
4163
4143
|
/**
|
|
4164
4144
|
* Create a named range or named expression. A named range refers to an
|
|
4165
|
-
* address or range. A named expression can be
|
|
4166
|
-
*
|
|
4145
|
+
* address or range. A named expression can be any value or formula. To set
|
|
4146
|
+
* the value as a literal string, enclose the string in double-quotes (as
|
|
4147
|
+
* you would when using a string as a function argument).
|
|
4167
4148
|
*
|
|
4168
4149
|
* @param value range, value or expression
|
|
4169
4150
|
*
|
|
@@ -4176,7 +4157,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4176
4157
|
*
|
|
4177
4158
|
* @public
|
|
4178
4159
|
*/
|
|
4179
|
-
public DefineName(name: string, value: RangeReference|CellValue): void {
|
|
4160
|
+
public DefineName(name: string, value: RangeReference|CellValue, scope?: string|number, overwrite = false): void {
|
|
4180
4161
|
|
|
4181
4162
|
// how can we unify named ranges and named expressions?
|
|
4182
4163
|
//
|
|
@@ -4199,9 +4180,19 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4199
4180
|
throw new Error('invalid value (null or undefined)');
|
|
4200
4181
|
}
|
|
4201
4182
|
|
|
4183
|
+
if (typeof scope === 'string') {
|
|
4184
|
+
const id = this.model.sheets.ID(scope);
|
|
4185
|
+
if (typeof id === 'number') {
|
|
4186
|
+
scope = id;
|
|
4187
|
+
}
|
|
4188
|
+
else {
|
|
4189
|
+
throw new Error('invalid scope; use a sheet name or sheet id');
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4202
4193
|
if (typeof value === 'object') {
|
|
4203
4194
|
if (IsCellAddress(value) || IsArea(value)) {
|
|
4204
|
-
this.grid.SetName(name, this.model.ResolveArea(value, this.grid.active_sheet));
|
|
4195
|
+
this.grid.SetName(name, this.model.ResolveArea(value, this.grid.active_sheet), undefined, scope, overwrite);
|
|
4205
4196
|
return;
|
|
4206
4197
|
}
|
|
4207
4198
|
}
|
|
@@ -4218,45 +4209,17 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4218
4209
|
switch (parse_result.expression.type) {
|
|
4219
4210
|
case 'address':
|
|
4220
4211
|
case 'range':
|
|
4221
|
-
this.grid.SetName(name, this.model.ResolveArea(parse_result.expression, this.grid.active_sheet));
|
|
4212
|
+
this.grid.SetName(name, this.model.ResolveArea(parse_result.expression, this.grid.active_sheet), undefined, scope, overwrite);
|
|
4222
4213
|
return;
|
|
4223
4214
|
}
|
|
4224
|
-
this.grid.SetName(name, undefined, value);
|
|
4215
|
+
this.grid.SetName(name, undefined, value, scope, overwrite);
|
|
4225
4216
|
|
|
4226
4217
|
}
|
|
4227
4218
|
else {
|
|
4228
|
-
this.grid.SetName(name, undefined, value.toString());
|
|
4219
|
+
this.grid.SetName(name, undefined, value.toString(), scope, overwrite);
|
|
4229
4220
|
}
|
|
4230
4221
|
|
|
4231
|
-
|
|
4232
|
-
/*
|
|
4233
|
-
// API v1 OK
|
|
4234
|
-
|
|
4235
|
-
if (!range) {
|
|
4236
|
-
const selection = this.GetSelectionReference();
|
|
4237
|
-
if (!selection.empty) {
|
|
4238
|
-
range = selection.area;
|
|
4239
|
-
}
|
|
4240
|
-
else {
|
|
4241
|
-
throw new Error('invalid reference');
|
|
4242
|
-
}
|
|
4243
|
-
}
|
|
4244
|
-
|
|
4245
|
-
// NOTE: AC is handled internally
|
|
4246
|
-
|
|
4247
|
-
this.grid.SetName(name, this.model.ResolveArea(range, this.grid.active_sheet));
|
|
4248
|
-
*/
|
|
4249
|
-
}
|
|
4250
|
-
|
|
4251
|
-
/* *
|
|
4252
|
-
* define a named expression
|
|
4253
|
-
*
|
|
4254
|
-
* @internal
|
|
4255
|
-
* /
|
|
4256
|
-
public DefineNamedExpression(name: string, expression: string): void {
|
|
4257
|
-
this.grid.SetName(name, undefined, expression);
|
|
4258
4222
|
}
|
|
4259
|
-
*/
|
|
4260
4223
|
|
|
4261
4224
|
/**
|
|
4262
4225
|
* Set or remove a link in a cell.
|
|
@@ -4297,7 +4260,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4297
4260
|
|
|
4298
4261
|
let resolved: Area|undefined = undefined;
|
|
4299
4262
|
|
|
4300
|
-
if (
|
|
4263
|
+
if (range) {
|
|
4301
4264
|
resolved = this.model.ResolveArea(range, this.grid.active_sheet);
|
|
4302
4265
|
if (resolved.start.sheet_id) {
|
|
4303
4266
|
if (resolved.start.sheet_id !== this.grid.active_sheet.id) {
|
|
@@ -4511,58 +4474,14 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4511
4474
|
}
|
|
4512
4475
|
}
|
|
4513
4476
|
|
|
4514
|
-
|
|
4515
|
-
// that there's a sheet name in any address/range.
|
|
4516
|
-
|
|
4517
|
-
const named_expressions: SerializedNamedExpression[] = [];
|
|
4518
|
-
if (this.model.named_expressions) {
|
|
4519
|
-
|
|
4520
|
-
for (const [name, expr] of this.model.named_expressions) {
|
|
4521
|
-
this.parser.Walk(expr, unit => {
|
|
4522
|
-
if (unit.type === 'address' || unit.type === 'range') {
|
|
4523
|
-
const test = unit.type === 'range' ? unit.start : unit;
|
|
4524
|
-
|
|
4525
|
-
test.absolute_column = test.absolute_row = true;
|
|
4526
|
-
|
|
4527
|
-
if (!test.sheet) {
|
|
4528
|
-
if (test.sheet_id) {
|
|
4529
|
-
const sheet = this.model.sheets.Find(test.sheet_id);
|
|
4530
|
-
if (sheet) {
|
|
4531
|
-
test.sheet = sheet.name;
|
|
4532
|
-
}
|
|
4533
|
-
}
|
|
4534
|
-
if (!test.sheet) {
|
|
4535
|
-
test.sheet = active_sheet.name;
|
|
4536
|
-
}
|
|
4537
|
-
}
|
|
4538
|
-
|
|
4539
|
-
if (unit.type === 'range') {
|
|
4540
|
-
unit.end.absolute_column = unit.end.absolute_row = true;
|
|
4541
|
-
}
|
|
4542
|
-
|
|
4543
|
-
return false;
|
|
4544
|
-
}
|
|
4545
|
-
else if (unit.type === 'call' && options.export_functions) {
|
|
4546
|
-
// ...
|
|
4547
|
-
}
|
|
4548
|
-
return true;
|
|
4549
|
-
});
|
|
4550
|
-
const rendered = this.parser.Render(expr, { missing: '' });
|
|
4551
|
-
named_expressions.push({
|
|
4552
|
-
name, expression: rendered
|
|
4553
|
-
});
|
|
4554
|
-
}
|
|
4555
|
-
}
|
|
4477
|
+
const named = this.model.SerializeNames(active_sheet);
|
|
4556
4478
|
|
|
4557
4479
|
return {
|
|
4558
4480
|
sheet_data,
|
|
4559
4481
|
active_sheet: active_sheet.id,
|
|
4560
|
-
|
|
4561
|
-
this.model.named_ranges.Serialize() :
|
|
4562
|
-
undefined,
|
|
4482
|
+
named: named.length ? named : undefined,
|
|
4563
4483
|
macro_functions,
|
|
4564
4484
|
tables,
|
|
4565
|
-
named_expressions: named_expressions.length ? named_expressions : undefined,
|
|
4566
4485
|
};
|
|
4567
4486
|
|
|
4568
4487
|
}
|
|
@@ -4677,7 +4596,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4677
4596
|
}
|
|
4678
4597
|
|
|
4679
4598
|
if (!this.export_worker) {
|
|
4680
|
-
this.export_worker = await this.LoadWorker(
|
|
4599
|
+
this.export_worker = await this.LoadWorker();
|
|
4681
4600
|
}
|
|
4682
4601
|
|
|
4683
4602
|
// this originally returned a Promise<Blob> but the actual
|
|
@@ -4760,11 +4679,11 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4760
4679
|
|
|
4761
4680
|
protected HandleCellEvent(event: CellEvent): void {
|
|
4762
4681
|
|
|
4763
|
-
const type = event.data?.type;
|
|
4764
|
-
if (type === 'hyperlink') {
|
|
4682
|
+
// const type = event.data?.type;
|
|
4683
|
+
if (event.data?.type === 'hyperlink') {
|
|
4765
4684
|
|
|
4766
4685
|
const hyperlink_error = 'hyperlink invalid target';
|
|
4767
|
-
const data = event.data.
|
|
4686
|
+
const data = event.data.reference || '';
|
|
4768
4687
|
|
|
4769
4688
|
if (typeof data === 'string') {
|
|
4770
4689
|
|
|
@@ -4884,24 +4803,6 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4884
4803
|
}
|
|
4885
4804
|
}
|
|
4886
4805
|
|
|
4887
|
-
/* *
|
|
4888
|
-
* replacement for fetch
|
|
4889
|
-
* FIXME: move to utils or other lib
|
|
4890
|
-
* FIXME: we don't need to do this for ES6, presumably...
|
|
4891
|
-
* can this move into the legacy/modern code? or is there a polyfill? (...)
|
|
4892
|
-
* /
|
|
4893
|
-
protected async Fetch(uri: string): Promise<string> {
|
|
4894
|
-
return new Promise<string>((resolve, reject) => {
|
|
4895
|
-
const xhr = new XMLHttpRequest();
|
|
4896
|
-
xhr.onload = () => resolve(xhr.response);
|
|
4897
|
-
xhr.onerror = () => reject('load error');
|
|
4898
|
-
xhr.ontimeout = () => reject('timeout');
|
|
4899
|
-
xhr.open('GET', uri);
|
|
4900
|
-
xhr.send();
|
|
4901
|
-
});
|
|
4902
|
-
}
|
|
4903
|
-
*/
|
|
4904
|
-
|
|
4905
4806
|
/**
|
|
4906
4807
|
* I'm restructuring the select file routine to simplify, in service
|
|
4907
4808
|
* of figuring out what's going wrong in OSX/Chrome. the current routine
|
|
@@ -5013,7 +4914,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5013
4914
|
// probably because there are some async calls; hence the
|
|
5014
4915
|
// src attribute is set before it's inflated.
|
|
5015
4916
|
|
|
5016
|
-
const annotation =
|
|
4917
|
+
// const annotation =
|
|
4918
|
+
this.grid.CreateAnnotation({
|
|
5017
4919
|
type: 'image',
|
|
5018
4920
|
formula: '',
|
|
5019
4921
|
data: {
|
|
@@ -5147,10 +5049,12 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5147
5049
|
protected UpdateAnnotations(): void {
|
|
5148
5050
|
|
|
5149
5051
|
for (const annotation of this.grid.active_sheet.annotations) {
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5052
|
+
|
|
5053
|
+
const vertex_data = annotation.temp as { vertex?: StateLeafVertex, state?: number };
|
|
5054
|
+
|
|
5055
|
+
if (vertex_data.vertex) {
|
|
5056
|
+
if (vertex_data.vertex.state_id !== vertex_data.state) {
|
|
5057
|
+
vertex_data.state = vertex_data.vertex.state_id;
|
|
5154
5058
|
|
|
5155
5059
|
// set all views dirty in this case
|
|
5156
5060
|
for (const view of annotation.view) {
|
|
@@ -5190,7 +5094,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5190
5094
|
|
|
5191
5095
|
protected UpdateConnectedElements() {
|
|
5192
5096
|
for (const element of this.model.connected_elements.values()) {
|
|
5193
|
-
const internal = (element.internal) as { vertex: StateLeafVertex, state:
|
|
5097
|
+
const internal = (element.internal) as { vertex: StateLeafVertex, state: unknown };
|
|
5194
5098
|
if (internal?.vertex && internal.vertex.state_id !== internal.state ) {
|
|
5195
5099
|
internal.state = internal.vertex.state_id;
|
|
5196
5100
|
const fn = element.update;
|
|
@@ -5666,7 +5570,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5666
5570
|
|
|
5667
5571
|
}
|
|
5668
5572
|
|
|
5669
|
-
protected UpdateDocumentStyles(
|
|
5573
|
+
protected UpdateDocumentStyles(): void {
|
|
5670
5574
|
|
|
5671
5575
|
const number_format_map: Record<string, number> = {};
|
|
5672
5576
|
const color_map: Record<string, number> = {};
|
|
@@ -5941,6 +5845,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5941
5845
|
|
|
5942
5846
|
this.grid.UpdateSheets(sheets, undefined, override_sheet || data.active_sheet);
|
|
5943
5847
|
|
|
5848
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5944
5849
|
for (const [name, table] of this.model.tables.entries()) {
|
|
5945
5850
|
if (table.area.start.sheet_id) {
|
|
5946
5851
|
const sheet = model.sheets.Find(table.area.start.sheet_id);
|
|
@@ -5957,52 +5862,56 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5957
5862
|
|
|
5958
5863
|
model.document_name = data.name;
|
|
5959
5864
|
model.user_data = data.user_data;
|
|
5960
|
-
model.named_ranges.Reset();
|
|
5961
5865
|
|
|
5962
|
-
//
|
|
5963
|
-
|
|
5866
|
+
// resets for both named ranges and named expressions, until we consolidate
|
|
5867
|
+
model.named.Reset();
|
|
5964
5868
|
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
named_range_data = sheets[0].named_ranges;
|
|
5869
|
+
if (data.named) {
|
|
5870
|
+
this.model.UnserializeNames(data.named, this.grid.active_sheet);
|
|
5968
5871
|
}
|
|
5872
|
+
else {
|
|
5969
5873
|
|
|
5970
|
-
|
|
5971
|
-
model.named_ranges.Deserialize(named_range_data);
|
|
5972
|
-
}
|
|
5874
|
+
// console.info("using old-style name import")
|
|
5973
5875
|
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5876
|
+
//------------------------------------------------------------------------
|
|
5877
|
+
//
|
|
5878
|
+
// old style handling of named ranges and expressions. we'll leave
|
|
5879
|
+
// this here for the time being. [update: rewriting slightly to share
|
|
5880
|
+
// some code]
|
|
5881
|
+
//
|
|
5882
|
+
//------------------------------------------------------------------------
|
|
5883
|
+
|
|
5884
|
+
// old models have it in sheet, new models have at top level -- we can
|
|
5885
|
+
// support old models, but write in the new syntax
|
|
5886
|
+
|
|
5887
|
+
let named_range_data = data.named_ranges;
|
|
5888
|
+
if (!named_range_data && sheets[0] && sheets[0].named_ranges) {
|
|
5889
|
+
named_range_data = sheets[0].named_ranges;
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5892
|
+
if (named_range_data) {
|
|
5893
|
+
for (const [name, value] of Object.entries(named_range_data)) {
|
|
5894
|
+
model.named.SetNamedRange(name, new Area(value.start, value.end));
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5897
|
+
|
|
5898
|
+
// when importing named expressions, we have to make sure there's a
|
|
5899
|
+
// sheet ID attached to each range/address. hopefully we have serialized
|
|
5900
|
+
// it with a sheet name so we can look up.
|
|
5901
|
+
|
|
5902
|
+
// model.named_expressions.clear(); // already reset (composite w/ named ranges)
|
|
5903
|
+
|
|
5904
|
+
if (data.named_expressions) {
|
|
5905
|
+
for (const pair of data.named_expressions) {
|
|
5906
|
+
|
|
5907
|
+
this.model.UnserializeNames([{
|
|
5908
|
+
name: pair.name,
|
|
5909
|
+
expression: pair.expression,
|
|
5910
|
+
}], this.grid.active_sheet);
|
|
5977
5911
|
|
|
5978
|
-
model.named_expressions.clear(); // = {};
|
|
5979
|
-
if (data.named_expressions) {
|
|
5980
|
-
for (const pair of data.named_expressions) {
|
|
5981
|
-
const parse_result = this.parser.Parse('' || pair.expression);
|
|
5982
|
-
if (parse_result.valid && parse_result.expression) {
|
|
5983
|
-
this.parser.Walk(parse_result.expression, unit => {
|
|
5984
|
-
if (unit.type === 'address' || unit.type === 'range') {
|
|
5985
|
-
if (unit.type === 'range') {
|
|
5986
|
-
unit = unit.start;
|
|
5987
|
-
}
|
|
5988
|
-
if (!unit.sheet_id) {
|
|
5989
|
-
if (unit.sheet) {
|
|
5990
|
-
const sheet = this.model.sheets.Find(unit.sheet);
|
|
5991
|
-
if (sheet) {
|
|
5992
|
-
unit.sheet_id = sheet.id;
|
|
5993
|
-
}
|
|
5994
|
-
}
|
|
5995
|
-
}
|
|
5996
|
-
if (!unit.sheet_id) {
|
|
5997
|
-
unit.sheet_id = this.grid.active_sheet.id;
|
|
5998
|
-
}
|
|
5999
|
-
return false; // don't continue in ranges
|
|
6000
|
-
}
|
|
6001
|
-
return true;
|
|
6002
|
-
});
|
|
6003
|
-
model.named_expressions.set(pair.name.toUpperCase(), parse_result.expression);
|
|
6004
5912
|
}
|
|
6005
5913
|
}
|
|
5914
|
+
|
|
6006
5915
|
}
|
|
6007
5916
|
|
|
6008
5917
|
model.macro_functions.clear();
|
|
@@ -6028,7 +5937,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
6028
5937
|
* load worker. optionally uses an ambient path as prefix; intended for
|
|
6029
5938
|
* loading in different directories (or different hosts?)
|
|
6030
5939
|
*/
|
|
6031
|
-
protected async LoadWorker(
|
|
5940
|
+
protected async LoadWorker(): Promise<Worker> {
|
|
6032
5941
|
|
|
6033
5942
|
// this is inlined to ensure the code will be tree-shaken properly
|
|
6034
5943
|
// (we're trying to force it to remove the imported worker script)
|
|
@@ -6042,7 +5951,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
6042
5951
|
if (export_worker_script) {
|
|
6043
5952
|
try {
|
|
6044
5953
|
const worker = new Worker(
|
|
6045
|
-
URL.createObjectURL(new Blob([(export_worker_script as
|
|
5954
|
+
URL.createObjectURL(new Blob([(export_worker_script as {default: string}).default], { type: 'application/javascript' })));
|
|
6046
5955
|
return worker;
|
|
6047
5956
|
}
|
|
6048
5957
|
catch (err) {
|
|
@@ -6058,60 +5967,6 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
6058
5967
|
|
|
6059
5968
|
throw new Error('creating worker failed');
|
|
6060
5969
|
|
|
6061
|
-
/*
|
|
6062
|
-
|
|
6063
|
-
if (!EmbeddedSpreadsheet.treb_base_path) {
|
|
6064
|
-
console.warn('worker path is not set. it you are loading TREB in an ESM module, please either '
|
|
6065
|
-
+ 'include the script in a document <script/> tag, or call the method TREB.SetScriptPath() to '
|
|
6066
|
-
+ 'set the load path for workers (this should be the path to TREB script files).');
|
|
6067
|
-
throw new Error('worker path not set');
|
|
6068
|
-
}
|
|
6069
|
-
|
|
6070
|
-
if (!/\.js$/.test(name)) name += ('-' + process.env.BUILD_VERSION + '.js');
|
|
6071
|
-
|
|
6072
|
-
let worker: Worker;
|
|
6073
|
-
let treb_path = EmbeddedSpreadsheet.treb_base_path;
|
|
6074
|
-
|
|
6075
|
-
if (treb_path) {
|
|
6076
|
-
if (!/\/$/.test(treb_path)) treb_path += '/';
|
|
6077
|
-
name = treb_path + name;
|
|
6078
|
-
}
|
|
6079
|
-
|
|
6080
|
-
// for remote workers, fetch and construct as blob. for local
|
|
6081
|
-
// workers we can just create.
|
|
6082
|
-
|
|
6083
|
-
// actually we're now getting a fully-qualified URL, so it will
|
|
6084
|
-
// always have a network prefix (or a file prefix)
|
|
6085
|
-
|
|
6086
|
-
// FIXME: testing... in particular URL.createObjectURL and new Blob
|
|
6087
|
-
|
|
6088
|
-
if (/^(http:|https:|\/\/)/.test(name)) {
|
|
6089
|
-
const response = await fetch(name);
|
|
6090
|
-
|
|
6091
|
-
if (!response.ok) {
|
|
6092
|
-
throw new Error('Error loading worker script');
|
|
6093
|
-
}
|
|
6094
|
-
|
|
6095
|
-
const script = await response.text();
|
|
6096
|
-
|
|
6097
|
-
// const script = await this.Fetch(name);
|
|
6098
|
-
worker = new Worker(URL.createObjectURL(new Blob([script], { type: 'application/javascript' })));
|
|
6099
|
-
}
|
|
6100
|
-
else if (/^file:/.test(name)) {
|
|
6101
|
-
throw new Error('invalid URI');
|
|
6102
|
-
}
|
|
6103
|
-
else {
|
|
6104
|
-
|
|
6105
|
-
// this was intended for relative URIs but now it is applied
|
|
6106
|
-
// to file:// URIs, which won't work anyway (in chrome, at least)
|
|
6107
|
-
|
|
6108
|
-
worker = new Worker(name);
|
|
6109
|
-
|
|
6110
|
-
}
|
|
6111
|
-
|
|
6112
|
-
return worker;
|
|
6113
|
-
*/
|
|
6114
|
-
|
|
6115
5970
|
}
|
|
6116
5971
|
|
|
6117
5972
|
/**
|