@trebco/treb 28.15.0 → 28.17.4
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/api-generator/api-generator.ts +5 -1
- package/dist/treb-spreadsheet-light.mjs +10 -10
- package/dist/treb-spreadsheet.mjs +15 -15
- package/dist/treb.d.ts +6 -1
- package/package.json +1 -1
- package/treb-base-types/src/area.ts +80 -1
- package/treb-base-types/src/cells.ts +187 -41
- package/treb-calculator/src/calculator.ts +13 -1
- package/treb-calculator/src/functions/base-functions.ts +71 -0
- package/treb-calculator/src/utilities.ts +37 -24
- package/treb-embed/markup/toolbar.html +5 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +5 -2
- package/treb-embed/src/embedded-spreadsheet.ts +46 -19
- package/treb-embed/src/options.ts +5 -0
- package/treb-embed/src/toolbar-message.ts +5 -0
- package/treb-embed/style/toolbar.scss +3 -0
- package/treb-embed/style/treb-icons.scss +6 -0
- package/treb-export/src/import2.ts +5 -16
- package/treb-export/src/workbook-style2.ts +15 -27
- package/treb-grid/src/render/tile_renderer.ts +37 -13
- package/treb-grid/src/types/grid.ts +49 -3
- package/treb-grid/src/types/grid_base.ts +156 -8
- package/treb-grid/src/types/grid_command.ts +8 -0
- package/treb-grid/src/types/sheet.ts +127 -7
|
@@ -1846,6 +1846,18 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
1846
1846
|
});
|
|
1847
1847
|
break;
|
|
1848
1848
|
|
|
1849
|
+
case 'indent':
|
|
1850
|
+
case 'outdent':
|
|
1851
|
+
|
|
1852
|
+
// hmmm. we should actually adjust selection cell-by-cell so
|
|
1853
|
+
// all entries get +1/-1 from their current level. we don't
|
|
1854
|
+
// want to normalize here. this is unusual.
|
|
1855
|
+
|
|
1856
|
+
// let's make a method here in case we want to use this again
|
|
1857
|
+
|
|
1858
|
+
this.grid.Indent(undefined, (event.command === 'indent') ? 1 : -1);
|
|
1859
|
+
break;
|
|
1860
|
+
|
|
1849
1861
|
default:
|
|
1850
1862
|
console.info('unhandled', event.command);
|
|
1851
1863
|
break;
|
|
@@ -2238,11 +2250,15 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2238
2250
|
}
|
|
2239
2251
|
|
|
2240
2252
|
/**
|
|
2253
|
+
* this is a generic version that takes a callback, so we can use
|
|
2254
|
+
* separately from charts. however (atm) we're using leaf vertices that
|
|
2255
|
+
* don't actually calculate, they just indicate the dirty state. so we
|
|
2256
|
+
* won't have access to the result of a calculation in the callback.
|
|
2257
|
+
*
|
|
2241
2258
|
* @internal
|
|
2242
2259
|
*
|
|
2243
|
-
* @returns an id that can be used to manage the reference
|
|
2244
2260
|
*/
|
|
2245
|
-
public
|
|
2261
|
+
public CreateConnectedFormula(formula: string, callback?: (instance: ConnectedElementType) => void, options: EvaluateOptions = {}): number {
|
|
2246
2262
|
|
|
2247
2263
|
// FIXME: merge w/ insert annotation?
|
|
2248
2264
|
|
|
@@ -2254,15 +2270,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2254
2270
|
|
|
2255
2271
|
if (argument_separator === ',') {
|
|
2256
2272
|
this.parser.SetLocaleSettings(DecimalMarkType.Period);
|
|
2257
|
-
|
|
2258
|
-
// this.parser.argument_separator = ArgumentSeparatorType.Comma;
|
|
2259
|
-
// this.parser.decimal_mark = DecimalMarkType.Period;
|
|
2260
2273
|
}
|
|
2261
2274
|
else {
|
|
2262
2275
|
this.parser.SetLocaleSettings(DecimalMarkType.Comma);
|
|
2263
|
-
|
|
2264
|
-
// this.parser.argument_separator = ArgumentSeparatorType.Semicolon;
|
|
2265
|
-
// this.parser.decimal_mark = DecimalMarkType.Comma;
|
|
2266
2276
|
}
|
|
2267
2277
|
|
|
2268
2278
|
const result = this.parser.Parse(formula);
|
|
@@ -2274,19 +2284,41 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2274
2284
|
}
|
|
2275
2285
|
else {
|
|
2276
2286
|
console.warn("invalid formula", result.error);
|
|
2287
|
+
throw new Error(`invalid formula`);
|
|
2277
2288
|
}
|
|
2278
2289
|
|
|
2279
|
-
const chart = this.CreateChart();
|
|
2280
|
-
chart.Initialize(target);
|
|
2281
|
-
|
|
2282
2290
|
const id = this.model.AddConnectedElement({
|
|
2291
|
+
|
|
2283
2292
|
formula,
|
|
2284
2293
|
|
|
2285
2294
|
// this is circular, but I want to leave `this` bound to the sheet
|
|
2286
2295
|
// instance in case we need it -- so what's a better approach? pass
|
|
2287
2296
|
// in the formula explicitly, and update if we need to make changes?
|
|
2288
2297
|
|
|
2289
|
-
update: (instance: ConnectedElementType) => {
|
|
2298
|
+
update: callback ? (instance: ConnectedElementType) => {
|
|
2299
|
+
callback.call(0, instance);
|
|
2300
|
+
} : undefined,
|
|
2301
|
+
|
|
2302
|
+
});
|
|
2303
|
+
|
|
2304
|
+
this.calculator.UpdateConnectedElements(this.grid.active_sheet);
|
|
2305
|
+
this.UpdateConnectedElements();
|
|
2306
|
+
|
|
2307
|
+
return id;
|
|
2308
|
+
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* @internal
|
|
2313
|
+
*
|
|
2314
|
+
* @returns an id that can be used to manage the reference
|
|
2315
|
+
*/
|
|
2316
|
+
public CreateConnectedChart(formula: string, target: HTMLElement, options: EvaluateOptions): number {
|
|
2317
|
+
|
|
2318
|
+
const chart = this.CreateChart();
|
|
2319
|
+
chart.Initialize(target);
|
|
2320
|
+
|
|
2321
|
+
const callback = (instance: ConnectedElementType) => {
|
|
2290
2322
|
|
|
2291
2323
|
const parse_result = this.parser.Parse(instance.formula);
|
|
2292
2324
|
|
|
@@ -2310,14 +2342,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
2310
2342
|
|
|
2311
2343
|
chart.Update();
|
|
2312
2344
|
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
});
|
|
2316
|
-
|
|
2317
|
-
this.calculator.UpdateConnectedElements(this.grid.active_sheet);
|
|
2318
|
-
this.UpdateConnectedElements();
|
|
2345
|
+
};
|
|
2319
2346
|
|
|
2320
|
-
return
|
|
2347
|
+
return this.CreateConnectedFormula(formula, callback, options);
|
|
2321
2348
|
|
|
2322
2349
|
}
|
|
2323
2350
|
|
|
@@ -80,6 +80,10 @@ export interface RevertIndicatorMessage {
|
|
|
80
80
|
command: 'revert-indicator';
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
export interface IndentMessage {
|
|
84
|
+
command: 'indent'|'outdent';
|
|
85
|
+
}
|
|
86
|
+
|
|
83
87
|
export type ToolbarMessage
|
|
84
88
|
= SetColorToolbarMessage
|
|
85
89
|
| CommentToolbarMessage
|
|
@@ -96,6 +100,7 @@ export type ToolbarMessage
|
|
|
96
100
|
| TableToolbarMessage
|
|
97
101
|
| CommandToolbarMessage
|
|
98
102
|
| StyleToolbarMessage
|
|
103
|
+
| IndentMessage
|
|
99
104
|
| NumberFormatToolbarMessage
|
|
100
105
|
| FontScaleToolbarMessage
|
|
101
106
|
;
|
|
@@ -264,6 +264,9 @@ $swatch-size: 18px;
|
|
|
264
264
|
[data-command=justify-right] { --icon: var(--icon-text-align-right); }
|
|
265
265
|
[data-command=justify-center] { --icon: var(--icon-text-align-center); }
|
|
266
266
|
|
|
267
|
+
[data-command=indent] { --icon: var(--icon-text-indent); }
|
|
268
|
+
[data-command=outdent] { --icon: var(--icon-text-outdent); }
|
|
269
|
+
|
|
267
270
|
[data-command=align-top] { --icon: var(--icon-text-align-top); }
|
|
268
271
|
[data-command=align-middle] { --icon: var(--icon-text-align-middle); }
|
|
269
272
|
[data-command=align-bottom] { --icon: var(--icon-text-align-bottom); }
|
|
@@ -38,6 +38,12 @@
|
|
|
38
38
|
|
|
39
39
|
// --- toolbar ---------------------------------------------------------------
|
|
40
40
|
|
|
41
|
+
/* source: bootstrap-icons-1.8.3/text-indent-left.svg */
|
|
42
|
+
--icon-text-indent: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-indent-left" viewBox="0 0 16 16"><path d="M2 3.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5m.646 2.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L4.293 8 2.646 6.354a.5.5 0 0 1 0-.708M7 6.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5m0 3a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5m-5 3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5"/></svg>');
|
|
43
|
+
|
|
44
|
+
/* source: bootstrap-icons-1.8.3/text-indent-right.svg */
|
|
45
|
+
--icon-text-outdent: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-indent-right" viewBox="0 0 16 16"><path d="M2 3.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5m10.646 2.146a.5.5 0 0 1 .708.708L11.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708zM2 6.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5m0 3a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5m0 3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5"/></svg>');
|
|
46
|
+
|
|
41
47
|
/* source: bootstrap-icons-1.8.3/text-left.svg */
|
|
42
48
|
--icon-text-align-left: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' viewBox='0 0 16 16'> <path fill-rule='evenodd' d='M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z'/> </svg>");
|
|
43
49
|
|
|
@@ -93,7 +93,7 @@ export class Importer {
|
|
|
93
93
|
ref?: string;
|
|
94
94
|
},
|
|
95
95
|
};
|
|
96
|
-
},
|
|
96
|
+
},
|
|
97
97
|
shared_formulae: SharedFormulaMap,
|
|
98
98
|
arrays: RangeType[],
|
|
99
99
|
merges: RangeType[],
|
|
@@ -117,11 +117,9 @@ export class Importer {
|
|
|
117
117
|
// console.info(element);
|
|
118
118
|
|
|
119
119
|
let value: undefined | number | boolean | string;
|
|
120
|
-
// let type: ValueType = ValueType.undefined;
|
|
121
120
|
let type: SerializedValueType = 'undefined';
|
|
122
121
|
|
|
123
122
|
let calculated_value: undefined | number | boolean | string;
|
|
124
|
-
// let calculated_type: ValueType = ValueType.undefined;
|
|
125
123
|
let calculated_type: SerializedValueType = 'undefined';
|
|
126
124
|
|
|
127
125
|
// QUESTIONS:
|
|
@@ -397,7 +395,6 @@ export class Importer {
|
|
|
397
395
|
if (rule.formula) {
|
|
398
396
|
|
|
399
397
|
if (typeof rule.formula !== 'string') {
|
|
400
|
-
console.info("conditional expression", {rule});
|
|
401
398
|
if (rule.formula.t$) {
|
|
402
399
|
|
|
403
400
|
// the only case (to date) we've seen here is that the attribute
|
|
@@ -407,6 +404,10 @@ export class Importer {
|
|
|
407
404
|
rule.formula = rule.formula.t$;
|
|
408
405
|
|
|
409
406
|
}
|
|
407
|
+
else {
|
|
408
|
+
console.info("unexpected conditional expression", {rule});
|
|
409
|
+
|
|
410
|
+
}
|
|
410
411
|
}
|
|
411
412
|
|
|
412
413
|
let style = {};
|
|
@@ -536,18 +537,6 @@ export class Importer {
|
|
|
536
537
|
}
|
|
537
538
|
}
|
|
538
539
|
|
|
539
|
-
/*
|
|
540
|
-
const area = sheet.TranslateAddress(element.a$.sqref);
|
|
541
|
-
if (element.cfRule) {
|
|
542
|
-
const rules = Array.isArray(element.cfRule) ? element.cfRule : [element.cfRule];
|
|
543
|
-
for (const rule of rules) {
|
|
544
|
-
const format = this.ParseConditionalFormat(area, rule);
|
|
545
|
-
if (format) {
|
|
546
|
-
conditional_formats.push(format);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
*/
|
|
551
540
|
}
|
|
552
541
|
}
|
|
553
542
|
|
|
@@ -669,7 +669,7 @@ export class StyleCache {
|
|
|
669
669
|
|
|
670
670
|
// indent
|
|
671
671
|
|
|
672
|
-
props.indent = xf.indent;
|
|
672
|
+
props.indent = (typeof xf.indent === 'string') ? Number(xf.indent) : xf.indent;
|
|
673
673
|
|
|
674
674
|
// wrap
|
|
675
675
|
|
|
@@ -722,6 +722,19 @@ export class StyleCache {
|
|
|
722
722
|
|
|
723
723
|
/** map all cell xfs to styles; retain order */
|
|
724
724
|
public CellXfToStyles(): CellStyle[] {
|
|
725
|
+
|
|
726
|
+
/*
|
|
727
|
+
const mapped = this.cell_xfs.map((xf, index) => {
|
|
728
|
+
const style = this.CellXfToStyle(xf);
|
|
729
|
+
if (style.font_size?.value && style.font_size.value > 200) {
|
|
730
|
+
console.info({index, fs: JSON.stringify(style.font_size), style, xf});
|
|
731
|
+
console.info(this);
|
|
732
|
+
}
|
|
733
|
+
return style;
|
|
734
|
+
});
|
|
735
|
+
return mapped;
|
|
736
|
+
*/
|
|
737
|
+
|
|
725
738
|
return this.cell_xfs.map((xf) => this.CellXfToStyle(xf));
|
|
726
739
|
}
|
|
727
740
|
|
|
@@ -1174,40 +1187,14 @@ export class StyleCache {
|
|
|
1174
1187
|
|
|
1175
1188
|
|
|
1176
1189
|
this.borders = composite.map(element => {
|
|
1177
|
-
|
|
1178
1190
|
const border: BorderStyle = JSON.parse(JSON.stringify(default_border));
|
|
1179
1191
|
|
|
1180
|
-
/*
|
|
1181
|
-
// we're relying on these being empty strings -> falsy, not a good look
|
|
1182
|
-
|
|
1183
|
-
if (element.left) {
|
|
1184
|
-
// border.left.style = element.left.a$.style;
|
|
1185
|
-
// border.left.color = Number(element.left.color?.a$?.indexed);
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
if (element.right) {
|
|
1189
|
-
// border.right.style = element.right.a$.style;
|
|
1190
|
-
// border.right.color = Number(element.right.color?.a$?.indexed);
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
if (element.top) {
|
|
1194
|
-
// border.top.style = element.top.a$.style;
|
|
1195
|
-
// border.top.color = Number(element.top.color?.a$?.indexed);
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
if (element.bottom) {
|
|
1199
|
-
// border.bottom.style = element.bottom.a$.style;
|
|
1200
|
-
// border.bottom.color = Number(element.bottom.color?.a$?.indexed);
|
|
1201
|
-
}
|
|
1202
|
-
*/
|
|
1203
|
-
|
|
1204
1192
|
ElementToBorderEdge(element.left, border.left);
|
|
1205
1193
|
ElementToBorderEdge(element.right, border.right);
|
|
1206
1194
|
ElementToBorderEdge(element.top, border.top);
|
|
1207
1195
|
ElementToBorderEdge(element.bottom, border.bottom);
|
|
1208
1196
|
|
|
1209
1197
|
return border;
|
|
1210
|
-
|
|
1211
1198
|
});
|
|
1212
1199
|
|
|
1213
1200
|
// ---
|
|
@@ -1313,6 +1300,7 @@ export class StyleCache {
|
|
|
1313
1300
|
if (element.color.a$?.rgb) {
|
|
1314
1301
|
font.color_argb = element.color.a$.rgb;
|
|
1315
1302
|
}
|
|
1303
|
+
|
|
1316
1304
|
}
|
|
1317
1305
|
|
|
1318
1306
|
return font;
|
|
@@ -23,7 +23,8 @@ import type { ICellAddress,
|
|
|
23
23
|
PreparedText, RenderTextPart,
|
|
24
24
|
Cell, Size,
|
|
25
25
|
CellStyle,
|
|
26
|
-
Theme
|
|
26
|
+
Theme,
|
|
27
|
+
HorizontalAlign} from 'treb-base-types';
|
|
27
28
|
import { TextPartFlag, Style, ValueType, Area, Rectangle, ThemeColor, ThemeColor2 } from 'treb-base-types';
|
|
28
29
|
|
|
29
30
|
import type { Tile } from '../types/tile';
|
|
@@ -146,12 +147,22 @@ export class TileRenderer {
|
|
|
146
147
|
// flush all, mark dirty and drop areas.
|
|
147
148
|
|
|
148
149
|
const cells = this.view.active_sheet.cells;
|
|
150
|
+
|
|
151
|
+
for (const cell of cells.Iterate()) {
|
|
152
|
+
if (cell.renderer_data?.overflowed) {
|
|
153
|
+
cell.renderer_data = undefined;
|
|
154
|
+
cell.render_clean[this.view.view_index] = false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/*
|
|
149
159
|
cells.IterateAll(cell => {
|
|
150
160
|
if (cell.renderer_data?.overflowed) {
|
|
151
161
|
cell.renderer_data = undefined;
|
|
152
162
|
cell.render_clean[this.view.view_index] = false;
|
|
153
163
|
}
|
|
154
164
|
});
|
|
165
|
+
*/
|
|
155
166
|
|
|
156
167
|
for (const overflow_area of this.overflow_areas) {
|
|
157
168
|
overflow_area.tile.dirty = true;
|
|
@@ -727,10 +738,22 @@ export class TileRenderer {
|
|
|
727
738
|
// precalculate indent as string so we can use layout
|
|
728
739
|
|
|
729
740
|
let indent = '';
|
|
741
|
+
let align: HorizontalAlign|undefined;
|
|
742
|
+
|
|
730
743
|
if (style.indent) {
|
|
744
|
+
|
|
731
745
|
for (let i = 0; i < style.indent; i++) {
|
|
732
746
|
indent += DEFAULT_INDENT;
|
|
733
747
|
}
|
|
748
|
+
|
|
749
|
+
align = style.horizontal_align;
|
|
750
|
+
|
|
751
|
+
// default might be left or right based on type
|
|
752
|
+
|
|
753
|
+
if (!align) {
|
|
754
|
+
align = (cell.type === ValueType.number || cell.calculated_type === ValueType.number) ? 'right' : 'left';
|
|
755
|
+
}
|
|
756
|
+
|
|
734
757
|
}
|
|
735
758
|
|
|
736
759
|
if (Array.isArray(formatted)) {
|
|
@@ -744,12 +767,13 @@ export class TileRenderer {
|
|
|
744
767
|
// this is a single line, with number formatting
|
|
745
768
|
|
|
746
769
|
if (indent) {
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
}
|
|
750
|
-
else if (style.horizontal_align === 'right') {
|
|
770
|
+
|
|
771
|
+
if (align === 'right') {
|
|
751
772
|
formatted.push({ text: indent });
|
|
752
773
|
}
|
|
774
|
+
else if (align === 'left') {
|
|
775
|
+
formatted.unshift({ text: indent });
|
|
776
|
+
}
|
|
753
777
|
}
|
|
754
778
|
|
|
755
779
|
for (const part of formatted) {
|
|
@@ -953,12 +977,12 @@ export class TileRenderer {
|
|
|
953
977
|
});
|
|
954
978
|
|
|
955
979
|
if (style.indent) {
|
|
956
|
-
if (
|
|
957
|
-
line_string.unshift({ text: indent, hidden: false, width: indent_width });
|
|
958
|
-
}
|
|
959
|
-
else if (style.horizontal_align === 'right') {
|
|
980
|
+
if (align === 'right') {
|
|
960
981
|
line_string.push({ text: indent, hidden: false, width: indent_width });
|
|
961
982
|
}
|
|
983
|
+
else if (align === 'left') {
|
|
984
|
+
line_string.unshift({ text: indent, hidden: false, width: indent_width });
|
|
985
|
+
}
|
|
962
986
|
}
|
|
963
987
|
|
|
964
988
|
strings.push(line_string);
|
|
@@ -977,12 +1001,12 @@ export class TileRenderer {
|
|
|
977
1001
|
const parts: RenderTextPart[] = [];
|
|
978
1002
|
|
|
979
1003
|
if (style.indent) {
|
|
980
|
-
if (
|
|
981
|
-
line.unshift({ text: indent });
|
|
982
|
-
}
|
|
983
|
-
else if (style.horizontal_align === 'right') {
|
|
1004
|
+
if (align === 'right') {
|
|
984
1005
|
line.push({ text: indent });
|
|
985
1006
|
}
|
|
1007
|
+
else if (align === 'left') {
|
|
1008
|
+
line.unshift({ text: indent });
|
|
1009
|
+
}
|
|
986
1010
|
}
|
|
987
1011
|
|
|
988
1012
|
let line_width = 0;
|
|
@@ -978,7 +978,7 @@ export class Grid extends GridBase {
|
|
|
978
978
|
|
|
979
979
|
const validated = this.model.named_ranges.ValidateNamed(name);
|
|
980
980
|
if (!validated) {
|
|
981
|
-
console.warn(`invalid name: ${name}
|
|
981
|
+
console.warn(`invalid name: ${name}`, import_data.names[name]);
|
|
982
982
|
continue;
|
|
983
983
|
}
|
|
984
984
|
|
|
@@ -2044,6 +2044,21 @@ export class Grid extends GridBase {
|
|
|
2044
2044
|
}
|
|
2045
2045
|
*/
|
|
2046
2046
|
|
|
2047
|
+
public Indent(area?: Area, delta = 0): void {
|
|
2048
|
+
|
|
2049
|
+
if (!area) {
|
|
2050
|
+
if (this.primary_selection.empty) { return; }
|
|
2051
|
+
area = this.primary_selection.area;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
this.ExecCommand({
|
|
2055
|
+
key: CommandKey.Indent,
|
|
2056
|
+
area,
|
|
2057
|
+
delta,
|
|
2058
|
+
});
|
|
2059
|
+
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2047
2062
|
/** updated API method, probably change the name */
|
|
2048
2063
|
public ApplyBorders2(area?: Area, borders: BorderConstants = BorderConstants.None, color?: Color, width = 1): void {
|
|
2049
2064
|
|
|
@@ -4972,6 +4987,15 @@ export class Grid extends GridBase {
|
|
|
4972
4987
|
}
|
|
4973
4988
|
}
|
|
4974
4989
|
else if (array) {
|
|
4990
|
+
|
|
4991
|
+
for (const cell of this.active_sheet.cells.Iterate(selection.area, false)) {
|
|
4992
|
+
if (cell.area) {
|
|
4993
|
+
this.Error(ErrorCode.array);
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
|
|
4998
|
+
/*
|
|
4975
4999
|
let existing_array = false;
|
|
4976
5000
|
this.active_sheet.cells.Apply(selection.area, (element: Cell) => {
|
|
4977
5001
|
if (element.area) {
|
|
@@ -4982,6 +5006,8 @@ export class Grid extends GridBase {
|
|
|
4982
5006
|
this.Error(ErrorCode.array);
|
|
4983
5007
|
return;
|
|
4984
5008
|
}
|
|
5009
|
+
*/
|
|
5010
|
+
|
|
4985
5011
|
}
|
|
4986
5012
|
|
|
4987
5013
|
if (cell.validation && cell.validation.error) {
|
|
@@ -6099,9 +6125,28 @@ export class Grid extends GridBase {
|
|
|
6099
6125
|
let real_area = this.active_sheet.RealArea(area);
|
|
6100
6126
|
if (!target) target = real_area.start;
|
|
6101
6127
|
|
|
6102
|
-
|
|
6128
|
+
// there has to be a better way to do this...
|
|
6129
|
+
|
|
6130
|
+
// the operation here is composing the selection by adding all merge
|
|
6131
|
+
// areas. the issue is that when you do that, you might be adding other
|
|
6132
|
+
// cells that are not in the merge area (because the selection has to
|
|
6133
|
+
// be a rectangle) and one of those new cells might itself be merged.
|
|
6134
|
+
// so we need to iterate. there's a lot of duplication here, though.
|
|
6135
|
+
|
|
6136
|
+
recheck_loop: while (true) {
|
|
6137
|
+
for (const cell of this.active_sheet.cells.Iterate(real_area, false)) {
|
|
6138
|
+
if (cell.merge_area && !real_area.ContainsArea(cell.merge_area)) {
|
|
6139
|
+
area.ConsumeArea(cell.merge_area);
|
|
6140
|
+
real_area = this.active_sheet.RealArea(area);
|
|
6141
|
+
continue recheck_loop;
|
|
6142
|
+
}
|
|
6143
|
+
}
|
|
6144
|
+
break;
|
|
6145
|
+
}
|
|
6103
6146
|
|
|
6104
|
-
|
|
6147
|
+
/*
|
|
6148
|
+
|
|
6149
|
+
let recheck = true;
|
|
6105
6150
|
|
|
6106
6151
|
while (recheck) {
|
|
6107
6152
|
recheck = false;
|
|
@@ -6113,6 +6158,7 @@ export class Grid extends GridBase {
|
|
|
6113
6158
|
}
|
|
6114
6159
|
});
|
|
6115
6160
|
}
|
|
6161
|
+
*/
|
|
6116
6162
|
|
|
6117
6163
|
selection.area = new Area({ ...area.start, sheet_id: this.active_sheet.id }, area.end);
|
|
6118
6164
|
if (target) {
|