@rowsncolumns/toolkit 24.4.1 → 24.4.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/dist/cjs/excel-parser/cfb-decryptor.d.ts +6 -0
- package/dist/cjs/excel-parser/cfb-decryptor.d.ts.map +1 -1
- package/dist/cjs/excel-parser/cfb-decryptor.js +6 -0
- package/dist/cjs/excel-parser/helpers.d.ts +9 -1
- package/dist/cjs/excel-parser/helpers.d.ts.map +1 -1
- package/dist/cjs/excel-parser/helpers.js +37 -0
- package/dist/cjs/excel-parser/interface.d.ts +10 -1
- package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/ods/index.d.ts +19 -0
- package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/ods/index.js +676 -304
- package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +43 -1
- package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/ods/styles.js +343 -45
- package/dist/cjs/excel-parser/plugins/xls/index.d.ts +11 -3
- package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xls/index.js +55 -6
- package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts +4 -0
- package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsb/index.js +21 -9
- package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +10 -0
- package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/charts.js +68 -9
- package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
- package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +155 -20
- package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +26 -1
- package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/index.js +567 -234
- package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +125 -37
- package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
- package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.js +4 -1
- package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/styles.js +12 -2
- package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
- package/dist/cjs/excel-parser/registry.js +2 -0
- package/dist/cjs/excel-parser/types.d.ts +7 -1
- package/dist/cjs/excel-parser/types.d.ts.map +1 -1
- package/dist/cjs/excel-parser/workbook.d.ts +1 -0
- package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
- package/dist/cjs/excel-parser/workbook.js +4 -0
- package/dist/cjs/excel-parser/worker.js +3 -1
- package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -1
- package/dist/cjs/exporter/ods/ods-export.js +432 -175
- package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
- package/dist/cjs/exporter/xlsx/chart-builder.js +210 -6
- package/dist/cjs/exporter/xlsx/pivot-builder.d.ts +8 -0
- package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -1
- package/dist/cjs/exporter/xlsx/pivot-builder.js +141 -42
- package/dist/cjs/exporter/xlsx/style-builder.js +9 -3
- package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
- package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
- package/dist/cjs/exporter/xlsx/threaded-comments-builder.js +15 -3
- package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +11 -2
- package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
- package/dist/cjs/exporter/xlsx/xlsx-export.js +678 -222
- package/dist/cjs/helpers/implicit-intersection.d.ts +16 -0
- package/dist/cjs/helpers/implicit-intersection.d.ts.map +1 -0
- package/dist/cjs/helpers/implicit-intersection.js +197 -0
- package/dist/cjs/print-settings.d.ts +105 -0
- package/dist/cjs/print-settings.d.ts.map +1 -0
- package/dist/cjs/print-settings.js +494 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/excel-parser/cfb-decryptor.d.ts +6 -0
- package/dist/esm/excel-parser/cfb-decryptor.d.ts.map +1 -1
- package/dist/esm/excel-parser/cfb-decryptor.js +6 -0
- package/dist/esm/excel-parser/helpers.d.ts +9 -1
- package/dist/esm/excel-parser/helpers.d.ts.map +1 -1
- package/dist/esm/excel-parser/helpers.js +34 -0
- package/dist/esm/excel-parser/interface.d.ts +10 -1
- package/dist/esm/excel-parser/interface.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/ods/index.d.ts +19 -0
- package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/ods/index.js +347 -33
- package/dist/esm/excel-parser/plugins/ods/styles.d.ts +43 -1
- package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/ods/styles.js +276 -2
- package/dist/esm/excel-parser/plugins/xls/index.d.ts +11 -3
- package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xls/index.js +37 -5
- package/dist/esm/excel-parser/plugins/xlsb/index.d.ts +4 -0
- package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsb/index.js +20 -6
- package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +10 -0
- package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/charts.js +69 -6
- package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
- package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/drawing.js +99 -0
- package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +26 -1
- package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/index.js +362 -26
- package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/pivots.js +86 -6
- package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
- package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/sheet-views.js +2 -0
- package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/styles.js +12 -2
- package/dist/esm/excel-parser/registry.d.ts.map +1 -1
- package/dist/esm/excel-parser/registry.js +2 -0
- package/dist/esm/excel-parser/types.d.ts +7 -1
- package/dist/esm/excel-parser/types.d.ts.map +1 -1
- package/dist/esm/excel-parser/workbook.d.ts +1 -0
- package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
- package/dist/esm/excel-parser/workbook.js +3 -0
- package/dist/esm/excel-parser/worker.js +2 -0
- package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -1
- package/dist/esm/exporter/ods/ods-export.js +306 -35
- package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
- package/dist/esm/exporter/xlsx/chart-builder.js +161 -0
- package/dist/esm/exporter/xlsx/pivot-builder.d.ts +8 -0
- package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -1
- package/dist/esm/exporter/xlsx/pivot-builder.js +104 -19
- package/dist/esm/exporter/xlsx/style-builder.js +9 -3
- package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
- package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
- package/dist/esm/exporter/xlsx/threaded-comments-builder.js +15 -3
- package/dist/esm/exporter/xlsx/xlsx-export.d.ts +11 -2
- package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
- package/dist/esm/exporter/xlsx/xlsx-export.js +449 -47
- package/dist/esm/helpers/implicit-intersection.d.ts +16 -0
- package/dist/esm/helpers/implicit-intersection.d.ts.map +1 -0
- package/dist/esm/helpers/implicit-intersection.js +184 -0
- package/dist/esm/print-settings.d.ts +105 -0
- package/dist/esm/print-settings.d.ts.map +1 -0
- package/dist/esm/print-settings.js +422 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -46,6 +46,13 @@ export declare class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
46
46
|
private getSpaceRepeatCount;
|
|
47
47
|
private extractEmbeddedObjects;
|
|
48
48
|
private buildAnchorKey;
|
|
49
|
+
/**
|
|
50
|
+
* Copy of a `<draw:frame>` attribute record without `svg:x` / `svg:y`.
|
|
51
|
+
* Frames in `<table:shapes>` carry sheet-absolute coordinates there,
|
|
52
|
+
* which `buildOverlayPlacement` would otherwise read as an offset inside
|
|
53
|
+
* the anchor cell.
|
|
54
|
+
*/
|
|
55
|
+
private withoutAbsoluteOffsets;
|
|
49
56
|
/**
|
|
50
57
|
* Walk the ordered content XML for each table and assign outline
|
|
51
58
|
* level + collapsed/hiddenByGroup state on `rowMetadata` and
|
|
@@ -71,6 +78,11 @@ export declare class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
71
78
|
private findFrameObjectNode;
|
|
72
79
|
private findFrameImageNode;
|
|
73
80
|
private loadChartNodeFromObject;
|
|
81
|
+
/**
|
|
82
|
+
* Loads an embedded chart object's `content.xml` and registers its
|
|
83
|
+
* `<office:automatic-styles>` into `styles` — the per-object table the
|
|
84
|
+
* caller resolves plot-area / series styles against.
|
|
85
|
+
*/
|
|
74
86
|
private loadChartNodeFromHref;
|
|
75
87
|
private resolveObjectPath;
|
|
76
88
|
private findChartNodeInDocument;
|
|
@@ -80,6 +92,13 @@ export declare class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
80
92
|
private extractChartSeriesColor;
|
|
81
93
|
private extractColorFromChartProperties;
|
|
82
94
|
private mapOdsChartClassToType;
|
|
95
|
+
/**
|
|
96
|
+
* The authored 3-D class token for an ODS chart: `chart:surface` is a
|
|
97
|
+
* surface, and any other class whose plot-area style declares
|
|
98
|
+
* `chart:three-dimensional="true"` maps to the OOXML 3-D variant of its
|
|
99
|
+
* 2-D base (`BAR_3D`, `LINE_3D`, `PIE_3D`, `AREA_3D`). Undefined for 2-D.
|
|
100
|
+
*/
|
|
101
|
+
private resolveOdsSourceChartType;
|
|
83
102
|
private findRangeString;
|
|
84
103
|
private looksLikeCellRangeAddress;
|
|
85
104
|
private createChartDataFromAddress;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/ods/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,qBAAqB,EAErB,wBAAwB,EAExB,aAAa,EAGb,UAAU,EACV,KAAK,EAEL,SAAS,EACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,4BAA4B,CAAC;AAOpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,KAAK,EACV,0BAA0B,EAC1B,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAUnD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/ods/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ import { extractDataValidations } from "./data-validations";
|
|
|
11
11
|
import { convertOdsFormulaToExcel } from "./formula";
|
|
12
12
|
import { extractSparklines, extractSparklineData, } from "./sparklines";
|
|
13
13
|
import { OdsStyles } from "./styles";
|
|
14
|
+
import { compactPrintSettings } from "../../../print-settings";
|
|
14
15
|
const ODS_XML_OPTIONS = {
|
|
15
16
|
ignoreAttributes: false,
|
|
16
17
|
attributeNamePrefix: "@_",
|
|
@@ -48,6 +49,112 @@ function getAttribute(node, attributeName) {
|
|
|
48
49
|
}
|
|
49
50
|
return undefined;
|
|
50
51
|
}
|
|
52
|
+
const ROW_WRAPPER_TAGS = [
|
|
53
|
+
"table:table-row-group",
|
|
54
|
+
"table:table-header-rows",
|
|
55
|
+
"table:table-rows",
|
|
56
|
+
"table-row-group",
|
|
57
|
+
"table-header-rows",
|
|
58
|
+
"table-rows",
|
|
59
|
+
];
|
|
60
|
+
const COLUMN_WRAPPER_TAGS = [
|
|
61
|
+
"table:table-column-group",
|
|
62
|
+
"table:table-header-columns",
|
|
63
|
+
"table:table-columns",
|
|
64
|
+
"table-column-group",
|
|
65
|
+
"table-header-columns",
|
|
66
|
+
"table-columns",
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Order-preserving `<table:table>` children → the `<table:table-row>` nodes in
|
|
70
|
+
* document order, descending into `<table:table-row-group>` (outline),
|
|
71
|
+
* `<table:table-header-rows>` (print titles) and `<table:table-rows>`
|
|
72
|
+
* wrappers. Rows inside a wrapper are ordinary rows for cell data, merges,
|
|
73
|
+
* metadata and positions.
|
|
74
|
+
*/
|
|
75
|
+
function flattenOrderedRows(children) {
|
|
76
|
+
const rows = [];
|
|
77
|
+
for (const child of children ?? []) {
|
|
78
|
+
if (!child || typeof child !== "object")
|
|
79
|
+
continue;
|
|
80
|
+
if (child["table:table-row"] || child["table-row"]) {
|
|
81
|
+
rows.push(child);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const wrapper = ROW_WRAPPER_TAGS.find((tag) => child[tag]);
|
|
85
|
+
if (wrapper)
|
|
86
|
+
rows.push(...flattenOrderedRows(child[wrapper]));
|
|
87
|
+
}
|
|
88
|
+
return rows;
|
|
89
|
+
}
|
|
90
|
+
/** Column counterpart of {@link flattenOrderedRows}. */
|
|
91
|
+
function flattenOrderedColumns(children) {
|
|
92
|
+
const columns = [];
|
|
93
|
+
for (const child of children ?? []) {
|
|
94
|
+
if (!child || typeof child !== "object")
|
|
95
|
+
continue;
|
|
96
|
+
if (child["table:table-column"] || child["table-column"]) {
|
|
97
|
+
columns.push(child);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const wrapper = COLUMN_WRAPPER_TAGS.find((tag) => child[tag]);
|
|
101
|
+
if (wrapper)
|
|
102
|
+
columns.push(...flattenOrderedColumns(child[wrapper]));
|
|
103
|
+
}
|
|
104
|
+
return columns;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The 1-based band covered by the `<table:table-header-rows>` /
|
|
108
|
+
* `<table:table-header-columns>` wrappers (ODS print titles), or undefined.
|
|
109
|
+
* A band that straddles an outline-group edge is written as several
|
|
110
|
+
* wrappers (ODF forbids a group inside header rows; LibreOffice closes and
|
|
111
|
+
* re-opens the wrapper around the group), so the segments are unioned back
|
|
112
|
+
* into one band — the same rule LibreOffice applies on import.
|
|
113
|
+
*/
|
|
114
|
+
function findOrderedHeaderBand(children, axis) {
|
|
115
|
+
const itemTags = axis === "row"
|
|
116
|
+
? ["table:table-row", "table-row"]
|
|
117
|
+
: ["table:table-column", "table-column"];
|
|
118
|
+
const headerTags = axis === "row"
|
|
119
|
+
? ["table:table-header-rows", "table-header-rows"]
|
|
120
|
+
: ["table:table-header-columns", "table-header-columns"];
|
|
121
|
+
const wrapperTags = axis === "row" ? ROW_WRAPPER_TAGS : COLUMN_WRAPPER_TAGS;
|
|
122
|
+
const repeatAttr = axis === "row" ? "table:number-rows-repeated" : "table:number-columns-repeated";
|
|
123
|
+
const flatten = axis === "row" ? flattenOrderedRows : flattenOrderedColumns;
|
|
124
|
+
const countItems = (nodes) => flatten(nodes).reduce((total, node) => {
|
|
125
|
+
const repeated = parseInt(getAttribute(node, repeatAttr) ?? "1", 10);
|
|
126
|
+
return total + (Number.isFinite(repeated) && repeated > 0 ? repeated : 1);
|
|
127
|
+
}, 0);
|
|
128
|
+
let position = 1;
|
|
129
|
+
let band;
|
|
130
|
+
const visit = (nodes) => {
|
|
131
|
+
for (const child of nodes ?? []) {
|
|
132
|
+
if (!child || typeof child !== "object")
|
|
133
|
+
continue;
|
|
134
|
+
if (itemTags.some((tag) => child[tag])) {
|
|
135
|
+
position += countItems([child]);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const header = headerTags.find((tag) => child[tag]);
|
|
139
|
+
if (header) {
|
|
140
|
+
const count = countItems(child[header]);
|
|
141
|
+
if (count) {
|
|
142
|
+
const end = position + count - 1;
|
|
143
|
+
band = band
|
|
144
|
+
? { start: Math.min(band.start, position), end: Math.max(band.end, end) }
|
|
145
|
+
: { start: position, end };
|
|
146
|
+
position = end + 1;
|
|
147
|
+
}
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const wrapper = wrapperTags.find((tag) => child[tag]);
|
|
151
|
+
if (wrapper)
|
|
152
|
+
visit(child[wrapper]);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
visit(children);
|
|
156
|
+
return band;
|
|
157
|
+
}
|
|
51
158
|
function fastMergeCellFormats(...formats) {
|
|
52
159
|
let result;
|
|
53
160
|
for (const format of formats) {
|
|
@@ -160,10 +267,24 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
160
267
|
if (styles) {
|
|
161
268
|
const parsedStyles = this.xmlParser.parse(styles);
|
|
162
269
|
this.odsStyles.parseStylesXml(parsedStyles);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
270
|
+
// Master pages carry mixed-content header/footer paragraphs
|
|
271
|
+
// (`Page <text:page-number/> of …`), so they are read from an
|
|
272
|
+
// order-preserving parse that also keeps the significant spaces
|
|
273
|
+
// around the fields and leaves the text verbatim (a `+1` after the
|
|
274
|
+
// page number is header text, not the number 1).
|
|
275
|
+
this.odsStyles.parseMasterPagesOrdered(new XMLParser({
|
|
276
|
+
...ODS_ORDERED_XML_OPTIONS,
|
|
277
|
+
trimValues: false,
|
|
278
|
+
parseTagValue: false,
|
|
279
|
+
}).parse(styles));
|
|
280
|
+
}
|
|
281
|
+
// settings.xml is optional in ODF (our own exporter omits it when no
|
|
282
|
+
// sheet has view settings); `Get` throws on a missing part.
|
|
283
|
+
if (this.zipParser.Has("settings.xml")) {
|
|
284
|
+
const settings = this.zipParser.Get("settings.xml");
|
|
285
|
+
if (settings) {
|
|
286
|
+
this.settingsXml = this.xmlParser.parse(settings);
|
|
287
|
+
}
|
|
167
288
|
}
|
|
168
289
|
}
|
|
169
290
|
catch (e) {
|
|
@@ -229,14 +350,26 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
229
350
|
}
|
|
230
351
|
buildSheetCache() {
|
|
231
352
|
const tables = this.getTables();
|
|
353
|
+
const orderedTables = this.getOrderedTableWrappers();
|
|
232
354
|
const sheets = [];
|
|
233
355
|
const sheetContexts = [];
|
|
356
|
+
// `table:print-ranges` per sheet, resolved once the sheet-name map exists.
|
|
357
|
+
const printRangesBySheetId = new Map();
|
|
234
358
|
tables.forEach((table, index) => {
|
|
235
359
|
const name = table["@_table:name"] ||
|
|
236
360
|
table["@_name"] ||
|
|
237
361
|
table["table:name"] ||
|
|
238
362
|
table["name"] ||
|
|
239
363
|
`Sheet${index + 1}`;
|
|
364
|
+
// Order-preserving children of the same table: rows/columns nested in
|
|
365
|
+
// `<table:table-header-rows>` / `<table:table-row-group>` only appear in
|
|
366
|
+
// document order there.
|
|
367
|
+
const orderedTable = orderedTables[index];
|
|
368
|
+
const orderedTableChildren = orderedTable
|
|
369
|
+
? orderedTable[orderedTable["table:table"] ? "table:table" : "table"]
|
|
370
|
+
: undefined;
|
|
371
|
+
const rowBreaks = [];
|
|
372
|
+
const columnBreaks = [];
|
|
240
373
|
const sheet = {
|
|
241
374
|
sheetId: index + 1,
|
|
242
375
|
title: name,
|
|
@@ -247,13 +380,27 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
247
380
|
columnMetadata: [],
|
|
248
381
|
merges: [],
|
|
249
382
|
};
|
|
383
|
+
// `table:protected="true"` is ODF's sheet-protection switch. The
|
|
384
|
+
// `table:protection-key` digest is not an OOXML hash, so only the master
|
|
385
|
+
// flag is modeled — the key itself cannot round-trip into `<sheetProtection>`.
|
|
386
|
+
const protectedAttr = table["@_table:protected"] ?? table["table:protected"];
|
|
387
|
+
if (protectedAttr === "true" || protectedAttr === true) {
|
|
388
|
+
sheet.sheetProtection = { sheet: true };
|
|
389
|
+
}
|
|
390
|
+
// Right-to-left sheets live on the table style's `style:writing-mode`
|
|
391
|
+
// (the ODF counterpart of `<sheetView rightToLeft="1">`).
|
|
392
|
+
if (this.odsStyles.isTableStyleRightToLeft(table["@_table:style-name"] || table["table:style-name"])) {
|
|
393
|
+
sheet.rightToLeft = true;
|
|
394
|
+
}
|
|
250
395
|
// Column metadata from table-column elements
|
|
251
396
|
const columnNodes = get(table, "table:table-column") || get(table, "table-column") || [];
|
|
252
|
-
const allColumns =
|
|
253
|
-
?
|
|
254
|
-
: columnNodes
|
|
255
|
-
?
|
|
256
|
-
:
|
|
397
|
+
const allColumns = orderedTableChildren
|
|
398
|
+
? flattenOrderedColumns(orderedTableChildren)
|
|
399
|
+
: Array.isArray(columnNodes)
|
|
400
|
+
? columnNodes
|
|
401
|
+
: columnNodes
|
|
402
|
+
? [columnNodes]
|
|
403
|
+
: [];
|
|
257
404
|
let currentColumnIndex = 1;
|
|
258
405
|
let detectedColumnCount = 0;
|
|
259
406
|
let defaultColumnWidth;
|
|
@@ -276,6 +423,10 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
276
423
|
visibility === "hidden" ||
|
|
277
424
|
visibility === "none" ||
|
|
278
425
|
columnStyle?.hidden;
|
|
426
|
+
// `fo:break-before="page"` on column N = a manual break after N-1.
|
|
427
|
+
if (columnStyle?.breakBefore && currentColumnIndex > 1) {
|
|
428
|
+
columnBreaks.push(currentColumnIndex - 1);
|
|
429
|
+
}
|
|
279
430
|
for (let c = 0; c < colsRepeated; c++) {
|
|
280
431
|
const props = {};
|
|
281
432
|
let shouldAssign = false;
|
|
@@ -309,7 +460,11 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
309
460
|
}
|
|
310
461
|
// Row metadata from table-row elements
|
|
311
462
|
const rowNodes = get(table, "table:table-row") || get(table, "table-row") || [];
|
|
312
|
-
const allRows =
|
|
463
|
+
const allRows = orderedTableChildren
|
|
464
|
+
? flattenOrderedRows(orderedTableChildren)
|
|
465
|
+
: Array.isArray(rowNodes)
|
|
466
|
+
? rowNodes
|
|
467
|
+
: [rowNodes];
|
|
313
468
|
// DO NOT DELETE
|
|
314
469
|
// console.log("allRows", allRows);
|
|
315
470
|
let currentRowIndex = 1;
|
|
@@ -335,6 +490,10 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
335
490
|
visibility === "none" ||
|
|
336
491
|
rowStyle?.hidden;
|
|
337
492
|
const effectiveRepeats = Math.min(rowsRepeated, 10000);
|
|
493
|
+
// `fo:break-before="page"` on row N = a manual break after N-1.
|
|
494
|
+
if (rowStyle?.breakBefore && currentRowIndex > 1) {
|
|
495
|
+
rowBreaks.push(currentRowIndex - 1);
|
|
496
|
+
}
|
|
338
497
|
const shouldProcessRowMetadata = typeof height === "number" || isHidden;
|
|
339
498
|
if (!shouldProcessRowMetadata) {
|
|
340
499
|
currentRowIndex += effectiveRepeats;
|
|
@@ -378,6 +537,53 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
378
537
|
if (detectedColumnCount > 0) {
|
|
379
538
|
sheet.columnCount = Math.max(sheet.columnCount ?? 0, detectedColumnCount);
|
|
380
539
|
}
|
|
540
|
+
// Print settings: the table style's master page (page layout +
|
|
541
|
+
// header/footer), manual breaks, and the header-rows/columns bands
|
|
542
|
+
// (print titles). `table:print-ranges` is resolved below.
|
|
543
|
+
const tableStyleName = table["@_table:style-name"] || table["table:style-name"];
|
|
544
|
+
const masterPageName = tableStyleName
|
|
545
|
+
? this.odsStyles.getTableMasterPageName(tableStyleName)
|
|
546
|
+
: undefined;
|
|
547
|
+
const masterPage = masterPageName
|
|
548
|
+
? this.odsStyles.getMasterPage(masterPageName)
|
|
549
|
+
: undefined;
|
|
550
|
+
const pageLayout = masterPage?.pageLayoutName
|
|
551
|
+
? this.odsStyles.getPageLayout(masterPage.pageLayoutName)
|
|
552
|
+
: undefined;
|
|
553
|
+
const headerRows = findOrderedHeaderBand(orderedTableChildren, "row");
|
|
554
|
+
const headerColumns = findOrderedHeaderBand(orderedTableChildren, "column");
|
|
555
|
+
const printSettings = compactPrintSettings({
|
|
556
|
+
pageSetup: pageLayout?.pageSetup,
|
|
557
|
+
pageMargins: pageLayout?.pageMargins,
|
|
558
|
+
printOptions: pageLayout?.printOptions,
|
|
559
|
+
headerFooter: masterPage?.header || masterPage?.footer
|
|
560
|
+
? {
|
|
561
|
+
...(masterPage.header ? { oddHeader: masterPage.header } : {}),
|
|
562
|
+
...(masterPage.footer ? { oddFooter: masterPage.footer } : {}),
|
|
563
|
+
}
|
|
564
|
+
: undefined,
|
|
565
|
+
printTitles: headerRows || headerColumns
|
|
566
|
+
? {
|
|
567
|
+
...(headerRows
|
|
568
|
+
? { rowStart: headerRows.start, rowEnd: headerRows.end }
|
|
569
|
+
: {}),
|
|
570
|
+
...(headerColumns
|
|
571
|
+
? {
|
|
572
|
+
columnStart: headerColumns.start,
|
|
573
|
+
columnEnd: headerColumns.end,
|
|
574
|
+
}
|
|
575
|
+
: {}),
|
|
576
|
+
}
|
|
577
|
+
: undefined,
|
|
578
|
+
rowBreaks,
|
|
579
|
+
columnBreaks,
|
|
580
|
+
});
|
|
581
|
+
if (printSettings)
|
|
582
|
+
sheet.printSettings = printSettings;
|
|
583
|
+
const printRanges = table["@_table:print-ranges"] || table["table:print-ranges"];
|
|
584
|
+
if (typeof printRanges === "string" && printRanges.trim()) {
|
|
585
|
+
printRangesBySheetId.set(sheet.sheetId, printRanges);
|
|
586
|
+
}
|
|
381
587
|
sheets.push(sheet);
|
|
382
588
|
sheetContexts.push({ node: table, sheetId: sheet.sheetId, name });
|
|
383
589
|
});
|
|
@@ -420,6 +626,16 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
420
626
|
const basicFilters = this.extractBasicFilters(sheetContexts, sheetNameMap, spreadsheetNode);
|
|
421
627
|
for (const sheet of sheets) {
|
|
422
628
|
sheet.merges = mergesMap.get(sheet.sheetId) ?? sheet.merges ?? [];
|
|
629
|
+
const printRanges = printRangesBySheetId.get(sheet.sheetId);
|
|
630
|
+
if (printRanges) {
|
|
631
|
+
const context = sheetContexts.find((c) => c.sheetId === sheet.sheetId);
|
|
632
|
+
const printArea = this.parseRangeList(printRanges, sheetNameMap, context)
|
|
633
|
+
.filter((range) => range.sheetId === sheet.sheetId)
|
|
634
|
+
.map(({ sheetId: _sheetId, ...range }) => range);
|
|
635
|
+
if (printArea.length) {
|
|
636
|
+
sheet.printSettings = { ...sheet.printSettings, printArea };
|
|
637
|
+
}
|
|
638
|
+
}
|
|
423
639
|
const settings = sheetSettings.get(sheet.sheetId);
|
|
424
640
|
if (settings) {
|
|
425
641
|
if (settings.frozenRowCount !== undefined) {
|
|
@@ -934,10 +1150,40 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
934
1150
|
const tableChildren = tableWrapper[tableNameKey];
|
|
935
1151
|
if (!tableChildren)
|
|
936
1152
|
continue;
|
|
937
|
-
const rows = tableChildren
|
|
1153
|
+
const rows = flattenOrderedRows(tableChildren);
|
|
938
1154
|
let currentRowIndex = 1;
|
|
939
1155
|
const sheetContext = sheetContexts[sheetIndex];
|
|
940
1156
|
const sheetId = sheetContext?.sheetId ?? sheetIndex + 1;
|
|
1157
|
+
// Sheet-level `<table:shapes>` frames (what LibreOffice and our own
|
|
1158
|
+
// ODS exporter write for charts/images floating over the grid). They
|
|
1159
|
+
// anchor through `table:anchor-cell-address`; their `svg:x`/`svg:y`
|
|
1160
|
+
// are sheet-absolute, so the cell anchor alone positions them.
|
|
1161
|
+
for (const shapesWrapper of tableChildren.filter((child) => child["table:shapes"] || child["shapes"])) {
|
|
1162
|
+
const shapeChildren = shapesWrapper["table:shapes"] || shapesWrapper["shapes"];
|
|
1163
|
+
// `collectFrameNodes` yields each frame child (the `draw:object` /
|
|
1164
|
+
// `draw:image` wrapper) as `frame` and the `<draw:frame>` attributes
|
|
1165
|
+
// as `cellAttrs`.
|
|
1166
|
+
for (const { frame, cellAttrs: frameAttrs } of this.collectFrameNodes(shapeChildren)) {
|
|
1167
|
+
const anchorAddress = frameAttrs?.["@_table:anchor-cell-address"] ||
|
|
1168
|
+
frameAttrs?.["@_anchor-cell-address"];
|
|
1169
|
+
const anchor = typeof anchorAddress === "string"
|
|
1170
|
+
? addressToCell(anchorAddress.split(".").pop() ?? anchorAddress)
|
|
1171
|
+
: null;
|
|
1172
|
+
const anchorRow = anchor?.rowIndex ?? 1;
|
|
1173
|
+
const anchorColumn = anchor?.columnIndex ?? 1;
|
|
1174
|
+
const placementAttrs = this.withoutAbsoluteOffsets(frameAttrs);
|
|
1175
|
+
const chart = this.convertFrameToEmbeddedChart(frame, sheetContext, sheetId, anchorRow, anchorColumn, sheetNameMap, placementAttrs);
|
|
1176
|
+
if (chart) {
|
|
1177
|
+
chartAnchors.add(this.buildAnchorKey(sheetId, anchorRow, anchorColumn));
|
|
1178
|
+
charts.push(chart);
|
|
1179
|
+
continue;
|
|
1180
|
+
}
|
|
1181
|
+
const embedded = this.convertFrameToEmbeddedObject(frame, sheetId, anchorRow, anchorColumn, imageCache, placementAttrs);
|
|
1182
|
+
if (embedded) {
|
|
1183
|
+
drawings.push(embedded);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
941
1187
|
for (const rowWrapper of rows) {
|
|
942
1188
|
const rowNameKey = rowWrapper["table:table-row"]
|
|
943
1189
|
? "table:table-row"
|
|
@@ -1005,6 +1251,18 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1005
1251
|
buildAnchorKey(sheetId, rowIndex, columnIndex) {
|
|
1006
1252
|
return `${sheetId}:${rowIndex}:${columnIndex}`;
|
|
1007
1253
|
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Copy of a `<draw:frame>` attribute record without `svg:x` / `svg:y`.
|
|
1256
|
+
* Frames in `<table:shapes>` carry sheet-absolute coordinates there,
|
|
1257
|
+
* which `buildOverlayPlacement` would otherwise read as an offset inside
|
|
1258
|
+
* the anchor cell.
|
|
1259
|
+
*/
|
|
1260
|
+
withoutAbsoluteOffsets(frameAttrs) {
|
|
1261
|
+
if (!frameAttrs || typeof frameAttrs !== "object")
|
|
1262
|
+
return frameAttrs;
|
|
1263
|
+
const { "@_svg:x": _x, "@_svg:y": _y, "@_x": _bareX, "@_y": _bareY, ...rest } = frameAttrs;
|
|
1264
|
+
return rest;
|
|
1265
|
+
}
|
|
1008
1266
|
/**
|
|
1009
1267
|
* Walk the ordered content XML for each table and assign outline
|
|
1010
1268
|
* level + collapsed/hiddenByGroup state on `rowMetadata` and
|
|
@@ -1051,7 +1309,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1051
1309
|
meta[index] = {};
|
|
1052
1310
|
Object.assign(meta[index], patch);
|
|
1053
1311
|
};
|
|
1054
|
-
const walk = (nodes, itemTag, groupTag, meta, repeatAttrs, summaryAfter) => {
|
|
1312
|
+
const walk = (nodes, itemTag, groupTag, wrapperTags, meta, repeatAttrs, summaryAfter) => {
|
|
1055
1313
|
let cursor = 1;
|
|
1056
1314
|
const openStack = [];
|
|
1057
1315
|
const collapsedDepth = () => openStack.some((g) => g.collapsed);
|
|
@@ -1060,6 +1318,14 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1060
1318
|
for (const child of children) {
|
|
1061
1319
|
if (!child)
|
|
1062
1320
|
continue;
|
|
1321
|
+
// `<table:table-header-rows>` / `<table:table-rows>` (and the
|
|
1322
|
+
// column twins) only group rows for printing; their rows keep
|
|
1323
|
+
// the surrounding outline level and still advance the cursor.
|
|
1324
|
+
const wrapper = wrapperTags.find((tag) => tag !== groupTag && child[tag]);
|
|
1325
|
+
if (wrapper) {
|
|
1326
|
+
visit(child[wrapper] || []);
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1063
1329
|
if (child[groupTag]) {
|
|
1064
1330
|
const attrs = child[":@"] || {};
|
|
1065
1331
|
const display = attrs["@_table:display"] ?? attrs["@_display"];
|
|
@@ -1110,8 +1376,8 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1110
1376
|
};
|
|
1111
1377
|
visit(nodes);
|
|
1112
1378
|
};
|
|
1113
|
-
walk(tableChildren, "table:table-column", "table:table-column-group", columnMetadata, ["table:number-columns-repeated", "number-columns-repeated"], summaryRight);
|
|
1114
|
-
walk(tableChildren, "table:table-row", "table:table-row-group", rowMetadata, ["table:number-rows-repeated", "number-rows-repeated"], summaryBelow);
|
|
1379
|
+
walk(tableChildren, "table:table-column", "table:table-column-group", COLUMN_WRAPPER_TAGS, columnMetadata, ["table:number-columns-repeated", "number-columns-repeated"], summaryRight);
|
|
1380
|
+
walk(tableChildren, "table:table-row", "table:table-row-group", ROW_WRAPPER_TAGS, rowMetadata, ["table:number-rows-repeated", "number-rows-repeated"], summaryBelow);
|
|
1115
1381
|
if (columnMetadata.length > 0)
|
|
1116
1382
|
sheet.columnMetadata = columnMetadata;
|
|
1117
1383
|
if (rowMetadata.length > 0)
|
|
@@ -1145,7 +1411,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1145
1411
|
const tableChildren = tableWrapper[tableNameKey];
|
|
1146
1412
|
if (!tableChildren)
|
|
1147
1413
|
continue;
|
|
1148
|
-
const rows = tableChildren
|
|
1414
|
+
const rows = flattenOrderedRows(tableChildren);
|
|
1149
1415
|
const sheetId = sheetContexts[sheetIndex]?.sheetId ?? sheetIndex + 1;
|
|
1150
1416
|
let currentRowIndex = 1;
|
|
1151
1417
|
for (const rowWrapper of rows) {
|
|
@@ -1274,7 +1540,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1274
1540
|
if (!tableChildren) {
|
|
1275
1541
|
return buildDefaultColumns();
|
|
1276
1542
|
}
|
|
1277
|
-
const rows = tableChildren
|
|
1543
|
+
const rows = flattenOrderedRows(tableChildren);
|
|
1278
1544
|
if (!rows.length) {
|
|
1279
1545
|
return buildDefaultColumns();
|
|
1280
1546
|
}
|
|
@@ -1551,14 +1817,24 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1551
1817
|
const frameAttrs = this.getAttributes(frameNode);
|
|
1552
1818
|
const inlineChart = this.findInlineChartNode(frameNode);
|
|
1553
1819
|
let chartNode = inlineChart;
|
|
1820
|
+
// An inline chart's styles live in the workbook's content.xml, so the
|
|
1821
|
+
// workbook-level table applies. An embedded object is its own ODF
|
|
1822
|
+
// document with its own <office:automatic-styles>, and every object
|
|
1823
|
+
// reuses the same automatic style names (LibreOffice: ch1/ch2…, our
|
|
1824
|
+
// exporter: plot1/series0…), so its styles are scoped to the object —
|
|
1825
|
+
// sharing one table would let the previous chart's
|
|
1826
|
+
// `chart:three-dimensional` flag or series colours leak into this one.
|
|
1827
|
+
let chartStyles = this.odsStyles;
|
|
1554
1828
|
if (!chartNode) {
|
|
1555
1829
|
const objectNode = this.findFrameObjectNode(frameNode);
|
|
1556
|
-
const
|
|
1830
|
+
const objectStyles = new OdsStyles();
|
|
1831
|
+
const chartFromObject = this.loadChartNodeFromObject(objectNode, frameAttrs, objectStyles);
|
|
1557
1832
|
chartNode = chartFromObject;
|
|
1833
|
+
chartStyles = objectStyles;
|
|
1558
1834
|
}
|
|
1559
1835
|
if (!chartNode)
|
|
1560
1836
|
return undefined;
|
|
1561
|
-
const spec = this.convertChartNodeToSpec(chartNode, sheetNameMap, sheetContext);
|
|
1837
|
+
const spec = this.convertChartNodeToSpec(chartNode, sheetNameMap, sheetContext, chartStyles);
|
|
1562
1838
|
if (!spec)
|
|
1563
1839
|
return undefined;
|
|
1564
1840
|
const { overlayPosition } = this.buildOverlayPlacement(frameAttrs, cellAttrs, rowIndex, columnIndex);
|
|
@@ -1625,24 +1901,32 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1625
1901
|
}
|
|
1626
1902
|
return undefined;
|
|
1627
1903
|
}
|
|
1628
|
-
loadChartNodeFromObject(objectNode, frameAttrs) {
|
|
1629
|
-
|
|
1904
|
+
loadChartNodeFromObject(objectNode, frameAttrs, styles) {
|
|
1905
|
+
// A self-closing `<draw:object xlink:href="…"/>` parses to an empty
|
|
1906
|
+
// child list with its attributes on the wrapper (`frameAttrs` here), so
|
|
1907
|
+
// the href must still be honoured when there is no object node.
|
|
1908
|
+
if (!objectNode && !frameAttrs)
|
|
1630
1909
|
return undefined;
|
|
1631
1910
|
const objectAttrs = this.getAttributes(objectNode);
|
|
1632
1911
|
const href = objectAttrs?.["@_xlink:href"] ||
|
|
1633
1912
|
objectAttrs?.["@_href"] ||
|
|
1634
1913
|
frameAttrs?.["@_xlink:href"] ||
|
|
1635
1914
|
frameAttrs?.["@_href"];
|
|
1636
|
-
return this.loadChartNodeFromHref(href);
|
|
1915
|
+
return this.loadChartNodeFromHref(href, styles);
|
|
1637
1916
|
}
|
|
1638
|
-
|
|
1917
|
+
/**
|
|
1918
|
+
* Loads an embedded chart object's `content.xml` and registers its
|
|
1919
|
+
* `<office:automatic-styles>` into `styles` — the per-object table the
|
|
1920
|
+
* caller resolves plot-area / series styles against.
|
|
1921
|
+
*/
|
|
1922
|
+
loadChartNodeFromHref(href, styles) {
|
|
1639
1923
|
const path = this.resolveObjectPath(href);
|
|
1640
1924
|
if (!path)
|
|
1641
1925
|
return undefined;
|
|
1642
1926
|
try {
|
|
1643
1927
|
const content = this.zipParser.Get(path);
|
|
1644
1928
|
const chartDoc = this.xmlParser.parse(content);
|
|
1645
|
-
|
|
1929
|
+
styles.parseContentXml(chartDoc);
|
|
1646
1930
|
return this.findChartNodeInDocument(chartDoc);
|
|
1647
1931
|
}
|
|
1648
1932
|
catch {
|
|
@@ -1718,11 +2002,12 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1718
2002
|
}
|
|
1719
2003
|
return undefined;
|
|
1720
2004
|
}
|
|
1721
|
-
convertChartNodeToSpec(chartNode, sheetNameMap, context) {
|
|
2005
|
+
convertChartNodeToSpec(chartNode, sheetNameMap, context, styles) {
|
|
1722
2006
|
if (!chartNode)
|
|
1723
2007
|
return undefined;
|
|
1724
2008
|
const chartAttrs = this.getAttributes(chartNode);
|
|
1725
|
-
const
|
|
2009
|
+
const chartClass = chartAttrs?.["@_chart:class"] || chartAttrs?.["@_class"];
|
|
2010
|
+
const chartType = this.mapOdsChartClassToType(chartClass);
|
|
1726
2011
|
const titleNode = get(chartNode, "chart:title.chart:title-text") ||
|
|
1727
2012
|
get(chartNode, "chart:title") ||
|
|
1728
2013
|
get(chartNode, "title");
|
|
@@ -1731,6 +2016,8 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1731
2016
|
const plotArea = get(chartNode, "chart:plot-area") || get(chartNode, "plot-area");
|
|
1732
2017
|
if (!plotArea)
|
|
1733
2018
|
return undefined;
|
|
2019
|
+
const plotAreaAttrs = this.getAttributes(plotArea);
|
|
2020
|
+
const sourceChartType = this.resolveOdsSourceChartType(chartClass, chartType, plotAreaAttrs?.["@_chart:style-name"] || plotAreaAttrs?.["@_style-name"], styles);
|
|
1734
2021
|
const seriesNodes = this.toArray(get(plotArea, "chart:series") ||
|
|
1735
2022
|
get(plotArea, "chart:data-series") ||
|
|
1736
2023
|
get(plotArea, "series"));
|
|
@@ -1758,7 +2045,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1758
2045
|
if (seriesData) {
|
|
1759
2046
|
const label = this.extractSeriesLabel(seriesNode);
|
|
1760
2047
|
seriesData.dataLabel = label || `Series ${seriesIndex}`;
|
|
1761
|
-
const color = this.extractChartSeriesColor(seriesNode);
|
|
2048
|
+
const color = this.extractChartSeriesColor(seriesNode, styles);
|
|
1762
2049
|
if (color) {
|
|
1763
2050
|
seriesData.color = color;
|
|
1764
2051
|
}
|
|
@@ -1776,6 +2063,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1776
2063
|
title,
|
|
1777
2064
|
domains: finalizedDomains,
|
|
1778
2065
|
series,
|
|
2066
|
+
...(sourceChartType ? { sourceChartType } : {}),
|
|
1779
2067
|
};
|
|
1780
2068
|
}
|
|
1781
2069
|
extractSeriesLabel(seriesNode) {
|
|
@@ -1787,7 +2075,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1787
2075
|
const label = labelNode ? this.extractTextContent(labelNode) : undefined;
|
|
1788
2076
|
return label?.trim() || undefined;
|
|
1789
2077
|
}
|
|
1790
|
-
extractChartSeriesColor(seriesNode) {
|
|
2078
|
+
extractChartSeriesColor(seriesNode, styles) {
|
|
1791
2079
|
if (!seriesNode)
|
|
1792
2080
|
return undefined;
|
|
1793
2081
|
const attrs = this.getAttributes(seriesNode);
|
|
@@ -1797,7 +2085,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1797
2085
|
attrs?.["@_style-name"],
|
|
1798
2086
|
];
|
|
1799
2087
|
for (const candidate of styleCandidates) {
|
|
1800
|
-
const color =
|
|
2088
|
+
const color = styles.getChartStyleColor(candidate);
|
|
1801
2089
|
if (color) {
|
|
1802
2090
|
return typeof color === "string" ? color : undefined;
|
|
1803
2091
|
}
|
|
@@ -1819,7 +2107,7 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1819
2107
|
pointAttrs?.["@_style-name"],
|
|
1820
2108
|
];
|
|
1821
2109
|
for (const candidate of pointStyleCandidates) {
|
|
1822
|
-
const color =
|
|
2110
|
+
const color = styles.getChartStyleColor(candidate);
|
|
1823
2111
|
if (color)
|
|
1824
2112
|
return typeof color === "string" ? color : undefined;
|
|
1825
2113
|
}
|
|
@@ -1855,14 +2143,40 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
1855
2143
|
if (normalized.includes("line") || normalized.includes("scatter")) {
|
|
1856
2144
|
return "line";
|
|
1857
2145
|
}
|
|
1858
|
-
if (normalized.includes("pie")) {
|
|
2146
|
+
if (normalized.includes("pie") || normalized.includes("circle")) {
|
|
1859
2147
|
return "pie";
|
|
1860
2148
|
}
|
|
1861
|
-
|
|
2149
|
+
// `chart:surface` degrades to area — the same 2-D base the OOXML
|
|
2150
|
+
// surfaceChart / surface3DChart import uses (sourceChartType SURFACE).
|
|
2151
|
+
if (normalized.includes("area") || normalized.includes("surface")) {
|
|
1862
2152
|
return "area";
|
|
1863
2153
|
}
|
|
1864
2154
|
return "bar";
|
|
1865
2155
|
}
|
|
2156
|
+
/**
|
|
2157
|
+
* The authored 3-D class token for an ODS chart: `chart:surface` is a
|
|
2158
|
+
* surface, and any other class whose plot-area style declares
|
|
2159
|
+
* `chart:three-dimensional="true"` maps to the OOXML 3-D variant of its
|
|
2160
|
+
* 2-D base (`BAR_3D`, `LINE_3D`, `PIE_3D`, `AREA_3D`). Undefined for 2-D.
|
|
2161
|
+
*/
|
|
2162
|
+
resolveOdsSourceChartType(chartClass, chartType, plotAreaStyleName, styles) {
|
|
2163
|
+
const threeDimensional = styles.isChartStyleThreeDimensional(plotAreaStyleName);
|
|
2164
|
+
if ((chartClass?.toLowerCase() || "").includes("surface")) {
|
|
2165
|
+
return threeDimensional ? "SURFACE_3D" : "SURFACE";
|
|
2166
|
+
}
|
|
2167
|
+
if (!threeDimensional)
|
|
2168
|
+
return undefined;
|
|
2169
|
+
switch (chartType) {
|
|
2170
|
+
case "bar":
|
|
2171
|
+
return "BAR_3D";
|
|
2172
|
+
case "line":
|
|
2173
|
+
return "LINE_3D";
|
|
2174
|
+
case "pie":
|
|
2175
|
+
return "PIE_3D";
|
|
2176
|
+
case "area":
|
|
2177
|
+
return "AREA_3D";
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
1866
2180
|
findRangeString(node, skipKeys) {
|
|
1867
2181
|
if (!node)
|
|
1868
2182
|
return undefined;
|
|
@@ -2472,8 +2786,8 @@ export class OdsPlugin extends BaseWorkbookPlugin {
|
|
|
2472
2786
|
? this.odsStyles.getTableCellFormat(tableStyleName)
|
|
2473
2787
|
: undefined;
|
|
2474
2788
|
// Get rows
|
|
2475
|
-
const rows = tableChildren
|
|
2476
|
-
const columnWrappers = tableChildren
|
|
2789
|
+
const rows = flattenOrderedRows(tableChildren);
|
|
2790
|
+
const columnWrappers = flattenOrderedColumns(tableChildren);
|
|
2477
2791
|
const columnFormats = new Map();
|
|
2478
2792
|
let formattedColumnIndex = 1;
|
|
2479
2793
|
for (const columnWrapper of columnWrappers) {
|