reamkit 1.11.0 → 1.13.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/dist/esm/core/converter/facade.js +1 -1
- package/dist/esm/core/converter/project.js +1 -0
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +24 -0
- package/dist/esm/core/ir/features.d.ts +1 -0
- package/dist/esm/core/ir/features.js +1 -0
- package/dist/esm/core/ir/flow.d.ts +3 -1
- package/dist/esm/core/ir/sheet.d.ts +14 -0
- package/dist/esm/core/po-helpers.d.ts +2 -0
- package/dist/esm/core/po-helpers.js +14 -1
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +34 -0
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/pivot-table-parser.d.ts +2 -0
- package/dist/esm/excel/pivot-table-parser.js +68 -0
- package/dist/esm/excel/print-model.d.ts +5 -2
- package/dist/esm/excel/print-model.js +123 -9
- package/dist/esm/excel/sheet-to-flow.js +5 -1
- package/dist/esm/excel/slicer-parser.d.ts +15 -0
- package/dist/esm/excel/slicer-parser.js +76 -0
- package/dist/esm/excel/table-parser.d.ts +10 -0
- package/dist/esm/excel/table-parser.js +36 -4
- package/dist/esm/excel/worksheet-parser.js +56 -0
- package/dist/esm/excel/xlsx-reader.js +129 -5
- package/dist/esm/excel/xlsx-writer.js +9 -1
- package/dist/esm/html/html-writer.js +56 -2
- package/dist/esm/layout/page-doc.d.ts +1 -0
- package/dist/esm/layout/styled-layout.d.ts +8 -1
- package/dist/esm/layout/styled-layout.js +154 -6
- package/dist/esm/pdf/styled-page-emitter.js +38 -0
- package/dist/esm/pptx/pptx-reader.d.ts +2 -0
- package/dist/esm/pptx/pptx-reader.js +30 -3
- package/dist/esm/pptx/slide-parser.d.ts +8 -2
- package/dist/esm/pptx/slide-parser.js +80 -12
- package/dist/esm/word/document-parser.d.ts +17 -2
- package/dist/esm/word/document-parser.js +178 -18
- package/dist/esm/word/docx-reader.js +54 -4
- package/dist/esm/word/docx-writer.js +84 -1
- package/dist/esm/word/drawing-parser.d.ts +7 -0
- package/dist/esm/word/drawing-parser.js +13 -0
- package/dist/esm/word/index.d.ts +2 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { FontRegistry } from "../font/font-registry.js";
|
|
|
2
2
|
import { FEATURES } from "../ir/features.js";
|
|
3
3
|
import { ConversionLossError } from "../ir/loss.js";
|
|
4
4
|
import { layoutStyledDocument } from "../../layout/styled-layout.js";
|
|
5
|
+
import { pptxReader } from "../../pptx/pptx-reader.js";
|
|
5
6
|
import { docxReader } from "../../word/docx-reader.js";
|
|
6
7
|
import { projectSheetDoc } from "../../excel/sheet-to-flow.js";
|
|
7
8
|
import { xlsxReader } from "../../excel/xlsx-reader.js";
|
|
@@ -13,7 +14,6 @@ import { writeHtml } from "../../html/html-writer.js";
|
|
|
13
14
|
import { writeSvg } from "../../svg/svg-writer.js";
|
|
14
15
|
import { convertDocxToPdf } from "../../word/docx-to-pdf.js";
|
|
15
16
|
import { convertXlsxToPdf } from "../../excel/xlsx-to-pdf.js";
|
|
16
|
-
import { pptxReader } from "../../pptx/pptx-reader.js";
|
|
17
17
|
import { pdfReader } from "../../pdf-reader/reader.js";
|
|
18
18
|
//#region src/core/converter/facade.ts
|
|
19
19
|
function toFlowDoc(doc) {
|
|
@@ -9,6 +9,7 @@ function flowRenderOptions(flow) {
|
|
|
9
9
|
...flow.headersFooters ? { headersFooters: flow.headersFooters } : {},
|
|
10
10
|
...flow.footnotes ? { footnotes: flow.footnotes } : {},
|
|
11
11
|
...flow.endnotes ? { endnotes: flow.endnotes } : {},
|
|
12
|
+
...flow.comments ? { comments: flow.comments } : {},
|
|
12
13
|
resources: flow.resources,
|
|
13
14
|
...flow.charts ? { charts: flow.charts } : {},
|
|
14
15
|
...flow.embeddedFonts ? { embeddedFonts: flow.embeddedFonts } : {},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { AbstractNumbering, Alignment, Border, BorderStyle, BodyElement, CellBorders, CellMerge, DocumentInfo, CellMargins, CellProperties, CellShading, CellDataBar, CellIcon, CellIconShape, CellSparkline, Chart, ChartBlock, ChartDataPoint, ChartSeries, ChartType, CustomGeometry, CustomPathCmd, DocumentModel, FontFamilyMap, HeaderFooterReference, HeaderFooterType, ImageBlock, InlineImage, MathAccent, MathBar, MathDelimiter, MathEqArray, MathFraction, MathFunc, MathGroupChr, MathLimit, MathMatrix, MathNary, MathNode, MathRadical, MathRow, MathRun, MathScript, Numbering, NumberingFormat, NumberingInstance, NumberingLevel, NumberingReference, PageMargins, PageSize, Paragraph, ParagraphProperties, Run, RunProperties, RowProperties, Section, FloatAnchor, SectionColumns, SectionProperties, ShapeBlock, ShapeDash, ShapeFill, ShapeFillKind, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform, Style, StyleSheet, StyleType, Table, TableCell, TableLook, TableProperties, TableStyleCondition, TableStyleConditionType, TableStyleLayer, TableRow, UnderlineStyle, VerticalAlign, } from './types.js';
|
|
1
|
+
export type { AbstractNumbering, Alignment, Border, BorderStyle, BodyElement, Comment, CellBorders, CellMerge, DocumentInfo, CellMargins, CellProperties, CellShading, CellDataBar, CellIcon, CellIconShape, CellSparkline, Chart, ChartBlock, ChartDataPoint, ChartSeries, ChartType, CustomGeometry, CustomPathCmd, DocumentModel, FontFamilyMap, HeaderFooterReference, HeaderFooterType, ImageBlock, InlineImage, MathAccent, MathBar, MathDelimiter, MathEqArray, MathFraction, MathFunc, MathGroupChr, MathLimit, MathMatrix, MathNary, MathNode, MathRadical, MathRow, MathRun, MathScript, Numbering, NumberingFormat, NumberingInstance, NumberingLevel, NumberingReference, PageMargins, PageSize, Paragraph, ParagraphProperties, Run, RunProperties, RowProperties, Section, FloatAnchor, SectionColumns, SectionProperties, ShapeBlock, ShapeDash, ShapeFill, ShapeFillKind, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform, Style, StyleSheet, StyleType, Table, TableCell, TableLook, TableProperties, TableStyleCondition, TableStyleConditionType, TableStyleLayer, TableRow, UnderlineStyle, VerticalAlign, } from './types.js';
|
|
@@ -132,6 +132,8 @@ export interface Run {
|
|
|
132
132
|
readonly anchor?: string;
|
|
133
133
|
readonly footnoteRef?: string;
|
|
134
134
|
readonly endnoteRef?: string;
|
|
135
|
+
readonly commentRef?: string;
|
|
136
|
+
readonly commentRangeRefs?: ReadonlyArray<string>;
|
|
135
137
|
readonly noteNumber?: true;
|
|
136
138
|
readonly listMarker?: true;
|
|
137
139
|
readonly inlineImage?: InlineImage;
|
|
@@ -144,6 +146,27 @@ export interface Paragraph {
|
|
|
144
146
|
readonly runs: ReadonlyArray<Run>;
|
|
145
147
|
readonly bookmarks?: ReadonlyArray<string>;
|
|
146
148
|
}
|
|
149
|
+
export interface Comment {
|
|
150
|
+
readonly content: ReadonlyArray<BodyElement>;
|
|
151
|
+
readonly author?: string;
|
|
152
|
+
readonly initials?: string;
|
|
153
|
+
/** Raw w:date timestamp (ISO 8601), as authored — not reformatted. */
|
|
154
|
+
readonly date?: string;
|
|
155
|
+
/**
|
|
156
|
+
* The author's resolved identity (usually an email) from word/people.xml
|
|
157
|
+
* (`w15:person` → `w15:presenceInfo/@w15:userId`), matched on the author name.
|
|
158
|
+
* Absent when the file ships no people part or the author is not listed.
|
|
159
|
+
*/
|
|
160
|
+
readonly authorId?: string;
|
|
161
|
+
/**
|
|
162
|
+
* Microsoft commentsExtended (w15) — the id of the comment this one replies
|
|
163
|
+
* to, forming a thread. Set only when word/commentsExtended.xml links this
|
|
164
|
+
* comment's paragraph to a parent (w15:paraIdParent). Top-level comments omit it.
|
|
165
|
+
*/
|
|
166
|
+
readonly parentId?: string;
|
|
167
|
+
/** w15:done — the comment thread was marked resolved. */
|
|
168
|
+
readonly done?: boolean;
|
|
169
|
+
}
|
|
147
170
|
export type NumberingFormat = 'decimal' | 'lowerLetter' | 'upperLetter' | 'lowerRoman' | 'upperRoman' | 'bullet' | 'none';
|
|
148
171
|
export interface NumberingReference {
|
|
149
172
|
readonly numId: string;
|
|
@@ -252,6 +275,7 @@ export interface CellProperties {
|
|
|
252
275
|
readonly dataBar?: CellDataBar;
|
|
253
276
|
readonly icon?: CellIcon;
|
|
254
277
|
readonly sparkline?: CellSparkline;
|
|
278
|
+
readonly dropdown?: boolean;
|
|
255
279
|
}
|
|
256
280
|
export interface RowProperties {
|
|
257
281
|
readonly height?: Pt;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BodyElement, Chart, DocumentInfo, Numbering, Section, SectionProperties, StyleSheet } from '../document-model/index.js';
|
|
1
|
+
import { BodyElement, Chart, Comment, DocumentInfo, Numbering, Section, SectionProperties, StyleSheet } from '../document-model/index.js';
|
|
2
2
|
import { FontRegistry } from '../font/index.js';
|
|
3
3
|
import { ResourceStore } from './resources.js';
|
|
4
4
|
export interface FlowDoc {
|
|
@@ -14,6 +14,8 @@ export interface FlowDoc {
|
|
|
14
14
|
/** §17.11 footnotes/endnotes content by id (separator stubs excluded). */
|
|
15
15
|
readonly footnotes?: ReadonlyMap<string, ReadonlyArray<BodyElement>>;
|
|
16
16
|
readonly endnotes?: ReadonlyMap<string, ReadonlyArray<BodyElement>>;
|
|
17
|
+
/** §17.13.4 review comments by id, anchored from a run's `commentRef`. */
|
|
18
|
+
readonly comments?: ReadonlyMap<string, Comment>;
|
|
17
19
|
/** Parsed charts keyed by relationship id (ChartBlock.chartRelId). */
|
|
18
20
|
readonly charts?: ReadonlyMap<string, Chart>;
|
|
19
21
|
/** Content-addressed binary resources (images). */
|
|
@@ -6,10 +6,24 @@ export interface SheetChartRef {
|
|
|
6
6
|
readonly widthPt: number;
|
|
7
7
|
readonly heightPt: number;
|
|
8
8
|
}
|
|
9
|
+
export interface SheetSlicerItem {
|
|
10
|
+
readonly label: string;
|
|
11
|
+
readonly selected: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface SheetSlicer {
|
|
14
|
+
readonly caption: string;
|
|
15
|
+
readonly columnCount: number;
|
|
16
|
+
readonly items: ReadonlyArray<SheetSlicerItem>;
|
|
17
|
+
readonly headerHex?: string;
|
|
18
|
+
readonly selectedHex?: string;
|
|
19
|
+
readonly headerTextHex?: string;
|
|
20
|
+
readonly selectedTextHex?: string;
|
|
21
|
+
}
|
|
9
22
|
export interface Sheet {
|
|
10
23
|
readonly name: string;
|
|
11
24
|
readonly grid: ParsedWorksheet;
|
|
12
25
|
readonly charts?: ReadonlyArray<SheetChartRef>;
|
|
26
|
+
readonly slicers?: ReadonlyArray<SheetSlicer>;
|
|
13
27
|
}
|
|
14
28
|
export interface SheetDoc {
|
|
15
29
|
readonly kind: 'sheet';
|
|
@@ -6,6 +6,8 @@ export declare function poChildren(node: PoNode | undefined): ReadonlyArray<PoNo
|
|
|
6
6
|
export declare function poChildrenWith(node: PoNode | undefined, tag: string): Array<PoNode>;
|
|
7
7
|
export declare function poFirstChild(node: PoNode | undefined, tag: string): PoNode | undefined;
|
|
8
8
|
export declare function poAttr(node: PoNode | undefined, name: string): string | undefined;
|
|
9
|
+
export declare function poAttrLocal(node: PoNode | undefined, name: string): string | undefined;
|
|
10
|
+
export declare function poIsLocal(node: PoNode | undefined, name: string): boolean;
|
|
9
11
|
export declare function poIntAttr(node: PoNode | undefined, name: string): number | undefined;
|
|
10
12
|
export declare function poVal(node: PoNode | undefined): string | undefined;
|
|
11
13
|
export declare function poToggle(node: PoNode | undefined): boolean | undefined;
|
|
@@ -28,6 +28,19 @@ function poAttr(node, name) {
|
|
|
28
28
|
const v = a[`@_w:${name}`] ?? a[`@_r:${name}`] ?? a[`@_m:${name}`] ?? a[`@_xml:${name}`] ?? a[`@_${name}`];
|
|
29
29
|
return typeof v === "string" ? v : void 0;
|
|
30
30
|
}
|
|
31
|
+
function poAttrLocal(node, name) {
|
|
32
|
+
if (!node || typeof node !== "object") return void 0;
|
|
33
|
+
const attrs = node[ATTRS_KEY];
|
|
34
|
+
if (!attrs || typeof attrs !== "object") return void 0;
|
|
35
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
36
|
+
if (!k.startsWith("@_")) continue;
|
|
37
|
+
if (k.slice(2).split(":").pop() === name && typeof v === "string") return v;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function poIsLocal(node, name) {
|
|
41
|
+
const tag = poTag(node);
|
|
42
|
+
return tag !== void 0 && (tag === name || tag.split(":").pop() === name);
|
|
43
|
+
}
|
|
31
44
|
function poIntAttr(node, name) {
|
|
32
45
|
const v = poAttr(node, name);
|
|
33
46
|
if (v === void 0) return void 0;
|
|
@@ -73,4 +86,4 @@ function poFindDescendant(node, tag) {
|
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
//#endregion
|
|
76
|
-
export { poAttr, poChildren, poChildrenWith, poFindByPath, poFindDescendant, poFirstChild, poIntAttr, poIs, poTag, poText, poToggle, poVal };
|
|
89
|
+
export { poAttr, poAttrLocal, poChildren, poChildrenWith, poFindByPath, poFindDescendant, poFirstChild, poIntAttr, poIs, poIsLocal, poTag, poText, poToggle, poVal };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { CellType, WorksheetCell, ColumnWidth, MergedRange, RowHeight, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRule, ConditionalFormat, SparklineKind, ParsedSparkline, ExcelTable, SheetPane, } from './types.js';
|
|
1
|
+
export type { CellType, WorksheetCell, ColumnWidth, MergedRange, RowHeight, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRule, ConditionalFormat, DataValidationType, DataValidation, SparklineKind, ParsedSparkline, ExcelTable, PivotTable, SheetPane, } from './types.js';
|
|
@@ -58,9 +58,11 @@ export interface ParsedWorksheet {
|
|
|
58
58
|
readonly colBreaks?: ReadonlyArray<number>;
|
|
59
59
|
readonly drawingRelId?: string;
|
|
60
60
|
readonly conditionalFormats?: ReadonlyArray<ConditionalFormat>;
|
|
61
|
+
readonly dataValidations?: ReadonlyArray<DataValidation>;
|
|
61
62
|
readonly sparklines?: ReadonlyArray<ParsedSparkline>;
|
|
62
63
|
readonly tablePartRelIds?: ReadonlyArray<string>;
|
|
63
64
|
readonly tables?: ReadonlyArray<ExcelTable>;
|
|
65
|
+
readonly pivotTables?: ReadonlyArray<PivotTable>;
|
|
64
66
|
readonly pane?: SheetPane;
|
|
65
67
|
}
|
|
66
68
|
export interface SheetPane {
|
|
@@ -81,6 +83,21 @@ export interface ExcelTable {
|
|
|
81
83
|
readonly bandHex?: string;
|
|
82
84
|
readonly headerTextHex?: string;
|
|
83
85
|
}
|
|
86
|
+
export interface PivotTable {
|
|
87
|
+
readonly ref: MergedRange;
|
|
88
|
+
readonly name?: string;
|
|
89
|
+
readonly styleName?: string;
|
|
90
|
+
readonly firstHeaderRow: number;
|
|
91
|
+
readonly firstDataRow: number;
|
|
92
|
+
readonly firstDataCol: number;
|
|
93
|
+
readonly showRowStripes: boolean;
|
|
94
|
+
readonly showColStripes: boolean;
|
|
95
|
+
readonly rowItemTypes?: ReadonlyArray<string | undefined>;
|
|
96
|
+
readonly colItemTypes?: ReadonlyArray<string | undefined>;
|
|
97
|
+
readonly headerHex?: string;
|
|
98
|
+
readonly bandHex?: string;
|
|
99
|
+
readonly headerTextHex?: string;
|
|
100
|
+
}
|
|
84
101
|
export type SparklineKind = 'line' | 'column' | 'winLoss';
|
|
85
102
|
export interface ParsedSparkline {
|
|
86
103
|
readonly kind: SparklineKind;
|
|
@@ -187,3 +204,20 @@ export interface ConditionalFormat {
|
|
|
187
204
|
readonly ranges: ReadonlyArray<MergedRange>;
|
|
188
205
|
readonly rules: ReadonlyArray<CfRule>;
|
|
189
206
|
}
|
|
207
|
+
export type DataValidationType = 'none' | 'whole' | 'decimal' | 'list' | 'date' | 'time' | 'textLength' | 'custom';
|
|
208
|
+
export interface DataValidation {
|
|
209
|
+
readonly type: DataValidationType;
|
|
210
|
+
readonly ranges: ReadonlyArray<MergedRange>;
|
|
211
|
+
readonly operator?: string;
|
|
212
|
+
readonly allowBlank?: boolean;
|
|
213
|
+
readonly showDropDown?: boolean;
|
|
214
|
+
readonly showInputMessage?: boolean;
|
|
215
|
+
readonly showErrorMessage?: boolean;
|
|
216
|
+
readonly errorStyle?: string;
|
|
217
|
+
readonly formula1?: string;
|
|
218
|
+
readonly formula2?: string;
|
|
219
|
+
readonly promptTitle?: string;
|
|
220
|
+
readonly prompt?: string;
|
|
221
|
+
readonly errorTitle?: string;
|
|
222
|
+
readonly error?: string;
|
|
223
|
+
}
|
|
@@ -7,7 +7,7 @@ export { parseWorkbook } from './workbook-parser.js';
|
|
|
7
7
|
export type { ParsedWorkbook, SheetReference } from './workbook-parser.js';
|
|
8
8
|
export type { DefinedName } from '../core/spreadsheet-model/index.js';
|
|
9
9
|
export { parseWorksheet } from './worksheet-parser.js';
|
|
10
|
-
export type { CellType, ColumnWidth, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
|
|
10
|
+
export type { CellType, ColumnWidth, DataValidation, DataValidationType, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
|
|
11
11
|
export { parseXlsxStyles, EMPTY_XLSX_STYLES } from './styles-parser.js';
|
|
12
12
|
export type { XlsxBorder, XlsxBorderEdge, XlsxBorderStyleName, XlsxCellAlignment, XlsxCellXf, XlsxFill, XlsxFont, XlsxHorizontalAlign, XlsxStyles, XlsxVerticalAlign, } from '../core/spreadsheet-model/index.js';
|
|
13
13
|
export { applyNumberFormat } from './number-format.js';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { parseAreaRef } from "./defined-name-ref.js";
|
|
2
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3
|
+
//#region src/excel/pivot-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 parsePivotTablePart(data) {
|
|
13
|
+
const def = asObj(parser.parse(decoder.decode(data))["pivotTableDefinition"]);
|
|
14
|
+
if (!def) return void 0;
|
|
15
|
+
const loc = asObj(def["location"]);
|
|
16
|
+
const refStr = loc ? strAttr(loc, "ref") : void 0;
|
|
17
|
+
const ref = refStr ? parseAreaRef(refStr) : void 0;
|
|
18
|
+
if (!ref) return void 0;
|
|
19
|
+
const si = asObj(def["pivotTableStyleInfo"]);
|
|
20
|
+
const name = strAttr(def, "name");
|
|
21
|
+
const styleName = si ? strAttr(si, "name") : void 0;
|
|
22
|
+
const rowItemTypes = itemTypes(asObj(def["rowItems"]));
|
|
23
|
+
const colItemTypes = itemTypes(asObj(def["colItems"]));
|
|
24
|
+
const hasRowTotals = rowItemTypes?.some((t) => t !== void 0) ?? false;
|
|
25
|
+
const hasColTotals = colItemTypes?.some((t) => t !== void 0) ?? false;
|
|
26
|
+
return {
|
|
27
|
+
ref,
|
|
28
|
+
...name ? { name } : {},
|
|
29
|
+
...styleName ? { styleName } : {},
|
|
30
|
+
firstHeaderRow: (loc ? numAttr(loc, "firstHeaderRow") : void 0) ?? 1,
|
|
31
|
+
firstDataRow: (loc ? numAttr(loc, "firstDataRow") : void 0) ?? 1,
|
|
32
|
+
firstDataCol: (loc ? numAttr(loc, "firstDataCol") : void 0) ?? 0,
|
|
33
|
+
showRowStripes: si ? boolAttr(si, "showRowStripes") : false,
|
|
34
|
+
showColStripes: si ? boolAttr(si, "showColStripes") : false,
|
|
35
|
+
...hasRowTotals && rowItemTypes ? { rowItemTypes } : {},
|
|
36
|
+
...hasColTotals && colItemTypes ? { colItemTypes } : {}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function itemTypes(node) {
|
|
40
|
+
if (!node) return void 0;
|
|
41
|
+
return toArray(node["i"]).map((i) => {
|
|
42
|
+
const o = asObj(i);
|
|
43
|
+
return o ? strAttr(o, "t") : void 0;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function toArray(v) {
|
|
47
|
+
if (v === void 0 || v === null) return [];
|
|
48
|
+
return Array.isArray(v) ? v : [v];
|
|
49
|
+
}
|
|
50
|
+
function asObj(v) {
|
|
51
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
52
|
+
}
|
|
53
|
+
function strAttr(obj, name) {
|
|
54
|
+
const v = obj[`@_${name}`];
|
|
55
|
+
return typeof v === "string" ? v : void 0;
|
|
56
|
+
}
|
|
57
|
+
function numAttr(obj, name) {
|
|
58
|
+
const v = strAttr(obj, name);
|
|
59
|
+
if (v === void 0) return void 0;
|
|
60
|
+
const n = Number(v);
|
|
61
|
+
return Number.isFinite(n) ? n : void 0;
|
|
62
|
+
}
|
|
63
|
+
function boolAttr(obj, name) {
|
|
64
|
+
const v = strAttr(obj, name);
|
|
65
|
+
return v === "1" || v === "true";
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { parsePivotTablePart };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { BodyElement, SectionProperties } from '../core/document-model/index.js';
|
|
2
|
-
import { CellRange, DefinedName, ParsedWorksheet, XlsxStyles } from './index.js';
|
|
1
|
+
import { BodyElement, SectionProperties, Table } from '../core/document-model/index.js';
|
|
2
|
+
import { CellRange, DefinedName, ParsedWorksheet, WorksheetCell, XlsxStyles } from './index.js';
|
|
3
|
+
import { SheetSlicer } from '../core/ir/sheet.js';
|
|
3
4
|
export declare const TWIPS_PER_EXCEL_CHAR = 105;
|
|
4
5
|
export declare const DEFAULT_COL_TWIPS = 960;
|
|
5
6
|
export declare const DEFAULT_ROW_TWIPS = 300;
|
|
@@ -19,4 +20,6 @@ interface PrintModelOptions {
|
|
|
19
20
|
readonly sheetGrids?: ReadonlyMap<string, ParsedWorksheet>;
|
|
20
21
|
}
|
|
21
22
|
export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array<BodyElement>;
|
|
23
|
+
export declare function resolveCellText(cell: WorksheetCell, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean): string;
|
|
24
|
+
export declare function slicerTable(slicer: SheetSlicer): Table;
|
|
22
25
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { eighthPtToPt, halfPtToPt, twipsToPt } from "../core/ir/units.js";
|
|
1
|
+
import { eighthPtToPt, halfPtToPt, pt, twipsToPt } from "../core/ir/units.js";
|
|
2
2
|
import { parseAreaRef, parseTitleRowRange } from "./defined-name-ref.js";
|
|
3
3
|
import { applyNumberFormat } from "./number-format.js";
|
|
4
4
|
import "./index.js";
|
|
@@ -195,6 +195,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
195
195
|
const cfFormatter = buildConditionalFormatter(worksheet.conditionalFormats, styles, worksheet.cells);
|
|
196
196
|
const sparklineByCell = buildSparklineLookup(worksheet, print);
|
|
197
197
|
const tableFormatByCell = buildTableFormatLookup(worksheet);
|
|
198
|
+
const dropdownRanges = listDropdownRanges(worksheet.dataValidations);
|
|
198
199
|
const rows = [];
|
|
199
200
|
for (let r = 0; r < rowCount; r++) {
|
|
200
201
|
const absR = r + rowStart;
|
|
@@ -246,6 +247,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
246
247
|
if (text.length > charsFit) text = text.slice(0, charsFit);
|
|
247
248
|
}
|
|
248
249
|
}
|
|
250
|
+
const dropdown = dropdownRanges.length > 0 && rangesCover(dropdownRanges, absR, absC);
|
|
249
251
|
const visibleEndCol = merge ? Math.min(merge.endColumn, colWindowEnd) : 0;
|
|
250
252
|
const properties = {
|
|
251
253
|
...merge && visibleEndCol > merge.startColumn ? { colSpan: visibleEndCol - merge.startColumn + 1 } : {},
|
|
@@ -254,7 +256,8 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
254
256
|
...dataBar ? { dataBar } : {},
|
|
255
257
|
...icon ? { icon } : {},
|
|
256
258
|
...sparkline ? { sparkline } : {},
|
|
257
|
-
...borders ? { borders } : {}
|
|
259
|
+
...borders ? { borders } : {},
|
|
260
|
+
...dropdown ? { dropdown: true } : {}
|
|
258
261
|
};
|
|
259
262
|
const paragraphProps = cellParaProps(alignment);
|
|
260
263
|
cells.push({
|
|
@@ -474,6 +477,19 @@ function mapBorderStyle(style) {
|
|
|
474
477
|
function key(row, col) {
|
|
475
478
|
return `${row},${col}`;
|
|
476
479
|
}
|
|
480
|
+
function listDropdownRanges(dvs) {
|
|
481
|
+
if (!dvs || dvs.length === 0) return [];
|
|
482
|
+
const out = [];
|
|
483
|
+
for (const dv of dvs) {
|
|
484
|
+
if (dv.type !== "list" || dv.showDropDown) continue;
|
|
485
|
+
out.push(...dv.ranges);
|
|
486
|
+
}
|
|
487
|
+
return out;
|
|
488
|
+
}
|
|
489
|
+
function rangesCover(ranges, row, col) {
|
|
490
|
+
for (const r of ranges) if (row >= r.startRow && row <= r.endRow && col >= r.startColumn && col <= r.endColumn) return true;
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
477
493
|
function buildSparklineLookup(worksheet, print) {
|
|
478
494
|
const out = /* @__PURE__ */ new Map();
|
|
479
495
|
for (const sp of worksheet.sparklines ?? []) {
|
|
@@ -525,18 +541,23 @@ function collectSeriesValues(cells, area) {
|
|
|
525
541
|
for (let r = area.startRow; r <= area.endRow; r++) for (let col = area.startColumn; col <= area.endColumn; col++) out.push(byKey.get(key(r, col)) ?? null);
|
|
526
542
|
return out;
|
|
527
543
|
}
|
|
544
|
+
function isPivotTotal(t) {
|
|
545
|
+
return t !== void 0 && t !== "data" && t !== "blank";
|
|
546
|
+
}
|
|
528
547
|
function buildTableFormatLookup(worksheet) {
|
|
529
548
|
const out = /* @__PURE__ */ new Map();
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
const firstDataRow = ref.startRow + t.headerRowCount;
|
|
549
|
+
const band = (ref, headerRows, style, isTotalRow) => {
|
|
550
|
+
const firstDataRow = ref.startRow + headerRows;
|
|
533
551
|
for (let r = ref.startRow; r <= ref.endRow; r++) {
|
|
534
552
|
let colorHex;
|
|
535
553
|
let fontColorHex;
|
|
536
554
|
if (r < firstDataRow) {
|
|
537
|
-
colorHex =
|
|
538
|
-
fontColorHex =
|
|
539
|
-
} else if (
|
|
555
|
+
colorHex = style.headerHex;
|
|
556
|
+
fontColorHex = style.headerTextHex;
|
|
557
|
+
} else if (isTotalRow?.(r - firstDataRow)) {
|
|
558
|
+
colorHex = style.headerHex;
|
|
559
|
+
fontColorHex = style.headerTextHex;
|
|
560
|
+
} else if (style.showRowStripes && style.bandHex) colorHex = (r - firstDataRow) % 2 === 1 ? style.bandHex : void 0;
|
|
540
561
|
if (!colorHex && !fontColorHex) continue;
|
|
541
562
|
const fmt = {
|
|
542
563
|
...colorHex ? { shading: { colorHex } } : {},
|
|
@@ -544,11 +565,104 @@ function buildTableFormatLookup(worksheet) {
|
|
|
544
565
|
};
|
|
545
566
|
for (let c = ref.startColumn; c <= ref.endColumn; c++) out.set(key(r, c), fmt);
|
|
546
567
|
}
|
|
568
|
+
};
|
|
569
|
+
for (const t of worksheet.tables ?? []) band(t.ref, t.headerRowCount, t);
|
|
570
|
+
for (const p of worksheet.pivotTables ?? []) band(p.ref, p.firstDataRow, p, (off) => isPivotTotal(p.rowItemTypes?.[off]));
|
|
571
|
+
for (const p of worksheet.pivotTables ?? []) {
|
|
572
|
+
if (!p.colItemTypes || p.headerHex === void 0) continue;
|
|
573
|
+
const firstDataRow = p.ref.startRow + p.firstDataRow;
|
|
574
|
+
const firstDataCol = p.ref.startColumn + p.firstDataCol;
|
|
575
|
+
const totalFmt = {
|
|
576
|
+
shading: { colorHex: p.headerHex },
|
|
577
|
+
...p.headerTextHex ? { fontColorHex: p.headerTextHex } : {}
|
|
578
|
+
};
|
|
579
|
+
for (let i = 0; i < p.colItemTypes.length; i++) {
|
|
580
|
+
if (!isPivotTotal(p.colItemTypes[i])) continue;
|
|
581
|
+
const c = firstDataCol + i;
|
|
582
|
+
if (c > p.ref.endColumn) continue;
|
|
583
|
+
for (let r = firstDataRow; r <= p.ref.endRow; r++) out.set(key(r, c), totalFmt);
|
|
584
|
+
}
|
|
547
585
|
}
|
|
548
586
|
return out;
|
|
549
587
|
}
|
|
550
588
|
function cellHasContent(cell) {
|
|
551
589
|
return !!cell && (cell.rawValue !== "" || cell.inlineText !== void 0);
|
|
552
590
|
}
|
|
591
|
+
var SLICER_WIDTH_PT = 108;
|
|
592
|
+
var SLICER_ROW_PT = 16;
|
|
593
|
+
var SLICER_UNSELECTED_HEX = "F2F2F2";
|
|
594
|
+
function slicerTable(slicer) {
|
|
595
|
+
const cols = Math.max(1, slicer.columnCount);
|
|
596
|
+
const colWidthPt = SLICER_WIDTH_PT / cols;
|
|
597
|
+
const thin = {
|
|
598
|
+
style: "single",
|
|
599
|
+
width: eighthPtToPt(4)
|
|
600
|
+
};
|
|
601
|
+
const rowProps = {
|
|
602
|
+
height: pt(SLICER_ROW_PT),
|
|
603
|
+
heightRule: "atLeast"
|
|
604
|
+
};
|
|
605
|
+
const rows = [];
|
|
606
|
+
rows.push({
|
|
607
|
+
properties: rowProps,
|
|
608
|
+
cells: [{
|
|
609
|
+
properties: {
|
|
610
|
+
...cols > 1 ? { colSpan: cols } : {},
|
|
611
|
+
...slicer.headerHex ? { shading: { colorHex: slicer.headerHex } } : {}
|
|
612
|
+
},
|
|
613
|
+
content: [slicerParagraph(slicer.caption, {
|
|
614
|
+
bold: true,
|
|
615
|
+
...slicer.headerTextHex ? { colorHex: slicer.headerTextHex } : {}
|
|
616
|
+
})]
|
|
617
|
+
}]
|
|
618
|
+
});
|
|
619
|
+
for (let i = 0; i < slicer.items.length; i += cols) {
|
|
620
|
+
const cells = [];
|
|
621
|
+
for (let c = 0; c < cols; c++) {
|
|
622
|
+
const item = slicer.items[i + c];
|
|
623
|
+
if (!item) {
|
|
624
|
+
cells.push({
|
|
625
|
+
properties: {},
|
|
626
|
+
content: [slicerParagraph("", {})]
|
|
627
|
+
});
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
const fill = item.selected ? slicer.selectedHex : SLICER_UNSELECTED_HEX;
|
|
631
|
+
const textHex = item.selected ? slicer.selectedTextHex : void 0;
|
|
632
|
+
cells.push({
|
|
633
|
+
properties: fill ? { shading: { colorHex: fill } } : {},
|
|
634
|
+
content: [slicerParagraph(item.label, textHex ? { colorHex: textHex } : {})]
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
rows.push({
|
|
638
|
+
properties: rowProps,
|
|
639
|
+
cells
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
return {
|
|
643
|
+
properties: { borders: {
|
|
644
|
+
top: thin,
|
|
645
|
+
bottom: thin,
|
|
646
|
+
left: thin,
|
|
647
|
+
right: thin,
|
|
648
|
+
insideH: thin,
|
|
649
|
+
insideV: thin
|
|
650
|
+
} },
|
|
651
|
+
grid: Array.from({ length: cols }, () => pt(colWidthPt)),
|
|
652
|
+
rows
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
function slicerParagraph(text, runProps) {
|
|
656
|
+
return {
|
|
657
|
+
kind: "paragraph",
|
|
658
|
+
paragraph: {
|
|
659
|
+
properties: {},
|
|
660
|
+
runs: text.length > 0 ? [{
|
|
661
|
+
text,
|
|
662
|
+
properties: runProps
|
|
663
|
+
}] : []
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
}
|
|
553
667
|
//#endregion
|
|
554
|
-
export { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, worksheetToBody };
|
|
668
|
+
export { resolveCellText, resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pt } from "../core/ir/units.js";
|
|
2
2
|
import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
|
|
3
3
|
import "../core/style-cascade/index.js";
|
|
4
|
-
import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, worksheetToBody } from "./print-model.js";
|
|
4
|
+
import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody } from "./print-model.js";
|
|
5
5
|
//#region src/excel/sheet-to-flow.ts
|
|
6
6
|
function projectSheetDoc(sheet) {
|
|
7
7
|
const body = [];
|
|
@@ -35,6 +35,10 @@ function projectSheetDoc(sheet) {
|
|
|
35
35
|
paragraphProperties: {}
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
|
+
for (const slicer of ws.slicers ?? []) body.push({
|
|
39
|
+
kind: "table",
|
|
40
|
+
table: slicerTable(slicer)
|
|
41
|
+
});
|
|
38
42
|
}
|
|
39
43
|
return {
|
|
40
44
|
kind: "flow",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SlicerDef {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly cacheName: string;
|
|
4
|
+
readonly caption: string;
|
|
5
|
+
readonly columnCount: number;
|
|
6
|
+
readonly styleName?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SlicerCacheDef {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly sourceName?: string;
|
|
11
|
+
readonly tableId?: number;
|
|
12
|
+
readonly columnId?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function parseSlicerPart(data: Uint8Array): Array<SlicerDef>;
|
|
15
|
+
export declare function parseSlicerCachePart(data: Uint8Array): SlicerCacheDef | undefined;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { XMLParser } from "fast-xml-parser";
|
|
2
|
+
//#region src/excel/slicer-parser.ts
|
|
3
|
+
var decoder = new TextDecoder("utf-8");
|
|
4
|
+
var parser = new XMLParser({
|
|
5
|
+
ignoreAttributes: false,
|
|
6
|
+
attributeNamePrefix: "@_",
|
|
7
|
+
parseAttributeValue: false,
|
|
8
|
+
parseTagValue: false,
|
|
9
|
+
removeNSPrefix: true
|
|
10
|
+
});
|
|
11
|
+
function parseSlicerPart(data) {
|
|
12
|
+
const root = asObj(parser.parse(decoder.decode(data))["slicers"]);
|
|
13
|
+
if (!root) return [];
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const s of asArray(root["slicer"])) {
|
|
16
|
+
const o = asObj(s);
|
|
17
|
+
if (!o) continue;
|
|
18
|
+
const name = strAttr(o, "name");
|
|
19
|
+
const cacheName = strAttr(o, "cache");
|
|
20
|
+
if (!name || !cacheName) continue;
|
|
21
|
+
const caption = strAttr(o, "caption") ?? name;
|
|
22
|
+
const styleName = strAttr(o, "style");
|
|
23
|
+
out.push({
|
|
24
|
+
name,
|
|
25
|
+
cacheName,
|
|
26
|
+
caption,
|
|
27
|
+
columnCount: Math.max(1, numAttr(o, "columnCount") ?? 1),
|
|
28
|
+
...styleName ? { styleName } : {}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
function parseSlicerCachePart(data) {
|
|
34
|
+
const root = asObj(parser.parse(decoder.decode(data))["slicerCacheDefinition"]);
|
|
35
|
+
if (!root) return void 0;
|
|
36
|
+
const name = strAttr(root, "name");
|
|
37
|
+
if (!name) return void 0;
|
|
38
|
+
const sourceName = strAttr(root, "sourceName");
|
|
39
|
+
let tableId;
|
|
40
|
+
let columnId;
|
|
41
|
+
const extLst = asObj(root["extLst"]);
|
|
42
|
+
if (extLst) for (const ext of asArray(extLst["ext"])) {
|
|
43
|
+
const e = asObj(ext);
|
|
44
|
+
const inner = e ? asObj(e["slicerCacheDefinition"]) : void 0;
|
|
45
|
+
const tsc = inner ? asObj(inner["tableSlicerCache"]) : void 0;
|
|
46
|
+
if (tsc) {
|
|
47
|
+
tableId = numAttr(tsc, "tableId");
|
|
48
|
+
columnId = numAttr(tsc, "column");
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
name,
|
|
54
|
+
...sourceName ? { sourceName } : {},
|
|
55
|
+
...tableId !== void 0 ? { tableId } : {},
|
|
56
|
+
...columnId !== void 0 ? { columnId } : {}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function asObj(v) {
|
|
60
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
61
|
+
}
|
|
62
|
+
function asArray(v) {
|
|
63
|
+
return Array.isArray(v) ? v : v === void 0 || v === null ? [] : [v];
|
|
64
|
+
}
|
|
65
|
+
function strAttr(obj, name) {
|
|
66
|
+
const v = obj[`@_${name}`];
|
|
67
|
+
return typeof v === "string" ? v : void 0;
|
|
68
|
+
}
|
|
69
|
+
function numAttr(obj, name) {
|
|
70
|
+
const v = strAttr(obj, name);
|
|
71
|
+
if (v === void 0) return void 0;
|
|
72
|
+
const n = Number(v);
|
|
73
|
+
return Number.isFinite(n) ? n : void 0;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { parseSlicerCachePart, parseSlicerPart };
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import { ExcelTable } from '../core/spreadsheet-model/index.js';
|
|
2
|
+
export interface TableFilterColumn {
|
|
3
|
+
readonly colId: number;
|
|
4
|
+
readonly values: ReadonlyArray<string>;
|
|
5
|
+
}
|
|
6
|
+
export interface ParsedTablePart {
|
|
7
|
+
readonly table: ExcelTable;
|
|
8
|
+
readonly id?: number;
|
|
9
|
+
readonly filters: ReadonlyArray<TableFilterColumn>;
|
|
10
|
+
}
|
|
2
11
|
export declare function parseTablePart(data: Uint8Array): ExcelTable | undefined;
|
|
12
|
+
export declare function parseTablePartFull(data: Uint8Array): ParsedTablePart | undefined;
|