@trebco/treb 32.14.0 → 36.1.3
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-types.ts +3 -0
- package/api-generator/api-generator.ts +15 -1
- package/bun.lock +145 -99
- package/dist/chunk-43DLP2OX.mjs +11 -0
- package/dist/chunk-4CKS56PE.mjs +11 -0
- package/dist/chunk-75PARUQE.mjs +11 -0
- package/dist/chunk-7QD63AZS.mjs +24601 -0
- package/dist/chunk-A55ARVRD.mjs +11 -0
- package/dist/chunk-DESAKYW4.mjs +11 -0
- package/dist/chunk-EQ2R5W6P.mjs +24565 -0
- package/dist/chunk-IYJU2J6D.mjs +24601 -0
- package/dist/chunk-KSJFPGXT.mjs +11 -0
- package/dist/chunk-ORQFKLXM.mjs +24601 -0
- package/dist/chunk-SFDNNDHY.mjs +11 -0
- package/dist/chunk-T47DX5MI.mjs +11 -0
- package/dist/chunk-T6ILBVEX.mjs +11 -0
- package/dist/chunk-TPRCDYYG.mjs +11 -0
- package/dist/chunk-YAHNOOHO.mjs +11 -0
- package/dist/chunk-YLCFKX2G.mjs +24601 -0
- package/dist/treb-export-worker.mjs +9 -2
- package/dist/treb-spreadsheet.mjs +7 -19
- package/dist/treb.d.ts +144 -117
- package/esbuild-composite.mjs +18 -6
- package/esbuild-utils.mjs +62 -3
- package/i18n/languages/treb-i18n-da.mjs +1 -1
- package/i18n/languages/treb-i18n-de.mjs +1 -1
- package/i18n/languages/treb-i18n-es.mjs +1 -1
- package/i18n/languages/treb-i18n-fr.mjs +1 -1
- package/i18n/languages/treb-i18n-it.mjs +1 -1
- package/i18n/languages/treb-i18n-nl.mjs +1 -1
- package/i18n/languages/treb-i18n-no.mjs +1 -1
- package/i18n/languages/treb-i18n-pl.mjs +1 -1
- package/i18n/languages/treb-i18n-pt.mjs +1 -1
- package/i18n/languages/treb-i18n-sv.mjs +1 -1
- package/ooxml-types/README.md +141 -0
- package/ooxml-types/package.json +5 -0
- package/ooxml-types/src/types/drawingml/chart.ts +327 -0
- package/ooxml-types/src/types/drawingml/index.ts +63 -0
- package/ooxml-types/src/types/drawingml/spreadsheetDrawing.ts +105 -0
- package/ooxml-types/src/types/drawingml/theme.ts +104 -0
- package/ooxml-types/src/types/index.ts +3 -0
- package/ooxml-types/src/types/package/contentTypes.ts +49 -0
- package/ooxml-types/src/types/package/docProps.ts +46 -0
- package/ooxml-types/src/types/package/index.ts +17 -0
- package/ooxml-types/src/types/package/relationships.ts +37 -0
- package/ooxml-types/src/types/spreadsheetml/columns.ts +20 -0
- package/ooxml-types/src/types/spreadsheetml/comments.ts +30 -0
- package/ooxml-types/src/types/spreadsheetml/dataFeatures.ts +261 -0
- package/ooxml-types/src/types/spreadsheetml/enums.ts +175 -0
- package/ooxml-types/src/types/spreadsheetml/index.ts +186 -0
- package/ooxml-types/src/types/spreadsheetml/metadata.ts +90 -0
- package/ooxml-types/src/types/spreadsheetml/misc.ts +35 -0
- package/ooxml-types/src/types/spreadsheetml/pageLayout.ts +83 -0
- package/ooxml-types/src/types/spreadsheetml/sharedStrings.ts +33 -0
- package/ooxml-types/src/types/spreadsheetml/sheetData.ts +70 -0
- package/ooxml-types/src/types/spreadsheetml/sheetProperties.ts +86 -0
- package/ooxml-types/src/types/spreadsheetml/sheetViews.ts +51 -0
- package/ooxml-types/src/types/spreadsheetml/sparkline.ts +46 -0
- package/ooxml-types/src/types/spreadsheetml/styles.ts +274 -0
- package/ooxml-types/src/types/spreadsheetml/table.ts +106 -0
- package/ooxml-types/src/types/spreadsheetml/util.ts +15 -0
- package/ooxml-types/src/types/spreadsheetml/workbook.ts +165 -0
- package/ooxml-types/src/types/spreadsheetml/worksheet.ts +60 -0
- package/package.json +13 -11
- package/treb-base-types/src/api_types.ts +1 -1
- package/treb-base-types/src/area-utils.ts +1 -1
- package/treb-base-types/src/area.ts +1 -1
- package/treb-base-types/src/basic_types.ts +1 -1
- package/treb-base-types/src/cell.ts +1 -1
- package/treb-base-types/src/cells.ts +1 -1
- package/treb-base-types/src/color.ts +1 -1
- package/treb-base-types/src/dom-utilities.ts +1 -1
- package/treb-base-types/src/evaluate-options.ts +1 -1
- package/treb-base-types/src/font-stack.ts +1 -1
- package/treb-base-types/src/gradient.ts +1 -1
- package/treb-base-types/src/import.ts +1 -1
- package/treb-base-types/src/index-standalone.ts +1 -1
- package/treb-base-types/src/index.ts +2 -1
- package/treb-base-types/src/layout.ts +1 -1
- package/treb-base-types/src/localization.ts +1 -1
- package/treb-base-types/src/rectangle.ts +1 -1
- package/treb-base-types/src/render_text.ts +7 -1
- package/treb-base-types/src/style.ts +1 -1
- package/treb-base-types/src/table.ts +1 -1
- package/treb-base-types/src/text_part.ts +1 -1
- package/treb-base-types/src/theme.ts +1 -1
- package/treb-base-types/src/union.ts +4 -1
- package/treb-base-types/src/value-type.ts +1 -1
- package/treb-base-types/src/worker-proxy.ts +294 -0
- package/treb-base-types/style/resizable.css +1 -1
- package/treb-calculator/src/calculator.ts +133 -14
- package/treb-calculator/src/complex-math.ts +1 -1
- package/treb-calculator/src/dag/array-vertex.ts +1 -1
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -1
- package/treb-calculator/src/dag/graph.ts +1 -1
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +1 -1
- package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +1 -1
- package/treb-calculator/src/dag/state_leaf_vertex.ts +1 -1
- package/treb-calculator/src/dag/vertex.ts +1 -1
- package/treb-calculator/src/descriptors.ts +9 -1
- package/treb-calculator/src/expression-calculator.ts +1 -1
- package/treb-calculator/src/function-error.ts +1 -1
- package/treb-calculator/src/function-library.ts +1 -1
- package/treb-calculator/src/functions/base-functions.ts +8 -4
- package/treb-calculator/src/functions/beta.ts +1 -1
- package/treb-calculator/src/functions/checkbox.ts +1 -1
- package/treb-calculator/src/functions/complex-functions.ts +1 -1
- package/treb-calculator/src/functions/date-utils.ts +1 -1
- package/treb-calculator/src/functions/finance-functions.ts +2 -4
- package/treb-calculator/src/functions/fp.ts +1 -1
- package/treb-calculator/src/functions/function-utilities.ts +1 -1
- package/treb-calculator/src/functions/gamma.ts +1 -1
- package/treb-calculator/src/functions/information-functions.ts +1 -1
- package/treb-calculator/src/functions/lambda-functions.ts +4 -1
- package/treb-calculator/src/functions/matrix-functions.ts +1 -1
- package/treb-calculator/src/functions/normal.ts +1 -1
- package/treb-calculator/src/functions/regex-functions.ts +13 -4
- package/treb-calculator/src/functions/sparkline.ts +1 -1
- package/treb-calculator/src/functions/statistics-functions.ts +1 -1
- package/treb-calculator/src/functions/students-t.ts +1 -1
- package/treb-calculator/src/functions/text-functions.ts +5 -1
- package/treb-calculator/src/index.ts +1 -1
- package/treb-calculator/src/notifier-types.ts +1 -1
- package/treb-calculator/src/primitives.ts +1 -1
- package/treb-calculator/src/utilities.ts +1 -1
- package/treb-charts/src/chart-functions.ts +1 -1
- package/treb-charts/src/chart-types.ts +1 -1
- package/treb-charts/src/chart-utils.ts +1 -1
- package/treb-charts/src/chart.ts +1 -1
- package/treb-charts/src/default-chart-renderer.ts +1 -1
- package/treb-charts/src/index.ts +1 -1
- package/treb-charts/src/main.ts +1 -1
- package/treb-charts/src/quicksort.ts +1 -1
- package/treb-charts/src/rectangle.ts +1 -1
- package/treb-charts/src/renderer-type.ts +1 -1
- package/treb-charts/src/renderer.ts +1 -1
- package/treb-charts/src/util.ts +1 -1
- package/treb-charts/style/charts.scss +1 -1
- package/treb-data-model/src/annotation.ts +1 -1
- package/treb-data-model/src/conditional_format.ts +1 -1
- package/treb-data-model/src/data-validation.ts +1 -1
- package/treb-data-model/src/data_model.ts +32 -5
- package/treb-data-model/src/index.ts +1 -1
- package/treb-data-model/src/language-model.ts +1 -1
- package/treb-data-model/src/named.ts +1 -1
- package/treb-data-model/src/serialize_options.ts +1 -1
- package/treb-data-model/src/sheet.ts +1 -1
- package/treb-data-model/src/sheet_collection.ts +1 -1
- package/treb-data-model/src/sheet_selection.ts +1 -1
- package/treb-data-model/src/sheet_types.ts +1 -1
- package/treb-data-model/src/types.ts +1 -1
- package/treb-embed/src/content-types.d.ts +1 -1
- package/treb-embed/src/custom-element/global.d.ts +1 -1
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1 -1
- package/treb-embed/src/custom-element/treb-global.ts +1 -1
- package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +1 -1
- package/treb-embed/src/embedded-spreadsheet.ts +357 -154
- package/treb-embed/src/index.ts +1 -1
- package/treb-embed/src/options.ts +4 -2
- package/treb-embed/src/plugin.ts +1 -1
- package/treb-embed/src/progress-dialog.ts +1 -1
- package/treb-embed/src/selection-state.ts +1 -1
- package/treb-embed/src/spinner.ts +1 -1
- package/treb-embed/src/toolbar-message.ts +6 -1
- package/treb-embed/src/types.ts +13 -1
- package/treb-embed/style/autocomplete.scss +1 -1
- package/treb-embed/style/dark-theme.scss +1 -1
- package/treb-embed/style/defaults.scss +1 -1
- package/treb-embed/style/dialog.scss +1 -1
- package/treb-embed/style/dropdown-select.scss +1 -1
- package/treb-embed/style/font-stacks.scss +1 -1
- package/treb-embed/style/formula-bar.scss +1 -1
- package/treb-embed/style/grid.scss +1 -1
- package/treb-embed/style/layout.scss +1 -1
- package/treb-embed/style/mouse-mask.scss +1 -1
- package/treb-embed/style/note.scss +1 -1
- package/treb-embed/style/overlay-editor.scss +1 -1
- package/treb-embed/style/spinner.scss +1 -1
- package/treb-embed/style/tab-bar.scss +1 -1
- package/treb-embed/style/table.scss +1 -1
- package/treb-embed/style/theme-defaults.scss +1 -1
- package/treb-embed/style/toolbar.scss +1 -1
- package/treb-embed/style/tooltip.scss +1 -1
- package/treb-embed/style/treb-icons.scss +1 -1
- package/treb-embed/style/treb-spreadsheet-element.scss +1 -1
- package/treb-embed/style/z-index.scss +1 -1
- package/treb-export/src/address-type.ts +1 -1
- package/treb-export/src/base-template.ts +1 -1
- package/treb-export/src/column-width.ts +1 -1
- package/treb-export/src/drawing/bubble-chart-template.ts +1 -1
- package/treb-export/src/drawing/chart-template-components2.ts +1 -1
- package/treb-export/src/drawing/chart.ts +1 -1
- package/treb-export/src/drawing/column-chart-template2.ts +1 -1
- package/treb-export/src/drawing/donut-chart-template2.ts +1 -1
- package/treb-export/src/drawing/drawing.ts +1 -1
- package/treb-export/src/drawing/embedded-image.ts +1 -1
- package/treb-export/src/drawing/scatter-chart-template2.ts +1 -1
- package/treb-export/src/export.ts +10 -6
- package/treb-export/src/import-export-messages.ts +61 -0
- package/treb-export/src/import.ts +318 -301
- package/treb-export/src/index.worker.ts +85 -53
- package/treb-export/src/metadata.ts +71 -3
- package/treb-export/src/ooxml.ts +47 -0
- package/treb-export/src/relationship.ts +1 -1
- package/treb-export/src/shared-strings.ts +19 -15
- package/treb-export/src/template-2.ts +1 -1
- package/treb-export/src/unescape_xml.ts +1 -1
- package/treb-export/src/workbook-sheet.ts +11 -6
- package/treb-export/src/workbook-style.ts +137 -25
- package/treb-export/src/workbook-theme.ts +20 -4
- package/treb-export/src/workbook.ts +85 -88
- package/treb-export/src/xml-test.ts +1 -1
- package/treb-export/src/xml-utils.ts +1 -1
- package/treb-export/src/zip-wrapper.ts +1 -1
- package/treb-export/tsconfig.json +2 -1
- package/treb-format/src/format.test.ts +1 -1
- package/treb-format/src/format.ts +12 -5
- package/treb-format/src/format_cache.ts +3 -3
- package/treb-format/src/format_parser.ts +1 -1
- package/treb-format/src/index.ts +1 -1
- package/treb-format/src/number_format_section.ts +1 -1
- package/treb-format/src/value_parser.ts +1 -1
- package/treb-grid/src/editors/autocomplete.ts +1 -1
- package/treb-grid/src/editors/autocomplete_matcher.ts +1 -1
- package/treb-grid/src/editors/editor.ts +15 -6
- package/treb-grid/src/editors/external_editor.ts +33 -8
- package/treb-grid/src/editors/formula_bar.ts +12 -1
- package/treb-grid/src/editors/overlay_editor.ts +4 -1
- package/treb-grid/src/index.ts +1 -1
- package/treb-grid/src/layout/base_layout.ts +1 -1
- package/treb-grid/src/layout/grid_layout.ts +1 -1
- package/treb-grid/src/layout/mock-layout.ts +1 -1
- package/treb-grid/src/render/selection-renderer.ts +1 -1
- package/treb-grid/src/render/svg_header_overlay.ts +1 -1
- package/treb-grid/src/render/svg_selection_block.ts +1 -1
- package/treb-grid/src/render/tile_renderer.ts +36 -7
- package/treb-grid/src/types/border_constants.ts +1 -1
- package/treb-grid/src/types/clipboard_data.ts +1 -1
- package/treb-grid/src/types/clipboard_data2.ts +1 -1
- package/treb-grid/src/types/drag_mask.ts +1 -1
- package/treb-grid/src/types/external_editor_config.ts +1 -1
- package/treb-grid/src/types/grid.ts +181 -40
- package/treb-grid/src/types/grid_base.ts +7 -4
- package/treb-grid/src/types/grid_command.ts +7 -1
- package/treb-grid/src/types/grid_events.ts +2 -1
- package/treb-grid/src/types/grid_options.ts +1 -1
- package/treb-grid/src/types/scale-control.ts +1 -1
- package/treb-grid/src/types/set_range_options.ts +1 -1
- package/treb-grid/src/types/tab_bar.ts +1 -1
- package/treb-grid/src/types/tile.ts +1 -1
- package/treb-grid/src/types/update_flags.ts +1 -1
- package/treb-grid/src/util/fontmetrics.ts +1 -1
- package/treb-grid/src/util/ua.ts +1 -1
- package/treb-parser/src/csv-parser.ts +1 -1
- package/treb-parser/src/index.ts +1 -1
- package/treb-parser/src/md-parser.ts +1 -1
- package/treb-parser/src/parser-types.ts +1 -1
- package/treb-parser/src/parser.ts +1 -1
- package/treb-utils/src/event_source.ts +1 -1
- package/treb-utils/src/ievent_source.ts +1 -1
- package/treb-utils/src/index.ts +1 -1
- package/treb-utils/src/measurement.ts +1 -1
- package/treb-utils/src/scale.ts +1 -1
- package/treb-utils/src/serialize_html.ts +1 -1
- package/treb-utils/src/validate_uri.ts +1 -1
- package/tsproject.json +2 -3
- package/treb-embed/src/export-worker.ts +0 -44
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* You should have received a copy of the GNU General Public License along
|
|
15
15
|
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
*
|
|
17
|
-
* Copyright 2022-
|
|
17
|
+
* Copyright 2022-2026 trebco, llc.
|
|
18
18
|
* info@treb.app
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
@@ -35,7 +35,7 @@ import type { SerializedValueType } from 'treb-base-types';
|
|
|
35
35
|
import type { Sheet} from './workbook-sheet';
|
|
36
36
|
import { VisibleState } from './workbook-sheet';
|
|
37
37
|
import type { CellAnchor } from './drawing/drawing';
|
|
38
|
-
import { type GenericDOMElement, XMLUtils } from './xml-utils';
|
|
38
|
+
// import { type GenericDOMElement, XMLUtils } from './xml-utils';
|
|
39
39
|
|
|
40
40
|
// import { one_hundred_pixels } from './constants';
|
|
41
41
|
import { ColumnWidthToPixels } from './column-width';
|
|
@@ -44,6 +44,10 @@ import { ZipWrapper } from './zip-wrapper';
|
|
|
44
44
|
import type { ConditionalFormat } from 'treb-data-model';
|
|
45
45
|
import { LookupMetadata, type MetadataFlags } from './metadata';
|
|
46
46
|
|
|
47
|
+
import * as OOXML from 'ooxml-types';
|
|
48
|
+
import { EnsureArray, FirstTag, IterateTags } from './ooxml';
|
|
49
|
+
|
|
50
|
+
|
|
47
51
|
interface SharedFormula {
|
|
48
52
|
row: number;
|
|
49
53
|
column: number;
|
|
@@ -53,6 +57,7 @@ interface SharedFormula {
|
|
|
53
57
|
|
|
54
58
|
interface SharedFormulaMap { [index: string]: SharedFormula }
|
|
55
59
|
|
|
60
|
+
/*
|
|
56
61
|
interface CellElementType {
|
|
57
62
|
a$: {
|
|
58
63
|
r?: string;
|
|
@@ -121,6 +126,7 @@ interface ConditionalFormatRule {
|
|
|
121
126
|
const ElementHasTextNode = (test: unknown): test is {t$: string} => {
|
|
122
127
|
return typeof test === 'object' && typeof (test as {$t: string}).$t !== 'undefined';
|
|
123
128
|
}
|
|
129
|
+
*/
|
|
124
130
|
|
|
125
131
|
export class Importer {
|
|
126
132
|
|
|
@@ -146,7 +152,7 @@ export class Importer {
|
|
|
146
152
|
|
|
147
153
|
public ParseCell(
|
|
148
154
|
sheet: Sheet,
|
|
149
|
-
element: CellElementType,
|
|
155
|
+
element: OOXML.Cell, // CellElementType,
|
|
150
156
|
shared_formulae: SharedFormulaMap,
|
|
151
157
|
arrays: RangeType[],
|
|
152
158
|
dynamic_arrays: RangeType[],
|
|
@@ -156,8 +162,8 @@ export class Importer {
|
|
|
156
162
|
): CellParseResult | undefined {
|
|
157
163
|
|
|
158
164
|
// must have, at minimum, an address (must be a single cell? FIXME)
|
|
159
|
-
const address_attr = element
|
|
160
|
-
if (
|
|
165
|
+
const address_attr = element.$attributes?.r;
|
|
166
|
+
if (address_attr === undefined) {
|
|
161
167
|
console.warn('cell missing address');
|
|
162
168
|
return undefined;
|
|
163
169
|
}
|
|
@@ -168,10 +174,10 @@ export class Importer {
|
|
|
168
174
|
return undefined;
|
|
169
175
|
}
|
|
170
176
|
|
|
171
|
-
//
|
|
177
|
+
// metadata
|
|
172
178
|
let metadata_flags: MetadataFlags = {};
|
|
173
|
-
if (element
|
|
174
|
-
const cm_index =
|
|
179
|
+
if (element.$attributes?.cm !== undefined) {
|
|
180
|
+
const cm_index = element.$attributes.cm;
|
|
175
181
|
if (this.workbook?.metadata) {
|
|
176
182
|
metadata_flags = LookupMetadata(this.workbook.metadata, 'cell', cm_index).flags;
|
|
177
183
|
}
|
|
@@ -207,10 +213,10 @@ export class Importer {
|
|
|
207
213
|
|
|
208
214
|
// console.info(address, 'e', element, 'm', mapped);
|
|
209
215
|
|
|
210
|
-
if (element
|
|
211
|
-
type = 'string';
|
|
212
|
-
if (
|
|
213
|
-
const index = Number(element.v);
|
|
216
|
+
if (element.$attributes?.t === 's') {
|
|
217
|
+
type = 'string';
|
|
218
|
+
if (element.v?.$text !== undefined) {
|
|
219
|
+
const index = Number(element.v.$text);
|
|
214
220
|
if (!isNaN(index) && sheet.shared_strings) {
|
|
215
221
|
value = sheet.shared_strings.Get(index) || '';
|
|
216
222
|
if (value[0] === '=') { value = '\'' + value; }
|
|
@@ -218,15 +224,11 @@ export class Importer {
|
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
else {
|
|
221
|
-
if (
|
|
222
|
-
type = 'formula';
|
|
223
|
-
|
|
224
|
-
const formula = (typeof element.f === 'string' ? element.f : element.f.t$) || '';
|
|
225
|
-
|
|
227
|
+
if (element.f !== undefined) {
|
|
228
|
+
type = 'formula';
|
|
229
|
+
const formula = element.f.$text || '';
|
|
226
230
|
if (formula) {
|
|
227
231
|
|
|
228
|
-
// console.info("F", formula);
|
|
229
|
-
|
|
230
232
|
// doing it like this is sloppy (also does not work properly).
|
|
231
233
|
value = '=' + formula.replace(/^_xll\./g, '');
|
|
232
234
|
|
|
@@ -245,11 +247,15 @@ export class Importer {
|
|
|
245
247
|
name = name.substring(5);
|
|
246
248
|
}
|
|
247
249
|
if (/^_xlfn\./.test(name)) {
|
|
248
|
-
|
|
250
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
251
|
+
console.info("xlfn:", name);
|
|
252
|
+
}
|
|
249
253
|
name = name.substring(6);
|
|
250
254
|
}
|
|
251
255
|
if (/^_xlws\./.test(name)) {
|
|
252
|
-
|
|
256
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
257
|
+
console.info("xlws:", name);
|
|
258
|
+
}
|
|
253
259
|
name = name.substring(6);
|
|
254
260
|
}
|
|
255
261
|
|
|
@@ -294,19 +300,26 @@ export class Importer {
|
|
|
294
300
|
|
|
295
301
|
unit.name = TrimPrefixes(unit.name);
|
|
296
302
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
|
|
303
|
+
// excel export may be translating dynamic range references
|
|
304
|
+
// (e.g D2#) to `ANCHORARRAY(D2)`. this is for compatibility
|
|
305
|
+
// with older versions of excel, I guess?
|
|
306
|
+
|
|
307
|
+
// we can translate these but let's be conservative here and
|
|
308
|
+
// start with just ANCHORARRAY taking a single address --
|
|
309
|
+
// that we know we can handle.
|
|
310
|
+
|
|
311
|
+
// so for example, if the formula is `=SUM(ANCHORARRAY(D2))`
|
|
312
|
+
// we can translate that to explicitly `=SUM(D2#)`. in our
|
|
313
|
+
// scheme that's just the address plus a flag bit indicating
|
|
314
|
+
// "take the full dynamic array range".
|
|
315
|
+
|
|
316
|
+
if (unit.name === 'ANCHORARRAY') {
|
|
317
|
+
if (unit.args.length === 1 && unit.args[0].type === 'address') {
|
|
318
|
+
return {
|
|
319
|
+
...(unit.args[0]), spill: true,
|
|
320
|
+
}
|
|
321
|
+
}
|
|
308
322
|
}
|
|
309
|
-
*/
|
|
310
323
|
|
|
311
324
|
}
|
|
312
325
|
return true;
|
|
@@ -319,20 +332,18 @@ export class Importer {
|
|
|
319
332
|
}
|
|
320
333
|
}
|
|
321
334
|
|
|
322
|
-
if (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
};
|
|
330
|
-
}
|
|
335
|
+
if (element.f.$attributes?.t === 'shared' && element.f.$attributes.si !== undefined) {
|
|
336
|
+
shared_formulae[element.f.$attributes.si] = {
|
|
337
|
+
row: address.row - 1,
|
|
338
|
+
column: address.col - 1,
|
|
339
|
+
formula: value,
|
|
340
|
+
parse_result: this.parser.Parse(value),
|
|
341
|
+
};
|
|
331
342
|
}
|
|
332
343
|
|
|
333
344
|
}
|
|
334
|
-
else if (
|
|
335
|
-
const f = shared_formulae[element.f.
|
|
345
|
+
else if (element.f.$attributes?.t === 'shared' && element.f.$attributes.si !== undefined) {
|
|
346
|
+
const f = shared_formulae[element.f.$attributes.si];
|
|
336
347
|
if (f) {
|
|
337
348
|
if (f.parse_result.expression) {
|
|
338
349
|
value = '=' + this.parser.Render(f.parse_result.expression, {
|
|
@@ -354,8 +365,8 @@ export class Importer {
|
|
|
354
365
|
// arrays and spill/dynamic arrays
|
|
355
366
|
//
|
|
356
367
|
|
|
357
|
-
if (
|
|
358
|
-
const translated = sheet.TranslateAddress(element.f.
|
|
368
|
+
if (element.f.$attributes?.t === 'array') {
|
|
369
|
+
const translated = sheet.TranslateAddress(element.f.$attributes.ref ?? '');
|
|
359
370
|
|
|
360
371
|
// why are we checking "is_range" here? this should be valid
|
|
361
372
|
// even if the ref attribute is one cell, if it explicitly
|
|
@@ -385,31 +396,37 @@ export class Importer {
|
|
|
385
396
|
}
|
|
386
397
|
}
|
|
387
398
|
|
|
388
|
-
if (
|
|
399
|
+
if (element.v !== undefined) {
|
|
400
|
+
|
|
401
|
+
const V = element.v?.$text ?? '';
|
|
389
402
|
|
|
390
|
-
|
|
403
|
+
// FIXME: use parser?
|
|
391
404
|
|
|
392
|
-
const num = Number(V
|
|
405
|
+
const num = Number(V);
|
|
393
406
|
if (!isNaN(num)) {
|
|
394
|
-
calculated_type = 'number';
|
|
407
|
+
calculated_type = 'number';
|
|
395
408
|
calculated_value = num;
|
|
396
409
|
}
|
|
397
410
|
else {
|
|
398
|
-
calculated_type = 'string';
|
|
399
|
-
calculated_value = V
|
|
411
|
+
calculated_type = 'string';
|
|
412
|
+
calculated_value = V;
|
|
400
413
|
}
|
|
414
|
+
|
|
401
415
|
}
|
|
402
416
|
|
|
403
417
|
}
|
|
404
|
-
else if (
|
|
405
|
-
|
|
418
|
+
else if (element.v !== undefined) {
|
|
419
|
+
|
|
420
|
+
// FIXME: use parser?
|
|
421
|
+
|
|
422
|
+
const num = Number(element.v.$text || '');
|
|
406
423
|
if (!isNaN(num)) {
|
|
407
|
-
type = 'number';
|
|
424
|
+
type = 'number';
|
|
408
425
|
value = num;
|
|
409
426
|
}
|
|
410
427
|
else {
|
|
411
|
-
type = 'string';
|
|
412
|
-
value = element.v
|
|
428
|
+
type = 'string';
|
|
429
|
+
value = element.v.$text || '';
|
|
413
430
|
}
|
|
414
431
|
}
|
|
415
432
|
}
|
|
@@ -441,8 +458,8 @@ export class Importer {
|
|
|
441
458
|
result.calculated = calculated_value;
|
|
442
459
|
}
|
|
443
460
|
|
|
444
|
-
if (element
|
|
445
|
-
result.style_ref =
|
|
461
|
+
if (element.$attributes?.s !== undefined) {
|
|
462
|
+
result.style_ref = element.$attributes.s;
|
|
446
463
|
}
|
|
447
464
|
|
|
448
465
|
for (const link of links) {
|
|
@@ -522,68 +539,70 @@ export class Importer {
|
|
|
522
539
|
|
|
523
540
|
}
|
|
524
541
|
|
|
525
|
-
public ParseConditionalFormat(
|
|
542
|
+
public ParseConditionalFormat(
|
|
543
|
+
address: RangeType|AddressType,
|
|
544
|
+
rule: OOXML.CfRule, // ConditionalFormatRule,
|
|
545
|
+
extensions: OOXML.X14ConditionalFormatting[] = []): ConditionalFormat|ConditionalFormat[]|undefined {
|
|
526
546
|
|
|
527
547
|
const area = this.AddressToArea(address);
|
|
528
548
|
const operators = ConditionalFormatOperators;
|
|
529
549
|
|
|
530
550
|
// console.info({rule});
|
|
531
551
|
|
|
532
|
-
switch (rule
|
|
552
|
+
switch (rule.$attributes?.type) {
|
|
533
553
|
case 'duplicateValues':
|
|
534
554
|
case 'uniqueValues':
|
|
535
555
|
|
|
536
556
|
{
|
|
537
557
|
let style = {};
|
|
538
558
|
|
|
539
|
-
if (rule.
|
|
540
|
-
|
|
541
|
-
if (!isNaN(index)) {
|
|
542
|
-
style = this.workbook?.style_cache.dxf_styles[index] || {};
|
|
543
|
-
}
|
|
559
|
+
if (rule.$attributes.dxfId !== undefined) {
|
|
560
|
+
style = this.workbook?.style_cache.dxf_styles[rule.$attributes.dxfId] || {};
|
|
544
561
|
}
|
|
545
562
|
|
|
546
563
|
return {
|
|
547
564
|
type: 'duplicate-values',
|
|
548
565
|
area,
|
|
549
566
|
style,
|
|
550
|
-
unique: (rule.
|
|
551
|
-
priority: rule.
|
|
552
|
-
|
|
567
|
+
unique: (rule.$attributes.type === 'uniqueValues'),
|
|
568
|
+
priority: rule.$attributes.priority,
|
|
553
569
|
};
|
|
570
|
+
|
|
554
571
|
}
|
|
555
572
|
|
|
556
573
|
case 'cellIs':
|
|
557
|
-
if (rule.
|
|
574
|
+
if (rule.$attributes.operator && rule.formula) {
|
|
558
575
|
let style = {};
|
|
559
576
|
|
|
560
|
-
if (rule.
|
|
561
|
-
|
|
562
|
-
if (!isNaN(index)) {
|
|
563
|
-
style = this.workbook?.style_cache.dxf_styles[index] || {};
|
|
564
|
-
}
|
|
577
|
+
if (rule.$attributes.dxfId !== undefined) {
|
|
578
|
+
style = this.workbook?.style_cache.dxf_styles[rule.$attributes.dxfId] || {};
|
|
565
579
|
}
|
|
566
580
|
|
|
567
|
-
if (rule.
|
|
568
|
-
if (Array.isArray(rule.formula) && rule.formula.length === 2
|
|
569
|
-
&& typeof rule.formula[0] === 'number' && typeof rule.formula[1] === 'number') {
|
|
581
|
+
if (rule.$attributes.operator === 'between') {
|
|
582
|
+
if (Array.isArray(rule.formula) && rule.formula.length === 2) {
|
|
583
|
+
// && typeof rule.formula[0] === 'number' && typeof rule.formula[1] === 'number') {
|
|
584
|
+
|
|
585
|
+
const between: [number, number] = [
|
|
586
|
+
Number(rule.formula[0]?.$text || ''),
|
|
587
|
+
Number(rule.formula[1]?.$text || ''),
|
|
588
|
+
];
|
|
570
589
|
|
|
571
590
|
return {
|
|
572
591
|
type: 'cell-match',
|
|
573
592
|
expression: '',
|
|
574
|
-
between: rule.formula, // special case? ugh
|
|
593
|
+
between, // : rule.formula, // special case? ugh
|
|
575
594
|
area,
|
|
576
595
|
style,
|
|
577
|
-
priority: rule.
|
|
596
|
+
priority: rule.$attributes.priority,
|
|
578
597
|
};
|
|
579
598
|
|
|
580
599
|
}
|
|
581
600
|
}
|
|
582
601
|
|
|
583
|
-
const operator = operators[rule.
|
|
602
|
+
const operator = operators[rule.$attributes.operator || ''];
|
|
584
603
|
|
|
585
604
|
if (!operator) {
|
|
586
|
-
console.info('unhandled cellIs operator:', rule.
|
|
605
|
+
console.info('unhandled cellIs operator:', rule.$attributes.operator, {rule});
|
|
587
606
|
}
|
|
588
607
|
else {
|
|
589
608
|
return {
|
|
@@ -591,7 +610,7 @@ export class Importer {
|
|
|
591
610
|
expression: operator + ' ' + rule.formula,
|
|
592
611
|
area,
|
|
593
612
|
style,
|
|
594
|
-
priority: rule.
|
|
613
|
+
priority: rule.$attributes.priority,
|
|
595
614
|
};
|
|
596
615
|
}
|
|
597
616
|
|
|
@@ -607,6 +626,10 @@ export class Importer {
|
|
|
607
626
|
|
|
608
627
|
if (rule.formula) {
|
|
609
628
|
|
|
629
|
+
const first = FirstTag(rule.formula);
|
|
630
|
+
const formula = first?.$text || '';
|
|
631
|
+
|
|
632
|
+
/*
|
|
610
633
|
if (typeof rule.formula !== 'string') {
|
|
611
634
|
if (ElementHasTextNode(rule.formula)) {
|
|
612
635
|
|
|
@@ -622,17 +645,15 @@ export class Importer {
|
|
|
622
645
|
rule.formula = '';
|
|
623
646
|
}
|
|
624
647
|
}
|
|
648
|
+
*/
|
|
625
649
|
|
|
626
650
|
let style = {};
|
|
627
651
|
|
|
628
|
-
if (rule.
|
|
629
|
-
|
|
630
|
-
if (!isNaN(index)) {
|
|
631
|
-
style = this.workbook?.style_cache.dxf_styles[index] || {};
|
|
632
|
-
}
|
|
652
|
+
if (rule.$attributes.dxfId !== undefined) {
|
|
653
|
+
style = this.workbook?.style_cache.dxf_styles[rule.$attributes.dxfId] || {};
|
|
633
654
|
}
|
|
634
655
|
|
|
635
|
-
if (rule.
|
|
656
|
+
if (rule.$attributes.type === 'expression' && (area.start.row !== area.end.row || area.start.column !== area.end.column)) {
|
|
636
657
|
|
|
637
658
|
// (1) this is only required if there are relative references
|
|
638
659
|
// in the formula. so we could check and short-circuit.
|
|
@@ -646,7 +667,7 @@ export class Importer {
|
|
|
646
667
|
const list: ConditionalFormat[] = [];
|
|
647
668
|
const a2 = new Area(area.start, area.end);
|
|
648
669
|
|
|
649
|
-
const parse_result = this.parser.Parse(
|
|
670
|
+
const parse_result = this.parser.Parse(formula);
|
|
650
671
|
if (parse_result.expression) {
|
|
651
672
|
for (const cell of a2) {
|
|
652
673
|
const f = this.parser.Render(parse_result.expression, {
|
|
@@ -659,7 +680,7 @@ export class Importer {
|
|
|
659
680
|
expression: f,
|
|
660
681
|
style,
|
|
661
682
|
area: { start: cell, end: cell },
|
|
662
|
-
priority: rule.
|
|
683
|
+
priority: rule.$attributes.priority,
|
|
663
684
|
})
|
|
664
685
|
|
|
665
686
|
// console.info(f);
|
|
@@ -673,10 +694,10 @@ export class Importer {
|
|
|
673
694
|
|
|
674
695
|
return {
|
|
675
696
|
type: 'expression',
|
|
676
|
-
expression:
|
|
697
|
+
expression: formula,
|
|
677
698
|
area,
|
|
678
699
|
style,
|
|
679
|
-
priority: rule.
|
|
700
|
+
priority: rule.$attributes.priority,
|
|
680
701
|
};
|
|
681
702
|
|
|
682
703
|
}
|
|
@@ -684,38 +705,49 @@ export class Importer {
|
|
|
684
705
|
|
|
685
706
|
case 'dataBar':
|
|
686
707
|
{
|
|
687
|
-
const
|
|
688
|
-
let extension: any = undefined;
|
|
708
|
+
const show_value = rule.dataBar?.$attributes?.showValue ?? true; // default true
|
|
689
709
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
710
|
+
// const hide_values = !rule.dataBar?.$attributes?.showValue;
|
|
711
|
+
// let extension: any = undefined;
|
|
712
|
+
|
|
713
|
+
let extension: OOXML.X14ConditionalFormatting|undefined;
|
|
714
|
+
|
|
715
|
+
IterateTags(rule.extLst?.ext, ext => {
|
|
716
|
+
if (ext.id !== undefined) {
|
|
717
|
+
for (const test of extensions) {
|
|
718
|
+
return IterateTags(test.cfRule, cfRule => {
|
|
719
|
+
if (cfRule.$attributes?.id === ext.id) {
|
|
720
|
+
extension = test;
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
695
724
|
}
|
|
696
725
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
if (!extension) {
|
|
729
|
+
console.info("conditional format extension not found");
|
|
700
730
|
}
|
|
701
731
|
|
|
702
|
-
if (rule.dataBar?.color?.
|
|
732
|
+
if (rule.dataBar?.color?.$attributes?.rgb) {
|
|
703
733
|
|
|
704
734
|
let negative: Color|undefined = undefined;
|
|
735
|
+
const first = FirstTag(extension?.cfRule);
|
|
705
736
|
|
|
706
|
-
|
|
707
|
-
|
|
737
|
+
const rgb = first?.dataBar?.negativeFillColor?.$attributes?.rgb;
|
|
738
|
+
if (rgb !== undefined) {
|
|
708
739
|
negative = { text: '#' + rgb.toString().substring(2) };
|
|
709
740
|
}
|
|
710
741
|
|
|
711
|
-
const fill: Color = { text: '#' + rule.dataBar.color.
|
|
742
|
+
const fill: Color = { text: '#' + rule.dataBar.color.$attributes.rgb.substring(2) };
|
|
712
743
|
return {
|
|
713
744
|
type: 'data-bar',
|
|
714
745
|
area,
|
|
715
746
|
fill,
|
|
716
|
-
hide_values,
|
|
747
|
+
hide_values: !show_value,
|
|
717
748
|
negative,
|
|
718
749
|
};
|
|
750
|
+
|
|
719
751
|
}
|
|
720
752
|
}
|
|
721
753
|
break;
|
|
@@ -729,17 +761,17 @@ export class Importer {
|
|
|
729
761
|
const color: Color = {};
|
|
730
762
|
|
|
731
763
|
const color_element = rule.colorScale.color[index];
|
|
732
|
-
if (color_element
|
|
733
|
-
(color as HTMLColor).text = '#' + color_element.
|
|
764
|
+
if (color_element.$attributes?.rgb) {
|
|
765
|
+
(color as HTMLColor).text = '#' + color_element.$attributes.rgb.substring(2);
|
|
734
766
|
}
|
|
735
|
-
else if (color_element
|
|
736
|
-
(color as ThemeColor).theme = Number(color_element.
|
|
737
|
-
if (color_element.
|
|
738
|
-
(color as ThemeColor).tint = Math.round(Number(color_element.
|
|
767
|
+
else if (color_element.$attributes?.theme) {
|
|
768
|
+
(color as ThemeColor).theme = Number(color_element.$attributes.theme) || 0;
|
|
769
|
+
if (color_element.$attributes.tint) {
|
|
770
|
+
(color as ThemeColor).tint = Math.round(Number(color_element.$attributes.tint) * 1000) / 1000;
|
|
739
771
|
}
|
|
740
772
|
}
|
|
741
773
|
|
|
742
|
-
switch (entry
|
|
774
|
+
switch (entry.$attributes?.type) {
|
|
743
775
|
case 'min':
|
|
744
776
|
value = 0;
|
|
745
777
|
break;
|
|
@@ -749,7 +781,7 @@ export class Importer {
|
|
|
749
781
|
break;
|
|
750
782
|
|
|
751
783
|
case 'percentile':
|
|
752
|
-
value = (Number(entry.
|
|
784
|
+
value = (Number(entry.$attributes.val) || 0) / 100;
|
|
753
785
|
break;
|
|
754
786
|
}
|
|
755
787
|
|
|
@@ -762,8 +794,7 @@ export class Importer {
|
|
|
762
794
|
stops,
|
|
763
795
|
color_space: 'RGB',
|
|
764
796
|
area,
|
|
765
|
-
priority: rule.
|
|
766
|
-
|
|
797
|
+
priority: rule.$attributes.priority,
|
|
767
798
|
};
|
|
768
799
|
|
|
769
800
|
}
|
|
@@ -811,25 +842,25 @@ export class Importer {
|
|
|
811
842
|
|
|
812
843
|
const annotations: AnchoredAnnotation[] = [];
|
|
813
844
|
|
|
814
|
-
const FindAll: <T = GenericDOMElement>(path: string) => T[] = XMLUtils.FindAll.bind(XMLUtils, sheet.sheet_data);
|
|
845
|
+
// const FindAll: <T = GenericDOMElement>(path: string) => T[] = XMLUtils.FindAll.bind(XMLUtils, sheet.sheet_data);
|
|
815
846
|
|
|
816
847
|
// tab color
|
|
817
848
|
|
|
818
|
-
const tab_color_element = FindAll('worksheet/sheetPr/tabColor');
|
|
849
|
+
// const tab_color_element = FindAll('worksheet/sheetPr/tabColor');
|
|
819
850
|
|
|
851
|
+
const tab_color_element = sheet.root.sheetPr?.tabColor;
|
|
820
852
|
let tab_color: Color|undefined;
|
|
821
853
|
|
|
822
|
-
if (tab_color_element
|
|
854
|
+
if (tab_color_element) {
|
|
823
855
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
tab_color.tint = Number(element.a$.tint);
|
|
856
|
+
if (tab_color_element.$attributes?.theme !== undefined) {
|
|
857
|
+
tab_color = { theme: tab_color_element.$attributes.theme };
|
|
858
|
+
if (tab_color_element.$attributes.tint !== undefined) {
|
|
859
|
+
tab_color.tint = tab_color_element.$attributes.tint;
|
|
829
860
|
}
|
|
830
861
|
}
|
|
831
|
-
if (
|
|
832
|
-
const argb =
|
|
862
|
+
if (tab_color_element.$attributes?.rgb !== undefined) {
|
|
863
|
+
const argb = tab_color_element.$attributes.rgb;
|
|
833
864
|
tab_color = {
|
|
834
865
|
text: '#' + (
|
|
835
866
|
argb.length > 6 ?
|
|
@@ -842,26 +873,31 @@ export class Importer {
|
|
|
842
873
|
|
|
843
874
|
// conditionals
|
|
844
875
|
|
|
845
|
-
const conditional_formatting = FindAll('worksheet/conditionalFormatting');
|
|
876
|
+
// const conditional_formatting = // FindAll('worksheet/conditionalFormatting');
|
|
877
|
+
// sheet.root.conditionalFormatting;
|
|
846
878
|
|
|
847
879
|
// we might need extensions as well? TODO
|
|
880
|
+
// const conditional_formattings = FindAll('worksheet/extLst/ext/x14:conditionalFormattings/x14:conditionalFormatting');
|
|
881
|
+
|
|
882
|
+
const extensions: OOXML.X14ConditionalFormatting[] = [];
|
|
883
|
+
IterateTags(sheet.root.extLst?.ext, ext => {
|
|
884
|
+
extensions.push(...EnsureArray(ext.conditionalFormattings?.conditionalFormatting));
|
|
885
|
+
});
|
|
848
886
|
|
|
849
|
-
|
|
887
|
+
IterateTags(sheet.root.conditionalFormatting, element => {
|
|
850
888
|
|
|
851
|
-
|
|
852
|
-
if (element.a$?.sqref ){
|
|
889
|
+
if (element.$attributes?.sqref ){
|
|
853
890
|
|
|
854
891
|
// FIXME: this attribute might include multiple ranges? e.g.:
|
|
855
892
|
//
|
|
856
893
|
// <conditionalFormatting sqref="B31:I31 B10:E30 G10:I30 F14:F15">
|
|
857
894
|
|
|
858
|
-
const parts = element.
|
|
895
|
+
const parts = element.$attributes.sqref.split(/\s+/);
|
|
859
896
|
for (const part of parts) {
|
|
860
897
|
const area = sheet.TranslateAddress(part);
|
|
861
898
|
if (element.cfRule) {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const format = this.ParseConditionalFormat(area, rule as unknown as ConditionalFormatRule, conditional_formattings);
|
|
899
|
+
IterateTags(element.cfRule, rule => {
|
|
900
|
+
const format = this.ParseConditionalFormat(area, rule, extensions);
|
|
865
901
|
if (format) {
|
|
866
902
|
if (Array.isArray(format)) {
|
|
867
903
|
conditional_formats.push(...format);
|
|
@@ -870,36 +906,37 @@ export class Importer {
|
|
|
870
906
|
conditional_formats.push(format);
|
|
871
907
|
}
|
|
872
908
|
}
|
|
873
|
-
}
|
|
909
|
+
});
|
|
874
910
|
}
|
|
875
911
|
}
|
|
876
912
|
|
|
877
913
|
}
|
|
878
|
-
|
|
914
|
+
|
|
915
|
+
});
|
|
879
916
|
|
|
880
917
|
// merges
|
|
881
918
|
|
|
882
|
-
const merge_cells = FindAll('worksheet/mergeCells/mergeCell');
|
|
919
|
+
// const merge_cells = FindAll('worksheet/mergeCells/mergeCell');
|
|
883
920
|
|
|
884
|
-
|
|
885
|
-
if (element
|
|
886
|
-
const merge = sheet.TranslateAddress(element.
|
|
921
|
+
IterateTags(sheet.root.mergeCells?.mergeCell, element => {
|
|
922
|
+
if (element.$attributes?.ref) {
|
|
923
|
+
const merge = sheet.TranslateAddress(element.$attributes.ref);
|
|
887
924
|
if (is_range(merge)) {
|
|
888
925
|
merges.push(ShiftRange(merge, -1, -1));
|
|
889
926
|
}
|
|
890
927
|
}
|
|
891
|
-
}
|
|
928
|
+
});
|
|
892
929
|
|
|
893
930
|
// validation
|
|
894
931
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
const type = entry
|
|
898
|
-
const ref = entry
|
|
899
|
-
const formula = entry.formula1;
|
|
932
|
+
IterateTags(sheet.root.dataValidations?.dataValidation, entry => {
|
|
933
|
+
|
|
934
|
+
const type = entry.$attributes?.type;
|
|
935
|
+
const ref = entry.$attributes?.sqref;
|
|
936
|
+
const formula = entry.formula1?.$text || '';
|
|
937
|
+
|
|
938
|
+
if (ref && formula && type === 'list') {
|
|
900
939
|
|
|
901
|
-
if (ref && formula && typeof formula === 'string' && type === 'list') {
|
|
902
|
-
// let address: ICellAddress|undefined;
|
|
903
940
|
let validation: DataValidation|undefined;
|
|
904
941
|
let parse_result = this.parser.Parse(ref);
|
|
905
942
|
const target: IArea[] = [];
|
|
@@ -912,11 +949,9 @@ export class Importer {
|
|
|
912
949
|
|
|
913
950
|
if (parse_result.expression) {
|
|
914
951
|
if (parse_result.expression.type === 'address') {
|
|
915
|
-
// address = parse_result.expression;
|
|
916
952
|
target.push({start: parse_result.expression, end: parse_result.expression});
|
|
917
953
|
}
|
|
918
954
|
else if (parse_result.expression.type === 'range') {
|
|
919
|
-
// address = parse_result.expression.start;
|
|
920
955
|
target.push(parse_result.expression);
|
|
921
956
|
}
|
|
922
957
|
}
|
|
@@ -991,15 +1026,15 @@ export class Importer {
|
|
|
991
1026
|
|
|
992
1027
|
}
|
|
993
1028
|
|
|
994
|
-
}
|
|
1029
|
+
});
|
|
995
1030
|
|
|
996
1031
|
// links
|
|
997
1032
|
|
|
998
|
-
const hyperlinks = FindAll('worksheet/hyperlinks/hyperlink');
|
|
1033
|
+
// const hyperlinks = FindAll('worksheet/hyperlinks/hyperlink');
|
|
1034
|
+
// for (const child of hyperlinks) {
|
|
1035
|
+
IterateTags(sheet.root.hyperlinks?.hyperlink, child => {
|
|
999
1036
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
let address = sheet.TranslateAddress(child.a$?.ref || '');
|
|
1037
|
+
let address = sheet.TranslateAddress(child.$attributes?.ref || '');
|
|
1003
1038
|
if (is_range(address)) {
|
|
1004
1039
|
address = address.from;
|
|
1005
1040
|
}
|
|
@@ -1007,42 +1042,46 @@ export class Importer {
|
|
|
1007
1042
|
let text = '';
|
|
1008
1043
|
let reference = '';
|
|
1009
1044
|
|
|
1010
|
-
if (child
|
|
1045
|
+
if (child.$attributes?.id !== undefined) {
|
|
1011
1046
|
|
|
1012
1047
|
text = 'remote link';
|
|
1013
|
-
const relationship = sheet.rels[child.
|
|
1048
|
+
const relationship = sheet.rels[child.$attributes.id];
|
|
1014
1049
|
if (relationship) {
|
|
1015
1050
|
reference = relationship.target || '';
|
|
1016
1051
|
}
|
|
1017
1052
|
|
|
1018
1053
|
}
|
|
1019
1054
|
else {
|
|
1055
|
+
|
|
1056
|
+
// what's up with these weird attributes? did we change this at
|
|
1057
|
+
// some point and not update this block? (probably)
|
|
1058
|
+
|
|
1059
|
+
/*
|
|
1020
1060
|
reference = typeof child.__location === 'string' ? child.__location : '';
|
|
1021
1061
|
text = typeof child.__display === 'string' ? child.__display : '';
|
|
1062
|
+
*/
|
|
1063
|
+
|
|
1064
|
+
reference = child.$attributes?.location || '';
|
|
1065
|
+
text = child.$attributes?.display || '';
|
|
1066
|
+
|
|
1022
1067
|
}
|
|
1023
1068
|
|
|
1024
1069
|
links.push({ address, reference, text });
|
|
1025
|
-
|
|
1070
|
+
|
|
1071
|
+
});
|
|
1026
1072
|
|
|
1027
1073
|
// base
|
|
1028
1074
|
|
|
1029
1075
|
let default_row_height = 21;
|
|
1030
1076
|
let default_column_width = 100; // ?
|
|
1031
1077
|
|
|
1032
|
-
const sheet_format = sheet.
|
|
1078
|
+
const sheet_format = sheet.root.sheetFormatPr;
|
|
1033
1079
|
if (sheet_format) {
|
|
1034
|
-
if (sheet_format
|
|
1035
|
-
|
|
1036
|
-
if (!isNaN(width)) {
|
|
1037
|
-
// default_column_width = Math.round(width / one_hundred_pixels * 100);
|
|
1038
|
-
default_column_width = ColumnWidthToPixels(width);
|
|
1039
|
-
}
|
|
1080
|
+
if (sheet_format.$attributes?.defaultColWidth !== undefined) {
|
|
1081
|
+
default_column_width = ColumnWidthToPixels(sheet_format.$attributes.defaultColWidth);
|
|
1040
1082
|
}
|
|
1041
|
-
if (sheet_format
|
|
1042
|
-
|
|
1043
|
-
if (!isNaN(height)) {
|
|
1044
|
-
default_row_height = Math.round(height * 4 / 3); // ??
|
|
1045
|
-
}
|
|
1083
|
+
if (sheet_format.$attributes?.defaultRowHeight) {
|
|
1084
|
+
default_row_height = Math.round((sheet_format.$attributes.defaultRowHeight) * 4 / 3); // ??
|
|
1046
1085
|
}
|
|
1047
1086
|
}
|
|
1048
1087
|
|
|
@@ -1051,30 +1090,24 @@ export class Importer {
|
|
|
1051
1090
|
const row_heights: number[] = [];
|
|
1052
1091
|
const outline: number[] = [];
|
|
1053
1092
|
|
|
1054
|
-
const rows = FindAll('worksheet/sheetData/row');
|
|
1093
|
+
// const rows = FindAll('worksheet/sheetData/row');
|
|
1094
|
+
// for (const row of rows) {
|
|
1095
|
+
|
|
1096
|
+
IterateTags(sheet.root.sheetData.row, row => {
|
|
1055
1097
|
|
|
1056
|
-
|
|
1057
|
-
const row_index = row.a$?.r ? Number(row.a$.r) : 1;
|
|
1098
|
+
const row_index = row.$attributes?.r ?? 1;
|
|
1058
1099
|
|
|
1059
1100
|
let height = default_row_height;
|
|
1060
|
-
if (row
|
|
1061
|
-
|
|
1062
|
-
if (!isNaN(num)) {
|
|
1063
|
-
height = Math.round(num * 4 / 3); // seems to be the excel unit -> pixel ratio
|
|
1064
|
-
}
|
|
1101
|
+
if (row.$attributes?.ht !== undefined) {
|
|
1102
|
+
height = Math.round((row.$attributes.ht) * 4 / 3); // seems to be the excel unit -> pixel ratio
|
|
1065
1103
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
outline[row_index - 1] = num;
|
|
1070
|
-
}
|
|
1104
|
+
|
|
1105
|
+
if (row.$attributes?.outlineLevel !== undefined) {
|
|
1106
|
+
outline[row_index - 1] = row.$attributes?.outlineLevel;
|
|
1071
1107
|
}
|
|
1072
1108
|
|
|
1073
|
-
if (row
|
|
1074
|
-
|
|
1075
|
-
if (!isNaN(style_reference)) {
|
|
1076
|
-
row_styles[row_index - 1] = style_reference;
|
|
1077
|
-
}
|
|
1109
|
+
if (row.$attributes?.s !== undefined) {
|
|
1110
|
+
row_styles[row_index - 1] = row.$attributes.s;
|
|
1078
1111
|
}
|
|
1079
1112
|
|
|
1080
1113
|
// if there's a height which is not === default height, but
|
|
@@ -1085,32 +1118,30 @@ export class Importer {
|
|
|
1085
1118
|
row_heights[row_index - 1] = height;
|
|
1086
1119
|
}
|
|
1087
1120
|
|
|
1088
|
-
const cells = row.c ? Array.isArray(row.c) ? row.c : [row.c] : [];
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
const cell = this.ParseCell(sheet, element
|
|
1121
|
+
// const cells = row.c ? Array.isArray(row.c) ? row.c : [row.c] : [];
|
|
1122
|
+
// for (const element of cells) {
|
|
1123
|
+
IterateTags(row.c, element => {
|
|
1124
|
+
const cell = this.ParseCell(sheet, element, shared_formulae, arrays, dynamic_arrays, merges, links);
|
|
1092
1125
|
if (cell) {
|
|
1093
1126
|
data.push(cell);
|
|
1094
1127
|
}
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1128
|
+
});
|
|
1129
|
+
|
|
1130
|
+
});
|
|
1097
1131
|
|
|
1098
1132
|
const column_styles: number[] = [];
|
|
1099
1133
|
let default_column_style = -1;
|
|
1100
1134
|
const column_widths: number[] = [];
|
|
1101
1135
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
const max = Number(child.a$?.max);
|
|
1108
|
-
|
|
1109
|
-
if (child.a$?.style) {
|
|
1136
|
+
IterateTags(sheet.root.cols, cols => {
|
|
1137
|
+
IterateTags(cols.col, child => {
|
|
1138
|
+
|
|
1139
|
+
const min = child.$attributes?.min ?? 0;
|
|
1140
|
+
const max = child.$attributes?.max ?? 0;
|
|
1110
1141
|
|
|
1111
|
-
|
|
1142
|
+
if (child.$attributes?.style !== undefined) {
|
|
1112
1143
|
|
|
1113
|
-
|
|
1144
|
+
const style = child.$attributes.style;
|
|
1114
1145
|
|
|
1115
1146
|
// this is not the way to do this? for the time being
|
|
1116
1147
|
// it's OK because style doesn't need to extend past
|
|
@@ -1126,13 +1157,9 @@ export class Importer {
|
|
|
1126
1157
|
}
|
|
1127
1158
|
|
|
1128
1159
|
}
|
|
1160
|
+
if (child.$attributes?.customWidth) {
|
|
1129
1161
|
|
|
1130
|
-
|
|
1131
|
-
if (child.a$?.customWidth) {
|
|
1132
|
-
|
|
1133
|
-
let width = Number(child.a$.width);
|
|
1134
|
-
|
|
1135
|
-
if (!isNaN(min) && !isNaN(max) && !isNaN(width)) {
|
|
1162
|
+
let width = child.$attributes.width ?? 0;
|
|
1136
1163
|
|
|
1137
1164
|
if (max === 16384) {
|
|
1138
1165
|
|
|
@@ -1152,97 +1179,103 @@ export class Importer {
|
|
|
1152
1179
|
}
|
|
1153
1180
|
}
|
|
1154
1181
|
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1157
1184
|
|
|
1158
1185
|
// --- import tables -------------------------------------------------------
|
|
1159
1186
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
const rel = child.a$ ? child.a$['r:id'] : undefined;
|
|
1163
|
-
if (rel) {
|
|
1164
|
-
let reference = '';
|
|
1187
|
+
IterateTags(sheet.root.tableParts, tablePart => {
|
|
1188
|
+
IterateTags(tablePart.tablePart, child => {
|
|
1165
1189
|
|
|
1166
|
-
const
|
|
1167
|
-
if (
|
|
1168
|
-
reference =
|
|
1169
|
-
const description = this.workbook.ReadTable(reference);
|
|
1170
|
-
if (description) {
|
|
1171
|
-
|
|
1172
|
-
// console.info({description});
|
|
1173
|
-
|
|
1174
|
-
const ref = sheet.TranslateAddress(description.ref);
|
|
1175
|
-
const area: IArea = is_address(ref) ? {
|
|
1176
|
-
start: { row: ref.row - 1, column: ref.col - 1},
|
|
1177
|
-
end: { row: ref.row - 1, column: ref.col - 1},
|
|
1178
|
-
} : {
|
|
1179
|
-
start: { row: ref.from.row - 1, column: ref.from.col - 1},
|
|
1180
|
-
end: { row: ref.to.row - 1, column: ref.to.col - 1},
|
|
1181
|
-
};
|
|
1190
|
+
const rel = child.$attributes?.id;
|
|
1191
|
+
if (rel !== undefined) {
|
|
1192
|
+
let reference = '';
|
|
1182
1193
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
totals_row: (!!description.totals_row_count),
|
|
1194
|
+
const relationship = sheet.rels[rel];
|
|
1195
|
+
if (relationship) {
|
|
1196
|
+
reference = relationship.target || '';
|
|
1197
|
+
const description = this.workbook?.ReadTable(reference);
|
|
1198
|
+
if (description) {
|
|
1189
1199
|
|
|
1190
|
-
|
|
1191
|
-
// read them from here. not super efficient but we do it
|
|
1192
|
-
// that way for regular loads as well
|
|
1200
|
+
// console.info({description});
|
|
1193
1201
|
|
|
1202
|
+
const ref = sheet.TranslateAddress(description.ref);
|
|
1203
|
+
const area: IArea = is_address(ref) ? {
|
|
1204
|
+
start: { row: ref.row - 1, column: ref.col - 1},
|
|
1205
|
+
end: { row: ref.row - 1, column: ref.col - 1},
|
|
1206
|
+
} : {
|
|
1207
|
+
start: { row: ref.from.row - 1, column: ref.from.col - 1},
|
|
1208
|
+
end: { row: ref.to.row - 1, column: ref.to.col - 1},
|
|
1194
1209
|
};
|
|
1195
|
-
|
|
1210
|
+
|
|
1211
|
+
for (const cell of data) {
|
|
1212
|
+
if (cell.row === area.start.row && cell.column === area.start.column) {
|
|
1213
|
+
cell.table = {
|
|
1214
|
+
area,
|
|
1215
|
+
name: description.name,
|
|
1216
|
+
totals_row: (!!description.totals_row_count),
|
|
1217
|
+
|
|
1218
|
+
// NOTE: column headers are added on first load, we don't
|
|
1219
|
+
// read them from here. not super efficient but we do it
|
|
1220
|
+
// that way for regular loads as well
|
|
1221
|
+
|
|
1222
|
+
};
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1196
1225
|
}
|
|
1226
|
+
|
|
1197
1227
|
}
|
|
1198
1228
|
|
|
1199
1229
|
}
|
|
1200
|
-
|
|
1201
1230
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1231
|
+
|
|
1232
|
+
});
|
|
1233
|
+
});
|
|
1204
1234
|
|
|
1205
1235
|
// --- import drawings -----------------------------------------------------
|
|
1206
1236
|
|
|
1207
1237
|
// wip...
|
|
1208
1238
|
|
|
1209
|
-
const drawings = FindAll('worksheet/drawing');
|
|
1239
|
+
// const drawings = FindAll('worksheet/drawing');
|
|
1210
1240
|
const chart_descriptors: AnchoredChartDescription[] = [];
|
|
1211
1241
|
const image_descriptors: AnchoredImageDescription[] = [];
|
|
1212
1242
|
const textbox_descriptors: AnchoredTextBoxDescription[] = [];
|
|
1213
1243
|
|
|
1214
|
-
|
|
1244
|
+
if (this.workbook) {
|
|
1245
|
+
const workbook = this.workbook;
|
|
1246
|
+
IterateTags(sheet.root.drawing, child => {
|
|
1215
1247
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1248
|
+
const rel = child.$attributes?.id;
|
|
1249
|
+
if (rel !== undefined) {
|
|
1218
1250
|
|
|
1219
|
-
|
|
1251
|
+
let reference = '';
|
|
1220
1252
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1253
|
+
const relationship = sheet.rels[rel];
|
|
1254
|
+
if (relationship) {
|
|
1255
|
+
reference = relationship.target || '';
|
|
1256
|
+
}
|
|
1225
1257
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1258
|
+
if (reference) {
|
|
1259
|
+
const drawing = workbook.ReadDrawing(reference);
|
|
1260
|
+
if (drawing && drawing.length) {
|
|
1261
|
+
for (const entry of drawing) {
|
|
1262
|
+
switch (entry.type) {
|
|
1263
|
+
case 'chart':
|
|
1264
|
+
chart_descriptors.push(entry);
|
|
1265
|
+
break;
|
|
1266
|
+
case 'image':
|
|
1267
|
+
image_descriptors.push(entry);
|
|
1268
|
+
break;
|
|
1269
|
+
case 'textbox':
|
|
1270
|
+
textbox_descriptors.push(entry);
|
|
1271
|
+
break;
|
|
1272
|
+
}
|
|
1240
1273
|
}
|
|
1241
1274
|
}
|
|
1242
1275
|
}
|
|
1243
|
-
}
|
|
1244
1276
|
|
|
1245
|
-
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1246
1279
|
}
|
|
1247
1280
|
|
|
1248
1281
|
const AnchorToCorner = (anchor: CellAnchor): LayoutCorner => {
|
|
@@ -1470,43 +1503,27 @@ export class Importer {
|
|
|
1470
1503
|
|
|
1471
1504
|
// /wip
|
|
1472
1505
|
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
//
|
|
1477
|
-
|
|
1478
|
-
for (const key of Object.keys(entry?.a$ || {})) {
|
|
1479
|
-
const match = key.match(/^xmlns:(.*)$/);
|
|
1480
|
-
if (match) {
|
|
1481
|
-
prefix = match[1];
|
|
1482
|
-
break;
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1506
|
+
IterateTags(sheet.root.extLst?.ext, entry => {
|
|
1507
|
+
IterateTags(entry.sparklineGroups?.sparklineGroup, group => {
|
|
1508
|
+
|
|
1509
|
+
// const groups = XMLUtils.FindAll(entry, `${prefix}:sparklineGroups/${prefix}:sparklineGroup`);
|
|
1510
|
+
// for (const group of groups) {
|
|
1485
1511
|
|
|
1486
|
-
const groups = XMLUtils.FindAll(entry, `${prefix}:sparklineGroups/${prefix}:sparklineGroup`);
|
|
1487
|
-
for (const group of groups) {
|
|
1488
1512
|
let func = 'Sparkline.line';
|
|
1489
1513
|
let reference = '';
|
|
1490
1514
|
let source = '';
|
|
1491
1515
|
|
|
1492
|
-
if (group
|
|
1516
|
+
if (group.$attributes?.type === 'column') {
|
|
1493
1517
|
func = 'Sparkline.column';
|
|
1494
1518
|
}
|
|
1495
1519
|
|
|
1496
1520
|
// TODO: gap optional
|
|
1497
1521
|
// TODO: colors
|
|
1498
1522
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
source = sparkline[key];
|
|
1504
|
-
}
|
|
1505
|
-
else if (/:sqref$/.test(key)) {
|
|
1506
|
-
reference = sparkline[key];
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1523
|
+
IterateTags(group.sparklines.sparkline, sparkline => {
|
|
1524
|
+
source = sparkline.f?.$text ?? '';
|
|
1525
|
+
reference = sparkline.sqref?.$text ?? '';
|
|
1526
|
+
});
|
|
1510
1527
|
|
|
1511
1528
|
//
|
|
1512
1529
|
|
|
@@ -1552,9 +1569,9 @@ export class Importer {
|
|
|
1552
1569
|
|
|
1553
1570
|
//
|
|
1554
1571
|
|
|
1555
|
-
}
|
|
1572
|
+
});
|
|
1556
1573
|
|
|
1557
|
-
}
|
|
1574
|
+
});
|
|
1558
1575
|
|
|
1559
1576
|
const result: ImportedSheetData = {
|
|
1560
1577
|
name: sheet.options.name,
|