@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.
- package/dist/treb-spreadsheet-light.mjs +11 -11
- package/dist/treb-spreadsheet.mjs +11 -11
- package/dist/treb.d.ts +3 -25
- package/package.json +1 -1
- package/treb-base-types/src/area.ts +25 -1
- package/treb-base-types/src/cell.ts +2 -46
- package/treb-base-types/src/cells.ts +14 -8
- package/treb-base-types/src/import.ts +2 -2
- package/treb-calculator/src/calculator.ts +22 -12
- package/treb-calculator/src/dag/graph.ts +12 -3
- package/treb-calculator/src/expression-calculator.ts +66 -74
- package/treb-calculator/src/functions/base-functions.ts +2 -2
- package/treb-calculator/src/functions/statistics-functions.ts +31 -1
- package/treb-data-model/src/data-validation.ts +44 -0
- package/treb-data-model/src/data_model.ts +12 -8
- package/treb-data-model/src/index.ts +1 -1
- package/treb-data-model/src/named.ts +35 -10
- package/treb-data-model/src/sheet.ts +61 -0
- package/treb-data-model/src/sheet_types.ts +4 -0
- package/treb-embed/src/embedded-spreadsheet.ts +21 -15
- package/treb-embed/src/progress-dialog.ts +4 -1
- package/treb-export/src/export2.ts +27 -14
- package/treb-export/src/import2.ts +58 -12
- package/treb-grid/src/layout/base_layout.ts +2 -11
- package/treb-grid/src/types/grid.ts +29 -18
- package/treb-grid/src/types/grid_base.ts +83 -16
- package/treb-grid/src/types/grid_command.ts +2 -1
- package/treb-parser/src/parser.ts +22 -4
|
@@ -21,9 +21,6 @@
|
|
|
21
21
|
|
|
22
22
|
// --- imports -----------------------------------------------------------------
|
|
23
23
|
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
25
|
-
/// <reference path="./content-types.d.ts" />
|
|
26
|
-
|
|
27
24
|
import type {
|
|
28
25
|
GridEvent,
|
|
29
26
|
SheetChangeEvent, GridOptions,
|
|
@@ -103,6 +100,11 @@ import type { StateLeafVertex } from 'treb-calculator';
|
|
|
103
100
|
|
|
104
101
|
// --- worker ------------------------------------------------------------------
|
|
105
102
|
|
|
103
|
+
/**
|
|
104
|
+
* import type for our worker, plus markup files
|
|
105
|
+
*/
|
|
106
|
+
import './content-types.d.ts';
|
|
107
|
+
|
|
106
108
|
/**
|
|
107
109
|
* import the worker as a script file. tsc will read this on typecheck but
|
|
108
110
|
* that's actually to the good; when we build with esbuild we will inline
|
|
@@ -3005,7 +3007,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
3005
3007
|
|
|
3006
3008
|
this.grid.Reset();
|
|
3007
3009
|
this.ResetInternal();
|
|
3008
|
-
this.calculator.AttachModel();
|
|
3010
|
+
// this.calculator.AttachModel();
|
|
3009
3011
|
this.UpdateAC();
|
|
3010
3012
|
|
|
3011
3013
|
this.Publish({ type: 'reset' });
|
|
@@ -3491,25 +3493,30 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
3491
3493
|
/**
|
|
3492
3494
|
* set or clear cell valiation.
|
|
3493
3495
|
*
|
|
3494
|
-
* @param
|
|
3496
|
+
* @param target - target cell/area
|
|
3495
3497
|
* @param validation - a spreadsheet range, list of data, or undefined. pass
|
|
3496
3498
|
* undefined to remove existing cell validation.
|
|
3497
3499
|
* @param error - setting an invalid value in the target cell is an error (and
|
|
3498
3500
|
* is blocked). defaults to false.
|
|
3499
3501
|
*/
|
|
3500
|
-
public SetValidation(
|
|
3502
|
+
public SetValidation(target: RangeReference, validation?: RangeReference|CellValue[], error?: boolean) {
|
|
3501
3503
|
|
|
3502
|
-
if (typeof
|
|
3503
|
-
const reference = this.model.ResolveAddress(
|
|
3504
|
-
|
|
3504
|
+
if (typeof target === 'string') {
|
|
3505
|
+
const reference = this.model.ResolveAddress(target, this.grid.active_sheet);
|
|
3506
|
+
target = IsArea(reference) ? new Area(reference.start, reference.end) : new Area(reference);
|
|
3507
|
+
// address = IsCellAddress(reference) ? reference : reference.start;
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
if (IsCellAddress(target)) {
|
|
3511
|
+
target = new Area(target);
|
|
3505
3512
|
}
|
|
3506
3513
|
|
|
3507
3514
|
if (typeof validation === 'undefined' || Array.isArray(validation)) {
|
|
3508
|
-
this.grid.SetValidation(
|
|
3515
|
+
this.grid.SetValidation(target, validation, error);
|
|
3509
3516
|
}
|
|
3510
3517
|
else {
|
|
3511
3518
|
const range = this.model.ResolveArea(validation, this.grid.active_sheet);
|
|
3512
|
-
this.grid.SetValidation(
|
|
3519
|
+
this.grid.SetValidation(target, range, error);
|
|
3513
3520
|
}
|
|
3514
3521
|
|
|
3515
3522
|
}
|
|
@@ -4626,7 +4633,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
4626
4633
|
|
|
4627
4634
|
// this one _is_ the grid cells
|
|
4628
4635
|
|
|
4629
|
-
this.calculator.AttachModel();
|
|
4636
|
+
// this.calculator.AttachModel();
|
|
4630
4637
|
this.Publish({ type: 'load', source, });
|
|
4631
4638
|
this.UpdateDocumentStyles();
|
|
4632
4639
|
|
|
@@ -5845,9 +5852,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
|
|
|
5845
5852
|
|
|
5846
5853
|
this.grid.UpdateSheets(sheets, undefined, override_sheet || data.active_sheet);
|
|
5847
5854
|
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
if (table.area.start.sheet_id) {
|
|
5855
|
+
for (const table of this.model.tables.values()) {
|
|
5856
|
+
if (table.area.start.sheet_id) {
|
|
5851
5857
|
const sheet = model.sheets.Find(table.area.start.sheet_id);
|
|
5852
5858
|
if (sheet) {
|
|
5853
5859
|
for (let row = table.area.start.row; row <= table.area.end.row; row++) {
|
|
@@ -57,7 +57,6 @@ export type ResolutionFunction = () => void;
|
|
|
57
57
|
*/
|
|
58
58
|
export class Dialog {
|
|
59
59
|
|
|
60
|
-
// private model: NodeModel;
|
|
61
60
|
private model: Record<string, HTMLElement> = {};
|
|
62
61
|
|
|
63
62
|
private layout_element: HTMLElement;
|
|
@@ -192,6 +191,10 @@ export class Dialog {
|
|
|
192
191
|
|
|
193
192
|
}
|
|
194
193
|
|
|
194
|
+
public Node(name: string): HTMLElement|undefined {
|
|
195
|
+
return this.model[name];
|
|
196
|
+
}
|
|
197
|
+
|
|
195
198
|
public Update(options: Partial<MessageDialogOptions>, delta = true): void {
|
|
196
199
|
if (delta) {
|
|
197
200
|
options = { ...this.options_, ... options};
|
|
@@ -34,11 +34,11 @@ import { PixelsToColumnWidth } from './column-width';
|
|
|
34
34
|
const XMLDeclaration = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n`;
|
|
35
35
|
|
|
36
36
|
import { template } from './template-2';
|
|
37
|
-
import type { SerializedModel, SerializedSheet } from 'treb-data-model';
|
|
37
|
+
import type { SerializedModel, SerializedSheet, DataValidation } from 'treb-data-model';
|
|
38
38
|
|
|
39
|
-
import type { IArea, ICellAddress, CellValue,
|
|
39
|
+
import type { IArea, ICellAddress, CellValue, CellStyle,
|
|
40
40
|
AnnotationLayout, Corner as LayoutCorner, Cell, Rectangle } from 'treb-base-types';
|
|
41
|
-
import { Area, Cells, ValueType, Style
|
|
41
|
+
import { Area, Cells, ValueType, Style } from 'treb-base-types';
|
|
42
42
|
|
|
43
43
|
// import * as xmlparser from 'fast-xml-parser';
|
|
44
44
|
import type { XmlBuilderOptions} from 'fast-xml-parser';
|
|
@@ -1417,10 +1417,12 @@ export class Exporter {
|
|
|
1417
1417
|
const merges: Area[] = [];
|
|
1418
1418
|
const tables: TableDescription[] = [];
|
|
1419
1419
|
|
|
1420
|
+
/*
|
|
1420
1421
|
const validations: Array<{
|
|
1421
1422
|
address: ICellAddress,
|
|
1422
1423
|
validation: DataValidation,
|
|
1423
1424
|
}> = [];
|
|
1425
|
+
*/
|
|
1424
1426
|
|
|
1425
1427
|
// --
|
|
1426
1428
|
|
|
@@ -1606,12 +1608,14 @@ export class Exporter {
|
|
|
1606
1608
|
});
|
|
1607
1609
|
}
|
|
1608
1610
|
|
|
1611
|
+
/*
|
|
1609
1612
|
if (cell.validation && (cell.validation.type === ValidationType.List || cell.validation.type === ValidationType.Range)) {
|
|
1610
1613
|
validations.push({
|
|
1611
1614
|
address: {row: r, column: c},
|
|
1612
1615
|
validation: cell.validation,
|
|
1613
1616
|
});
|
|
1614
1617
|
}
|
|
1618
|
+
*/
|
|
1615
1619
|
|
|
1616
1620
|
// short-circuit here
|
|
1617
1621
|
if (cell.type === ValueType.formula && /^=?sparkline\./i.test(cell.value as string)) {
|
|
@@ -1929,37 +1933,46 @@ export class Exporter {
|
|
|
1929
1933
|
|
|
1930
1934
|
// --- validation ----------------------------------------------------------
|
|
1931
1935
|
|
|
1932
|
-
if (
|
|
1936
|
+
if (sheet.data_validations?.length) {
|
|
1933
1937
|
|
|
1934
1938
|
dom.worksheet.dataValidations = {
|
|
1935
|
-
a$: { count:
|
|
1936
|
-
dataValidation:
|
|
1939
|
+
a$: { count: sheet.data_validations.length },
|
|
1940
|
+
dataValidation: sheet.data_validations.map(validation => {
|
|
1941
|
+
|
|
1942
|
+
const sqref = validation.target.map(target => {
|
|
1943
|
+
return new Area(target.start, target.end).spreadsheet_label;
|
|
1944
|
+
}).join(' ');
|
|
1945
|
+
|
|
1937
1946
|
const entry: any = {
|
|
1938
1947
|
a$: {
|
|
1939
1948
|
type: 'list',
|
|
1940
1949
|
allowBlank: 1,
|
|
1941
1950
|
showInputMessage: 1,
|
|
1942
1951
|
showErrorMessage: 1,
|
|
1943
|
-
sqref: new Area(validation.address).spreadsheet_label,
|
|
1952
|
+
sqref, // : new Area(validation.address).spreadsheet_label,
|
|
1944
1953
|
},
|
|
1945
1954
|
};
|
|
1946
|
-
if (validation.
|
|
1955
|
+
if (validation.type === 'range') {
|
|
1947
1956
|
|
|
1948
1957
|
const range: UnitRange = {
|
|
1949
1958
|
id: 0,
|
|
1950
1959
|
type: 'range',
|
|
1951
1960
|
label: '', position: 0,
|
|
1952
1961
|
start:
|
|
1953
|
-
{...validation.
|
|
1962
|
+
{...validation.area.start, absolute_column: true, absolute_row: true, id: 0, label: '', position: 0, type: 'address', },
|
|
1954
1963
|
end:
|
|
1955
|
-
{...validation.
|
|
1964
|
+
{...validation.area.end, absolute_column: true, absolute_row: true, id: 0, label: '', position: 0, type: 'address', }
|
|
1956
1965
|
,
|
|
1957
1966
|
}
|
|
1958
1967
|
|
|
1959
|
-
|
|
1960
|
-
|
|
1968
|
+
console.info("AA", {validation});
|
|
1969
|
+
|
|
1970
|
+
if (typeof validation.area.start.sheet_id !== 'undefined') {
|
|
1971
|
+
range.start.sheet = sheet_name_map[validation.area.start.sheet_id];
|
|
1961
1972
|
}
|
|
1962
1973
|
|
|
1974
|
+
console.info("m1");
|
|
1975
|
+
|
|
1963
1976
|
/*
|
|
1964
1977
|
const area = new Area(
|
|
1965
1978
|
{...validation.validation.area.start, absolute_column: true, absolute_row: true},
|
|
@@ -1971,8 +1984,8 @@ export class Exporter {
|
|
|
1971
1984
|
entry.formula1 = this.parser.Render(range);
|
|
1972
1985
|
|
|
1973
1986
|
}
|
|
1974
|
-
else if (validation.
|
|
1975
|
-
entry.formula1 = `"${validation.
|
|
1987
|
+
else if (validation.type === 'list') {
|
|
1988
|
+
entry.formula1 = `"${validation.list.join(',')}"`;
|
|
1976
1989
|
}
|
|
1977
1990
|
return entry;
|
|
1978
1991
|
}),
|
|
@@ -30,8 +30,8 @@ import type { ParseResult } from 'treb-parser';
|
|
|
30
30
|
import { Parser } from 'treb-parser';
|
|
31
31
|
import type { RangeType, AddressType, HyperlinkType } from './address-type';
|
|
32
32
|
import { is_range, ShiftRange, InRange, is_address } from './address-type';
|
|
33
|
-
import type { ImportedSheetData, AnchoredAnnotation, CellParseResult, AnnotationLayout, Corner as LayoutCorner,
|
|
34
|
-
import {
|
|
33
|
+
import type { ImportedSheetData, AnchoredAnnotation, CellParseResult, AnnotationLayout, Corner as LayoutCorner, IArea, GradientStop, Color } from 'treb-base-types';
|
|
34
|
+
import type { SerializedValueType } from 'treb-base-types';
|
|
35
35
|
import type { Sheet} from './workbook-sheet2';
|
|
36
36
|
import { VisibleState } from './workbook-sheet2';
|
|
37
37
|
import type { CellAnchor } from './drawing2/drawing2';
|
|
@@ -39,7 +39,7 @@ import { XMLUtils } from './xml-utils';
|
|
|
39
39
|
|
|
40
40
|
// import { one_hundred_pixels } from './constants';
|
|
41
41
|
import { ColumnWidthToPixels } from './column-width';
|
|
42
|
-
import type { AnnotationType } from 'treb-data-model';
|
|
42
|
+
import type { DataValidation, AnnotationType } from 'treb-data-model';
|
|
43
43
|
import { ZipWrapper } from './zip-wrapper';
|
|
44
44
|
import type { ConditionalFormat } from 'treb-data-model';
|
|
45
45
|
|
|
@@ -99,7 +99,7 @@ export class Importer {
|
|
|
99
99
|
arrays: RangeType[],
|
|
100
100
|
merges: RangeType[],
|
|
101
101
|
links: HyperlinkType[],
|
|
102
|
-
validations: Array<{ address: ICellAddress, validation: DataValidation }>,
|
|
102
|
+
// validations: Array<{ address: ICellAddress, validation: DataValidation }>,
|
|
103
103
|
): CellParseResult | undefined {
|
|
104
104
|
|
|
105
105
|
// must have, at minimum, an address (must be a single cell? FIXME)
|
|
@@ -285,12 +285,14 @@ export class Importer {
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/*
|
|
288
289
|
for (const validation of validations) {
|
|
289
290
|
if (validation.address.row === shifted.row && validation.address.column === shifted.col) {
|
|
290
291
|
result.validation = validation.validation;
|
|
291
292
|
break;
|
|
292
293
|
}
|
|
293
294
|
}
|
|
295
|
+
*/
|
|
294
296
|
|
|
295
297
|
for (const range of merges) {
|
|
296
298
|
if (InRange(range, shifted)) {
|
|
@@ -512,10 +514,15 @@ export class Importer {
|
|
|
512
514
|
const conditional_formats: ConditionalFormat[] = [];
|
|
513
515
|
const links: HyperlinkType[] = [];
|
|
514
516
|
const row_styles: number[] = []; // may be sparse
|
|
517
|
+
|
|
518
|
+
/*
|
|
515
519
|
const validations: Array<{
|
|
516
520
|
address: ICellAddress,
|
|
517
521
|
validation: DataValidation,
|
|
518
522
|
}> = [];
|
|
523
|
+
*/
|
|
524
|
+
const validations: DataValidation[] = [];
|
|
525
|
+
|
|
519
526
|
const annotations: AnchoredAnnotation[] = [];
|
|
520
527
|
|
|
521
528
|
const FindAll: (path: string) => any[] = XMLUtils.FindAll.bind(XMLUtils, sheet.sheet_data);
|
|
@@ -569,33 +576,68 @@ export class Importer {
|
|
|
569
576
|
const formula = entry.formula1;
|
|
570
577
|
|
|
571
578
|
if (ref && formula && type === 'list') {
|
|
572
|
-
let address: ICellAddress|undefined;
|
|
579
|
+
// let address: ICellAddress|undefined;
|
|
573
580
|
let validation: DataValidation|undefined;
|
|
574
581
|
let parse_result = this.parser.Parse(ref);
|
|
582
|
+
const target: IArea[] = [];
|
|
575
583
|
|
|
576
584
|
// apparently these are encoded as ranges for merged cells...
|
|
577
585
|
|
|
586
|
+
// NOTE: actually you can have a range, then validation applies
|
|
587
|
+
// to every cell in the range. also you can have multiple ranges,
|
|
588
|
+
// apparently separated by spaces.
|
|
589
|
+
|
|
578
590
|
if (parse_result.expression) {
|
|
579
591
|
if (parse_result.expression.type === 'address') {
|
|
580
|
-
address = parse_result.expression;
|
|
592
|
+
// address = parse_result.expression;
|
|
593
|
+
target.push({start: parse_result.expression, end: parse_result.expression});
|
|
581
594
|
}
|
|
582
595
|
else if (parse_result.expression.type === 'range') {
|
|
583
|
-
address = parse_result.expression.start;
|
|
596
|
+
// address = parse_result.expression.start;
|
|
597
|
+
target.push(parse_result.expression);
|
|
584
598
|
}
|
|
585
599
|
}
|
|
586
600
|
|
|
587
601
|
parse_result = this.parser.Parse(formula);
|
|
602
|
+
|
|
588
603
|
if (parse_result.expression) {
|
|
589
604
|
if (parse_result.expression.type === 'range') {
|
|
590
605
|
validation = {
|
|
591
|
-
type:
|
|
606
|
+
type: 'range',
|
|
592
607
|
area: parse_result.expression,
|
|
608
|
+
target,
|
|
593
609
|
};
|
|
594
610
|
}
|
|
595
611
|
else if (parse_result.expression.type === 'literal') {
|
|
596
612
|
validation = {
|
|
597
|
-
type:
|
|
613
|
+
type: 'list',
|
|
614
|
+
target,
|
|
598
615
|
list: parse_result.expression.value.toString().split(/,/).map(value => {
|
|
616
|
+
|
|
617
|
+
// there are no formulas here. value is a string, separated
|
|
618
|
+
// by commas. there is no way to escape a comma (AFAICT; not
|
|
619
|
+
// official, but search). if you did want a comma, you'd need
|
|
620
|
+
// to use a range.
|
|
621
|
+
|
|
622
|
+
// but the uptake is split on commas. after that you can try
|
|
623
|
+
// to check for numbers or bools, but they will be in the string.
|
|
624
|
+
|
|
625
|
+
// I think excel might sort the entries? not sure. don't do it
|
|
626
|
+
// for now.
|
|
627
|
+
|
|
628
|
+
const num = Number(value);
|
|
629
|
+
if (!isNaN(num)) {
|
|
630
|
+
return num;
|
|
631
|
+
}
|
|
632
|
+
if (value.toLowerCase() === 'true') {
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
if (value.toLowerCase() === 'false') {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
return value; // string
|
|
639
|
+
|
|
640
|
+
/*
|
|
599
641
|
const tmp = this.parser.Parse(value);
|
|
600
642
|
|
|
601
643
|
// if type is "group", that means we saw some spaces. this
|
|
@@ -612,13 +654,16 @@ export class Importer {
|
|
|
612
654
|
return tmp.expression.name;
|
|
613
655
|
}
|
|
614
656
|
return undefined;
|
|
657
|
+
*/
|
|
658
|
+
|
|
615
659
|
}),
|
|
616
660
|
};
|
|
617
661
|
}
|
|
618
662
|
}
|
|
619
663
|
|
|
620
|
-
if (
|
|
621
|
-
validations.push({address, validation});
|
|
664
|
+
if (target.length && validation) {
|
|
665
|
+
// validations.push({address, validation});
|
|
666
|
+
validations.push(validation);
|
|
622
667
|
}
|
|
623
668
|
|
|
624
669
|
}
|
|
@@ -730,7 +775,7 @@ export class Importer {
|
|
|
730
775
|
if (!Array.isArray(cells)) { cells = [cells]; }
|
|
731
776
|
|
|
732
777
|
for (const element of cells) {
|
|
733
|
-
const cell = this.ParseCell(sheet, element, shared_formulae, arrays, merges, links, validations);
|
|
778
|
+
const cell = this.ParseCell(sheet, element, shared_formulae, arrays, merges, links); // , validations);
|
|
734
779
|
if (cell) {
|
|
735
780
|
data.push(cell);
|
|
736
781
|
}
|
|
@@ -1178,6 +1223,7 @@ export class Importer {
|
|
|
1178
1223
|
row_styles,
|
|
1179
1224
|
annotations,
|
|
1180
1225
|
conditional_formats,
|
|
1226
|
+
data_validations: validations,
|
|
1181
1227
|
styles: this.workbook?.style_cache?.CellXfToStyles() || [],
|
|
1182
1228
|
};
|
|
1183
1229
|
|
|
@@ -1295,19 +1295,8 @@ export abstract class BaseLayout {
|
|
|
1295
1295
|
}
|
|
1296
1296
|
}
|
|
1297
1297
|
|
|
1298
|
-
/*
|
|
1299
|
-
this.tooltip.style.fontFamily = theme.tooltip_font_face || '';
|
|
1300
|
-
this.tooltip.style.fontSize = theme.tooltip_font_size ? `${theme.tooltip_font_size}pt` : '';
|
|
1301
|
-
this.tooltip.style.backgroundColor = theme.tooltip_background || '';
|
|
1302
|
-
this.tooltip.style.borderColor = theme.tooltip_background || ''; // for arrow
|
|
1303
|
-
this.tooltip.style.color = theme.tooltip_color || '';
|
|
1304
|
-
*/
|
|
1305
|
-
|
|
1306
1298
|
// TODO: dropdown caret
|
|
1307
1299
|
|
|
1308
|
-
// this.dropdown_list.style.fontFamily = theme.cell_font || '';
|
|
1309
|
-
// const font_size = (theme.cell_font_size_value || 10) * this.scale;
|
|
1310
|
-
// this.dropdown_list.style.fontSize = (font_size) + (theme.cell_font_size_unit || 'pt');
|
|
1311
1300
|
this.dropdown_list.style.font = Style.Font(theme.grid_cell || {});
|
|
1312
1301
|
|
|
1313
1302
|
}
|
|
@@ -1415,6 +1404,8 @@ export abstract class BaseLayout {
|
|
|
1415
1404
|
this.dropdown_list.style.left = `${target_rect.left + 2}px`;
|
|
1416
1405
|
this.dropdown_list.style.minWidth = `${target_rect.width}px`;
|
|
1417
1406
|
|
|
1407
|
+
this.dropdown_list.style.fontSize = (this.scale.toFixed(2) + 'em');
|
|
1408
|
+
|
|
1418
1409
|
this.dropdown_list.textContent = '';
|
|
1419
1410
|
for (const value of list) {
|
|
1420
1411
|
const entry = this.DOM.Div(undefined, this.dropdown_list);
|
|
@@ -40,7 +40,6 @@ import {
|
|
|
40
40
|
ValueType,
|
|
41
41
|
Localization,
|
|
42
42
|
IsCellAddress,
|
|
43
|
-
ValidationType,
|
|
44
43
|
LoadThemeProperties,
|
|
45
44
|
DefaultTheme,
|
|
46
45
|
ComplexToString,
|
|
@@ -1465,20 +1464,22 @@ export class Grid extends GridBase {
|
|
|
1465
1464
|
* and will render as a dropdown; the list can be a list of values or
|
|
1466
1465
|
* a range reference.
|
|
1467
1466
|
*/
|
|
1468
|
-
public SetValidation(target?:
|
|
1467
|
+
public SetValidation(target?: IArea, data?: CellValue[]|IArea, error?: boolean): void {
|
|
1469
1468
|
|
|
1470
1469
|
if (!target) {
|
|
1471
1470
|
if (this.primary_selection.empty) {
|
|
1472
1471
|
throw new Error('invalid target in set validation');
|
|
1473
1472
|
}
|
|
1474
|
-
target = this.primary_selection.
|
|
1473
|
+
target = this.primary_selection.area;
|
|
1475
1474
|
}
|
|
1476
1475
|
|
|
1476
|
+
const area = new Area(target.start, target.end);
|
|
1477
|
+
|
|
1477
1478
|
// console.info({target, data});
|
|
1478
1479
|
|
|
1479
1480
|
const command: DataValidationCommand = {
|
|
1480
1481
|
key: CommandKey.DataValidation,
|
|
1481
|
-
area:
|
|
1482
|
+
area: { start: area.start, end: area.end },
|
|
1482
1483
|
error,
|
|
1483
1484
|
};
|
|
1484
1485
|
|
|
@@ -1502,9 +1503,11 @@ export class Grid extends GridBase {
|
|
|
1502
1503
|
//
|
|
1503
1504
|
|
|
1504
1505
|
if (!this.primary_selection.empty &&
|
|
1505
|
-
(!target.sheet_id || target.sheet_id === this.active_sheet.id) &&
|
|
1506
|
-
(this.primary_selection.target
|
|
1507
|
-
|
|
1506
|
+
(!target.start.sheet_id || target.start.sheet_id === this.active_sheet.id) &&
|
|
1507
|
+
area.Contains(this.primary_selection.target)) {
|
|
1508
|
+
|
|
1509
|
+
// (this.primary_selection.target.row === target.start.row) &&
|
|
1510
|
+
// (this.primary_selection.target.column === target.start.column)) {
|
|
1508
1511
|
|
|
1509
1512
|
// console.info('repaint selection');
|
|
1510
1513
|
|
|
@@ -4966,15 +4969,19 @@ export class Grid extends GridBase {
|
|
|
4966
4969
|
|
|
4967
4970
|
}
|
|
4968
4971
|
|
|
4969
|
-
|
|
4972
|
+
const validation = this.active_sheet.GetValidation(target)[0];
|
|
4973
|
+
|
|
4974
|
+
// only consider the first result
|
|
4975
|
+
|
|
4976
|
+
if (validation && validation.error) {
|
|
4970
4977
|
|
|
4971
4978
|
let list: CellValue[]|undefined;
|
|
4972
4979
|
|
|
4973
|
-
if (
|
|
4974
|
-
list =
|
|
4980
|
+
if (validation.type === 'list') {
|
|
4981
|
+
list = validation.list;
|
|
4975
4982
|
}
|
|
4976
|
-
else if (
|
|
4977
|
-
list = this.GetValidationRange(
|
|
4983
|
+
else if (validation.type === 'range') {
|
|
4984
|
+
list = this.GetValidationRange(validation.area);
|
|
4978
4985
|
}
|
|
4979
4986
|
|
|
4980
4987
|
if (list && list.length) {
|
|
@@ -6216,15 +6223,19 @@ export class Grid extends GridBase {
|
|
|
6216
6223
|
// sync up, so it would be a separate function but called at the
|
|
6217
6224
|
// same time.
|
|
6218
6225
|
|
|
6219
|
-
|
|
6226
|
+
// less true now that they're maintained separately
|
|
6227
|
+
|
|
6228
|
+
const validation = this.active_sheet.GetValidation(this.primary_selection.target)[0];
|
|
6229
|
+
|
|
6230
|
+
if (validation && !data.style?.locked) {
|
|
6220
6231
|
|
|
6221
6232
|
let list: CellValue[] | undefined;
|
|
6222
6233
|
|
|
6223
|
-
if (
|
|
6224
|
-
list =
|
|
6234
|
+
if (validation.type === 'list') {
|
|
6235
|
+
list = validation.list;
|
|
6225
6236
|
}
|
|
6226
|
-
else if (
|
|
6227
|
-
list = this.GetValidationRange(
|
|
6237
|
+
else if (validation.type === 'range') {
|
|
6238
|
+
list = this.GetValidationRange(validation.area);
|
|
6228
6239
|
}
|
|
6229
6240
|
|
|
6230
6241
|
if (list && list.length) {
|
|
@@ -6541,7 +6552,7 @@ export class Grid extends GridBase {
|
|
|
6541
6552
|
// tsv_row.push(cell.formatted);
|
|
6542
6553
|
|
|
6543
6554
|
let text_value = '';
|
|
6544
|
-
if (cell.calculated) {
|
|
6555
|
+
if (cell.calculated !== undefined) {
|
|
6545
6556
|
if (cell.calculated_type === ValueType.complex) {
|
|
6546
6557
|
text_value = ComplexToString(cell.calculated as Complex);
|
|
6547
6558
|
}
|