@rowsncolumns/toolkit 24.4.2 → 24.4.4
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 +15 -2
- package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/base/index.d.ts +2 -0
- package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/base/index.js +3 -0
- 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 +55 -1
- package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xls/index.js +518 -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 +33 -14
- package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
- package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
- package/dist/cjs/excel-parser/plugins/xlsx/chartex.js +244 -0
- 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/form-controls.d.ts +70 -0
- package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
- package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +295 -0
- package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +35 -2
- package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/index.js +737 -257
- 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 +15 -1
- package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
- package/dist/cjs/excel-parser/plugins/xlsx/styles.js +102 -6
- package/dist/cjs/excel-parser/registry.d.ts +7 -0
- package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
- package/dist/cjs/excel-parser/registry.js +29 -0
- package/dist/cjs/excel-parser/types.d.ts +17 -2
- package/dist/cjs/excel-parser/types.d.ts.map +1 -1
- package/dist/cjs/excel-parser/workbook.d.ts +3 -0
- package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
- package/dist/cjs/excel-parser/workbook.js +24 -14
- package/dist/cjs/excel-parser/worker.js +131 -131
- 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 +215 -39
- package/dist/cjs/exporter/xlsx/chartex-builder.d.ts +36 -0
- package/dist/cjs/exporter/xlsx/chartex-builder.d.ts.map +1 -0
- package/dist/cjs/exporter/xlsx/chartex-builder.js +109 -0
- package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +61 -0
- package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
- package/dist/cjs/exporter/xlsx/form-controls-builder.js +197 -0
- 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 +991 -297
- 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 +15 -2
- package/dist/esm/excel-parser/interface.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/base/index.d.ts +2 -0
- package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/base/index.js +3 -0
- 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 +55 -1
- package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xls/index.js +441 -3
- 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 +30 -9
- package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
- package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
- package/dist/esm/excel-parser/plugins/xlsx/chartex.js +199 -0
- 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/form-controls.d.ts +70 -0
- package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
- package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +246 -0
- package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +35 -2
- package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/index.js +454 -32
- 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 +15 -1
- package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
- package/dist/esm/excel-parser/plugins/xlsx/styles.js +92 -2
- package/dist/esm/excel-parser/registry.d.ts +7 -0
- package/dist/esm/excel-parser/registry.d.ts.map +1 -1
- package/dist/esm/excel-parser/registry.js +19 -0
- package/dist/esm/excel-parser/types.d.ts +17 -2
- package/dist/esm/excel-parser/types.d.ts.map +1 -1
- package/dist/esm/excel-parser/workbook.d.ts +3 -0
- package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
- package/dist/esm/excel-parser/workbook.js +19 -10
- package/dist/esm/excel-parser/worker.js +12 -18
- 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 -28
- package/dist/esm/exporter/xlsx/chartex-builder.d.ts +36 -0
- package/dist/esm/exporter/xlsx/chartex-builder.d.ts.map +1 -0
- package/dist/esm/exporter/xlsx/chartex-builder.js +97 -0
- package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +61 -0
- package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
- package/dist/esm/exporter/xlsx/form-controls-builder.js +173 -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 +675 -64
- 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
- package/xlsx.d.ts +14 -0
|
@@ -1,7 +1,445 @@
|
|
|
1
|
+
import { getCellXfsKey, ssfFormat, uuid } from "@rowsncolumns/utils";
|
|
2
|
+
import { read as readSheetJsWorkbook, utils as sheetJsUtils, } from "xlsx/xlsx.mjs";
|
|
3
|
+
import { detectCfbContainerKind, LEGACY_XLS_UNSUPPORTED_MESSAGE, XLS_NOT_A_WORKBOOK_MESSAGE, } from "../../cfb-decryptor";
|
|
4
|
+
import { excelColumnWidthToPixels, getRangeFromAddressRef } from "../../helpers";
|
|
1
5
|
import { BaseWorkbookPlugin } from "../base/index";
|
|
6
|
+
export const ZIP_SIGNATURE = [0x50, 0x4b, 0x03, 0x04];
|
|
7
|
+
export const CFB_SIGNATURE = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];
|
|
8
|
+
export const readHeader = async (source, length) => {
|
|
9
|
+
const slice = source instanceof File
|
|
10
|
+
? await source.slice(0, length).arrayBuffer()
|
|
11
|
+
: source.slice(0, length);
|
|
12
|
+
return new Uint8Array(slice);
|
|
13
|
+
};
|
|
14
|
+
export const startsWith = (header, signature) => header.length >= signature.length &&
|
|
15
|
+
signature.every((byte, index) => header[index] === byte);
|
|
16
|
+
/**
|
|
17
|
+
* BIFF8 error codes (MS-XLS 2.5.97 `BErr`) → Excel error literals. SheetJS
|
|
18
|
+
* surfaces an error cell as `{ t: "e", v: <code>, w: "#DIV/0!" }`.
|
|
19
|
+
*/
|
|
20
|
+
const BIFF_ERROR_CODES = {
|
|
21
|
+
0x00: "#NULL!",
|
|
22
|
+
0x07: "#DIV/0!",
|
|
23
|
+
0x0f: "#VALUE!",
|
|
24
|
+
0x17: "#REF!",
|
|
25
|
+
0x1d: "#NAME?",
|
|
26
|
+
0x24: "#NUM!",
|
|
27
|
+
0x2a: "#N/A",
|
|
28
|
+
0x2b: "#GETTING_DATA",
|
|
29
|
+
};
|
|
30
|
+
const getNumberFormatType = (pattern) => {
|
|
31
|
+
const lower = pattern.toLowerCase();
|
|
32
|
+
if (lower.includes("yy") || lower.includes("dd"))
|
|
33
|
+
return "DATE";
|
|
34
|
+
if (lower.includes("h:") || lower.includes("am/pm"))
|
|
35
|
+
return "TIME";
|
|
36
|
+
if (lower.includes("%"))
|
|
37
|
+
return "PERCENT";
|
|
38
|
+
// Excel's builtin 49 (`@`) and any text-placeholder format — same facet
|
|
39
|
+
// type the xlsx styles reader yields for the cell.
|
|
40
|
+
if (lower.includes("@"))
|
|
41
|
+
return "TEXT";
|
|
42
|
+
if (lower.includes("$") ||
|
|
43
|
+
lower.includes("€") ||
|
|
44
|
+
lower.includes("£") ||
|
|
45
|
+
lower.includes("¥")) {
|
|
46
|
+
return "CURRENCY";
|
|
47
|
+
}
|
|
48
|
+
if (lower.includes("0") || lower.includes("#"))
|
|
49
|
+
return "NUMBER";
|
|
50
|
+
return "GENERAL";
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* BIFF `NAME` records (SheetJS `Workbook.Names`) → `NamedRange`s. Builtin
|
|
54
|
+
* names (`_xlnm.Print_Area`, `_xlnm._FilterDatabase`, …) are print / filter
|
|
55
|
+
* metadata, not user names, and are skipped. A reference that parses as a
|
|
56
|
+
* range becomes `range` (pinned to the sheet the ref names, else the name's
|
|
57
|
+
* own sheet scope, else the first sheet); anything else is kept as a
|
|
58
|
+
* formula `value`.
|
|
59
|
+
*/
|
|
60
|
+
export const mapDefinedNames = (names, sheets) => names.flatMap((name) => {
|
|
61
|
+
if (!name?.Name || !name.Ref)
|
|
62
|
+
return [];
|
|
63
|
+
if (name.Name.startsWith("_xlnm."))
|
|
64
|
+
return [];
|
|
65
|
+
const namedRange = {
|
|
66
|
+
namedRangeId: uuid(),
|
|
67
|
+
name: name.Name,
|
|
68
|
+
};
|
|
69
|
+
const scopedSheetId = name.Sheet != null ? sheets[name.Sheet]?.sheetId : undefined;
|
|
70
|
+
const ref = name.Ref.replace(/^=/, "");
|
|
71
|
+
const bang = ref.lastIndexOf("!");
|
|
72
|
+
const sheetPart = bang >= 0 ? ref.slice(0, bang) : undefined;
|
|
73
|
+
const refPart = bang >= 0 ? ref.slice(bang + 1) : ref;
|
|
74
|
+
const targetTitle = sheetPart
|
|
75
|
+
?.replace(/^'(.*)'$/, "$1")
|
|
76
|
+
.replace(/''/g, "'");
|
|
77
|
+
const targetSheetId = (targetTitle
|
|
78
|
+
? sheets.find((s) => s.title === targetTitle)?.sheetId
|
|
79
|
+
: undefined) ??
|
|
80
|
+
scopedSheetId ??
|
|
81
|
+
sheets[0]?.sheetId ??
|
|
82
|
+
1;
|
|
83
|
+
const gridRange = getRangeFromAddressRef(refPart);
|
|
84
|
+
if (gridRange) {
|
|
85
|
+
namedRange.range = { ...gridRange, sheetId: targetSheetId };
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
namedRange.value = `=${ref}`;
|
|
89
|
+
}
|
|
90
|
+
return [namedRange];
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
93
|
+
* Legacy `.xls` (BIFF8, Excel 97-2003) reader.
|
|
94
|
+
*
|
|
95
|
+
* The BIFF record stream is decoded by SheetJS (`xlsx`, already a toolkit
|
|
96
|
+
* dependency for the CFB container reader used by the password decryptor),
|
|
97
|
+
* and the decoded workbook is mapped onto the same plugin contract the
|
|
98
|
+
* xlsx / xlsb readers implement: sheet names + visibility, cell values with
|
|
99
|
+
* their number formats, formulas with their cached results, merges, column
|
|
100
|
+
* widths / row heights, hyperlinks, cell notes, defined names and the 1904
|
|
101
|
+
* date-system flag. Cell fonts / fills / borders are not decoded (BIFF XF
|
|
102
|
+
* styling is outside SheetJS's open-source decoder), so a `.xls` opens with
|
|
103
|
+
* its data and number formatting; export goes through XLSX like XLSB.
|
|
104
|
+
*
|
|
105
|
+
* `load` also keeps the previous routing guards: an OOXML package saved with a
|
|
106
|
+
* `.xls` name is rejected here so `WorkBook` hands it to the xlsx parser, an
|
|
107
|
+
* encrypted container still asks for a password, and an HTML / text export
|
|
108
|
+
* saved as `.xls` fails with an actionable message.
|
|
109
|
+
*/
|
|
2
110
|
export class XlsPlugin extends BaseWorkbookPlugin {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
111
|
+
sheets = [];
|
|
112
|
+
namedRanges = [];
|
|
113
|
+
cellXfs = new Map();
|
|
114
|
+
formatIds = new Map();
|
|
115
|
+
use1904 = false;
|
|
116
|
+
async load(buffer, _password) {
|
|
117
|
+
const header = await readHeader(buffer, CFB_SIGNATURE.length);
|
|
118
|
+
if (startsWith(header, ZIP_SIGNATURE)) {
|
|
119
|
+
// An OOXML package mislabelled `.xls` — `WorkBook.load` routes these
|
|
120
|
+
// to the xlsx parser before reaching here; guard direct callers.
|
|
121
|
+
throw new Error("NOT_A_BIFF_WORKBOOK");
|
|
122
|
+
}
|
|
123
|
+
if (!startsWith(header, CFB_SIGNATURE)) {
|
|
124
|
+
throw new Error(XLS_NOT_A_WORKBOOK_MESSAGE);
|
|
125
|
+
}
|
|
126
|
+
const kind = await detectCfbContainerKind(buffer);
|
|
127
|
+
if (kind === "encrypted-ooxml") {
|
|
128
|
+
throw new Error("PASSWORD_REQUIRED");
|
|
129
|
+
}
|
|
130
|
+
if (kind !== "legacy-xls") {
|
|
131
|
+
throw new Error(XLS_NOT_A_WORKBOOK_MESSAGE);
|
|
132
|
+
}
|
|
133
|
+
const bytes = new Uint8Array(buffer instanceof File ? await buffer.arrayBuffer() : buffer);
|
|
134
|
+
let workbook;
|
|
135
|
+
try {
|
|
136
|
+
workbook = readSheetJsWorkbook(bytes, {
|
|
137
|
+
type: "array",
|
|
138
|
+
cellNF: true,
|
|
139
|
+
cellStyles: true,
|
|
140
|
+
cellDates: false,
|
|
141
|
+
cellText: false,
|
|
142
|
+
sheetStubs: false,
|
|
143
|
+
dense: false,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
// A password-protected BIFF workbook (RC4 / XOR obfuscation) surfaces
|
|
148
|
+
// here — SheetJS refuses it. There is no BIFF decryptor, so the only
|
|
149
|
+
// actionable guidance is the save-as-xlsx one.
|
|
150
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
151
|
+
if (/password/i.test(message) || /encrypt/i.test(message)) {
|
|
152
|
+
throw new Error(LEGACY_XLS_UNSUPPORTED_MESSAGE);
|
|
153
|
+
}
|
|
154
|
+
throw new Error(`${LEGACY_XLS_UNSUPPORTED_MESSAGE} (${message})`);
|
|
155
|
+
}
|
|
156
|
+
this.use1904 = Boolean(workbook.Workbook?.WBProps?.date1904);
|
|
157
|
+
this.sheets = workbook.SheetNames.map((title, index) => {
|
|
158
|
+
const worksheet = workbook.Sheets[title] ?? {};
|
|
159
|
+
const props = workbook.Workbook?.Sheets?.[index];
|
|
160
|
+
const hiddenState = props?.Hidden ?? 0;
|
|
161
|
+
const visibility = hiddenState === 2
|
|
162
|
+
? "veryHidden"
|
|
163
|
+
: hiddenState === 1
|
|
164
|
+
? "hidden"
|
|
165
|
+
: "visible";
|
|
166
|
+
const ref = worksheet["!ref"];
|
|
167
|
+
const range = ref ? sheetJsUtils.decode_range(ref) : undefined;
|
|
168
|
+
const rowCount = range ? range.e.r + 1 : 0;
|
|
169
|
+
const columnCount = range ? range.e.c + 1 : 0;
|
|
170
|
+
const merges = (worksheet["!merges"] ?? []).map((merge) => ({
|
|
171
|
+
startRowIndex: merge.s.r + 1,
|
|
172
|
+
endRowIndex: merge.e.r + 1,
|
|
173
|
+
startColumnIndex: merge.s.c + 1,
|
|
174
|
+
endColumnIndex: merge.e.c + 1,
|
|
175
|
+
}));
|
|
176
|
+
const columnMetadata = [];
|
|
177
|
+
(worksheet["!cols"] ?? []).forEach((col, colIndex) => {
|
|
178
|
+
if (!col)
|
|
179
|
+
return;
|
|
180
|
+
const props = {};
|
|
181
|
+
if (col.hidden)
|
|
182
|
+
props.hiddenByUser = true;
|
|
183
|
+
const size = col.wpx ??
|
|
184
|
+
(col.wch != null ? excelColumnWidthToPixels(col.wch) : undefined) ??
|
|
185
|
+
(col.width != null ? excelColumnWidthToPixels(col.width) : undefined);
|
|
186
|
+
if (size != null && size > 0) {
|
|
187
|
+
props.size = size;
|
|
188
|
+
props.resizedByUser = true;
|
|
189
|
+
}
|
|
190
|
+
if (Object.keys(props).length > 0) {
|
|
191
|
+
columnMetadata[colIndex + 1] = props;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
const rowMetadata = [];
|
|
195
|
+
(worksheet["!rows"] ?? []).forEach((row, rowIndex) => {
|
|
196
|
+
if (!row)
|
|
197
|
+
return;
|
|
198
|
+
const props = {};
|
|
199
|
+
if (row.hidden)
|
|
200
|
+
props.hiddenByUser = true;
|
|
201
|
+
const size = row.hpx ?? (row.hpt != null ? (row.hpt * 96) / 72 : undefined);
|
|
202
|
+
if (size != null && size > 0) {
|
|
203
|
+
props.size = Math.round(size);
|
|
204
|
+
props.resizedByUser = true;
|
|
205
|
+
}
|
|
206
|
+
if (Object.keys(props).length > 0) {
|
|
207
|
+
rowMetadata[rowIndex + 1] = props;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
return {
|
|
211
|
+
sheetId: index + 1,
|
|
212
|
+
title,
|
|
213
|
+
hidden: visibility !== "visible",
|
|
214
|
+
visibility,
|
|
215
|
+
worksheet,
|
|
216
|
+
rowCount,
|
|
217
|
+
columnCount,
|
|
218
|
+
merges,
|
|
219
|
+
rowMetadata,
|
|
220
|
+
columnMetadata,
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
this.namedRanges = mapDefinedNames(workbook.Workbook?.Names ?? [], this.sheets.map((s) => ({ sheetId: s.sheetId, title: s.title })));
|
|
224
|
+
}
|
|
225
|
+
dispose() {
|
|
226
|
+
this.sheets = [];
|
|
227
|
+
this.namedRanges = [];
|
|
228
|
+
this.cellXfs.clear();
|
|
229
|
+
this.formatIds.clear();
|
|
230
|
+
}
|
|
231
|
+
getSheetCount() {
|
|
232
|
+
return this.sheets.length;
|
|
233
|
+
}
|
|
234
|
+
async getSheets(minRowCount = 0, minColumnCount = 0) {
|
|
235
|
+
const sheets = this.sheets.map((sheet) => ({
|
|
236
|
+
sheetId: sheet.sheetId,
|
|
237
|
+
title: sheet.title,
|
|
238
|
+
hidden: sheet.hidden,
|
|
239
|
+
...(sheet.visibility !== "visible"
|
|
240
|
+
? { visibility: sheet.visibility }
|
|
241
|
+
: {}),
|
|
242
|
+
rowCount: Math.max(minRowCount, sheet.rowCount),
|
|
243
|
+
columnCount: Math.max(minColumnCount, sheet.columnCount),
|
|
244
|
+
rowMetadata: sheet.rowMetadata,
|
|
245
|
+
columnMetadata: sheet.columnMetadata,
|
|
246
|
+
merges: sheet.merges,
|
|
247
|
+
}));
|
|
248
|
+
return [sheets, []];
|
|
249
|
+
}
|
|
250
|
+
getCellXfs() {
|
|
251
|
+
return this.cellXfs;
|
|
252
|
+
}
|
|
253
|
+
registerFormat(format) {
|
|
254
|
+
const key = getCellXfsKey(format);
|
|
255
|
+
if (!this.cellXfs.has(key)) {
|
|
256
|
+
this.cellXfs.set(key, format);
|
|
257
|
+
}
|
|
258
|
+
return key;
|
|
259
|
+
}
|
|
260
|
+
getNamedRanges() {
|
|
261
|
+
return this.namedRanges;
|
|
262
|
+
}
|
|
263
|
+
/** `WBProps.date1904` — Mac-origin workbooks shift every date serial. */
|
|
264
|
+
getUse1904Epoch() {
|
|
265
|
+
return this.use1904;
|
|
266
|
+
}
|
|
267
|
+
/** Formulas carry their BIFF cached results, so no load-time recalc. */
|
|
268
|
+
requiresRecalc() {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
toCellData(cell, enableCellXfsRegistry) {
|
|
272
|
+
const format = {};
|
|
273
|
+
const pattern = typeof cell.z === "string" && cell.z.toLowerCase() !== "general"
|
|
274
|
+
? cell.z
|
|
275
|
+
: undefined;
|
|
276
|
+
if (pattern) {
|
|
277
|
+
format.numberFormat = { type: getNumberFormatType(pattern), pattern };
|
|
278
|
+
}
|
|
279
|
+
const hasFormat = Object.keys(format).length > 0;
|
|
280
|
+
let style;
|
|
281
|
+
if (enableCellXfsRegistry && hasFormat && pattern) {
|
|
282
|
+
let id = this.formatIds.get(pattern);
|
|
283
|
+
if (id === undefined) {
|
|
284
|
+
id = this.formatIds.size;
|
|
285
|
+
this.formatIds.set(pattern, id);
|
|
286
|
+
}
|
|
287
|
+
style = { sid: `xls:${id}` };
|
|
288
|
+
if (!this.cellXfs.has(style.sid)) {
|
|
289
|
+
this.cellXfs.set(style.sid, format);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const formatFields = style
|
|
293
|
+
? { ef: style, uf: style }
|
|
294
|
+
: hasFormat
|
|
295
|
+
? { ef: format, uf: format }
|
|
296
|
+
: {};
|
|
297
|
+
const formula = typeof cell.f === "string" && cell.f.length > 0
|
|
298
|
+
? `=${cell.f.replace(/^=/, "")}`
|
|
299
|
+
: undefined;
|
|
300
|
+
let cellData = null;
|
|
301
|
+
switch (cell.t) {
|
|
302
|
+
case "s":
|
|
303
|
+
case "d": {
|
|
304
|
+
const text = cell.v == null ? "" : String(cell.v);
|
|
305
|
+
cellData = {
|
|
306
|
+
...formatFields,
|
|
307
|
+
ue: formula ? { fv: formula } : { sv: text },
|
|
308
|
+
ev: { sv: text },
|
|
309
|
+
...(formula ? {} : { fv: text }),
|
|
310
|
+
};
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
case "n": {
|
|
314
|
+
const value = Number(cell.v);
|
|
315
|
+
if (!Number.isFinite(value))
|
|
316
|
+
return null;
|
|
317
|
+
cellData = {
|
|
318
|
+
...formatFields,
|
|
319
|
+
ue: formula ? { fv: formula } : { nv: value },
|
|
320
|
+
ev: { nv: value },
|
|
321
|
+
...(formula ? {} : { fv: ssfFormat(pattern ?? "GENERAL", value) }),
|
|
322
|
+
};
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
case "b": {
|
|
326
|
+
const value = Boolean(cell.v);
|
|
327
|
+
cellData = {
|
|
328
|
+
...formatFields,
|
|
329
|
+
ue: formula ? { fv: formula } : { bv: value },
|
|
330
|
+
ev: { bv: value },
|
|
331
|
+
...(formula ? {} : { fv: value ? "TRUE" : "FALSE" }),
|
|
332
|
+
};
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
case "e": {
|
|
336
|
+
const code = (typeof cell.v === "number" ? BIFF_ERROR_CODES[cell.v] : undefined) ??
|
|
337
|
+
(typeof cell.w === "string" && cell.w.startsWith("#")
|
|
338
|
+
? cell.w
|
|
339
|
+
: "#VALUE!");
|
|
340
|
+
const errorValue = {
|
|
341
|
+
ev: { type: "Error", name: code, message: code },
|
|
342
|
+
};
|
|
343
|
+
cellData = {
|
|
344
|
+
...formatFields,
|
|
345
|
+
ue: formula ? { fv: formula } : errorValue,
|
|
346
|
+
ev: errorValue,
|
|
347
|
+
...(formula ? {} : { fv: code }),
|
|
348
|
+
};
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
case "z":
|
|
352
|
+
default: {
|
|
353
|
+
if (formula) {
|
|
354
|
+
cellData = { ...formatFields, ue: { fv: formula } };
|
|
355
|
+
}
|
|
356
|
+
else if (hasFormat) {
|
|
357
|
+
cellData = { ...formatFields };
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (cell.l?.Target) {
|
|
365
|
+
const target = cell.l.Target;
|
|
366
|
+
const tooltip = cell.l.Tooltip ? { tooltip: cell.l.Tooltip } : {};
|
|
367
|
+
cellData.hyperlink = target.startsWith("#")
|
|
368
|
+
? { kind: "internal", location: target.slice(1), ...tooltip }
|
|
369
|
+
: { kind: "external", url: target, ...tooltip };
|
|
370
|
+
}
|
|
371
|
+
if (Array.isArray(cell.c) && cell.c.length > 0) {
|
|
372
|
+
const note = cell.c
|
|
373
|
+
.map((comment) => comment?.t ?? "")
|
|
374
|
+
.filter((text) => text.length > 0)
|
|
375
|
+
.join("\n");
|
|
376
|
+
if (note)
|
|
377
|
+
cellData.note = note;
|
|
378
|
+
}
|
|
379
|
+
return cellData;
|
|
380
|
+
}
|
|
381
|
+
async *processSheetData(chunkSize = 100, enableCellXfsRegistry = false, _enableSharedStrings) {
|
|
382
|
+
const totalSheets = this.sheets.length;
|
|
383
|
+
for (let index = 0; index < this.sheets.length; index++) {
|
|
384
|
+
const sheet = this.sheets[index];
|
|
385
|
+
const rows = new Map();
|
|
386
|
+
for (const address of Object.keys(sheet.worksheet)) {
|
|
387
|
+
if (address.startsWith("!"))
|
|
388
|
+
continue;
|
|
389
|
+
const cell = sheet.worksheet[address];
|
|
390
|
+
if (!cell || typeof cell !== "object")
|
|
391
|
+
continue;
|
|
392
|
+
const { r, c } = sheetJsUtils.decode_cell(address);
|
|
393
|
+
if (r < 0 || c < 0)
|
|
394
|
+
continue;
|
|
395
|
+
const cellData = this.toCellData(cell, enableCellXfsRegistry);
|
|
396
|
+
if (!cellData)
|
|
397
|
+
continue;
|
|
398
|
+
let row = rows.get(r + 1);
|
|
399
|
+
if (!row) {
|
|
400
|
+
row = { values: [] };
|
|
401
|
+
rows.set(r + 1, row);
|
|
402
|
+
}
|
|
403
|
+
row.values[c + 1] = cellData;
|
|
404
|
+
}
|
|
405
|
+
const sortedRows = Array.from(rows.entries()).sort((a, b) => a[0] - b[0]);
|
|
406
|
+
let chunkRows = [];
|
|
407
|
+
let chunkRowIndices = [];
|
|
408
|
+
let chunkIndex = 0;
|
|
409
|
+
let startRowIndex = -1;
|
|
410
|
+
let endRowIndex = -1;
|
|
411
|
+
const emit = (isLastChunk) => ({
|
|
412
|
+
sheetId: sheet.sheetId,
|
|
413
|
+
title: sheet.title,
|
|
414
|
+
currentSheetIndex: index,
|
|
415
|
+
totalSheets,
|
|
416
|
+
chunkIndex,
|
|
417
|
+
rows: chunkRows,
|
|
418
|
+
rowIndices: chunkRowIndices,
|
|
419
|
+
startRowIndex,
|
|
420
|
+
endRowIndex,
|
|
421
|
+
totalRows: sheet.rowCount,
|
|
422
|
+
isLastChunk,
|
|
423
|
+
cellXfs: this.cellXfs,
|
|
424
|
+
});
|
|
425
|
+
for (const [rowIndex, rowData] of sortedRows) {
|
|
426
|
+
if (chunkRows.length === 0)
|
|
427
|
+
startRowIndex = rowIndex;
|
|
428
|
+
chunkRows.push(rowData);
|
|
429
|
+
chunkRowIndices.push(rowIndex);
|
|
430
|
+
endRowIndex = rowIndex;
|
|
431
|
+
if (chunkRows.length >= chunkSize) {
|
|
432
|
+
yield emit(false);
|
|
433
|
+
chunkRows = [];
|
|
434
|
+
chunkRowIndices = [];
|
|
435
|
+
chunkIndex += 1;
|
|
436
|
+
startRowIndex = -1;
|
|
437
|
+
endRowIndex = -1;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (chunkRows.length) {
|
|
441
|
+
yield emit(true);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
6
444
|
}
|
|
7
445
|
}
|
|
@@ -2,6 +2,10 @@ import type { Color, IterativeCalculationOptions } from "@rowsncolumns/common-ty
|
|
|
2
2
|
import type { BorderStyle, ConditionalFormatRule, DataValidationRuleRecord, EmbeddedChart, NamedRange, Sheet, SpreadsheetTheme, TableView } from "@rowsncolumns/spreadsheet";
|
|
3
3
|
import type { EmbeddedObjectWithPosition, ProcessSheetDataResult } from "../../types";
|
|
4
4
|
import { BaseWorkbookPlugin } from "../base/index";
|
|
5
|
+
export declare const parseBrtWsViewPayload: (payload: Uint8Array) => {
|
|
6
|
+
showGridLines: boolean;
|
|
7
|
+
rightToLeft: boolean;
|
|
8
|
+
};
|
|
5
9
|
export declare const parseBrtNamePayload: (payload: Uint8Array, resolveSheetNameByXti?: (ixti: number) => string | undefined) => {
|
|
6
10
|
name: string;
|
|
7
11
|
formula: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsb/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAEL,2BAA2B,EAE5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,WAAW,EAGX,qBAAqB,EACrB,wBAAwB,EAExB,aAAa,EACb,UAAU,EACV,KAAK,EACL,gBAAgB,EAChB,SAAS,EACV,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsb/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,13 +4,14 @@ import { XMLParser } from "fast-xml-parser";
|
|
|
4
4
|
import { get } from "lodash-es";
|
|
5
5
|
import { parseRgce } from "./rgce-parser";
|
|
6
6
|
import { StreamingZipParser } from "../../zip-parser-streaming";
|
|
7
|
-
import { createFilterSpecsFromAutoFilter, excelColumnWidthToPixels, getRangeFromAddressRef, } from "../../helpers";
|
|
7
|
+
import { createFilterSpecsFromAutoFilter, excelColumnWidthToPixels, getRangeFromAddressRef, parseTableColumnTotals, } from "../../helpers";
|
|
8
8
|
import { defaultSpreadsheetTheme } from "../../theme-default";
|
|
9
9
|
import { BaseWorkbookPlugin } from "../base/index";
|
|
10
10
|
import { processChart } from "../xlsx/charts";
|
|
11
11
|
import { processAnchors } from "../xlsx/drawing";
|
|
12
12
|
import { readAllRecordHeaders } from "./biff-record-reader";
|
|
13
13
|
import { standardExcelFormatCodeById } from "../xlsx/numfmt";
|
|
14
|
+
import { DATE_1904_OFFSET_DAYS, isEpochShiftedFormat } from "../xlsx/styles";
|
|
14
15
|
import { extractThemeColors, extractThemeFonts, generateDarkThemeColors, } from "../xlsx/theme";
|
|
15
16
|
const RT = {
|
|
16
17
|
BrtCellRk: 0x0002,
|
|
@@ -274,10 +275,17 @@ const parseBrtShrFmla = (payload) => {
|
|
|
274
275
|
const parseWsView = (payload) => {
|
|
275
276
|
const reader = new Reader(payload);
|
|
276
277
|
const flags = reader.readUInt16LE();
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
// MS-XLSB 2.4.865 BrtWsView flag word: A fWnProt (0x0001), B fDspFmla
|
|
279
|
+
// (0x0002), C fDspGrid (0x0004), D fDspRwCol (0x0008), E fDspZeros
|
|
280
|
+
// (0x0010), F fRightToLeft (0x0020), G fSelected (0x0040), … Excel writes
|
|
281
|
+
// 0x039c for a plain sheet and 0x0398 for `showGridLines="0"`: gridlines
|
|
282
|
+
// are bit C, not bit B (which is "show formulas" and is normally clear).
|
|
283
|
+
const showGridLines = (flags & 0x0004) !== 0;
|
|
284
|
+
// OOXML `<sheetView rightToLeft="1">`.
|
|
285
|
+
const rightToLeft = (flags & 0x0020) !== 0;
|
|
286
|
+
return { showGridLines, rightToLeft };
|
|
280
287
|
};
|
|
288
|
+
export const parseBrtWsViewPayload = parseWsView;
|
|
281
289
|
const parsePane = (payload) => {
|
|
282
290
|
const reader = new Reader(payload);
|
|
283
291
|
const xSplit = reader.readFloat64LE();
|
|
@@ -932,7 +940,7 @@ const resolveXf = (styles, xfIndex) => {
|
|
|
932
940
|
indent: xf.indent ?? parent.indent,
|
|
933
941
|
};
|
|
934
942
|
};
|
|
935
|
-
const toCellData = (parsed, styles, sharedStrings, enableCellXfsRegistry, enableSharedStrings, cellXfs) => {
|
|
943
|
+
const toCellData = (parsed, styles, sharedStrings, enableCellXfsRegistry, enableSharedStrings, cellXfs, use1904) => {
|
|
936
944
|
const xf = resolveXf(styles, parsed.styleRef);
|
|
937
945
|
const format = {};
|
|
938
946
|
const pattern = xf
|
|
@@ -1045,7 +1053,13 @@ const toCellData = (parsed, styles, sharedStrings, enableCellXfsRegistry, enable
|
|
|
1045
1053
|
};
|
|
1046
1054
|
}
|
|
1047
1055
|
if (parsed.kind === "n") {
|
|
1048
|
-
|
|
1056
|
+
// A 1904-system workbook (`BrtWbProp.fDate1904`) stores date serials
|
|
1057
|
+
// 1462 days below the engine's 1900 system; date-formatted numbers are
|
|
1058
|
+
// converted on the way in, like the XLSX importer does.
|
|
1059
|
+
const value = Number(parsed.value) +
|
|
1060
|
+
(use1904 && isEpochShiftedFormat(format.numberFormat?.type)
|
|
1061
|
+
? DATE_1904_OFFSET_DAYS
|
|
1062
|
+
: 0);
|
|
1049
1063
|
const pattern = format.numberFormat?.pattern ?? "GENERAL";
|
|
1050
1064
|
const fv = ssfFormat(pattern, value);
|
|
1051
1065
|
// If there's a formula, use it in ue.fv, otherwise use the numeric value
|
|
@@ -1267,6 +1281,7 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1267
1281
|
sheet.rowMetadata = stats.rowMetadata;
|
|
1268
1282
|
sheet.columnMetadata = stats.columnMetadata;
|
|
1269
1283
|
sheet.showGridLines = stats.showGridLines;
|
|
1284
|
+
sheet.rightToLeft = stats.rightToLeft;
|
|
1270
1285
|
sheet.frozenRowCount = stats.frozenRowCount;
|
|
1271
1286
|
sheet.frozenColumnCount = stats.frozenColumnCount;
|
|
1272
1287
|
sheet.basicFilterRange = stats.basicFilterRange;
|
|
@@ -1532,12 +1547,13 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1532
1547
|
: [];
|
|
1533
1548
|
const columns = columnDefsArray.map((colDef) => {
|
|
1534
1549
|
const name = colDef?.a$?.name || "";
|
|
1550
|
+
const totals = parseTableColumnTotals(colDef);
|
|
1535
1551
|
const calculatedColumnFormula = get(colDef, "calculatedColumnFormula") ||
|
|
1536
1552
|
get(colDef, "x:calculatedColumnFormula");
|
|
1537
1553
|
if (calculatedColumnFormula) {
|
|
1538
|
-
return { name, formula: calculatedColumnFormula };
|
|
1554
|
+
return { name, ...totals, formula: calculatedColumnFormula };
|
|
1539
1555
|
}
|
|
1540
|
-
return { name };
|
|
1556
|
+
return { name, ...totals };
|
|
1541
1557
|
});
|
|
1542
1558
|
const autoFilter = tableDefinition.autoFilter ?? tableDefinition["x:autoFilter"];
|
|
1543
1559
|
const filterSpecs = createFilterSpecsFromAutoFilter(autoFilter);
|
|
@@ -1578,6 +1594,7 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1578
1594
|
const rowMetadata = [];
|
|
1579
1595
|
const columnMetadata = [];
|
|
1580
1596
|
let showGridLines;
|
|
1597
|
+
let rightToLeft;
|
|
1581
1598
|
let frozenRowCount;
|
|
1582
1599
|
let frozenColumnCount;
|
|
1583
1600
|
let basicFilterRange;
|
|
@@ -1587,6 +1604,8 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1587
1604
|
if (record.type === RT.BrtWsView) {
|
|
1588
1605
|
const view = parseWsView(payload);
|
|
1589
1606
|
showGridLines = view.showGridLines;
|
|
1607
|
+
if (view.rightToLeft)
|
|
1608
|
+
rightToLeft = true;
|
|
1590
1609
|
continue;
|
|
1591
1610
|
}
|
|
1592
1611
|
if (record.type === RT.BrtPane) {
|
|
@@ -1671,6 +1690,7 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1671
1690
|
rowMetadata,
|
|
1672
1691
|
columnMetadata,
|
|
1673
1692
|
showGridLines,
|
|
1693
|
+
rightToLeft,
|
|
1674
1694
|
frozenRowCount,
|
|
1675
1695
|
frozenColumnCount,
|
|
1676
1696
|
basicFilterRange,
|
|
@@ -1727,6 +1747,7 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1727
1747
|
...(sheet.showGridLines !== undefined
|
|
1728
1748
|
? { showGridLines: sheet.showGridLines }
|
|
1729
1749
|
: {}),
|
|
1750
|
+
...(sheet.rightToLeft ? { rightToLeft: true } : {}),
|
|
1730
1751
|
...(sheet.frozenRowCount !== undefined && sheet.frozenRowCount > 0
|
|
1731
1752
|
? { frozenRowCount: sheet.frozenRowCount }
|
|
1732
1753
|
: {}),
|
|
@@ -1847,7 +1868,7 @@ export class XlsbPlugin extends BaseWorkbookPlugin {
|
|
|
1847
1868
|
row = { values: [] };
|
|
1848
1869
|
rows.set(parsed.row, row);
|
|
1849
1870
|
}
|
|
1850
|
-
row.values[parsed.col] = toCellData(parsed, this.styles, this.sharedStrings, enableCellXfsRegistry, enableSharedStrings, this.cellXfs);
|
|
1871
|
+
row.values[parsed.col] = toCellData(parsed, this.styles, this.sharedStrings, enableCellXfsRegistry, enableSharedStrings, this.cellXfs, this.use1904);
|
|
1851
1872
|
}
|
|
1852
1873
|
// Apply merge cell formatting
|
|
1853
1874
|
// In Excel, merged cells should have formatting from the top-left (anchor) cell
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { EmbeddedChart, SheetRange } from "@rowsncolumns/spreadsheet";
|
|
2
|
+
import type { StreamingZipParser } from "../../zip-parser-streaming";
|
|
3
|
+
import { type ResolveSheetId, type SheetDimensions } from "./charts";
|
|
4
|
+
/**
|
|
5
|
+
* Excel 2016+ "chartex" charts (`xl/charts/chartEx{N}.xml`, namespace
|
|
6
|
+
* `http://schemas.microsoft.com/office/drawing/2014/chartex`): treemap,
|
|
7
|
+
* sunburst, histogram / pareto, box & whisker, waterfall, funnel. They are
|
|
8
|
+
* anchored through an `mc:AlternateContent` whose `Choice` graphic frame
|
|
9
|
+
* carries `<cx:chart r:id>` instead of `<c:chart>`, and their data lives in
|
|
10
|
+
* `<cx:chartData><cx:data>` dimensions (`strDim type="cat"` for the
|
|
11
|
+
* hierarchy, `numDim type="size"|"val"` for the numbers) referenced by the
|
|
12
|
+
* series through `<cx:dataId>`.
|
|
13
|
+
*
|
|
14
|
+
* The exporter counterpart is `exporter/xlsx/chartex-builder.ts`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const CHART_EX_REL_TYPE = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
|
|
17
|
+
export declare const CHART_EX_GRAPHIC_URI = "http://schemas.microsoft.com/office/drawing/2014/chartex";
|
|
18
|
+
/**
|
|
19
|
+
* `<cx:chart r:id>` inside an anchor's `mc:AlternateContent` choice (Excel
|
|
20
|
+
* also writes a plain `xdr:graphicFrame` for some producers — both forms are
|
|
21
|
+
* checked). Returns the `cx:chart` node or undefined for non-chartex anchors.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getChartExReferenceFromAnchor(anchor: any): any;
|
|
24
|
+
/**
|
|
25
|
+
* Split a multi-column hierarchy range (Excel lays the treemap hierarchy out
|
|
26
|
+
* as columns, top level first, leaf last) into `parentLabels` (one entry per
|
|
27
|
+
* parent column) and `labels` (the leaf column).
|
|
28
|
+
*/
|
|
29
|
+
export declare const splitHierarchyRange: (range: SheetRange) => {
|
|
30
|
+
parentLabels: SheetRange[];
|
|
31
|
+
labels: SheetRange;
|
|
32
|
+
};
|
|
33
|
+
/** Parse a `cx:chartSpace` DOM into an `EmbeddedChart` spec (null when unsupported). */
|
|
34
|
+
export declare function parseChartExSpec(chartSpaceDom: any, sheetId: number, resolveSheetId?: ResolveSheetId): EmbeddedChart["spec"] | null;
|
|
35
|
+
/** Resolve + parse one chartex part referenced from a drawing anchor. */
|
|
36
|
+
export declare function processChartEx(chartTarget: string, drawingPath: string, anchor: any, sheetId: number, zipParser: StreamingZipParser, xmlParser: any, sheetDimensions?: SheetDimensions, resolveSheetId?: ResolveSheetId): Promise<EmbeddedChart | null>;
|
|
37
|
+
//# sourceMappingURL=chartex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chartex.d.ts","sourceRoot":"","sources":["../../../../../excel-parser/plugins/xlsx/chartex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EACX,MAAM,2BAA2B,CAAC;AAInC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,iBAAiB,mEACoC,CAAC;AACnE,eAAO,MAAM,oBAAoB,6DAC2B,CAAC;AAyB7D;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAoB9D;AA8BD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,UAAU,KAChB;IAAE,YAAY,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAalD,CAAC;AAWF,wFAAwF;AACxF,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,GAAG,EAClB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,cAAc,GAC9B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CA0D9B;AAED,yEAAyE;AACzE,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,kBAAkB,EAC7B,SAAS,EAAE,GAAG,EACd,eAAe,CAAC,EAAE,eAAe,EACjC,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAsB/B"}
|