@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.
Files changed (166) hide show
  1. package/dist/cjs/excel-parser/cfb-decryptor.d.ts +6 -0
  2. package/dist/cjs/excel-parser/cfb-decryptor.d.ts.map +1 -1
  3. package/dist/cjs/excel-parser/cfb-decryptor.js +6 -0
  4. package/dist/cjs/excel-parser/helpers.d.ts +9 -1
  5. package/dist/cjs/excel-parser/helpers.d.ts.map +1 -1
  6. package/dist/cjs/excel-parser/helpers.js +37 -0
  7. package/dist/cjs/excel-parser/interface.d.ts +15 -2
  8. package/dist/cjs/excel-parser/interface.d.ts.map +1 -1
  9. package/dist/cjs/excel-parser/plugins/base/index.d.ts +2 -0
  10. package/dist/cjs/excel-parser/plugins/base/index.d.ts.map +1 -1
  11. package/dist/cjs/excel-parser/plugins/base/index.js +3 -0
  12. package/dist/cjs/excel-parser/plugins/ods/index.d.ts +19 -0
  13. package/dist/cjs/excel-parser/plugins/ods/index.d.ts.map +1 -1
  14. package/dist/cjs/excel-parser/plugins/ods/index.js +676 -304
  15. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts +43 -1
  16. package/dist/cjs/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  17. package/dist/cjs/excel-parser/plugins/ods/styles.js +343 -45
  18. package/dist/cjs/excel-parser/plugins/xls/index.d.ts +55 -1
  19. package/dist/cjs/excel-parser/plugins/xls/index.d.ts.map +1 -1
  20. package/dist/cjs/excel-parser/plugins/xls/index.js +518 -6
  21. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts +4 -0
  22. package/dist/cjs/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  23. package/dist/cjs/excel-parser/plugins/xlsb/index.js +33 -14
  24. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  25. package/dist/cjs/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  26. package/dist/cjs/excel-parser/plugins/xlsx/chartex.js +244 -0
  27. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  28. package/dist/cjs/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  29. package/dist/cjs/excel-parser/plugins/xlsx/charts.js +68 -9
  30. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  31. package/dist/cjs/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  32. package/dist/cjs/excel-parser/plugins/xlsx/drawing.js +155 -20
  33. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  34. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  35. package/dist/cjs/excel-parser/plugins/xlsx/form-controls.js +295 -0
  36. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts +35 -2
  37. package/dist/cjs/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  38. package/dist/cjs/excel-parser/plugins/xlsx/index.js +737 -257
  39. package/dist/cjs/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  40. package/dist/cjs/excel-parser/plugins/xlsx/pivots.js +125 -37
  41. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  42. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  43. package/dist/cjs/excel-parser/plugins/xlsx/sheet-views.js +4 -1
  44. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  45. package/dist/cjs/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  46. package/dist/cjs/excel-parser/plugins/xlsx/styles.js +102 -6
  47. package/dist/cjs/excel-parser/registry.d.ts +7 -0
  48. package/dist/cjs/excel-parser/registry.d.ts.map +1 -1
  49. package/dist/cjs/excel-parser/registry.js +29 -0
  50. package/dist/cjs/excel-parser/types.d.ts +17 -2
  51. package/dist/cjs/excel-parser/types.d.ts.map +1 -1
  52. package/dist/cjs/excel-parser/workbook.d.ts +3 -0
  53. package/dist/cjs/excel-parser/workbook.d.ts.map +1 -1
  54. package/dist/cjs/excel-parser/workbook.js +24 -14
  55. package/dist/cjs/excel-parser/worker.js +131 -131
  56. package/dist/cjs/exporter/ods/ods-export.d.ts.map +1 -1
  57. package/dist/cjs/exporter/ods/ods-export.js +432 -175
  58. package/dist/cjs/exporter/xlsx/chart-builder.d.ts.map +1 -1
  59. package/dist/cjs/exporter/xlsx/chart-builder.js +215 -39
  60. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts +36 -0
  61. package/dist/cjs/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  62. package/dist/cjs/exporter/xlsx/chartex-builder.js +109 -0
  63. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts +61 -0
  64. package/dist/cjs/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  65. package/dist/cjs/exporter/xlsx/form-controls-builder.js +197 -0
  66. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts +8 -0
  67. package/dist/cjs/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  68. package/dist/cjs/exporter/xlsx/pivot-builder.js +141 -42
  69. package/dist/cjs/exporter/xlsx/style-builder.js +9 -3
  70. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  71. package/dist/cjs/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  72. package/dist/cjs/exporter/xlsx/threaded-comments-builder.js +15 -3
  73. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts +11 -2
  74. package/dist/cjs/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  75. package/dist/cjs/exporter/xlsx/xlsx-export.js +991 -297
  76. package/dist/cjs/helpers/implicit-intersection.d.ts +16 -0
  77. package/dist/cjs/helpers/implicit-intersection.d.ts.map +1 -0
  78. package/dist/cjs/helpers/implicit-intersection.js +197 -0
  79. package/dist/cjs/print-settings.d.ts +105 -0
  80. package/dist/cjs/print-settings.d.ts.map +1 -0
  81. package/dist/cjs/print-settings.js +494 -0
  82. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  83. package/dist/esm/excel-parser/cfb-decryptor.d.ts +6 -0
  84. package/dist/esm/excel-parser/cfb-decryptor.d.ts.map +1 -1
  85. package/dist/esm/excel-parser/cfb-decryptor.js +6 -0
  86. package/dist/esm/excel-parser/helpers.d.ts +9 -1
  87. package/dist/esm/excel-parser/helpers.d.ts.map +1 -1
  88. package/dist/esm/excel-parser/helpers.js +34 -0
  89. package/dist/esm/excel-parser/interface.d.ts +15 -2
  90. package/dist/esm/excel-parser/interface.d.ts.map +1 -1
  91. package/dist/esm/excel-parser/plugins/base/index.d.ts +2 -0
  92. package/dist/esm/excel-parser/plugins/base/index.d.ts.map +1 -1
  93. package/dist/esm/excel-parser/plugins/base/index.js +3 -0
  94. package/dist/esm/excel-parser/plugins/ods/index.d.ts +19 -0
  95. package/dist/esm/excel-parser/plugins/ods/index.d.ts.map +1 -1
  96. package/dist/esm/excel-parser/plugins/ods/index.js +347 -33
  97. package/dist/esm/excel-parser/plugins/ods/styles.d.ts +43 -1
  98. package/dist/esm/excel-parser/plugins/ods/styles.d.ts.map +1 -1
  99. package/dist/esm/excel-parser/plugins/ods/styles.js +276 -2
  100. package/dist/esm/excel-parser/plugins/xls/index.d.ts +55 -1
  101. package/dist/esm/excel-parser/plugins/xls/index.d.ts.map +1 -1
  102. package/dist/esm/excel-parser/plugins/xls/index.js +441 -3
  103. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts +4 -0
  104. package/dist/esm/excel-parser/plugins/xlsb/index.d.ts.map +1 -1
  105. package/dist/esm/excel-parser/plugins/xlsb/index.js +30 -9
  106. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts +37 -0
  107. package/dist/esm/excel-parser/plugins/xlsx/chartex.d.ts.map +1 -0
  108. package/dist/esm/excel-parser/plugins/xlsx/chartex.js +199 -0
  109. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts +10 -0
  110. package/dist/esm/excel-parser/plugins/xlsx/charts.d.ts.map +1 -1
  111. package/dist/esm/excel-parser/plugins/xlsx/charts.js +69 -6
  112. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts +28 -1
  113. package/dist/esm/excel-parser/plugins/xlsx/drawing.d.ts.map +1 -1
  114. package/dist/esm/excel-parser/plugins/xlsx/drawing.js +99 -0
  115. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts +70 -0
  116. package/dist/esm/excel-parser/plugins/xlsx/form-controls.d.ts.map +1 -0
  117. package/dist/esm/excel-parser/plugins/xlsx/form-controls.js +246 -0
  118. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts +35 -2
  119. package/dist/esm/excel-parser/plugins/xlsx/index.d.ts.map +1 -1
  120. package/dist/esm/excel-parser/plugins/xlsx/index.js +454 -32
  121. package/dist/esm/excel-parser/plugins/xlsx/pivots.d.ts.map +1 -1
  122. package/dist/esm/excel-parser/plugins/xlsx/pivots.js +86 -6
  123. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts +3 -0
  124. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.d.ts.map +1 -1
  125. package/dist/esm/excel-parser/plugins/xlsx/sheet-views.js +2 -0
  126. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts +15 -1
  127. package/dist/esm/excel-parser/plugins/xlsx/styles.d.ts.map +1 -1
  128. package/dist/esm/excel-parser/plugins/xlsx/styles.js +92 -2
  129. package/dist/esm/excel-parser/registry.d.ts +7 -0
  130. package/dist/esm/excel-parser/registry.d.ts.map +1 -1
  131. package/dist/esm/excel-parser/registry.js +19 -0
  132. package/dist/esm/excel-parser/types.d.ts +17 -2
  133. package/dist/esm/excel-parser/types.d.ts.map +1 -1
  134. package/dist/esm/excel-parser/workbook.d.ts +3 -0
  135. package/dist/esm/excel-parser/workbook.d.ts.map +1 -1
  136. package/dist/esm/excel-parser/workbook.js +19 -10
  137. package/dist/esm/excel-parser/worker.js +12 -18
  138. package/dist/esm/exporter/ods/ods-export.d.ts.map +1 -1
  139. package/dist/esm/exporter/ods/ods-export.js +306 -35
  140. package/dist/esm/exporter/xlsx/chart-builder.d.ts.map +1 -1
  141. package/dist/esm/exporter/xlsx/chart-builder.js +161 -28
  142. package/dist/esm/exporter/xlsx/chartex-builder.d.ts +36 -0
  143. package/dist/esm/exporter/xlsx/chartex-builder.d.ts.map +1 -0
  144. package/dist/esm/exporter/xlsx/chartex-builder.js +97 -0
  145. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts +61 -0
  146. package/dist/esm/exporter/xlsx/form-controls-builder.d.ts.map +1 -0
  147. package/dist/esm/exporter/xlsx/form-controls-builder.js +173 -0
  148. package/dist/esm/exporter/xlsx/pivot-builder.d.ts +8 -0
  149. package/dist/esm/exporter/xlsx/pivot-builder.d.ts.map +1 -1
  150. package/dist/esm/exporter/xlsx/pivot-builder.js +104 -19
  151. package/dist/esm/exporter/xlsx/style-builder.js +9 -3
  152. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts +7 -1
  153. package/dist/esm/exporter/xlsx/threaded-comments-builder.d.ts.map +1 -1
  154. package/dist/esm/exporter/xlsx/threaded-comments-builder.js +15 -3
  155. package/dist/esm/exporter/xlsx/xlsx-export.d.ts +11 -2
  156. package/dist/esm/exporter/xlsx/xlsx-export.d.ts.map +1 -1
  157. package/dist/esm/exporter/xlsx/xlsx-export.js +675 -64
  158. package/dist/esm/helpers/implicit-intersection.d.ts +16 -0
  159. package/dist/esm/helpers/implicit-intersection.d.ts.map +1 -0
  160. package/dist/esm/helpers/implicit-intersection.js +184 -0
  161. package/dist/esm/print-settings.d.ts +105 -0
  162. package/dist/esm/print-settings.d.ts.map +1 -0
  163. package/dist/esm/print-settings.js +422 -0
  164. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  165. package/package.json +3 -3
  166. 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
- async load(_buffer, _password) {
4
- // TODO: Implement XLS loading (CFB format)
5
- console.warn("XLS support not implemented yet");
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":"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"}
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
- // Bit 1 (0x0002): fShowGridLines - if 0, gridlines are hidden
278
- const showGridLines = (flags & 0x0002) !== 0;
279
- return { showGridLines };
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
- const value = Number(parsed.value);
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"}