@trebco/treb 25.9.1 → 26.0.5
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-config.json +0 -1
- package/dist/treb-spreadsheet.mjs +13 -13
- package/dist/treb.d.ts +620 -3
- package/package.json +1 -1
- package/treb-base-types/src/cell.ts +11 -11
- package/treb-base-types/src/cells.ts +73 -7
- package/treb-base-types/src/import.ts +3 -3
- package/treb-base-types/src/value-type.ts +37 -5
- package/treb-embed/src/types.ts +41 -3
- package/treb-export/src/export2.ts +188 -5
- package/treb-export/src/import2.ts +21 -14
- package/treb-grid/src/types/data_model.ts +0 -1
- package/treb-grid/src/types/grid.ts +3 -1
- package/treb-grid/src/types/sheet_types.ts +45 -9
|
@@ -100,7 +100,7 @@ export interface ClickFunctionResult {
|
|
|
100
100
|
export type ClickFunction = (options: ClickFunctionOptions) => ClickFunctionResult;
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
/*
|
|
104
104
|
* restructuring from the old system, which had lots of separate arrays for
|
|
105
105
|
* things. for the most part I think having a single array (or object) with
|
|
106
106
|
* objects will be more useful (if not necessarily more efficient). the
|
|
@@ -121,11 +121,11 @@ export type ClickFunction = (options: ClickFunctionOptions) => ClickFunctionResu
|
|
|
121
121
|
* validation TODO: date, number, boolean, &c
|
|
122
122
|
*/
|
|
123
123
|
export enum ValidationType {
|
|
124
|
-
List,
|
|
125
|
-
Date,
|
|
126
|
-
Range,
|
|
127
|
-
Number,
|
|
128
|
-
Boolean,
|
|
124
|
+
List = 'list',
|
|
125
|
+
Date = 'date',
|
|
126
|
+
Range = 'range',
|
|
127
|
+
Number = 'number',
|
|
128
|
+
Boolean = 'boolean',
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
export interface DataValidationBase {
|
|
@@ -133,25 +133,25 @@ export interface DataValidationBase {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
export interface DataValidationRange extends DataValidationBase {
|
|
136
|
-
type: ValidationType.Range;
|
|
136
|
+
type: 'range'; // ValidationType.Range;
|
|
137
137
|
area: IArea;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
export interface DataValidationList extends DataValidationBase {
|
|
141
|
-
type: ValidationType.List;
|
|
141
|
+
type: 'list'; // ValidationType.List;
|
|
142
142
|
list: CellValue[];
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
export interface DataValidationDate extends DataValidationBase {
|
|
146
|
-
type: ValidationType.Date;
|
|
146
|
+
type: 'date'; // ValidationType.Date;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
export interface DataValidationNumber extends DataValidationBase {
|
|
150
|
-
type: ValidationType.Number;
|
|
150
|
+
type: 'number'; // ValidationType.Number;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
export interface DataValidationBoolean extends DataValidationBase {
|
|
154
|
-
type: ValidationType.Boolean;
|
|
154
|
+
type: 'boolean'; // ValidationType.Boolean;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
export type DataValidation
|
|
@@ -29,7 +29,7 @@ import { Area, IsCellAddress } from './area';
|
|
|
29
29
|
import type { DataValidation } from './cell';
|
|
30
30
|
import { Cell } from './cell';
|
|
31
31
|
import type { Table } from './table';
|
|
32
|
-
import { ValueType, GetValueType } from './value-type';
|
|
32
|
+
import { type SerializedValueType, ValueType, GetValueType, ValueTypeList } from './value-type';
|
|
33
33
|
import type { CellValue, UnionValue } from './union';
|
|
34
34
|
import type { Style } from './style';
|
|
35
35
|
|
|
@@ -80,10 +80,10 @@ export interface BaseCellData {
|
|
|
80
80
|
area?: IArea;
|
|
81
81
|
merge_area?: IArea;
|
|
82
82
|
validation?: DataValidation;
|
|
83
|
-
calculated_type?: ValueType;
|
|
83
|
+
calculated_type?: SerializedValueType; // ValueType;
|
|
84
84
|
note?: string;
|
|
85
85
|
hyperlink?: string;
|
|
86
|
-
type?: ValueType;
|
|
86
|
+
type?: SerializedValueType; // ValueType;
|
|
87
87
|
sheet_id?: number;
|
|
88
88
|
// locked?: boolean;
|
|
89
89
|
}
|
|
@@ -132,6 +132,17 @@ export const IsNestedRowArray = (test: NestedRowData[]|NestedColumnData[]): test
|
|
|
132
132
|
|
|
133
133
|
// ...
|
|
134
134
|
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* this is the reverse map, i.e. type => number
|
|
138
|
+
* FIXME: why is this getting exported by the API generator?
|
|
139
|
+
* FIXME: I get why it's dynamic, but for practical purposes why not just
|
|
140
|
+
* create a static map?
|
|
141
|
+
*/
|
|
142
|
+
const ValueTypeMap =
|
|
143
|
+
ValueTypeList.map((key, index) => ({ [key]: index })).reduce((set, value) => ({...set, ...value}), {}) as Record<SerializedValueType, ValueType>;
|
|
144
|
+
|
|
145
|
+
|
|
135
146
|
/**
|
|
136
147
|
* collection of cells, basically a wrapper around an
|
|
137
148
|
* array, with some accessor and control methods.
|
|
@@ -357,6 +368,53 @@ export class Cells {
|
|
|
357
368
|
this.columns_ = columns;
|
|
358
369
|
}
|
|
359
370
|
|
|
371
|
+
public SerializedTypeToValueType(type?: SerializedValueType|ValueType): ValueType|undefined {
|
|
372
|
+
|
|
373
|
+
if (!type) {
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (typeof type === 'number') {
|
|
378
|
+
return type as ValueType;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return ValueTypeMap[type] || undefined;
|
|
382
|
+
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
public ValueTypeToSerializedType(type?: ValueType): SerializedValueType|undefined {
|
|
386
|
+
return type ? ValueTypeList[type] : undefined;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* this method is used for importing legacy data validation types. in those
|
|
391
|
+
* those we used a numeric enum. we're just dropping that altogether (c.f.
|
|
392
|
+
* ValueType, which we're keeping) so we need to translate for backcompat.
|
|
393
|
+
* it's ugly, but it gets us to a better place. we can probably drop at some
|
|
394
|
+
* point in the future.
|
|
395
|
+
*
|
|
396
|
+
* export enum ValidationType {
|
|
397
|
+
* List = 'list',
|
|
398
|
+
* Date = 'date',
|
|
399
|
+
* Range = 'range',
|
|
400
|
+
* Number = 'number',
|
|
401
|
+
* Boolean = 'boolean',
|
|
402
|
+
* }
|
|
403
|
+
*
|
|
404
|
+
*/
|
|
405
|
+
public ImportDataValidation(value: DataValidation): DataValidation|undefined {
|
|
406
|
+
|
|
407
|
+
if (typeof (value as any).type === 'number') {
|
|
408
|
+
const types = ['list', 'date', 'range', 'number', 'boolean'];
|
|
409
|
+
(value as any).type = types[(value as any).type];
|
|
410
|
+
if (!value.type) {
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return value;
|
|
416
|
+
}
|
|
417
|
+
|
|
360
418
|
/**
|
|
361
419
|
* UPDATE: adding optional style refs, for export
|
|
362
420
|
*/
|
|
@@ -423,7 +481,7 @@ export class Cells {
|
|
|
423
481
|
if (typeof obj.calculated !== 'undefined') {
|
|
424
482
|
// cell.calculated = obj.calculated;
|
|
425
483
|
// cell.calculated_type = obj.calculated_type;
|
|
426
|
-
cell.SetCalculatedValue(obj.calculated, obj.calculated_type);
|
|
484
|
+
cell.SetCalculatedValue(obj.calculated, this.SerializedTypeToValueType(obj.calculated_type));
|
|
427
485
|
}
|
|
428
486
|
|
|
429
487
|
if (style_refs) {
|
|
@@ -494,7 +552,13 @@ export class Cells {
|
|
|
494
552
|
}
|
|
495
553
|
|
|
496
554
|
if (obj.validation) {
|
|
497
|
-
|
|
555
|
+
|
|
556
|
+
// the old type used a numeric enum. we just dropped that in favor
|
|
557
|
+
// of a string enum, so we can export it as a type. but for backwards
|
|
558
|
+
// compatibility we still need to think about the numeric enum.
|
|
559
|
+
|
|
560
|
+
cell.validation = this.ImportDataValidation(obj.validation);
|
|
561
|
+
|
|
498
562
|
}
|
|
499
563
|
|
|
500
564
|
}
|
|
@@ -606,7 +670,9 @@ export class Cells {
|
|
|
606
670
|
obj.hyperlink = cell.hyperlink;
|
|
607
671
|
}
|
|
608
672
|
|
|
609
|
-
if (options.preserve_type)
|
|
673
|
+
if (options.preserve_type) {
|
|
674
|
+
obj.type = this.ValueTypeToSerializedType(cell.type);
|
|
675
|
+
}
|
|
610
676
|
if (options.sheet_id) obj.sheet_id = options.sheet_id;
|
|
611
677
|
if (options.calculated_value &&
|
|
612
678
|
typeof cell.calculated !== 'undefined') { // && cell.calculated_type !== ValueType.error) {
|
|
@@ -614,7 +680,7 @@ export class Cells {
|
|
|
614
680
|
|
|
615
681
|
// always preserve error type, because we can't infer
|
|
616
682
|
if (options.preserve_type || cell.calculated_type === ValueType.error) {
|
|
617
|
-
obj.calculated_type = cell.calculated_type;
|
|
683
|
+
obj.calculated_type = this.ValueTypeToSerializedType(cell.calculated_type);
|
|
618
684
|
}
|
|
619
685
|
}
|
|
620
686
|
if (cell.table && table_head) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import type { Style } from './style';
|
|
23
|
-
import type { ValueType } from './value-type';
|
|
23
|
+
import type { SerializedValueType, ValueType } from './value-type';
|
|
24
24
|
import type { IArea } from './area';
|
|
25
25
|
import type { AnnotationLayout } from './layout';
|
|
26
26
|
import type { DataValidation } from './cell';
|
|
@@ -30,10 +30,10 @@ import type { AnnotationType } from 'treb-grid';
|
|
|
30
30
|
export interface CellParseResult {
|
|
31
31
|
row: number,
|
|
32
32
|
column: number,
|
|
33
|
-
type: ValueType,
|
|
33
|
+
type: SerializedValueType; // ValueType,
|
|
34
34
|
value: number|string|undefined|boolean,
|
|
35
35
|
calculated?: number|string|undefined|boolean,
|
|
36
|
-
calculated_type?: ValueType,
|
|
36
|
+
calculated_type?: SerializedValueType; // ValueType,
|
|
37
37
|
style_ref?: number,
|
|
38
38
|
hyperlink?: string,
|
|
39
39
|
validation?: DataValidation,
|
|
@@ -84,12 +84,44 @@ export const IsDimensionedQuantity = (value: unknown): value is DimensionedQuant
|
|
|
84
84
|
&& (typeof (value as DimensionedQuantity).unit === 'string');
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* this is the list of value types. internally, we use an enum. I don't
|
|
89
|
+
* want to change that, at least not at the moment, but that presents a
|
|
90
|
+
* problem for exporting types.
|
|
91
|
+
*
|
|
92
|
+
* we'll switch to string types for import/export, although we still support
|
|
93
|
+
* importing the old numeric enum types for backwards compatibility.
|
|
94
|
+
*/
|
|
95
|
+
export const ValueTypeList = [
|
|
96
|
+
'undefined',
|
|
97
|
+
'formula',
|
|
98
|
+
'string',
|
|
99
|
+
'number',
|
|
100
|
+
'boolean',
|
|
101
|
+
'object',
|
|
102
|
+
'error',
|
|
103
|
+
'complex',
|
|
104
|
+
'array',
|
|
105
|
+
'dimensioned_quantity',
|
|
106
|
+
] as const;
|
|
107
|
+
|
|
87
108
|
/**
|
|
88
|
-
*
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
* string types for import/export
|
|
110
|
+
*/
|
|
111
|
+
export type SerializedValueType = typeof ValueTypeList[number];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* this enum goes back a long way and is pretty ingrained, so I don't
|
|
115
|
+
* want to change it (at least not right now). but if we're exporting types,
|
|
116
|
+
* using enums is a problem.
|
|
117
|
+
*
|
|
118
|
+
* what we will do is keep the enum internally but switch the exported type
|
|
119
|
+
* to a string. the problem then becomes keeping the types matched up
|
|
120
|
+
* properly. I can't arrive at a good way of doing that automatically.
|
|
121
|
+
*
|
|
122
|
+
* old comments:
|
|
123
|
+
* ---
|
|
124
|
+
*
|
|
93
125
|
* undefined is 0 so we can test it as falsy.
|
|
94
126
|
*
|
|
95
127
|
* we're passing this type information out to calculators, so it needs
|
package/treb-embed/src/types.ts
CHANGED
|
@@ -46,23 +46,61 @@ export enum SaveFileType {
|
|
|
46
46
|
* I would like to do it, though, that `any` looks bad in the public API.
|
|
47
47
|
*/
|
|
48
48
|
export interface TREBDocument {
|
|
49
|
+
|
|
50
|
+
/** app name, as identifier */
|
|
49
51
|
app: string;
|
|
52
|
+
|
|
53
|
+
/** app version. we'll warn if you use a file from a newer version */
|
|
50
54
|
version: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* revision number. this is a value that increments on any document change,
|
|
58
|
+
* useful for checking if a document is "dirty".
|
|
59
|
+
*/
|
|
51
60
|
revision?: number;
|
|
61
|
+
|
|
62
|
+
/** document name */
|
|
52
63
|
name?: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* opaque user data. we don't read or parse this, but applications can
|
|
67
|
+
* use it to store arbitrary data.
|
|
68
|
+
*/
|
|
53
69
|
user_data?: any;
|
|
54
|
-
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* per-sheet data. this should be an array, but for historical reasons
|
|
73
|
+
* we still support a single sheet outside of an array.
|
|
74
|
+
*/
|
|
75
|
+
sheet_data?: SerializedSheet|SerializedSheet[];
|
|
76
|
+
|
|
77
|
+
/** document decimal mark */
|
|
55
78
|
decimal_mark?: '.' | ',';
|
|
79
|
+
|
|
80
|
+
/** active sheet. if unset we'll show the first un-hidden sheet */
|
|
56
81
|
active_sheet?: number;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* this document includes rendered calculated values. using this lets the
|
|
85
|
+
* app show a document faster, without requiring an initial calculation.
|
|
86
|
+
*/
|
|
57
87
|
rendered_values?: boolean;
|
|
58
88
|
|
|
59
|
-
|
|
89
|
+
/** document named ranges */
|
|
60
90
|
named_ranges?: Record<string, IArea>;
|
|
61
91
|
|
|
62
|
-
|
|
92
|
+
/** document named expressions */
|
|
63
93
|
named_expressions?: SerializedNamedExpression[];
|
|
94
|
+
|
|
95
|
+
/** document macro functions */
|
|
96
|
+
macro_functions?: SerializedMacroFunction[];
|
|
97
|
+
|
|
98
|
+
/** document tables */
|
|
64
99
|
tables?: Table[];
|
|
100
|
+
|
|
101
|
+
/** document shared resources (usually images) */
|
|
65
102
|
shared_resources?: Record<string, string>;
|
|
103
|
+
|
|
66
104
|
}
|
|
67
105
|
|
|
68
106
|
export interface ResizeEvent {
|
|
@@ -510,6 +510,66 @@ export class Exporter {
|
|
|
510
510
|
}
|
|
511
511
|
*/
|
|
512
512
|
|
|
513
|
+
/**
|
|
514
|
+
* FIXME: we might not always need this.
|
|
515
|
+
*/
|
|
516
|
+
public SheetStyle(sheet: SerializedSheet, style_cache: StyleCache) {
|
|
517
|
+
|
|
518
|
+
if (!sheet.sheet_style) {
|
|
519
|
+
return 0;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const options = style_cache.StyleOptionsFromProperties(sheet.sheet_style);
|
|
523
|
+
return style_cache.EnsureStyle(options);
|
|
524
|
+
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
public RowStyle(sheet: SerializedSheet, style_cache: StyleCache, row: number) {
|
|
528
|
+
|
|
529
|
+
const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
|
|
530
|
+
const list: Style.Properties[] = [sheet.sheet_style];
|
|
531
|
+
|
|
532
|
+
if (sheet.row_style) {
|
|
533
|
+
let style = sheet.row_style[row];
|
|
534
|
+
if (typeof style === 'number') {
|
|
535
|
+
style = cell_style_refs[style];
|
|
536
|
+
if (style) {
|
|
537
|
+
list.push(style);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else if (style) {
|
|
541
|
+
list.push(style);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const options = style_cache.StyleOptionsFromProperties(Style.Composite(list));
|
|
546
|
+
return style_cache.EnsureStyle(options);
|
|
547
|
+
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
public ColumnStyle(sheet: SerializedSheet, style_cache: StyleCache, column: number) {
|
|
551
|
+
|
|
552
|
+
const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
|
|
553
|
+
const list: Style.Properties[] = [sheet.sheet_style];
|
|
554
|
+
|
|
555
|
+
if (sheet.column_style) {
|
|
556
|
+
let style = sheet.column_style[column];
|
|
557
|
+
if (typeof style === 'number') {
|
|
558
|
+
style = cell_style_refs[style];
|
|
559
|
+
if (style) {
|
|
560
|
+
list.push(style);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
else if (style) {
|
|
564
|
+
list.push(style);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const options = style_cache.StyleOptionsFromProperties(Style.Composite(list));
|
|
569
|
+
return style_cache.EnsureStyle(options);
|
|
570
|
+
|
|
571
|
+
}
|
|
572
|
+
|
|
513
573
|
public StyleFromCell(sheet: SerializedSheet, style_cache: StyleCache, row: number, column: number, style: Style.Properties = {}) {
|
|
514
574
|
|
|
515
575
|
//if (row === 2 && column === 5)
|
|
@@ -1205,6 +1265,8 @@ export class Exporter {
|
|
|
1205
1265
|
const cells = new Cells();
|
|
1206
1266
|
cells.FromJSON(sheet.data, cell_style_refs);
|
|
1207
1267
|
|
|
1268
|
+
// console.info({ss: sheet.sheet_style, sheet});
|
|
1269
|
+
|
|
1208
1270
|
// these are cells with style but no contents
|
|
1209
1271
|
|
|
1210
1272
|
for (const entry of sheet.cell_styles) {
|
|
@@ -1249,7 +1311,20 @@ export class Exporter {
|
|
|
1249
1311
|
|
|
1250
1312
|
// --
|
|
1251
1313
|
|
|
1314
|
+
//
|
|
1315
|
+
// this is a map of column number -> column style. we need this
|
|
1316
|
+
// for two things: (1) so we can skip cells that are empty, but
|
|
1317
|
+
// have a style from the column; and (2) so we can create the list
|
|
1318
|
+
// of columns, including styles.
|
|
1319
|
+
//
|
|
1320
|
+
const column_style_map: number[] = [];
|
|
1321
|
+
|
|
1322
|
+
const sheet_style = this.SheetStyle(sheet, style_cache);
|
|
1323
|
+
|
|
1252
1324
|
for (let r = 0; r < cells.data.length; r++ ) {
|
|
1325
|
+
|
|
1326
|
+
const row_style = this.RowStyle(sheet, style_cache, r);
|
|
1327
|
+
|
|
1253
1328
|
if (cells.data[r] && cells.data[r].length) {
|
|
1254
1329
|
|
|
1255
1330
|
// push out the extent (reversed)
|
|
@@ -1262,6 +1337,11 @@ export class Exporter {
|
|
|
1262
1337
|
const row: any = [];
|
|
1263
1338
|
|
|
1264
1339
|
for (let c = 0; c < cells.data[r].length; c++) {
|
|
1340
|
+
|
|
1341
|
+
if (!column_style_map[c]) {
|
|
1342
|
+
column_style_map[c] = this.ColumnStyle(sheet, style_cache, c);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1265
1345
|
const cell = cells.data[r][c];
|
|
1266
1346
|
if (cell) {
|
|
1267
1347
|
|
|
@@ -1447,6 +1527,17 @@ export class Exporter {
|
|
|
1447
1527
|
// s is style, index into the style table
|
|
1448
1528
|
const s: number|undefined = this.StyleFromCell(sheet, style_cache, r, c, cell.style);
|
|
1449
1529
|
|
|
1530
|
+
if (cell.type === ValueType.undefined) {
|
|
1531
|
+
|
|
1532
|
+
// you can skip if (1) there's a row style, and style === row style;
|
|
1533
|
+
// (2) there's a column style, no row style, and style === column style
|
|
1534
|
+
|
|
1535
|
+
if ((row_style && s === row_style) ||
|
|
1536
|
+
(!row_style && (column_style_map[c] && s === column_style_map[c]))) {
|
|
1537
|
+
continue; // can skip
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1450
1541
|
// v (child element) is the value
|
|
1451
1542
|
let v: CellValue = undefined;
|
|
1452
1543
|
let t: string|undefined;
|
|
@@ -1516,7 +1607,13 @@ export class Exporter {
|
|
|
1516
1607
|
element.a$.t = t;
|
|
1517
1608
|
}
|
|
1518
1609
|
if (s !== undefined) {
|
|
1610
|
+
|
|
1611
|
+
// we could skip this if it's equal to row style,
|
|
1612
|
+
// or there is no row style and it's equal to column style
|
|
1613
|
+
// or there is no column style and it's equal to sheet style
|
|
1614
|
+
|
|
1519
1615
|
element.a$.s = s;
|
|
1616
|
+
|
|
1520
1617
|
}
|
|
1521
1618
|
if (f !== undefined) {
|
|
1522
1619
|
element.f = f;
|
|
@@ -1530,11 +1627,12 @@ export class Exporter {
|
|
|
1530
1627
|
}
|
|
1531
1628
|
}
|
|
1532
1629
|
|
|
1533
|
-
if (row.length) {
|
|
1630
|
+
if (row.length || (row_style && row_style !== sheet_style)) {
|
|
1631
|
+
|
|
1534
1632
|
const row_data: any = {
|
|
1535
1633
|
a$: {
|
|
1536
1634
|
r: r + 1,
|
|
1537
|
-
spans: `${span.start + 1}:${span.end + 1}`,
|
|
1635
|
+
spans: `${span.start + 1}:${span.end + 1}`, // this works out to 0:0 for an empty row, will that work?
|
|
1538
1636
|
},
|
|
1539
1637
|
c: row,
|
|
1540
1638
|
};
|
|
@@ -1546,6 +1644,11 @@ export class Exporter {
|
|
|
1546
1644
|
row_data.a$.ht = sheet.row_height[r] * 3 / 4;
|
|
1547
1645
|
}
|
|
1548
1646
|
|
|
1647
|
+
if (row_style && row_style !== sheet_style) {
|
|
1648
|
+
row_data.a$.s = row_style;
|
|
1649
|
+
row_data.a$.customFormat = 1;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1549
1652
|
sheet_data.row.push(row_data);
|
|
1550
1653
|
}
|
|
1551
1654
|
|
|
@@ -1563,6 +1666,10 @@ export class Exporter {
|
|
|
1563
1666
|
index: number;
|
|
1564
1667
|
}> = [];
|
|
1565
1668
|
|
|
1669
|
+
// we only need to include column style if it's !== sheet style,
|
|
1670
|
+
// because we'll have a default entry for columns that have the
|
|
1671
|
+
// sheet style. this is only for columns that are different.
|
|
1672
|
+
|
|
1566
1673
|
if (sheet.default_column_width) {
|
|
1567
1674
|
dom.worksheet.sheetFormatPr.a$.defaultColWidth = // sheet.default_column_width * one_hundred_pixels / 100;
|
|
1568
1675
|
PixelsToColumnWidth(sheet.default_column_width);
|
|
@@ -1582,7 +1689,14 @@ export class Exporter {
|
|
|
1582
1689
|
|
|
1583
1690
|
}
|
|
1584
1691
|
|
|
1692
|
+
let style = column_style_map[c];
|
|
1693
|
+
if (style && style !== sheet_style) {
|
|
1694
|
+
entry.style = style;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
/*
|
|
1585
1698
|
let style = sheet.column_style[c];
|
|
1699
|
+
|
|
1586
1700
|
if (typeof style === 'number') {
|
|
1587
1701
|
style = cell_style_refs[style];
|
|
1588
1702
|
if (style) {
|
|
@@ -1592,6 +1706,7 @@ export class Exporter {
|
|
|
1592
1706
|
else if (style) {
|
|
1593
1707
|
entry.style = style_cache.EnsureStyle(style_cache.StyleOptionsFromProperties(style));
|
|
1594
1708
|
}
|
|
1709
|
+
*/
|
|
1595
1710
|
|
|
1596
1711
|
//if (sheet.column_style[c]) {
|
|
1597
1712
|
// entry.style = style_cache.EnsureStyle(style_cache.StyleOptionsFromProperties(sheet.column_style[c]));
|
|
@@ -1605,8 +1720,73 @@ export class Exporter {
|
|
|
1605
1720
|
// we're short-cutting here, these should be arranged in blocks if
|
|
1606
1721
|
// there's overlap. not sure how much of an issue that is though.
|
|
1607
1722
|
|
|
1608
|
-
if (column_entries.length) {
|
|
1609
|
-
|
|
1723
|
+
if (column_entries.length || sheet_style) {
|
|
1724
|
+
|
|
1725
|
+
const filled: any[] = [];
|
|
1726
|
+
const default_column_width = PixelsToColumnWidth(sheet.default_column_width || 90);
|
|
1727
|
+
|
|
1728
|
+
// FIXME: can merge these two branches
|
|
1729
|
+
|
|
1730
|
+
{ // if (sheet_style) {
|
|
1731
|
+
|
|
1732
|
+
let start_index = 0;
|
|
1733
|
+
for (const entry of column_entries) {
|
|
1734
|
+
if (!entry) { continue; }
|
|
1735
|
+
|
|
1736
|
+
// fill with defaults
|
|
1737
|
+
|
|
1738
|
+
if (sheet_style && (entry.index > start_index + 1)) {
|
|
1739
|
+
filled.push({
|
|
1740
|
+
a$: {
|
|
1741
|
+
min: start_index + 1,
|
|
1742
|
+
max: entry.index,
|
|
1743
|
+
style: sheet_style,
|
|
1744
|
+
width: default_column_width,
|
|
1745
|
+
},
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
const a$: any = {
|
|
1750
|
+
min: entry.index + 1,
|
|
1751
|
+
max: entry.index + 1,
|
|
1752
|
+
};
|
|
1753
|
+
if (entry.style === undefined) {
|
|
1754
|
+
a$.style = sheet_style;
|
|
1755
|
+
}
|
|
1756
|
+
else {
|
|
1757
|
+
a$.style = entry.style;
|
|
1758
|
+
}
|
|
1759
|
+
if (entry.width !== undefined) {
|
|
1760
|
+
a$.width = entry.width;
|
|
1761
|
+
a$.customWidth = 1;
|
|
1762
|
+
}
|
|
1763
|
+
else {
|
|
1764
|
+
a$.width = default_column_width;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
filled.push({a$});
|
|
1768
|
+
|
|
1769
|
+
start_index = entry.index;
|
|
1770
|
+
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
if (sheet_style && (start_index < 16384)) { // OK, sure why not
|
|
1774
|
+
filled.push({
|
|
1775
|
+
a$: {
|
|
1776
|
+
min: start_index + 1,
|
|
1777
|
+
max: 16384,
|
|
1778
|
+
style: sheet_style,
|
|
1779
|
+
width: default_column_width,
|
|
1780
|
+
},
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
dom.worksheet.cols.col = filled;
|
|
1785
|
+
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
/*
|
|
1789
|
+
else {
|
|
1610
1790
|
dom.worksheet.cols.col = column_entries.map(entry => {
|
|
1611
1791
|
const a$: any = {
|
|
1612
1792
|
min: entry.index + 1,
|
|
@@ -1621,12 +1801,15 @@ export class Exporter {
|
|
|
1621
1801
|
}
|
|
1622
1802
|
else {
|
|
1623
1803
|
a$.width = // (sheet.default_column_width || 100) / 100 * one_hundred_pixels;
|
|
1624
|
-
PixelsToColumnWidth(sheet.default_column_width || 90);
|
|
1804
|
+
default_column_width; // PixelsToColumnWidth(sheet.default_column_width || 90);
|
|
1625
1805
|
}
|
|
1626
1806
|
return {a$};
|
|
1627
1807
|
});
|
|
1628
1808
|
}
|
|
1809
|
+
console.info({cols: dom.worksheet.cols});
|
|
1810
|
+
*/
|
|
1629
1811
|
}
|
|
1812
|
+
|
|
1630
1813
|
else {
|
|
1631
1814
|
delete dom.worksheet.cols;
|
|
1632
1815
|
}
|