reamkit 1.3.0 → 1.5.0
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/README.md +14 -9
- package/dist/esm/core/converter/facade.d.ts +12 -6
- package/dist/esm/core/converter/facade.js +39 -3
- package/dist/esm/core/converter/ream.d.ts +5 -3
- package/dist/esm/core/converter/ream.js +26 -3
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +18 -0
- package/dist/esm/core/drawingml/sparkline-geometry.d.ts +8 -0
- package/dist/esm/core/drawingml/sparkline-geometry.js +111 -0
- package/dist/esm/core/ir/adapters.d.ts +5 -5
- package/dist/esm/core/ir/sheet.d.ts +31 -0
- package/dist/esm/core/opc/index.d.ts +2 -0
- package/dist/esm/core/opc/index.js +1 -0
- package/dist/esm/core/opc/opc-writer.d.ts +28 -0
- package/dist/esm/core/opc/opc-writer.js +60 -0
- package/dist/esm/core/opc/relationships.js +1 -0
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -0
- package/dist/esm/core/spreadsheet-model/types.d.ts +184 -0
- package/dist/esm/excel/conditional-format.d.ts +16 -0
- package/dist/esm/excel/conditional-format.js +305 -0
- package/dist/esm/excel/index.d.ts +4 -3
- package/dist/esm/excel/print-model.d.ts +2 -1
- package/dist/esm/excel/print-model.js +114 -2
- package/dist/esm/excel/sheet-drawing.d.ts +1 -1
- package/dist/esm/excel/sheet-to-flow.d.ts +3 -0
- package/dist/esm/excel/sheet-to-flow.js +51 -0
- package/dist/esm/excel/styles-parser.d.ts +1 -50
- package/dist/esm/excel/styles-parser.js +38 -1
- package/dist/esm/excel/table-parser.d.ts +2 -0
- package/dist/esm/excel/table-parser.js +51 -0
- package/dist/esm/excel/workbook-parser.d.ts +1 -5
- package/dist/esm/excel/worksheet-parser.d.ts +1 -60
- package/dist/esm/excel/worksheet-parser.js +239 -1
- package/dist/esm/excel/xlsx-reader.d.ts +3 -1
- package/dist/esm/excel/xlsx-reader.js +86 -51
- package/dist/esm/excel/xlsx-writer.d.ts +4 -0
- package/dist/esm/excel/xlsx-writer.js +271 -0
- package/dist/esm/html/html-writer.js +27 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/layout/styled-layout.js +91 -1
- package/dist/esm/word/document-parser.js +47 -13
- package/dist/esm/word/docx-writer.d.ts +4 -0
- package/dist/esm/word/docx-writer.js +602 -0
- package/dist/esm/word/drawing-parser.d.ts +1 -0
- package/dist/esm/word/drawing-parser.js +37 -2
- package/package.json +5 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OpcPackage } from '../core/opc/index.js';
|
|
2
|
-
import { ParsedWorksheet } from '
|
|
2
|
+
import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
|
|
3
3
|
export interface SheetChartRef {
|
|
4
4
|
readonly chartPartPath: string;
|
|
5
5
|
readonly widthPt: number;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { pt } from "../core/ir/units.js";
|
|
2
|
+
import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
|
|
3
|
+
import "../core/style-cascade/index.js";
|
|
4
|
+
import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, worksheetToBody } from "./print-model.js";
|
|
5
|
+
//#region src/excel/sheet-to-flow.ts
|
|
6
|
+
function projectSheetDoc(sheet) {
|
|
7
|
+
const body = [];
|
|
8
|
+
let firstSheetSection;
|
|
9
|
+
const sheetGrids = new Map(sheet.sheets.map((s) => [s.name, s.grid]));
|
|
10
|
+
for (let sheetIdx = 0; sheetIdx < sheet.sheets.length; sheetIdx++) {
|
|
11
|
+
const ws = sheet.sheets[sheetIdx];
|
|
12
|
+
if (sheetIdx === 0) firstSheetSection = sectionFromWorksheet(ws.grid);
|
|
13
|
+
if (sheetIdx > 0) body.push({
|
|
14
|
+
kind: "paragraph",
|
|
15
|
+
paragraph: {
|
|
16
|
+
properties: { pageBreakBefore: true },
|
|
17
|
+
runs: []
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const printArea = resolvePrintArea(sheet.definedNames, sheetIdx);
|
|
21
|
+
const titleRows = resolvePrintTitleRows(sheet.definedNames, sheetIdx);
|
|
22
|
+
const gridLines = ws.grid.printOptions?.gridLines === true;
|
|
23
|
+
body.push(...worksheetToBody(ws.grid, sheet.sharedStrings, sheet.styles, sheet.date1904, {
|
|
24
|
+
...printArea ? { printArea } : {},
|
|
25
|
+
...titleRows ? { titleRows } : {},
|
|
26
|
+
gridLines,
|
|
27
|
+
sheetGrids
|
|
28
|
+
}));
|
|
29
|
+
for (const ref of ws.charts ?? []) body.push({
|
|
30
|
+
kind: "chart",
|
|
31
|
+
chart: {
|
|
32
|
+
chartRelId: ref.chartPartPath,
|
|
33
|
+
width: pt(ref.widthPt),
|
|
34
|
+
height: pt(ref.heightPt),
|
|
35
|
+
paragraphProperties: {}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
kind: "flow",
|
|
41
|
+
body: resolveBodyStyles(body, EMPTY_STYLE_SHEET),
|
|
42
|
+
sections: [],
|
|
43
|
+
...firstSheetSection ? { section: firstSheetSection } : {},
|
|
44
|
+
styles: EMPTY_STYLE_SHEET,
|
|
45
|
+
resources: sheet.resources,
|
|
46
|
+
...sheet.chartData && sheet.chartData.size > 0 ? { charts: sheet.chartData } : {},
|
|
47
|
+
...sheet.info ? { info: sheet.info } : {}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { projectSheetDoc };
|
|
@@ -1,52 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
readonly sizePt?: number;
|
|
3
|
-
readonly bold?: boolean;
|
|
4
|
-
readonly italic?: boolean;
|
|
5
|
-
readonly underline?: boolean;
|
|
6
|
-
readonly colorHex?: string;
|
|
7
|
-
readonly name?: string;
|
|
8
|
-
}
|
|
9
|
-
export interface XlsxFill {
|
|
10
|
-
readonly patternType?: string;
|
|
11
|
-
readonly fgColorHex?: string;
|
|
12
|
-
readonly bgColorHex?: string;
|
|
13
|
-
}
|
|
14
|
-
export type XlsxBorderStyleName = 'none' | 'thin' | 'medium' | 'thick' | 'hair' | 'dashed' | 'dotted' | 'double' | 'mediumDashed' | 'dashDot' | 'mediumDashDot' | 'dashDotDot' | 'mediumDashDotDot' | 'slantDashDot';
|
|
15
|
-
export interface XlsxBorderEdge {
|
|
16
|
-
readonly style?: XlsxBorderStyleName;
|
|
17
|
-
readonly colorHex?: string;
|
|
18
|
-
}
|
|
19
|
-
export interface XlsxBorder {
|
|
20
|
-
readonly top?: XlsxBorderEdge;
|
|
21
|
-
readonly right?: XlsxBorderEdge;
|
|
22
|
-
readonly bottom?: XlsxBorderEdge;
|
|
23
|
-
readonly left?: XlsxBorderEdge;
|
|
24
|
-
}
|
|
25
|
-
export type XlsxHorizontalAlign = 'left' | 'center' | 'right' | 'fill' | 'justify' | 'centerContinuous' | 'distributed';
|
|
26
|
-
export type XlsxVerticalAlign = 'top' | 'center' | 'bottom' | 'justify' | 'distributed';
|
|
27
|
-
export interface XlsxCellAlignment {
|
|
28
|
-
readonly horizontal?: XlsxHorizontalAlign;
|
|
29
|
-
readonly vertical?: XlsxVerticalAlign;
|
|
30
|
-
readonly wrapText?: boolean;
|
|
31
|
-
}
|
|
32
|
-
export interface XlsxCellXf {
|
|
33
|
-
readonly numFmtId: number;
|
|
34
|
-
readonly fontId: number;
|
|
35
|
-
readonly fillId: number;
|
|
36
|
-
readonly borderId: number;
|
|
37
|
-
readonly applyNumberFormat?: boolean;
|
|
38
|
-
readonly applyFont?: boolean;
|
|
39
|
-
readonly applyFill?: boolean;
|
|
40
|
-
readonly applyBorder?: boolean;
|
|
41
|
-
readonly applyAlignment?: boolean;
|
|
42
|
-
readonly alignment?: XlsxCellAlignment;
|
|
43
|
-
}
|
|
44
|
-
export interface XlsxStyles {
|
|
45
|
-
readonly numFmts: ReadonlyMap<number, string>;
|
|
46
|
-
readonly fonts: ReadonlyArray<XlsxFont>;
|
|
47
|
-
readonly fills: ReadonlyArray<XlsxFill>;
|
|
48
|
-
readonly borders: ReadonlyArray<XlsxBorder>;
|
|
49
|
-
readonly cellXfs: ReadonlyArray<XlsxCellXf>;
|
|
50
|
-
}
|
|
1
|
+
import { XlsxStyles } from '../core/spreadsheet-model/index.js';
|
|
51
2
|
export declare const EMPTY_XLSX_STYLES: XlsxStyles;
|
|
52
3
|
export declare function parseXlsxStyles(data: Uint8Array): XlsxStyles;
|
|
@@ -21,14 +21,51 @@ function parseXlsxStyles(data) {
|
|
|
21
21
|
const xml = decoder.decode(data);
|
|
22
22
|
const root = asObject(parser.parse(xml)["styleSheet"]);
|
|
23
23
|
if (!root) return EMPTY_XLSX_STYLES;
|
|
24
|
+
const dxfs = parseDxfs(root);
|
|
24
25
|
return {
|
|
25
26
|
numFmts: parseNumFmts(root),
|
|
26
27
|
fonts: parseFonts(root),
|
|
27
28
|
fills: parseFills(root),
|
|
28
29
|
borders: parseBorders(root),
|
|
29
|
-
cellXfs: parseCellXfs(root)
|
|
30
|
+
cellXfs: parseCellXfs(root),
|
|
31
|
+
...dxfs.length > 0 ? { dxfs } : {}
|
|
30
32
|
};
|
|
31
33
|
}
|
|
34
|
+
function parseDxfs(root) {
|
|
35
|
+
const node = asObject(root["dxfs"]);
|
|
36
|
+
if (!node) return [];
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const item of asArray(node["dxf"])) {
|
|
39
|
+
const obj = asObject(item);
|
|
40
|
+
if (!obj) {
|
|
41
|
+
out.push({});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const dxf = {};
|
|
45
|
+
const fontObj = asObject(obj["font"]);
|
|
46
|
+
if (fontObj) {
|
|
47
|
+
const font = {};
|
|
48
|
+
if (hasChild(fontObj, "b")) font.bold = childToggle(fontObj, "b");
|
|
49
|
+
if (hasChild(fontObj, "i")) font.italic = childToggle(fontObj, "i");
|
|
50
|
+
const colorHex = colorOf(asObject(fontObj["color"]));
|
|
51
|
+
if (colorHex) font.colorHex = colorHex;
|
|
52
|
+
if (Object.keys(font).length > 0) dxf.font = font;
|
|
53
|
+
}
|
|
54
|
+
const pf = asObject(asObject(obj["fill"])?.["patternFill"]);
|
|
55
|
+
if (pf) {
|
|
56
|
+
const fill = {};
|
|
57
|
+
const pt = strAttr(pf, "patternType");
|
|
58
|
+
if (pt) fill.patternType = pt;
|
|
59
|
+
const fg = colorOf(asObject(pf["fgColor"]));
|
|
60
|
+
const bg = colorOf(asObject(pf["bgColor"]));
|
|
61
|
+
if (fg) fill.fgColorHex = fg;
|
|
62
|
+
if (bg) fill.bgColorHex = bg;
|
|
63
|
+
if (Object.keys(fill).length > 0) dxf.fill = fill;
|
|
64
|
+
}
|
|
65
|
+
out.push(dxf);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
32
69
|
var VALID_BORDER_STYLES = new Set([
|
|
33
70
|
"none",
|
|
34
71
|
"thin",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { parseAreaRef } from "./defined-name-ref.js";
|
|
2
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3
|
+
//#region src/excel/table-parser.ts
|
|
4
|
+
var decoder = new TextDecoder("utf-8");
|
|
5
|
+
var parser = new XMLParser({
|
|
6
|
+
ignoreAttributes: false,
|
|
7
|
+
attributeNamePrefix: "@_",
|
|
8
|
+
parseAttributeValue: false,
|
|
9
|
+
parseTagValue: false,
|
|
10
|
+
removeNSPrefix: true
|
|
11
|
+
});
|
|
12
|
+
function parseTablePart(data) {
|
|
13
|
+
const t = asObj(parser.parse(decoder.decode(data))["table"]);
|
|
14
|
+
if (!t) return void 0;
|
|
15
|
+
const refStr = strAttr(t, "ref");
|
|
16
|
+
const ref = refStr ? parseAreaRef(refStr) : void 0;
|
|
17
|
+
if (!ref) return void 0;
|
|
18
|
+
const si = asObj(t["tableStyleInfo"]);
|
|
19
|
+
const name = strAttr(t, "name");
|
|
20
|
+
const styleName = si ? strAttr(si, "name") : void 0;
|
|
21
|
+
return {
|
|
22
|
+
ref,
|
|
23
|
+
...name ? { name } : {},
|
|
24
|
+
...styleName ? { styleName } : {},
|
|
25
|
+
headerRowCount: numAttr(t, "headerRowCount") ?? 1,
|
|
26
|
+
showRowStripes: si ? boolAttr(si, "showRowStripes") : false,
|
|
27
|
+
showColumnStripes: si ? boolAttr(si, "showColumnStripes") : false,
|
|
28
|
+
showFirstColumn: si ? boolAttr(si, "showFirstColumn") : false,
|
|
29
|
+
showLastColumn: si ? boolAttr(si, "showLastColumn") : false,
|
|
30
|
+
autoFilter: asObj(t["autoFilter"]) !== void 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function asObj(v) {
|
|
34
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
35
|
+
}
|
|
36
|
+
function strAttr(obj, name) {
|
|
37
|
+
const v = obj[`@_${name}`];
|
|
38
|
+
return typeof v === "string" ? v : void 0;
|
|
39
|
+
}
|
|
40
|
+
function numAttr(obj, name) {
|
|
41
|
+
const v = strAttr(obj, name);
|
|
42
|
+
if (v === void 0) return void 0;
|
|
43
|
+
const n = Number(v);
|
|
44
|
+
return Number.isFinite(n) ? n : void 0;
|
|
45
|
+
}
|
|
46
|
+
function boolAttr(obj, name) {
|
|
47
|
+
const v = strAttr(obj, name);
|
|
48
|
+
return v === "1" || v === "true";
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { parseTablePart };
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
+
import { DefinedName } from '../core/spreadsheet-model/index.js';
|
|
1
2
|
export interface SheetReference {
|
|
2
3
|
readonly name: string;
|
|
3
4
|
readonly sheetId: string;
|
|
4
5
|
readonly relationshipId: string;
|
|
5
6
|
}
|
|
6
|
-
export interface DefinedName {
|
|
7
|
-
readonly name: string;
|
|
8
|
-
readonly localSheetId?: number;
|
|
9
|
-
readonly value: string;
|
|
10
|
-
}
|
|
11
7
|
export interface ParsedWorkbook {
|
|
12
8
|
readonly sheets: ReadonlyArray<SheetReference>;
|
|
13
9
|
readonly date1904: boolean;
|
|
@@ -1,61 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export interface WorksheetCell {
|
|
3
|
-
readonly column: number;
|
|
4
|
-
readonly row: number;
|
|
5
|
-
readonly type: CellType;
|
|
6
|
-
readonly rawValue: string;
|
|
7
|
-
readonly inlineText?: string;
|
|
8
|
-
readonly styleIndex?: number;
|
|
9
|
-
}
|
|
10
|
-
export interface ColumnWidth {
|
|
11
|
-
readonly min: number;
|
|
12
|
-
readonly max: number;
|
|
13
|
-
readonly widthChars: number;
|
|
14
|
-
}
|
|
15
|
-
export interface MergedRange {
|
|
16
|
-
readonly startColumn: number;
|
|
17
|
-
readonly startRow: number;
|
|
18
|
-
readonly endColumn: number;
|
|
19
|
-
readonly endRow: number;
|
|
20
|
-
}
|
|
21
|
-
export interface RowHeight {
|
|
22
|
-
readonly row: number;
|
|
23
|
-
readonly heightPt: number;
|
|
24
|
-
readonly customHeight: boolean;
|
|
25
|
-
}
|
|
26
|
-
export interface XlsxPageMargins {
|
|
27
|
-
readonly leftInches: number;
|
|
28
|
-
readonly rightInches: number;
|
|
29
|
-
readonly topInches: number;
|
|
30
|
-
readonly bottomInches: number;
|
|
31
|
-
readonly headerInches?: number;
|
|
32
|
-
readonly footerInches?: number;
|
|
33
|
-
}
|
|
34
|
-
export interface XlsxPageSetup {
|
|
35
|
-
readonly paperSize?: number;
|
|
36
|
-
readonly orientation?: 'portrait' | 'landscape' | 'default';
|
|
37
|
-
readonly scale?: number;
|
|
38
|
-
readonly fitToWidth?: number;
|
|
39
|
-
readonly fitToHeight?: number;
|
|
40
|
-
}
|
|
41
|
-
export interface XlsxPrintOptions {
|
|
42
|
-
readonly gridLines?: boolean;
|
|
43
|
-
readonly horizontalCentered?: boolean;
|
|
44
|
-
readonly verticalCentered?: boolean;
|
|
45
|
-
}
|
|
46
|
-
export interface ParsedWorksheet {
|
|
47
|
-
readonly cells: ReadonlyArray<WorksheetCell>;
|
|
48
|
-
readonly maxRow: number;
|
|
49
|
-
readonly maxColumn: number;
|
|
50
|
-
readonly columns: ReadonlyArray<ColumnWidth>;
|
|
51
|
-
readonly merges: ReadonlyArray<MergedRange>;
|
|
52
|
-
readonly rowHeights: ReadonlyArray<RowHeight>;
|
|
53
|
-
readonly pageMargins?: XlsxPageMargins;
|
|
54
|
-
readonly pageSetup?: XlsxPageSetup;
|
|
55
|
-
readonly fitToPage?: boolean;
|
|
56
|
-
readonly printOptions?: XlsxPrintOptions;
|
|
57
|
-
readonly rowBreaks?: ReadonlyArray<number>;
|
|
58
|
-
readonly colBreaks?: ReadonlyArray<number>;
|
|
59
|
-
readonly drawingRelId?: string;
|
|
60
|
-
}
|
|
1
|
+
import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
|
|
61
2
|
export declare function parseWorksheet(data: Uint8Array): ParsedWorksheet;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseCellRef } from "./cell-reference.js";
|
|
2
|
+
import { parseAreaRef } from "./defined-name-ref.js";
|
|
2
3
|
import { XMLParser } from "fast-xml-parser";
|
|
3
4
|
//#region src/excel/worksheet-parser.ts
|
|
4
5
|
var decoder = new TextDecoder("utf-8");
|
|
@@ -34,6 +35,9 @@ function parseWorksheet(data) {
|
|
|
34
35
|
const colBreaks = parseBreaks(wsObj, "colBreaks");
|
|
35
36
|
const drawingNode = wsObj["drawing"];
|
|
36
37
|
const drawingRelId = drawingNode && typeof drawingNode === "object" ? strAttr(drawingNode, "id") : void 0;
|
|
38
|
+
const conditionalFormats = parseConditionalFormatting(wsObj);
|
|
39
|
+
const sparklines = parseSparklines(wsObj);
|
|
40
|
+
const tablePartRelIds = parseTableParts(wsObj);
|
|
37
41
|
const printModel = {
|
|
38
42
|
...pageMargins ? { pageMargins } : {},
|
|
39
43
|
...pageSetup ? { pageSetup } : {},
|
|
@@ -41,7 +45,10 @@ function parseWorksheet(data) {
|
|
|
41
45
|
...printOptions ? { printOptions } : {},
|
|
42
46
|
...rowBreaks.length > 0 ? { rowBreaks } : {},
|
|
43
47
|
...colBreaks.length > 0 ? { colBreaks } : {},
|
|
44
|
-
...drawingRelId !== void 0 ? { drawingRelId } : {}
|
|
48
|
+
...drawingRelId !== void 0 ? { drawingRelId } : {},
|
|
49
|
+
...conditionalFormats.length > 0 ? { conditionalFormats } : {},
|
|
50
|
+
...sparklines.length > 0 ? { sparklines } : {},
|
|
51
|
+
...tablePartRelIds.length > 0 ? { tablePartRelIds } : {}
|
|
45
52
|
};
|
|
46
53
|
const sheetData = wsObj["sheetData"];
|
|
47
54
|
if (!sheetData || typeof sheetData !== "object") return {
|
|
@@ -239,6 +246,237 @@ function parseMerges(ws) {
|
|
|
239
246
|
}
|
|
240
247
|
return out;
|
|
241
248
|
}
|
|
249
|
+
function parseConditionalFormatting(ws) {
|
|
250
|
+
const raw = ws["conditionalFormatting"];
|
|
251
|
+
const items = Array.isArray(raw) ? raw : raw !== void 0 ? [raw] : [];
|
|
252
|
+
const out = [];
|
|
253
|
+
for (const item of items) {
|
|
254
|
+
if (!item || typeof item !== "object") continue;
|
|
255
|
+
const obj = item;
|
|
256
|
+
const sqref = strAttr(obj, "sqref");
|
|
257
|
+
if (!sqref) continue;
|
|
258
|
+
const ranges = parseSqref(sqref);
|
|
259
|
+
if (ranges.length === 0) continue;
|
|
260
|
+
const ruleRaw = obj["cfRule"];
|
|
261
|
+
const ruleItems = Array.isArray(ruleRaw) ? ruleRaw : ruleRaw !== void 0 ? [ruleRaw] : [];
|
|
262
|
+
const rules = [];
|
|
263
|
+
for (const rn of ruleItems) {
|
|
264
|
+
if (!rn || typeof rn !== "object") continue;
|
|
265
|
+
const rule = parseCfRule(rn);
|
|
266
|
+
if (rule) rules.push(rule);
|
|
267
|
+
}
|
|
268
|
+
if (rules.length > 0) out.push({
|
|
269
|
+
ranges,
|
|
270
|
+
rules
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return out;
|
|
274
|
+
}
|
|
275
|
+
function parseSqref(sqref) {
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const token of sqref.split(/\s+/)) {
|
|
278
|
+
if (!token) continue;
|
|
279
|
+
const r = parseAreaRef(token);
|
|
280
|
+
if (r) out.push({
|
|
281
|
+
startColumn: r.startColumn,
|
|
282
|
+
startRow: r.startRow,
|
|
283
|
+
endColumn: r.endColumn,
|
|
284
|
+
endRow: r.endRow
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return out;
|
|
288
|
+
}
|
|
289
|
+
var CF_OPERATORS = new Set([
|
|
290
|
+
"lessThan",
|
|
291
|
+
"lessThanOrEqual",
|
|
292
|
+
"equal",
|
|
293
|
+
"notEqual",
|
|
294
|
+
"greaterThanOrEqual",
|
|
295
|
+
"greaterThan",
|
|
296
|
+
"between",
|
|
297
|
+
"notBetween"
|
|
298
|
+
]);
|
|
299
|
+
function parseCfRule(obj) {
|
|
300
|
+
const priority = parseNumericAttr(obj, "priority") ?? 0;
|
|
301
|
+
switch (strAttr(obj, "type")) {
|
|
302
|
+
case "cellIs": return parseCellIsRule(obj, priority);
|
|
303
|
+
case "colorScale": return parseColorScaleRule(obj, priority);
|
|
304
|
+
case "dataBar": return parseDataBarRule(obj, priority);
|
|
305
|
+
case "iconSet": return parseIconSetRule(obj, priority);
|
|
306
|
+
default: return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function parseIconSetRule(obj, priority) {
|
|
310
|
+
const is = obj["iconSet"];
|
|
311
|
+
if (!is || typeof is !== "object") return void 0;
|
|
312
|
+
const isObj = is;
|
|
313
|
+
const cfvos = parseCfvos(isObj["cfvo"]);
|
|
314
|
+
if (cfvos.length < 3) return void 0;
|
|
315
|
+
const iconSet = strAttr(isObj, "iconSet") ?? "3TrafficLights1";
|
|
316
|
+
const reverseRaw = strAttr(isObj, "reverse");
|
|
317
|
+
const reverse = reverseRaw === "1" || reverseRaw === "true";
|
|
318
|
+
return {
|
|
319
|
+
type: "iconSet",
|
|
320
|
+
priority,
|
|
321
|
+
iconSet,
|
|
322
|
+
cfvos,
|
|
323
|
+
...reverse ? { reverse } : {}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function parseDataBarRule(obj, priority) {
|
|
327
|
+
const db = obj["dataBar"];
|
|
328
|
+
if (!db || typeof db !== "object") return void 0;
|
|
329
|
+
const dbObj = db;
|
|
330
|
+
const cfvos = parseCfvos(dbObj["cfvo"]);
|
|
331
|
+
if (cfvos.length < 2) return void 0;
|
|
332
|
+
const colorHex = colorRgbHex(dbObj["color"]);
|
|
333
|
+
if (!colorHex) return void 0;
|
|
334
|
+
const minLength = parseNumericAttr(dbObj, "minLength");
|
|
335
|
+
const maxLength = parseNumericAttr(dbObj, "maxLength");
|
|
336
|
+
return {
|
|
337
|
+
type: "dataBar",
|
|
338
|
+
priority,
|
|
339
|
+
cfvos,
|
|
340
|
+
colorHex,
|
|
341
|
+
...minLength !== void 0 ? { minLength } : {},
|
|
342
|
+
...maxLength !== void 0 ? { maxLength } : {}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function parseCellIsRule(obj, priority) {
|
|
346
|
+
const operator = strAttr(obj, "operator");
|
|
347
|
+
if (!operator || !CF_OPERATORS.has(operator)) return void 0;
|
|
348
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
349
|
+
if (dxfId === void 0) return void 0;
|
|
350
|
+
const fRaw = obj["formula"];
|
|
351
|
+
const fItems = Array.isArray(fRaw) ? fRaw : fRaw !== void 0 ? [fRaw] : [];
|
|
352
|
+
const formulas = [];
|
|
353
|
+
for (const f of fItems) {
|
|
354
|
+
const text = formulaText(f);
|
|
355
|
+
if (text !== void 0) formulas.push(text);
|
|
356
|
+
}
|
|
357
|
+
if (formulas.length === 0) return void 0;
|
|
358
|
+
return {
|
|
359
|
+
type: "cellIs",
|
|
360
|
+
priority,
|
|
361
|
+
operator,
|
|
362
|
+
formulas,
|
|
363
|
+
dxfId
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
var CFVO_TYPES = new Set([
|
|
367
|
+
"num",
|
|
368
|
+
"percent",
|
|
369
|
+
"max",
|
|
370
|
+
"min",
|
|
371
|
+
"percentile",
|
|
372
|
+
"formula",
|
|
373
|
+
"autoMin",
|
|
374
|
+
"autoMax"
|
|
375
|
+
]);
|
|
376
|
+
function parseColorScaleRule(obj, priority) {
|
|
377
|
+
const cs = obj["colorScale"];
|
|
378
|
+
if (!cs || typeof cs !== "object") return void 0;
|
|
379
|
+
const csObj = cs;
|
|
380
|
+
const cfvos = parseCfvos(csObj["cfvo"]);
|
|
381
|
+
const colorsHex = parseScaleColors(csObj["color"]);
|
|
382
|
+
if (cfvos.length < 2 || cfvos.length !== colorsHex.length) return void 0;
|
|
383
|
+
return {
|
|
384
|
+
type: "colorScale",
|
|
385
|
+
priority,
|
|
386
|
+
cfvos,
|
|
387
|
+
colorsHex
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function parseCfvos(raw) {
|
|
391
|
+
const items = Array.isArray(raw) ? raw : raw !== void 0 ? [raw] : [];
|
|
392
|
+
const out = [];
|
|
393
|
+
for (const it of items) {
|
|
394
|
+
if (!it || typeof it !== "object") continue;
|
|
395
|
+
const o = it;
|
|
396
|
+
const type = strAttr(o, "type");
|
|
397
|
+
if (!type || !CFVO_TYPES.has(type)) return [];
|
|
398
|
+
const val = strAttr(o, "val");
|
|
399
|
+
out.push(val !== void 0 ? {
|
|
400
|
+
type,
|
|
401
|
+
val
|
|
402
|
+
} : { type });
|
|
403
|
+
}
|
|
404
|
+
return out;
|
|
405
|
+
}
|
|
406
|
+
function parseScaleColors(raw) {
|
|
407
|
+
const items = Array.isArray(raw) ? raw : raw !== void 0 ? [raw] : [];
|
|
408
|
+
const out = [];
|
|
409
|
+
for (const it of items) {
|
|
410
|
+
const hex = colorRgbHex(it);
|
|
411
|
+
if (!hex) return [];
|
|
412
|
+
out.push(hex);
|
|
413
|
+
}
|
|
414
|
+
return out;
|
|
415
|
+
}
|
|
416
|
+
function colorRgbHex(node) {
|
|
417
|
+
if (!node || typeof node !== "object") return void 0;
|
|
418
|
+
const rgb = strAttr(node, "rgb");
|
|
419
|
+
if (!rgb) return void 0;
|
|
420
|
+
if (/^[0-9A-Fa-f]{8}$/.test(rgb)) return rgb.substring(2).toUpperCase();
|
|
421
|
+
if (/^[0-9A-Fa-f]{6}$/.test(rgb)) return rgb.toUpperCase();
|
|
422
|
+
}
|
|
423
|
+
function formulaText(node) {
|
|
424
|
+
if (typeof node === "string") return node;
|
|
425
|
+
if (typeof node === "number") return String(node);
|
|
426
|
+
if (node && typeof node === "object") {
|
|
427
|
+
const t = node["#text"];
|
|
428
|
+
if (typeof t === "string") return t;
|
|
429
|
+
if (typeof t === "number") return String(t);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function toArray(v) {
|
|
433
|
+
return Array.isArray(v) ? v : v === void 0 || v === null ? [] : [v];
|
|
434
|
+
}
|
|
435
|
+
function parseSparklines(ws) {
|
|
436
|
+
const extLst = asObjectNode(ws["extLst"]);
|
|
437
|
+
if (!extLst) return [];
|
|
438
|
+
const out = [];
|
|
439
|
+
for (const ext of toArray(extLst["ext"])) {
|
|
440
|
+
const groupsNode = asObjectNode(asObjectNode(ext)?.["sparklineGroups"]);
|
|
441
|
+
if (!groupsNode) continue;
|
|
442
|
+
for (const g of toArray(groupsNode["sparklineGroup"])) {
|
|
443
|
+
const group = asObjectNode(g);
|
|
444
|
+
if (!group) continue;
|
|
445
|
+
const typeStr = strAttr(group, "type");
|
|
446
|
+
const kind = typeStr === "column" ? "column" : typeStr === "stacked" ? "winLoss" : "line";
|
|
447
|
+
const colorHex = colorRgbHex(group["colorSeries"]);
|
|
448
|
+
const slNode = asObjectNode(group["sparklines"]);
|
|
449
|
+
if (!slNode) continue;
|
|
450
|
+
for (const sl of toArray(slNode["sparkline"])) {
|
|
451
|
+
const spark = asObjectNode(sl);
|
|
452
|
+
if (!spark) continue;
|
|
453
|
+
const dataRange = formulaText(spark["f"]);
|
|
454
|
+
const sqref = formulaText(spark["sqref"]);
|
|
455
|
+
if (dataRange && sqref) out.push({
|
|
456
|
+
kind,
|
|
457
|
+
dataRange,
|
|
458
|
+
sqref,
|
|
459
|
+
...colorHex ? { colorHex } : {}
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return out;
|
|
465
|
+
}
|
|
466
|
+
function asObjectNode(v) {
|
|
467
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
468
|
+
}
|
|
469
|
+
function parseTableParts(ws) {
|
|
470
|
+
const node = asObjectNode(ws["tableParts"]);
|
|
471
|
+
if (!node) return [];
|
|
472
|
+
const out = [];
|
|
473
|
+
for (const tp of toArray(node["tablePart"])) {
|
|
474
|
+
const obj = asObjectNode(tp);
|
|
475
|
+
const rid = obj ? strAttr(obj, "id") : void 0;
|
|
476
|
+
if (rid) out.push(rid);
|
|
477
|
+
}
|
|
478
|
+
return out;
|
|
479
|
+
}
|
|
242
480
|
function parseCell(c, fallbackRow, fallbackCol) {
|
|
243
481
|
if (!c || typeof c !== "object") return null;
|
|
244
482
|
const obj = c;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { DocumentReader, ReadResult } from '../core/ir/adapters.js';
|
|
2
2
|
import { FlowDoc } from '../core/ir/flow.js';
|
|
3
|
+
import { SheetDoc } from '../core/ir/sheet.js';
|
|
3
4
|
export declare function readXlsx(xlsx: Uint8Array): ReadResult<FlowDoc>;
|
|
4
|
-
export declare
|
|
5
|
+
export declare function readXlsxToSheetDoc(xlsx: Uint8Array): SheetDoc;
|
|
6
|
+
export declare const xlsxReader: DocumentReader<SheetDoc>;
|