@trebco/treb 23.6.2 → 25.0.0-rc1
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/.eslintignore +8 -0
- package/.eslintrc.js +164 -0
- package/README-shadow-DOM.md +88 -0
- package/README.md +37 -130
- package/api-config.json +29 -0
- package/api-generator/api-generator-types.ts +82 -0
- package/api-generator/api-generator.ts +1172 -0
- package/api-generator/package.json +3 -0
- package/build/treb-spreadsheet.mjs +14 -0
- package/{treb.d.ts → build/treb.d.ts} +293 -299
- package/esbuild-custom-element.mjs +336 -0
- package/esbuild.js +305 -0
- package/package.json +43 -14
- package/treb-base-types/package.json +5 -0
- package/treb-base-types/src/api_types.ts +36 -0
- package/treb-base-types/src/area.ts +583 -0
- package/treb-base-types/src/basic_types.ts +45 -0
- package/treb-base-types/src/cell.ts +612 -0
- package/treb-base-types/src/cells.ts +1066 -0
- package/treb-base-types/src/color.ts +124 -0
- package/treb-base-types/src/import.ts +71 -0
- package/treb-base-types/src/index-standalone.ts +29 -0
- package/treb-base-types/src/index.ts +42 -0
- package/treb-base-types/src/layout.ts +47 -0
- package/treb-base-types/src/localization.ts +187 -0
- package/treb-base-types/src/rectangle.ts +145 -0
- package/treb-base-types/src/render_text.ts +72 -0
- package/treb-base-types/src/style.ts +545 -0
- package/treb-base-types/src/table.ts +109 -0
- package/treb-base-types/src/text_part.ts +54 -0
- package/treb-base-types/src/theme.ts +608 -0
- package/treb-base-types/src/union.ts +152 -0
- package/treb-base-types/src/value-type.ts +164 -0
- package/treb-base-types/style/resizable.css +59 -0
- package/treb-calculator/modern.tsconfig.json +11 -0
- package/treb-calculator/package.json +5 -0
- package/treb-calculator/src/calculator.ts +2546 -0
- package/treb-calculator/src/complex-math.ts +558 -0
- package/treb-calculator/src/dag/array-vertex.ts +198 -0
- package/treb-calculator/src/dag/graph.ts +951 -0
- package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
- package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
- package/treb-calculator/src/dag/vertex.ts +352 -0
- package/treb-calculator/src/descriptors.ts +162 -0
- package/treb-calculator/src/expression-calculator.ts +1069 -0
- package/treb-calculator/src/function-error.ts +103 -0
- package/treb-calculator/src/function-library.ts +103 -0
- package/treb-calculator/src/functions/base-functions.ts +1214 -0
- package/treb-calculator/src/functions/checkbox.ts +164 -0
- package/treb-calculator/src/functions/complex-functions.ts +253 -0
- package/treb-calculator/src/functions/finance-functions.ts +399 -0
- package/treb-calculator/src/functions/information-functions.ts +102 -0
- package/treb-calculator/src/functions/matrix-functions.ts +182 -0
- package/treb-calculator/src/functions/sparkline.ts +335 -0
- package/treb-calculator/src/functions/statistics-functions.ts +350 -0
- package/treb-calculator/src/functions/text-functions.ts +298 -0
- package/treb-calculator/src/index.ts +27 -0
- package/treb-calculator/src/notifier-types.ts +59 -0
- package/treb-calculator/src/primitives.ts +428 -0
- package/treb-calculator/src/utilities.ts +305 -0
- package/treb-charts/package.json +5 -0
- package/treb-charts/src/chart-functions.ts +156 -0
- package/treb-charts/src/chart-types.ts +230 -0
- package/treb-charts/src/chart.ts +1288 -0
- package/treb-charts/src/index.ts +24 -0
- package/treb-charts/src/main.ts +37 -0
- package/treb-charts/src/rectangle.ts +52 -0
- package/treb-charts/src/renderer.ts +1841 -0
- package/treb-charts/src/util.ts +122 -0
- package/treb-charts/style/charts.scss +221 -0
- package/treb-charts/style/old-charts.scss +250 -0
- package/treb-embed/markup/layout.html +137 -0
- package/treb-embed/markup/toolbar.html +175 -0
- package/treb-embed/modern.tsconfig.json +25 -0
- package/treb-embed/src/custom-element/content-types.d.ts +18 -0
- package/treb-embed/src/custom-element/global.d.ts +11 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
- package/treb-embed/src/custom-element/treb-global.ts +44 -0
- package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
- package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
- package/treb-embed/src/index.ts +16 -0
- package/treb-embed/src/language-model.ts +41 -0
- package/treb-embed/src/options.ts +320 -0
- package/treb-embed/src/progress-dialog.ts +228 -0
- package/treb-embed/src/selection-state.ts +16 -0
- package/treb-embed/src/spinner.ts +42 -0
- package/treb-embed/src/toolbar-message.ts +96 -0
- package/treb-embed/src/types.ts +167 -0
- package/treb-embed/style/autocomplete.scss +103 -0
- package/treb-embed/style/dark-theme.scss +114 -0
- package/treb-embed/style/defaults.scss +36 -0
- package/treb-embed/style/dialog.scss +181 -0
- package/treb-embed/style/dropdown-select.scss +101 -0
- package/treb-embed/style/formula-bar.scss +193 -0
- package/treb-embed/style/grid.scss +374 -0
- package/treb-embed/style/layout.scss +424 -0
- package/treb-embed/style/mouse-mask.scss +67 -0
- package/treb-embed/style/note.scss +92 -0
- package/treb-embed/style/overlay-editor.scss +102 -0
- package/treb-embed/style/spinner.scss +92 -0
- package/treb-embed/style/tab-bar.scss +228 -0
- package/treb-embed/style/table.scss +80 -0
- package/treb-embed/style/theme-defaults.scss +444 -0
- package/treb-embed/style/toolbar.scss +416 -0
- package/treb-embed/style/tooltip.scss +68 -0
- package/treb-embed/style/treb-icons.scss +130 -0
- package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
- package/treb-embed/style/z-index.scss +43 -0
- package/treb-export/docs/charts.md +68 -0
- package/treb-export/modern.tsconfig.json +19 -0
- package/treb-export/package.json +4 -0
- package/treb-export/src/address-type.ts +77 -0
- package/treb-export/src/base-template.ts +22 -0
- package/treb-export/src/column-width.ts +85 -0
- package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
- package/treb-export/src/drawing2/chart2.ts +282 -0
- package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
- package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
- package/treb-export/src/drawing2/drawing2.ts +355 -0
- package/treb-export/src/drawing2/embedded-image.ts +71 -0
- package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
- package/treb-export/src/export-worker/export-worker.ts +99 -0
- package/treb-export/src/export-worker/index-modern.ts +22 -0
- package/treb-export/src/export2.ts +2204 -0
- package/treb-export/src/import2.ts +882 -0
- package/treb-export/src/relationship.ts +36 -0
- package/treb-export/src/shared-strings2.ts +128 -0
- package/treb-export/src/template-2.ts +22 -0
- package/treb-export/src/unescape_xml.ts +47 -0
- package/treb-export/src/workbook-sheet2.ts +182 -0
- package/treb-export/src/workbook-style2.ts +1285 -0
- package/treb-export/src/workbook-theme2.ts +88 -0
- package/treb-export/src/workbook2.ts +491 -0
- package/treb-export/src/xml-utils.ts +201 -0
- package/treb-export/template/base/[Content_Types].xml +2 -0
- package/treb-export/template/base/_rels/.rels +2 -0
- package/treb-export/template/base/docProps/app.xml +2 -0
- package/treb-export/template/base/docProps/core.xml +12 -0
- package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
- package/treb-export/template/base/xl/sharedStrings.xml +2 -0
- package/treb-export/template/base/xl/styles.xml +2 -0
- package/treb-export/template/base/xl/theme/theme1.xml +2 -0
- package/treb-export/template/base/xl/workbook.xml +2 -0
- package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
- package/treb-export/template/base.xlsx +0 -0
- package/treb-format/package.json +8 -0
- package/treb-format/src/format.test.ts +213 -0
- package/treb-format/src/format.ts +942 -0
- package/treb-format/src/format_cache.ts +199 -0
- package/treb-format/src/format_parser.ts +723 -0
- package/treb-format/src/index.ts +25 -0
- package/treb-format/src/number_format_section.ts +100 -0
- package/treb-format/src/value_parser.ts +337 -0
- package/treb-grid/package.json +5 -0
- package/treb-grid/src/editors/autocomplete.ts +394 -0
- package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
- package/treb-grid/src/editors/formula_bar.ts +473 -0
- package/treb-grid/src/editors/formula_editor_base.ts +910 -0
- package/treb-grid/src/editors/overlay_editor.ts +511 -0
- package/treb-grid/src/index.ts +37 -0
- package/treb-grid/src/layout/base_layout.ts +2618 -0
- package/treb-grid/src/layout/grid_layout.ts +299 -0
- package/treb-grid/src/layout/rectangle_cache.ts +86 -0
- package/treb-grid/src/render/selection-renderer.ts +414 -0
- package/treb-grid/src/render/svg_header_overlay.ts +93 -0
- package/treb-grid/src/render/svg_selection_block.ts +187 -0
- package/treb-grid/src/render/tile_renderer.ts +2122 -0
- package/treb-grid/src/types/annotation.ts +216 -0
- package/treb-grid/src/types/border_constants.ts +34 -0
- package/treb-grid/src/types/clipboard_data.ts +31 -0
- package/treb-grid/src/types/data_model.ts +334 -0
- package/treb-grid/src/types/drag_mask.ts +81 -0
- package/treb-grid/src/types/grid.ts +7743 -0
- package/treb-grid/src/types/grid_base.ts +3644 -0
- package/treb-grid/src/types/grid_command.ts +470 -0
- package/treb-grid/src/types/grid_events.ts +124 -0
- package/treb-grid/src/types/grid_options.ts +97 -0
- package/treb-grid/src/types/grid_selection.ts +60 -0
- package/treb-grid/src/types/named_range.ts +369 -0
- package/treb-grid/src/types/scale-control.ts +202 -0
- package/treb-grid/src/types/serialize_options.ts +72 -0
- package/treb-grid/src/types/set_range_options.ts +52 -0
- package/treb-grid/src/types/sheet.ts +3099 -0
- package/treb-grid/src/types/sheet_types.ts +95 -0
- package/treb-grid/src/types/tab_bar.ts +464 -0
- package/treb-grid/src/types/tile.ts +59 -0
- package/treb-grid/src/types/update_flags.ts +75 -0
- package/treb-grid/src/util/dom_utilities.ts +44 -0
- package/treb-grid/src/util/fontmetrics2.ts +179 -0
- package/treb-grid/src/util/ua.ts +104 -0
- package/treb-logo.svg +18 -0
- package/treb-parser/package.json +5 -0
- package/treb-parser/src/csv-parser.ts +122 -0
- package/treb-parser/src/index.ts +25 -0
- package/treb-parser/src/md-parser.ts +526 -0
- package/treb-parser/src/parser-types.ts +397 -0
- package/treb-parser/src/parser.test.ts +298 -0
- package/treb-parser/src/parser.ts +2673 -0
- package/treb-utils/package.json +5 -0
- package/treb-utils/src/dispatch.ts +57 -0
- package/treb-utils/src/event_source.ts +147 -0
- package/treb-utils/src/ievent_source.ts +33 -0
- package/treb-utils/src/index.ts +31 -0
- package/treb-utils/src/measurement.ts +174 -0
- package/treb-utils/src/resizable.ts +160 -0
- package/treb-utils/src/scale.ts +137 -0
- package/treb-utils/src/serialize_html.ts +124 -0
- package/treb-utils/src/template.ts +70 -0
- package/treb-utils/src/validate_uri.ts +61 -0
- package/tsconfig.json +10 -0
- package/tsproject.json +30 -0
- package/util/license-plugin-esbuild.js +86 -0
- package/util/list-css-vars.sh +46 -0
- package/README-esm.md +0 -37
- package/treb-bundle.css +0 -2
- package/treb-bundle.mjs +0 -15
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { XMLUtils } from './xml-utils';
|
|
23
|
+
|
|
24
|
+
export interface ColorSchemeElement {
|
|
25
|
+
name?: string;
|
|
26
|
+
value?: string;
|
|
27
|
+
type?: 'rgb'|'system';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class Theme {
|
|
31
|
+
|
|
32
|
+
// where is this defined?
|
|
33
|
+
public static color_map = [
|
|
34
|
+
'lt1', // bg 1
|
|
35
|
+
'dk1', // text 1
|
|
36
|
+
'lt2', // bg 2
|
|
37
|
+
'dk2', // text 2
|
|
38
|
+
'accent1',
|
|
39
|
+
'accent2',
|
|
40
|
+
'accent3',
|
|
41
|
+
'accent4',
|
|
42
|
+
'accent5',
|
|
43
|
+
'accent6',
|
|
44
|
+
'hlink',
|
|
45
|
+
'folHlink',
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
public colors: {[index: string]: ColorSchemeElement} = {};
|
|
49
|
+
|
|
50
|
+
// private dom?: ElementTree.ElementTree;
|
|
51
|
+
|
|
52
|
+
public FromXML(xml: any): void {
|
|
53
|
+
|
|
54
|
+
const tag = Object.keys(xml)[0];
|
|
55
|
+
|
|
56
|
+
let namespace = '';
|
|
57
|
+
const match = tag.toString().match(/^(.*?):/);
|
|
58
|
+
|
|
59
|
+
if (match) {
|
|
60
|
+
namespace = match[1] + ':';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (xml[tag] && xml[tag][`${namespace}themeElements`]) {
|
|
64
|
+
const color_scheme = xml[tag][`${namespace}themeElements`][`${namespace}clrScheme`];
|
|
65
|
+
|
|
66
|
+
for (const name of Theme.color_map) {
|
|
67
|
+
const element = color_scheme[`${namespace}${name}`];
|
|
68
|
+
|
|
69
|
+
let value: string | undefined;
|
|
70
|
+
let type: 'rgb'|'system' = 'rgb';
|
|
71
|
+
|
|
72
|
+
if (element[`${namespace}srgbClr`]) {
|
|
73
|
+
type = 'rgb';
|
|
74
|
+
value = element[`${namespace}srgbClr`].a$.val || '';
|
|
75
|
+
}
|
|
76
|
+
else if (element[`${namespace}sysClr`]) {
|
|
77
|
+
type = 'system';
|
|
78
|
+
value = element[`${namespace}sysClr`].a$.lastClr || '';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.colors[name] = {name, value, type};
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type JSZip from 'jszip';
|
|
23
|
+
// import * as xmlparser from 'fast-xml-parser';
|
|
24
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
25
|
+
import { XMLUtils, XMLOptions, XMLOptions2 } from './xml-utils';
|
|
26
|
+
|
|
27
|
+
// const xmlparser = new XMLParser();
|
|
28
|
+
const xmlparser1 = new XMLParser(XMLOptions);
|
|
29
|
+
const xmlparser2 = new XMLParser(XMLOptions2);
|
|
30
|
+
|
|
31
|
+
// import * as he from 'he';
|
|
32
|
+
|
|
33
|
+
//import { Drawing, TwoCellAnchor, CellAnchor } from './drawing/drawing';
|
|
34
|
+
import type { TwoCellAnchor, CellAnchor } from './drawing2/drawing2';
|
|
35
|
+
|
|
36
|
+
// import { ImportedSheetData, IArea } from 'treb-base-types/src';
|
|
37
|
+
import { SharedStrings } from './shared-strings2';
|
|
38
|
+
import { StyleCache } from './workbook-style2';
|
|
39
|
+
import { Theme } from './workbook-theme2';
|
|
40
|
+
import { Sheet, VisibleState } from './workbook-sheet2';
|
|
41
|
+
import type { RelationshipMap } from './relationship';
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
const XMLTypeMap = {
|
|
46
|
+
'sheet': 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
|
|
47
|
+
'theme': 'application/vnd.openxmlformats-officedocument.theme+xml',
|
|
48
|
+
'drawing': 'application/vnd.openxmlformats-officedocument.drawing+xml',
|
|
49
|
+
'chart': 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml',
|
|
50
|
+
'themeOverride': 'application/vnd.openxmlformats-officedocument.themeOverride+xml',
|
|
51
|
+
'ctrlProp': 'application/vnd.ms-excel.controlproperties+xml',
|
|
52
|
+
'style': 'application/vnd.ms-office.chartstyle+xml',
|
|
53
|
+
'colors': 'application/vnd.ms-office.chartcolorstyle+xml',
|
|
54
|
+
};
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
export enum ChartType {
|
|
58
|
+
Unknown = 0, Column, Bar, Line, Scatter, Donut, Pie
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ChartSeries {
|
|
62
|
+
values?: string;
|
|
63
|
+
categories?: string;
|
|
64
|
+
title?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ChartDescription {
|
|
68
|
+
title?: string;
|
|
69
|
+
type: ChartType;
|
|
70
|
+
series?: ChartSeries[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface AnchoredChartDescription {
|
|
74
|
+
chart?: ChartDescription,
|
|
75
|
+
anchor: TwoCellAnchor,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface TableFooterType {
|
|
79
|
+
type: 'label'|'formula';
|
|
80
|
+
value: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface TableDescription {
|
|
84
|
+
name: string;
|
|
85
|
+
display_name: string;
|
|
86
|
+
ref: string;
|
|
87
|
+
filterRef?: string;
|
|
88
|
+
|
|
89
|
+
totals_row_shown?: number; // number? it's 0 in the xml
|
|
90
|
+
totals_row_count?: number; // apparently when there _is_ a totals row, we have this attribute instead of the other one
|
|
91
|
+
|
|
92
|
+
rel?: string;
|
|
93
|
+
index?: number;
|
|
94
|
+
columns?: string[];
|
|
95
|
+
footers?: TableFooterType[];
|
|
96
|
+
|
|
97
|
+
// auto filter?
|
|
98
|
+
|
|
99
|
+
// column names?
|
|
100
|
+
|
|
101
|
+
// style?
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class Workbook {
|
|
106
|
+
|
|
107
|
+
public xml: any = {};
|
|
108
|
+
|
|
109
|
+
/** start with an empty strings table, if we load a file we will update it */
|
|
110
|
+
public shared_strings = new SharedStrings();
|
|
111
|
+
|
|
112
|
+
/** document styles */
|
|
113
|
+
public style_cache = new StyleCache(); // public temp
|
|
114
|
+
|
|
115
|
+
/** theme */
|
|
116
|
+
public theme = new Theme();
|
|
117
|
+
|
|
118
|
+
/** defined names. these can be ranges or expressions. */
|
|
119
|
+
public defined_names: Record<string, string> = {};
|
|
120
|
+
|
|
121
|
+
/** the workbook "rels" */
|
|
122
|
+
public rels: RelationshipMap = {};
|
|
123
|
+
|
|
124
|
+
public sheets: Sheet[] = [];
|
|
125
|
+
|
|
126
|
+
public active_tab = 0;
|
|
127
|
+
|
|
128
|
+
public get sheet_count(): number {
|
|
129
|
+
return this.sheets.length;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
constructor(public zip: JSZip) {
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* given a path in the zip file, read and parse the rels file
|
|
138
|
+
*/
|
|
139
|
+
public async ReadRels(path: string): Promise<RelationshipMap> {
|
|
140
|
+
|
|
141
|
+
const rels: RelationshipMap = {};
|
|
142
|
+
const data = await this.zip.file(path)?.async('text') as string;
|
|
143
|
+
|
|
144
|
+
//
|
|
145
|
+
// force array on <Relationship/> elements, but be slack on the rest
|
|
146
|
+
// (we know they are single elements)
|
|
147
|
+
//
|
|
148
|
+
const xml = xmlparser2.parse(data || '');
|
|
149
|
+
|
|
150
|
+
for (const relationship of xml.Relationships?.Relationship || []) {
|
|
151
|
+
const id = relationship.a$.Id;
|
|
152
|
+
rels[id] = {
|
|
153
|
+
id,
|
|
154
|
+
type: relationship.a$.Type,
|
|
155
|
+
target: relationship.a$.Target,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return rels;
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public async Init(): Promise<void> {
|
|
164
|
+
|
|
165
|
+
// read workbook rels
|
|
166
|
+
this.rels = await this.ReadRels( 'xl/_rels/workbook.xml.rels');
|
|
167
|
+
|
|
168
|
+
// shared strings
|
|
169
|
+
let data = await this.zip.file('xl/sharedStrings.xml')?.async('text') as string;
|
|
170
|
+
let xml = xmlparser2.parse(data || '');
|
|
171
|
+
this.shared_strings.FromXML(xml);
|
|
172
|
+
|
|
173
|
+
// theme
|
|
174
|
+
data = await this.zip.file('xl/theme/theme1.xml')?.async('text') as string;
|
|
175
|
+
xml = xmlparser2.parse(data);
|
|
176
|
+
this.theme.FromXML(xml);
|
|
177
|
+
|
|
178
|
+
// styles
|
|
179
|
+
data = await this.zip.file('xl/styles.xml')?.async('text') as string;
|
|
180
|
+
xml = xmlparser2.parse(data);
|
|
181
|
+
this.style_cache.FromXML(xml, this.theme);
|
|
182
|
+
|
|
183
|
+
console.info({c: this.style_cache});
|
|
184
|
+
|
|
185
|
+
// read workbook
|
|
186
|
+
data = await this.zip.file('xl/workbook.xml')?.async('text') as string;
|
|
187
|
+
xml = xmlparser2.parse(data);
|
|
188
|
+
|
|
189
|
+
// defined names
|
|
190
|
+
this.defined_names = {};
|
|
191
|
+
const defined_names = XMLUtils.FindAll(xml, 'workbook/definedNames/definedName');
|
|
192
|
+
for (const defined_name of defined_names) {
|
|
193
|
+
const name = defined_name.a$?.name;
|
|
194
|
+
const expression = defined_name.t$ || '';
|
|
195
|
+
if (name && expression) {
|
|
196
|
+
this.defined_names[name] = expression;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const workbook_views = XMLUtils.FindAll(xml, 'workbook/bookViews/workbookView');
|
|
201
|
+
|
|
202
|
+
if (workbook_views[0]?.a$?.activeTab) {
|
|
203
|
+
this.active_tab = Number(workbook_views[0].a$.activeTab) || 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// read sheets. in this version we preparse everything.
|
|
207
|
+
const composite = XMLUtils.FindAll(xml, 'workbook/sheets/sheet');
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
for (const element of composite) {
|
|
211
|
+
const name = element.a$?.name;
|
|
212
|
+
|
|
213
|
+
if (name) {
|
|
214
|
+
|
|
215
|
+
const state = element.a$.state;
|
|
216
|
+
const rid = element.a$['r:id'];
|
|
217
|
+
|
|
218
|
+
const worksheet = new Sheet({
|
|
219
|
+
name, rid, id: Number(element.a$.sheetId)
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (state === 'hidden') {
|
|
223
|
+
worksheet.visible_state = VisibleState.hidden;
|
|
224
|
+
}
|
|
225
|
+
else if (state === 'veryHidden') {
|
|
226
|
+
worksheet.visible_state = VisibleState.very_hidden;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
worksheet.shared_strings = this.shared_strings;
|
|
230
|
+
|
|
231
|
+
worksheet.path = `xl/${this.rels[rid].target}`;
|
|
232
|
+
worksheet.rels_path = worksheet.path.replace('worksheets', 'worksheets/_rels') + '.rels';
|
|
233
|
+
|
|
234
|
+
data = await this.zip.file(worksheet.path)?.async('text') as string;
|
|
235
|
+
worksheet.sheet_data = xmlparser2.parse(data || '');
|
|
236
|
+
worksheet.rels = await this.ReadRels(worksheet.rels_path);
|
|
237
|
+
|
|
238
|
+
worksheet.Parse();
|
|
239
|
+
// console.info("TS", worksheet);
|
|
240
|
+
|
|
241
|
+
this.sheets.push(worksheet);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// console.info("TS", this.sheets);
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public async ReadTable(reference: string): Promise<TableDescription|undefined> {
|
|
251
|
+
|
|
252
|
+
const data = await this.zip.file(reference.replace(/^../, 'xl'))?.async('text') as string;
|
|
253
|
+
|
|
254
|
+
if (!data) {
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const xml = xmlparser2.parse(data);
|
|
259
|
+
const name = xml.table?.a$?.name || '';
|
|
260
|
+
|
|
261
|
+
const table: TableDescription = {
|
|
262
|
+
name,
|
|
263
|
+
display_name: xml.table?.a$?.displayName || name,
|
|
264
|
+
ref: xml.table?.a$.ref || '',
|
|
265
|
+
totals_row_shown: Number(xml.table?.a$.totalsRowShown || '0') || 0,
|
|
266
|
+
totals_row_count: Number(xml.table?.a$.totalsRowCount || '0') || 0,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return table;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
public async ReadDrawing(reference: string): Promise<AnchoredChartDescription[] | undefined> {
|
|
273
|
+
|
|
274
|
+
const data = await this.zip.file(reference.replace(/^../, 'xl'))?.async('text') as string;
|
|
275
|
+
if (!data) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
const xml = xmlparser2.parse(data);
|
|
279
|
+
|
|
280
|
+
const drawing_rels = await this.ReadRels(reference.replace(/^..\/drawings/, 'xl/drawings/_rels') + '.rels');
|
|
281
|
+
|
|
282
|
+
const results: AnchoredChartDescription[] = [];
|
|
283
|
+
const anchor_nodes = XMLUtils.FindAll(xml, 'xdr:wsDr/xdr:twoCellAnchor');
|
|
284
|
+
|
|
285
|
+
/* FIXME: move to drawing? */
|
|
286
|
+
const ParseAnchor = (node: any = {}): CellAnchor => {
|
|
287
|
+
const anchor: CellAnchor = {
|
|
288
|
+
column: node['xdr:col'] || 0,
|
|
289
|
+
column_offset: node['xdr:colOff'] || 0,
|
|
290
|
+
row: node['xdr:row'] || 0,
|
|
291
|
+
row_offset: node['xdr:rowOff'] || 0,
|
|
292
|
+
};
|
|
293
|
+
return anchor;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
for (const anchor_node of anchor_nodes) {
|
|
297
|
+
|
|
298
|
+
const anchor: TwoCellAnchor = {
|
|
299
|
+
from: ParseAnchor(anchor_node['xdr:from']),
|
|
300
|
+
to: ParseAnchor(anchor_node['xdr:to']),
|
|
301
|
+
};
|
|
302
|
+
const result: AnchoredChartDescription = { anchor };
|
|
303
|
+
|
|
304
|
+
const chart_reference = XMLUtils.FindAll(anchor_node, `xdr:graphicFrame/a:graphic/a:graphicData/c:chart`)[0];
|
|
305
|
+
|
|
306
|
+
if (chart_reference && chart_reference.a$ && chart_reference.a$['r:id']) {
|
|
307
|
+
const chart_rel = drawing_rels[chart_reference.a$['r:id']];
|
|
308
|
+
if (chart_rel && chart_rel.target) {
|
|
309
|
+
result.chart = await this.ReadChart(chart_rel.target);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
results.push(result);
|
|
314
|
+
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return results;
|
|
318
|
+
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
*
|
|
323
|
+
* FIXME: this is using the old options with old structure, just have
|
|
324
|
+
* not updated it yet
|
|
325
|
+
*/
|
|
326
|
+
public async ReadChart(reference: string): Promise<ChartDescription|undefined> {
|
|
327
|
+
|
|
328
|
+
const data = await this.zip.file(reference.replace(/^../, 'xl'))?.async('text') as string;
|
|
329
|
+
if (!data) { return undefined; }
|
|
330
|
+
|
|
331
|
+
const xml = xmlparser1.parse(data);
|
|
332
|
+
|
|
333
|
+
const result: ChartDescription = {
|
|
334
|
+
type: ChartType.Unknown
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// console.info("RC", xml);
|
|
338
|
+
|
|
339
|
+
const title_node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:title');
|
|
340
|
+
|
|
341
|
+
if (title_node) {
|
|
342
|
+
|
|
343
|
+
// FIXME: other types of title? (...)
|
|
344
|
+
const node = XMLUtils.FindChild(title_node, 'c:tx/c:strRef/c:f');
|
|
345
|
+
if (node) {
|
|
346
|
+
if (typeof node === 'string') {
|
|
347
|
+
result.title = node;
|
|
348
|
+
}
|
|
349
|
+
else if (node.text__) {
|
|
350
|
+
result.title = node.text__; // why is this not quoted, if the later one is quoted? is this a reference?
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
const nodes = XMLUtils.FindAll(title_node, 'c:tx/c:rich/a:p/a:r/a:t');
|
|
355
|
+
result.title = '"' + nodes.join('') + '"';
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const ParseSeries = (node: any, scatter = false): ChartSeries[] => {
|
|
361
|
+
|
|
362
|
+
const series: ChartSeries[] = [];
|
|
363
|
+
|
|
364
|
+
// const series_nodes = node.findall('./c:ser');
|
|
365
|
+
let series_nodes = node['c:ser'] || [];
|
|
366
|
+
if (!Array.isArray(series_nodes)) {
|
|
367
|
+
series_nodes = [series_nodes];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// console.info("SN", series_nodes);
|
|
371
|
+
|
|
372
|
+
for (const series_node of series_nodes) {
|
|
373
|
+
|
|
374
|
+
let index = series.length;
|
|
375
|
+
const order_node = series_node['c:order'];
|
|
376
|
+
if (order_node) {
|
|
377
|
+
index = Number(order_node.__val||0) || 0;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const series_data: ChartSeries = {};
|
|
381
|
+
|
|
382
|
+
let title_node = XMLUtils.FindChild(series_node, 'c:tx/c:v');
|
|
383
|
+
if (title_node) {
|
|
384
|
+
const title = title_node;
|
|
385
|
+
if (title) {
|
|
386
|
+
series_data.title = `"${title}"`;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
title_node = XMLUtils.FindChild(series_node, 'c:tx/c:strRef/c:f');
|
|
391
|
+
if (title_node) {
|
|
392
|
+
series_data.title = title_node;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (scatter) {
|
|
397
|
+
const x = XMLUtils.FindChild(series_node, 'c:xVal/c:numRef/c:f');
|
|
398
|
+
if (x) {
|
|
399
|
+
series_data.categories = x; // .text?.toString();
|
|
400
|
+
}
|
|
401
|
+
const y = XMLUtils.FindChild(series_node, 'c:yVal/c:numRef/c:f');
|
|
402
|
+
if (y) {
|
|
403
|
+
series_data.values = y; // .text?.toString();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
const value_node = XMLUtils.FindChild(series_node, 'c:val/c:numRef/c:f');
|
|
408
|
+
if (value_node) {
|
|
409
|
+
series_data.values = value_node; // .text?.toString();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
let cat_node = XMLUtils.FindChild(series_node, 'c:cat/c:strRef/c:f');
|
|
413
|
+
if (!cat_node) {
|
|
414
|
+
cat_node = XMLUtils.FindChild(series_node, 'c:cat/c:numRef/c:f');
|
|
415
|
+
}
|
|
416
|
+
if (cat_node) {
|
|
417
|
+
series_data.categories = cat_node; // .text?.toString();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
series[index] = series_data;
|
|
422
|
+
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return series;
|
|
426
|
+
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
let node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:plotArea/c:barChart');
|
|
430
|
+
if (node) {
|
|
431
|
+
|
|
432
|
+
result.type = ChartType.Bar;
|
|
433
|
+
// console.info("BD", node);
|
|
434
|
+
if (node['c:barDir']) {
|
|
435
|
+
if (node['c:barDir'].__val === 'col') {
|
|
436
|
+
result.type = ChartType.Column;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
result.series = ParseSeries(node);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (!node) {
|
|
444
|
+
node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:plotArea/c:lineChart');
|
|
445
|
+
if (node) {
|
|
446
|
+
result.type = ChartType.Line;
|
|
447
|
+
result.series = ParseSeries(node);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (!node) {
|
|
452
|
+
node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:plotArea/c:doughnutChart');
|
|
453
|
+
if (node) {
|
|
454
|
+
result.type = ChartType.Donut;
|
|
455
|
+
result.series = ParseSeries(node);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (!node) {
|
|
460
|
+
node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:plotArea/c:pieChart');
|
|
461
|
+
if (node) {
|
|
462
|
+
result.type = ChartType.Pie;
|
|
463
|
+
result.series = ParseSeries(node);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (!node) {
|
|
468
|
+
node = XMLUtils.FindChild(xml, 'c:chartSpace/c:chart/c:plotArea/c:scatterChart');
|
|
469
|
+
if (node) {
|
|
470
|
+
result.type = ChartType.Scatter;
|
|
471
|
+
result.series = ParseSeries(node, true);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// console.info("RX?", result);
|
|
475
|
+
|
|
476
|
+
return result;
|
|
477
|
+
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** FIXME: accessor */
|
|
481
|
+
public GetNamedRanges(): Record<string, string> {
|
|
482
|
+
|
|
483
|
+
// ... what does this do, not do, or what is it supposed to do?
|
|
484
|
+
// note that this is called by the import routine, so it probably
|
|
485
|
+
// expects to do something
|
|
486
|
+
|
|
487
|
+
return this.defined_names;
|
|
488
|
+
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
}
|