xls-codec 4.7.5 → 4.8.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.
Files changed (78) hide show
  1. package/README.md +7 -2
  2. package/dist/biff/record-types.cjs +21 -0
  3. package/dist/biff/record-types.d.cts +15 -1
  4. package/dist/biff/record-types.d.ts +15 -1
  5. package/dist/biff/record-types.js +15 -1
  6. package/dist/biff/substreams.cjs +7 -8
  7. package/dist/biff/substreams.d.cts +1 -1
  8. package/dist/biff/substreams.d.ts +1 -1
  9. package/dist/biff/substreams.js +7 -8
  10. package/dist/{conditional-format-12-DBhe7Zo6.d.cts → conditional-format-12-CZ43-CR4.d.cts} +2 -2
  11. package/dist/{conditional-format-12-D-X5g_O3.d.ts → conditional-format-12-Xl52VBCj.d.ts} +2 -2
  12. package/dist/{conditional-format-Czh2oTzQ.d.cts → conditional-format-Bt1vRWgc.d.cts} +1 -1
  13. package/dist/{conditional-format-DOdazxWe.d.ts → conditional-format-Cqcjnm7O.d.ts} +1 -1
  14. package/dist/content.cjs +40 -18
  15. package/dist/content.js +40 -18
  16. package/dist/{data-validation-BXvIVU0e.d.ts → data-validation-BeYpL3Nb.d.ts} +1 -1
  17. package/dist/{data-validation-DfpjUN-N.d.cts → data-validation-lJWM9-AP.d.cts} +1 -1
  18. package/dist/drawing/blips.cjs +83 -0
  19. package/dist/drawing/blips.d.cts +10 -0
  20. package/dist/drawing/blips.d.ts +10 -0
  21. package/dist/drawing/blips.js +82 -0
  22. package/dist/drawing/bytes.cjs +15 -0
  23. package/dist/drawing/bytes.d.cts +5 -0
  24. package/dist/drawing/bytes.d.ts +5 -0
  25. package/dist/drawing/bytes.js +14 -0
  26. package/dist/drawing/escher-constants.cjs +52 -0
  27. package/dist/drawing/escher-constants.d.cts +34 -0
  28. package/dist/drawing/escher-constants.d.ts +34 -0
  29. package/dist/drawing/escher-constants.js +34 -0
  30. package/dist/drawing/escher.cjs +84 -0
  31. package/dist/drawing/escher.d.cts +30 -0
  32. package/dist/drawing/escher.d.ts +30 -0
  33. package/dist/drawing/escher.js +80 -0
  34. package/dist/drawing/shapes.cjs +80 -0
  35. package/dist/drawing/shapes.d.cts +24 -0
  36. package/dist/drawing/shapes.d.ts +24 -0
  37. package/dist/drawing/shapes.js +79 -0
  38. package/dist/index.cjs +10 -1
  39. package/dist/index.d.cts +4 -4
  40. package/dist/index.d.ts +4 -4
  41. package/dist/index.js +4 -4
  42. package/dist/{print-names-CCwUHAoL.d.cts → print-names-B2OR0fvs.d.cts} +1 -1
  43. package/dist/{print-names-CxAbgcjB.d.ts → print-names-BXcmmwVi.d.ts} +1 -1
  44. package/dist/{substreams-Dp5cZoUo.d.ts → substreams-CgTHx5kX.d.ts} +1 -1
  45. package/dist/{substreams-CHv3oWmn.d.cts → substreams-XDNgDvRJ.d.cts} +1 -1
  46. package/dist/units.cjs +7 -0
  47. package/dist/units.d.cts +6 -1
  48. package/dist/units.d.ts +6 -1
  49. package/dist/units.js +6 -1
  50. package/dist/workbook/chart.cjs +230 -0
  51. package/dist/workbook/chart.d.cts +19 -0
  52. package/dist/workbook/chart.d.ts +19 -0
  53. package/dist/workbook/chart.js +229 -0
  54. package/dist/workbook/comments.cjs +2 -1
  55. package/dist/workbook/comments.d.cts +7 -2
  56. package/dist/workbook/comments.d.ts +7 -2
  57. package/dist/workbook/comments.js +2 -2
  58. package/dist/workbook/conditional-format-12.d.cts +1 -1
  59. package/dist/workbook/conditional-format-12.d.ts +1 -1
  60. package/dist/workbook/conditional-format.d.cts +1 -1
  61. package/dist/workbook/conditional-format.d.ts +1 -1
  62. package/dist/workbook/data-validation.d.cts +1 -1
  63. package/dist/workbook/data-validation.d.ts +1 -1
  64. package/dist/workbook/drawing.cjs +270 -0
  65. package/dist/workbook/drawing.d.cts +31 -0
  66. package/dist/workbook/drawing.d.ts +31 -0
  67. package/dist/workbook/drawing.js +268 -0
  68. package/dist/workbook/globals-writer.d.cts +1 -1
  69. package/dist/workbook/globals-writer.d.ts +1 -1
  70. package/dist/workbook/globals.d.cts +2 -2
  71. package/dist/workbook/globals.d.ts +2 -2
  72. package/dist/workbook/print-names.d.cts +1 -1
  73. package/dist/workbook/print-names.d.ts +1 -1
  74. package/dist/workbook/sheet-writer.cjs +1 -1
  75. package/dist/workbook/sheet-writer.js +1 -1
  76. package/dist/workbook/sheet.d.cts +4 -4
  77. package/dist/workbook/sheet.d.ts +4 -4
  78. package/package.json +3 -3
@@ -0,0 +1,230 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_biff_record_types = require("../biff/record-types.cjs");
3
+ const require_biff_cursor = require("../biff/cursor.cjs");
4
+ const require_biff_strings = require("../biff/strings.cjs");
5
+ const require_biff_errors = require("../biff/errors.cjs");
6
+ //#region src/workbook/chart.ts
7
+ /** [MS-XLS] "BRAI" 2.4's own `id` enumeration: which data role a given AI record links. */
8
+ const AI_ID_NAME = 0;
9
+ const AI_ID_VALUES = 1;
10
+ const AI_ID_CATEGORIES = 2;
11
+ /** [MS-XLS] "BRAI" 2.4's own `rt` enumeration: 0 auto-generated (no formula/value at all), 1 a literal value/text carried directly in the formula's own token, 2 a genuine cell-range reference. */
12
+ const AI_RT_LITERAL = 1;
13
+ const AI_RT_RANGE = 2;
14
+ /** [MS-XLS] "SIIndex" 2.4's own `numIndex` enumeration: which of the three SERIESDATA cache blocks follows. */
15
+ const SIINDEX_VALUES = 1;
16
+ const SIINDEX_CATEGORIES = 2;
17
+ /** Reads one chart substream's records (BOF/EOF already stripped by splitSubstreams) into its flattened series table. */
18
+ function readChartSeries(records, context) {
19
+ const seriesBuilders = [];
20
+ const cache = /* @__PURE__ */ new Map();
21
+ let currentCacheRole;
22
+ let pendingNameAiId;
23
+ for (const record of records) switch (record.type) {
24
+ case require_biff_record_types.RECORD_SERIES:
25
+ seriesBuilders.push(readSeriesHeader(record));
26
+ break;
27
+ case require_biff_record_types.RECORD_AI: {
28
+ const current = seriesBuilders[seriesBuilders.length - 1];
29
+ if (current !== void 0) readAiRecord(record, current, context);
30
+ pendingNameAiId = readAiId(record);
31
+ break;
32
+ }
33
+ case require_biff_record_types.RECORD_SERIESTEXT: {
34
+ const current = seriesBuilders[seriesBuilders.length - 1];
35
+ if (current !== void 0 && pendingNameAiId === AI_ID_NAME) current.cachedName = readSeriesText(record);
36
+ pendingNameAiId = void 0;
37
+ break;
38
+ }
39
+ case require_biff_record_types.RECORD_SIINDEX:
40
+ currentCacheRole = readCacheRole(record);
41
+ break;
42
+ case 515:
43
+ case 517:
44
+ case 513:
45
+ case 516: if (currentCacheRole !== void 0) addCacheEntry(cache, currentCacheRole, record);
46
+ }
47
+ return seriesBuilders.map((builder, seriesIndex) => ({
48
+ name: builder.cachedName ?? builder.literalName,
49
+ categories: resolvePoints(builder.categoryCount, seriesIndex, builder.categoriesRange, cache.get("categories"), context),
50
+ values: resolvePoints(builder.valueCount, seriesIndex, builder.valuesRange, cache.get("values"), context)
51
+ }));
52
+ }
53
+ /** [MS-OGRAPH] "Series" (https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-ograph/54527b2d-d529-4128-9a7f-a224cc575080): sdtX, sdtY (both a fixed, ignored data-type tag), cValx (category/point count), cValy (value count), sdtBSize (ignored), cValBSize (bubble-size count, not modelled). Only the two counts this reader actually resolves points against are kept. */
54
+ function readSeriesHeader(record) {
55
+ const cursor = new require_biff_cursor.BlockCursor(record.blocks);
56
+ cursor.skip(2);
57
+ cursor.skip(2);
58
+ const categoryCount = cursor.u16();
59
+ return {
60
+ literalName: void 0,
61
+ cachedName: void 0,
62
+ valuesRange: void 0,
63
+ categoriesRange: void 0,
64
+ valueCount: cursor.u16(),
65
+ categoryCount
66
+ };
67
+ }
68
+ function readAiId(record) {
69
+ return new require_biff_cursor.BlockCursor(record.blocks).u8();
70
+ }
71
+ /** [MS-XLS] "BRAI": id, rt, a flags/ifmt word this reader skips past, then a ChartParsedFormula (cce + rgce). Only id 0 (name)/1 (values)/2 (categories) are acted on; id 3 (bubble sizes) is read past like any other record this reader recognises but does not model further. */
72
+ function readAiRecord(record, series, context) {
73
+ const cursor = new require_biff_cursor.BlockCursor(record.blocks);
74
+ const id = cursor.u8();
75
+ const rt = cursor.u8();
76
+ cursor.skip(2);
77
+ cursor.skip(2);
78
+ const cce = cursor.u16();
79
+ const rgce = cursor.take(cce);
80
+ if (id === AI_ID_NAME) {
81
+ if (rt === AI_RT_LITERAL) series.literalName = readLiteralToken(rgce);
82
+ else if (rt === AI_RT_RANGE) {
83
+ const range = readRangeToken(rgce, context);
84
+ if (range !== void 0) series.literalName = cellText(range.startRow, range.startColumn, context);
85
+ }
86
+ return;
87
+ }
88
+ if (rt !== AI_RT_RANGE) return;
89
+ const range = readRangeToken(rgce, context);
90
+ if (id === AI_ID_VALUES) series.valuesRange = range;
91
+ else if (id === AI_ID_CATEGORIES) series.categoriesRange = range;
92
+ }
93
+ /** [MS-XLS] "SeriesText": a reserved word then a ShortXLUnicodeString (one-byte length prefix -- unlike the double-byte-length XLUnicodeString most other BIFF8 strings use). */
94
+ function readSeriesText(record) {
95
+ const cursor = new require_biff_cursor.BlockCursor(record.blocks);
96
+ cursor.skip(2);
97
+ return require_biff_strings.readShortXLUnicodeString(cursor);
98
+ }
99
+ function readCacheRole(record) {
100
+ const numIndex = new require_biff_cursor.BlockCursor(record.blocks).u16();
101
+ if (numIndex === SIINDEX_VALUES) return "values";
102
+ if (numIndex === SIINDEX_CATEGORIES) return "categories";
103
+ }
104
+ /** A cached Number/BoolErr/Blank/Label record ([MS-XLS] 2.4.180/2.4.24/2.4.20/2.4.148 -- the identical worksheet cell-record layout, reinterpreted here per "Chart Data Cache": `row` is the point's own 0-based position within its series, `col` the 0-based Series-record index it belongs to, rather than a worksheet cell address). A Blank adds nothing to the cache -- an explicit "no cached value at this point" the same way an absent cache entry already reads. */
105
+ function addCacheEntry(cache, role, record) {
106
+ const cursor = new require_biff_cursor.BlockCursor(record.blocks);
107
+ const point = cursor.u16();
108
+ const series = cursor.u16();
109
+ cursor.skip(2);
110
+ let text;
111
+ switch (record.type) {
112
+ case 515:
113
+ text = String(cursor.f64());
114
+ break;
115
+ case 516:
116
+ text = require_biff_strings.readXLUnicodeString(cursor);
117
+ break;
118
+ case 517: {
119
+ const value = cursor.u8();
120
+ text = cursor.u8() !== 0 ? require_biff_errors.errorTextOf(value) : value !== 0 ? "TRUE" : "FALSE";
121
+ break;
122
+ }
123
+ default: return;
124
+ }
125
+ if (text === void 0) return;
126
+ let bySeries = cache.get(role);
127
+ if (bySeries === void 0) {
128
+ bySeries = /* @__PURE__ */ new Map();
129
+ cache.set(role, bySeries);
130
+ }
131
+ let byPoint = bySeries.get(series);
132
+ if (byPoint === void 0) {
133
+ byPoint = /* @__PURE__ */ new Map();
134
+ bySeries.set(series, byPoint);
135
+ }
136
+ byPoint.set(point, text);
137
+ }
138
+ function resolvePoints(count, seriesIndex, range, cacheForRole, context) {
139
+ const cachedForSeries = cacheForRole?.get(seriesIndex);
140
+ const points = [];
141
+ for (let index = 0; index < count; index += 1) {
142
+ const cached = cachedForSeries?.get(index);
143
+ if (cached !== void 0) {
144
+ points.push(cached);
145
+ continue;
146
+ }
147
+ if (range !== void 0) {
148
+ const cell = pointInRange(range, index);
149
+ points.push(cellText(cell.row, cell.column, context) ?? "");
150
+ continue;
151
+ }
152
+ points.push("");
153
+ }
154
+ return points;
155
+ }
156
+ /** The Nth cell of a range, in reading order -- a single row walks across its columns, a single column (the common vertical-series case) walks down its rows, and a genuine rectangular box walks row-major. */
157
+ function pointInRange(range, index) {
158
+ const height = range.endRow - range.startRow + 1;
159
+ const width = range.endColumn - range.startColumn + 1;
160
+ if (height <= 1) return {
161
+ row: range.startRow,
162
+ column: range.startColumn + index
163
+ };
164
+ if (width <= 1) return {
165
+ row: range.startRow + index,
166
+ column: range.startColumn
167
+ };
168
+ return {
169
+ row: range.startRow + Math.floor(index / width),
170
+ column: range.startColumn + index % width
171
+ };
172
+ }
173
+ function cellText(row, column, context) {
174
+ return context.ownSheetCells.find((cell) => cell.row === row && cell.column === column)?.displayText;
175
+ }
176
+ /** A literal AI value/text -- id=0 (name) only meets this in practice, real files always resolving categories/values through a real range. Reads exactly one leading token (skipping a PtgParen display wrapper first, since a literal is sometimes wrapped in one), and only the literal-operand family: PtgInt/PtgNum/PtgStr. Anything else is a construct this reader does not resolve, exactly like a formula token this package's own biff/ptg.ts declines to resolve elsewhere. */
177
+ function readLiteralToken(rgce) {
178
+ const cursor = new require_biff_cursor.BlockCursor([rgce]);
179
+ if (!cursor.hasMore()) return;
180
+ let opcode = cursor.u8();
181
+ if (opcode === 21 && cursor.hasMore()) opcode = cursor.u8();
182
+ switch (opcode) {
183
+ case 30: return String(cursor.u16());
184
+ case 31: return String(cursor.f64());
185
+ case 23: return require_biff_strings.readShortXLUnicodeString(cursor);
186
+ default: return;
187
+ }
188
+ }
189
+ /** A range-reference AI value: PtgRef3d/PtgArea3d only, restricted to a reference INTO THE CHART'S OWN OWNING SHEET (see this module's own top comment for why a cross-sheet reference has no shortcut here) -- every other token this restricted BRAI grammar permits (PtgUnion, PtgNameX, PtgMemFunc, the RefErr/AreaErr variants) is a construct this reader does not resolve, matching biff/ptg.ts's own "unsupported construct -> absent" convention for a worksheet cell's ordinary Formula record. */
190
+ function readRangeToken(rgce, context) {
191
+ const cursor = new require_biff_cursor.BlockCursor([rgce]);
192
+ if (!cursor.hasMore()) return;
193
+ let opcode = cursor.u8();
194
+ if (opcode === 21 && cursor.hasMore()) opcode = cursor.u8();
195
+ const COLUMN_INDEX_MASK = 16383;
196
+ if (opcode === 58 || opcode === 90 || opcode === 122) {
197
+ const ixti = cursor.u16();
198
+ const row = cursor.u16();
199
+ const column = cursor.u16() & COLUMN_INDEX_MASK;
200
+ if (!isOwnSheetRef(ixti, context)) return;
201
+ return {
202
+ startRow: row,
203
+ endRow: row,
204
+ startColumn: column,
205
+ endColumn: column
206
+ };
207
+ }
208
+ if (opcode === 59 || opcode === 91 || opcode === 123) {
209
+ const ixti = cursor.u16();
210
+ const rowFirst = cursor.u16();
211
+ const rowLast = cursor.u16();
212
+ const columnFirst = cursor.u16() & COLUMN_INDEX_MASK;
213
+ const columnLast = cursor.u16() & COLUMN_INDEX_MASK;
214
+ if (!isOwnSheetRef(ixti, context)) return;
215
+ return {
216
+ startRow: Math.min(rowFirst, rowLast),
217
+ endRow: Math.max(rowFirst, rowLast),
218
+ startColumn: Math.min(columnFirst, columnLast),
219
+ endColumn: Math.max(columnFirst, columnLast)
220
+ };
221
+ }
222
+ }
223
+ /** Whether ixti resolves (through EXTERNSHEET/SupBook -- the identical resolution biff/ptg.ts's resolveSheetLabel performs for a worksheet formula's own 3D references) to a single-sheet range naming exactly the chart's own owning sheet -- the only case this reader has a cell table to resolve against at all. */
224
+ function isOwnSheetRef(ixti, context) {
225
+ const range = context.formulaSheets.sheetRanges[ixti];
226
+ if (range === void 0 || "label" in range) return false;
227
+ return range.firstSheetIndex === range.lastSheetIndex && range.firstSheetIndex === context.ownSheetIndex;
228
+ }
229
+ //#endregion
230
+ exports.readChartSeries = readChartSeries;
@@ -0,0 +1,19 @@
1
+ import { r as FormulaSheetContext } from "../ptg-CCBbJLZJ.cjs";
2
+ import { t as RecordGroup } from "../substreams-XDNgDvRJ.cjs";
3
+ import { ContentSheetCell } from "document-schema.js";
4
+ //#region src/workbook/chart.d.ts
5
+ /** One resolved series: its own name (undefined when neither a SeriesText cache nor a literal/same-sheet-resolvable AI id=0 named it) and its category/value points, in point order, verbatim source text (a cache or a resolved cell's own displayText) -- exactly what readChartTable's own ChartSeries carries for the xlsx/pptx case, so chartCells below can build the identical flattened-table shape. A point this reader cannot resolve at all -- a cross-sheet or external reference with no cache entry, an unsupported AI token -- is an empty string, matching readChartTable's own "absent or empty-text label/value reads as an empty cell" convention. */
6
+ interface ChartSeries {
7
+ readonly name: string | undefined;
8
+ readonly categories: readonly string[];
9
+ readonly values: readonly string[];
10
+ }
11
+ interface ChartRangeContext {
12
+ readonly formulaSheets: FormulaSheetContext;
13
+ readonly ownSheetIndex: number;
14
+ readonly ownSheetCells: readonly ContentSheetCell[];
15
+ }
16
+ /** Reads one chart substream's records (BOF/EOF already stripped by splitSubstreams) into its flattened series table. */
17
+ declare function readChartSeries(records: readonly RecordGroup[], context: ChartRangeContext): readonly ChartSeries[];
18
+ //#endregion
19
+ export { ChartRangeContext, ChartSeries, readChartSeries };
@@ -0,0 +1,19 @@
1
+ import { r as FormulaSheetContext } from "../ptg-CCBbJLZJ.js";
2
+ import { t as RecordGroup } from "../substreams-CgTHx5kX.js";
3
+ import { ContentSheetCell } from "document-schema.js";
4
+ //#region src/workbook/chart.d.ts
5
+ /** One resolved series: its own name (undefined when neither a SeriesText cache nor a literal/same-sheet-resolvable AI id=0 named it) and its category/value points, in point order, verbatim source text (a cache or a resolved cell's own displayText) -- exactly what readChartTable's own ChartSeries carries for the xlsx/pptx case, so chartCells below can build the identical flattened-table shape. A point this reader cannot resolve at all -- a cross-sheet or external reference with no cache entry, an unsupported AI token -- is an empty string, matching readChartTable's own "absent or empty-text label/value reads as an empty cell" convention. */
6
+ interface ChartSeries {
7
+ readonly name: string | undefined;
8
+ readonly categories: readonly string[];
9
+ readonly values: readonly string[];
10
+ }
11
+ interface ChartRangeContext {
12
+ readonly formulaSheets: FormulaSheetContext;
13
+ readonly ownSheetIndex: number;
14
+ readonly ownSheetCells: readonly ContentSheetCell[];
15
+ }
16
+ /** Reads one chart substream's records (BOF/EOF already stripped by splitSubstreams) into its flattened series table. */
17
+ declare function readChartSeries(records: readonly RecordGroup[], context: ChartRangeContext): readonly ChartSeries[];
18
+ //#endregion
19
+ export { ChartRangeContext, ChartSeries, readChartSeries };
@@ -0,0 +1,229 @@
1
+ import { RECORD_AI, RECORD_SERIES, RECORD_SERIESTEXT, RECORD_SIINDEX } from "../biff/record-types.js";
2
+ import { BlockCursor } from "../biff/cursor.js";
3
+ import { readShortXLUnicodeString, readXLUnicodeString } from "../biff/strings.js";
4
+ import { errorTextOf } from "../biff/errors.js";
5
+ //#region src/workbook/chart.ts
6
+ /** [MS-XLS] "BRAI" 2.4's own `id` enumeration: which data role a given AI record links. */
7
+ const AI_ID_NAME = 0;
8
+ const AI_ID_VALUES = 1;
9
+ const AI_ID_CATEGORIES = 2;
10
+ /** [MS-XLS] "BRAI" 2.4's own `rt` enumeration: 0 auto-generated (no formula/value at all), 1 a literal value/text carried directly in the formula's own token, 2 a genuine cell-range reference. */
11
+ const AI_RT_LITERAL = 1;
12
+ const AI_RT_RANGE = 2;
13
+ /** [MS-XLS] "SIIndex" 2.4's own `numIndex` enumeration: which of the three SERIESDATA cache blocks follows. */
14
+ const SIINDEX_VALUES = 1;
15
+ const SIINDEX_CATEGORIES = 2;
16
+ /** Reads one chart substream's records (BOF/EOF already stripped by splitSubstreams) into its flattened series table. */
17
+ function readChartSeries(records, context) {
18
+ const seriesBuilders = [];
19
+ const cache = /* @__PURE__ */ new Map();
20
+ let currentCacheRole;
21
+ let pendingNameAiId;
22
+ for (const record of records) switch (record.type) {
23
+ case RECORD_SERIES:
24
+ seriesBuilders.push(readSeriesHeader(record));
25
+ break;
26
+ case RECORD_AI: {
27
+ const current = seriesBuilders[seriesBuilders.length - 1];
28
+ if (current !== void 0) readAiRecord(record, current, context);
29
+ pendingNameAiId = readAiId(record);
30
+ break;
31
+ }
32
+ case RECORD_SERIESTEXT: {
33
+ const current = seriesBuilders[seriesBuilders.length - 1];
34
+ if (current !== void 0 && pendingNameAiId === AI_ID_NAME) current.cachedName = readSeriesText(record);
35
+ pendingNameAiId = void 0;
36
+ break;
37
+ }
38
+ case RECORD_SIINDEX:
39
+ currentCacheRole = readCacheRole(record);
40
+ break;
41
+ case 515:
42
+ case 517:
43
+ case 513:
44
+ case 516: if (currentCacheRole !== void 0) addCacheEntry(cache, currentCacheRole, record);
45
+ }
46
+ return seriesBuilders.map((builder, seriesIndex) => ({
47
+ name: builder.cachedName ?? builder.literalName,
48
+ categories: resolvePoints(builder.categoryCount, seriesIndex, builder.categoriesRange, cache.get("categories"), context),
49
+ values: resolvePoints(builder.valueCount, seriesIndex, builder.valuesRange, cache.get("values"), context)
50
+ }));
51
+ }
52
+ /** [MS-OGRAPH] "Series" (https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-ograph/54527b2d-d529-4128-9a7f-a224cc575080): sdtX, sdtY (both a fixed, ignored data-type tag), cValx (category/point count), cValy (value count), sdtBSize (ignored), cValBSize (bubble-size count, not modelled). Only the two counts this reader actually resolves points against are kept. */
53
+ function readSeriesHeader(record) {
54
+ const cursor = new BlockCursor(record.blocks);
55
+ cursor.skip(2);
56
+ cursor.skip(2);
57
+ const categoryCount = cursor.u16();
58
+ return {
59
+ literalName: void 0,
60
+ cachedName: void 0,
61
+ valuesRange: void 0,
62
+ categoriesRange: void 0,
63
+ valueCount: cursor.u16(),
64
+ categoryCount
65
+ };
66
+ }
67
+ function readAiId(record) {
68
+ return new BlockCursor(record.blocks).u8();
69
+ }
70
+ /** [MS-XLS] "BRAI": id, rt, a flags/ifmt word this reader skips past, then a ChartParsedFormula (cce + rgce). Only id 0 (name)/1 (values)/2 (categories) are acted on; id 3 (bubble sizes) is read past like any other record this reader recognises but does not model further. */
71
+ function readAiRecord(record, series, context) {
72
+ const cursor = new BlockCursor(record.blocks);
73
+ const id = cursor.u8();
74
+ const rt = cursor.u8();
75
+ cursor.skip(2);
76
+ cursor.skip(2);
77
+ const cce = cursor.u16();
78
+ const rgce = cursor.take(cce);
79
+ if (id === AI_ID_NAME) {
80
+ if (rt === AI_RT_LITERAL) series.literalName = readLiteralToken(rgce);
81
+ else if (rt === AI_RT_RANGE) {
82
+ const range = readRangeToken(rgce, context);
83
+ if (range !== void 0) series.literalName = cellText(range.startRow, range.startColumn, context);
84
+ }
85
+ return;
86
+ }
87
+ if (rt !== AI_RT_RANGE) return;
88
+ const range = readRangeToken(rgce, context);
89
+ if (id === AI_ID_VALUES) series.valuesRange = range;
90
+ else if (id === AI_ID_CATEGORIES) series.categoriesRange = range;
91
+ }
92
+ /** [MS-XLS] "SeriesText": a reserved word then a ShortXLUnicodeString (one-byte length prefix -- unlike the double-byte-length XLUnicodeString most other BIFF8 strings use). */
93
+ function readSeriesText(record) {
94
+ const cursor = new BlockCursor(record.blocks);
95
+ cursor.skip(2);
96
+ return readShortXLUnicodeString(cursor);
97
+ }
98
+ function readCacheRole(record) {
99
+ const numIndex = new BlockCursor(record.blocks).u16();
100
+ if (numIndex === SIINDEX_VALUES) return "values";
101
+ if (numIndex === SIINDEX_CATEGORIES) return "categories";
102
+ }
103
+ /** A cached Number/BoolErr/Blank/Label record ([MS-XLS] 2.4.180/2.4.24/2.4.20/2.4.148 -- the identical worksheet cell-record layout, reinterpreted here per "Chart Data Cache": `row` is the point's own 0-based position within its series, `col` the 0-based Series-record index it belongs to, rather than a worksheet cell address). A Blank adds nothing to the cache -- an explicit "no cached value at this point" the same way an absent cache entry already reads. */
104
+ function addCacheEntry(cache, role, record) {
105
+ const cursor = new BlockCursor(record.blocks);
106
+ const point = cursor.u16();
107
+ const series = cursor.u16();
108
+ cursor.skip(2);
109
+ let text;
110
+ switch (record.type) {
111
+ case 515:
112
+ text = String(cursor.f64());
113
+ break;
114
+ case 516:
115
+ text = readXLUnicodeString(cursor);
116
+ break;
117
+ case 517: {
118
+ const value = cursor.u8();
119
+ text = cursor.u8() !== 0 ? errorTextOf(value) : value !== 0 ? "TRUE" : "FALSE";
120
+ break;
121
+ }
122
+ default: return;
123
+ }
124
+ if (text === void 0) return;
125
+ let bySeries = cache.get(role);
126
+ if (bySeries === void 0) {
127
+ bySeries = /* @__PURE__ */ new Map();
128
+ cache.set(role, bySeries);
129
+ }
130
+ let byPoint = bySeries.get(series);
131
+ if (byPoint === void 0) {
132
+ byPoint = /* @__PURE__ */ new Map();
133
+ bySeries.set(series, byPoint);
134
+ }
135
+ byPoint.set(point, text);
136
+ }
137
+ function resolvePoints(count, seriesIndex, range, cacheForRole, context) {
138
+ const cachedForSeries = cacheForRole?.get(seriesIndex);
139
+ const points = [];
140
+ for (let index = 0; index < count; index += 1) {
141
+ const cached = cachedForSeries?.get(index);
142
+ if (cached !== void 0) {
143
+ points.push(cached);
144
+ continue;
145
+ }
146
+ if (range !== void 0) {
147
+ const cell = pointInRange(range, index);
148
+ points.push(cellText(cell.row, cell.column, context) ?? "");
149
+ continue;
150
+ }
151
+ points.push("");
152
+ }
153
+ return points;
154
+ }
155
+ /** The Nth cell of a range, in reading order -- a single row walks across its columns, a single column (the common vertical-series case) walks down its rows, and a genuine rectangular box walks row-major. */
156
+ function pointInRange(range, index) {
157
+ const height = range.endRow - range.startRow + 1;
158
+ const width = range.endColumn - range.startColumn + 1;
159
+ if (height <= 1) return {
160
+ row: range.startRow,
161
+ column: range.startColumn + index
162
+ };
163
+ if (width <= 1) return {
164
+ row: range.startRow + index,
165
+ column: range.startColumn
166
+ };
167
+ return {
168
+ row: range.startRow + Math.floor(index / width),
169
+ column: range.startColumn + index % width
170
+ };
171
+ }
172
+ function cellText(row, column, context) {
173
+ return context.ownSheetCells.find((cell) => cell.row === row && cell.column === column)?.displayText;
174
+ }
175
+ /** A literal AI value/text -- id=0 (name) only meets this in practice, real files always resolving categories/values through a real range. Reads exactly one leading token (skipping a PtgParen display wrapper first, since a literal is sometimes wrapped in one), and only the literal-operand family: PtgInt/PtgNum/PtgStr. Anything else is a construct this reader does not resolve, exactly like a formula token this package's own biff/ptg.ts declines to resolve elsewhere. */
176
+ function readLiteralToken(rgce) {
177
+ const cursor = new BlockCursor([rgce]);
178
+ if (!cursor.hasMore()) return;
179
+ let opcode = cursor.u8();
180
+ if (opcode === 21 && cursor.hasMore()) opcode = cursor.u8();
181
+ switch (opcode) {
182
+ case 30: return String(cursor.u16());
183
+ case 31: return String(cursor.f64());
184
+ case 23: return readShortXLUnicodeString(cursor);
185
+ default: return;
186
+ }
187
+ }
188
+ /** A range-reference AI value: PtgRef3d/PtgArea3d only, restricted to a reference INTO THE CHART'S OWN OWNING SHEET (see this module's own top comment for why a cross-sheet reference has no shortcut here) -- every other token this restricted BRAI grammar permits (PtgUnion, PtgNameX, PtgMemFunc, the RefErr/AreaErr variants) is a construct this reader does not resolve, matching biff/ptg.ts's own "unsupported construct -> absent" convention for a worksheet cell's ordinary Formula record. */
189
+ function readRangeToken(rgce, context) {
190
+ const cursor = new BlockCursor([rgce]);
191
+ if (!cursor.hasMore()) return;
192
+ let opcode = cursor.u8();
193
+ if (opcode === 21 && cursor.hasMore()) opcode = cursor.u8();
194
+ const COLUMN_INDEX_MASK = 16383;
195
+ if (opcode === 58 || opcode === 90 || opcode === 122) {
196
+ const ixti = cursor.u16();
197
+ const row = cursor.u16();
198
+ const column = cursor.u16() & COLUMN_INDEX_MASK;
199
+ if (!isOwnSheetRef(ixti, context)) return;
200
+ return {
201
+ startRow: row,
202
+ endRow: row,
203
+ startColumn: column,
204
+ endColumn: column
205
+ };
206
+ }
207
+ if (opcode === 59 || opcode === 91 || opcode === 123) {
208
+ const ixti = cursor.u16();
209
+ const rowFirst = cursor.u16();
210
+ const rowLast = cursor.u16();
211
+ const columnFirst = cursor.u16() & COLUMN_INDEX_MASK;
212
+ const columnLast = cursor.u16() & COLUMN_INDEX_MASK;
213
+ if (!isOwnSheetRef(ixti, context)) return;
214
+ return {
215
+ startRow: Math.min(rowFirst, rowLast),
216
+ endRow: Math.max(rowFirst, rowLast),
217
+ startColumn: Math.min(columnFirst, columnLast),
218
+ endColumn: Math.max(columnFirst, columnLast)
219
+ };
220
+ }
221
+ }
222
+ /** Whether ixti resolves (through EXTERNSHEET/SupBook -- the identical resolution biff/ptg.ts's resolveSheetLabel performs for a worksheet formula's own 3D references) to a single-sheet range naming exactly the chart's own owning sheet -- the only case this reader has a cell table to resolve against at all. */
223
+ function isOwnSheetRef(ixti, context) {
224
+ const range = context.formulaSheets.sheetRanges[ixti];
225
+ if (range === void 0 || "label" in range) return false;
226
+ return range.firstSheetIndex === range.lastSheetIndex && range.firstSheetIndex === context.ownSheetIndex;
227
+ }
228
+ //#endregion
229
+ export { readChartSeries };
@@ -24,7 +24,7 @@ function readNoteAnchor(group) {
24
24
  idObj
25
25
  };
26
26
  }
27
- /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "is this a Note object, and if so, what id does its own TxO get associated through": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj cross-references. */
27
+ /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "what kind of drawing object is this, and what id does a following TxO/other per-object record cross-reference": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj (here) and workbook/drawing.ts's own shape pairing (there) both key on. Exported for workbook/drawing.ts, which pairs each MsoDrawing shape with the Obj record immediately naming it -- the identical FtCmo structure every Obj record carries, comment-anchored or not. */
28
28
  function readObjTypeAndId(group) {
29
29
  const cursor = new require_biff_cursor.BlockCursor(group.blocks);
30
30
  cursor.skip(4);
@@ -82,4 +82,5 @@ function readSheetComments(records) {
82
82
  return comments;
83
83
  }
84
84
  //#endregion
85
+ exports.readObjTypeAndId = readObjTypeAndId;
85
86
  exports.readSheetComments = readSheetComments;
@@ -1,4 +1,4 @@
1
- import { t as RecordGroup } from "../substreams-CHv3oWmn.cjs";
1
+ import { t as RecordGroup } from "../substreams-XDNgDvRJ.cjs";
2
2
  import { ContentSheetCellComment } from "document-schema.js";
3
3
  //#region src/workbook/comments.d.ts
4
4
  /** One comment, resolved to the cell position it is anchored to. */
@@ -7,7 +7,12 @@ interface SheetCellComment {
7
7
  readonly column: number;
8
8
  readonly comment: ContentSheetCellComment;
9
9
  }
10
+ /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "what kind of drawing object is this, and what id does a following TxO/other per-object record cross-reference": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj (here) and workbook/drawing.ts's own shape pairing (there) both key on. Exported for workbook/drawing.ts, which pairs each MsoDrawing shape with the Obj record immediately naming it -- the identical FtCmo structure every Obj record carries, comment-anchored or not. */
11
+ declare function readObjTypeAndId(group: RecordGroup): {
12
+ readonly ot: number;
13
+ readonly id: number;
14
+ };
10
15
  /** Every cell comment a worksheet substream's records carry, keyed `${row}:${column}` to match ooxml.js's own readSheetCellComments convention. A Note record whose idObj resolves to no Obj+TxO pair (a malformed or unusually ordered file) is skipped rather than materialised with fabricated or missing text -- this reader is tolerant of unusual record ordering elsewhere in the substream (see workbook/sheet.ts's own top comment) but a comment with no recoverable text is not real content worth keeping. */
11
16
  declare function readSheetComments(records: readonly RecordGroup[]): ReadonlyMap<string, SheetCellComment>;
12
17
  //#endregion
13
- export { SheetCellComment, readSheetComments };
18
+ export { SheetCellComment, readObjTypeAndId, readSheetComments };
@@ -1,4 +1,4 @@
1
- import { t as RecordGroup } from "../substreams-Dp5cZoUo.js";
1
+ import { t as RecordGroup } from "../substreams-CgTHx5kX.js";
2
2
  import { ContentSheetCellComment } from "document-schema.js";
3
3
  //#region src/workbook/comments.d.ts
4
4
  /** One comment, resolved to the cell position it is anchored to. */
@@ -7,7 +7,12 @@ interface SheetCellComment {
7
7
  readonly column: number;
8
8
  readonly comment: ContentSheetCellComment;
9
9
  }
10
+ /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "what kind of drawing object is this, and what id does a following TxO/other per-object record cross-reference": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj (here) and workbook/drawing.ts's own shape pairing (there) both key on. Exported for workbook/drawing.ts, which pairs each MsoDrawing shape with the Obj record immediately naming it -- the identical FtCmo structure every Obj record carries, comment-anchored or not. */
11
+ declare function readObjTypeAndId(group: RecordGroup): {
12
+ readonly ot: number;
13
+ readonly id: number;
14
+ };
10
15
  /** Every cell comment a worksheet substream's records carry, keyed `${row}:${column}` to match ooxml.js's own readSheetCellComments convention. A Note record whose idObj resolves to no Obj+TxO pair (a malformed or unusually ordered file) is skipped rather than materialised with fabricated or missing text -- this reader is tolerant of unusual record ordering elsewhere in the substream (see workbook/sheet.ts's own top comment) but a comment with no recoverable text is not real content worth keeping. */
11
16
  declare function readSheetComments(records: readonly RecordGroup[]): ReadonlyMap<string, SheetCellComment>;
12
17
  //#endregion
13
- export { SheetCellComment, readSheetComments };
18
+ export { SheetCellComment, readObjTypeAndId, readSheetComments };
@@ -23,7 +23,7 @@ function readNoteAnchor(group) {
23
23
  idObj
24
24
  };
25
25
  }
26
- /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "is this a Note object, and if so, what id does its own TxO get associated through": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj cross-references. */
26
+ /** [MS-XLS] 2.5.92 FtCmo, read only far enough to answer "what kind of drawing object is this, and what id does a following TxO/other per-object record cross-reference": ft/cb are fixed reserved values this reader does not validate, ot is the object type, id is what a Note record's idObj (here) and workbook/drawing.ts's own shape pairing (there) both key on. Exported for workbook/drawing.ts, which pairs each MsoDrawing shape with the Obj record immediately naming it -- the identical FtCmo structure every Obj record carries, comment-anchored or not. */
27
27
  function readObjTypeAndId(group) {
28
28
  const cursor = new BlockCursor(group.blocks);
29
29
  cursor.skip(4);
@@ -81,4 +81,4 @@ function readSheetComments(records) {
81
81
  return comments;
82
82
  }
83
83
  //#endregion
84
- export { readSheetComments };
84
+ export { readObjTypeAndId, readSheetComments };
@@ -1,2 +1,2 @@
1
- import { a as RawConditionalFormat12, c as RawSimpleFilterFormat, d as RawTop10Format, f as readCondFmt12Group, i as RawColorScaleFormat, l as RawTimePeriod, n as RawAboveAverageFormat, o as RawDataBarFormat, r as RawCfColor, s as RawIconSetFormat, t as CondFmt12GroupResult, u as RawTimePeriodFormat } from "../conditional-format-12-DBhe7Zo6.cjs";
1
+ import { a as RawConditionalFormat12, c as RawSimpleFilterFormat, d as RawTop10Format, f as readCondFmt12Group, i as RawColorScaleFormat, l as RawTimePeriod, n as RawAboveAverageFormat, o as RawDataBarFormat, r as RawCfColor, s as RawIconSetFormat, t as CondFmt12GroupResult, u as RawTimePeriodFormat } from "../conditional-format-12-CZ43-CR4.cjs";
2
2
  export { CondFmt12GroupResult, RawAboveAverageFormat, RawCfColor, RawColorScaleFormat, RawConditionalFormat12, RawDataBarFormat, RawIconSetFormat, RawSimpleFilterFormat, RawTimePeriod, RawTimePeriodFormat, RawTop10Format, readCondFmt12Group };
@@ -1,2 +1,2 @@
1
- import { a as RawConditionalFormat12, c as RawSimpleFilterFormat, d as RawTop10Format, f as readCondFmt12Group, i as RawColorScaleFormat, l as RawTimePeriod, n as RawAboveAverageFormat, o as RawDataBarFormat, r as RawCfColor, s as RawIconSetFormat, t as CondFmt12GroupResult, u as RawTimePeriodFormat } from "../conditional-format-12-D-X5g_O3.js";
1
+ import { a as RawConditionalFormat12, c as RawSimpleFilterFormat, d as RawTop10Format, f as readCondFmt12Group, i as RawColorScaleFormat, l as RawTimePeriod, n as RawAboveAverageFormat, o as RawDataBarFormat, r as RawCfColor, s as RawIconSetFormat, t as CondFmt12GroupResult, u as RawTimePeriodFormat } from "../conditional-format-12-Xl52VBCj.js";
2
2
  export { CondFmt12GroupResult, RawAboveAverageFormat, RawCfColor, RawColorScaleFormat, RawConditionalFormat12, RawDataBarFormat, RawIconSetFormat, RawSimpleFilterFormat, RawTimePeriod, RawTimePeriodFormat, RawTop10Format, readCondFmt12Group };
@@ -1,2 +1,2 @@
1
- import { a as parseDxfStyle, i as RawConditionalFormatStyle, n as RawConditionalFormat, o as readCondFmtGroup, r as RawConditionalFormatFill, t as CondFmtGroupResult } from "../conditional-format-Czh2oTzQ.cjs";
1
+ import { a as parseDxfStyle, i as RawConditionalFormatStyle, n as RawConditionalFormat, o as readCondFmtGroup, r as RawConditionalFormatFill, t as CondFmtGroupResult } from "../conditional-format-Bt1vRWgc.cjs";
2
2
  export { CondFmtGroupResult, RawConditionalFormat, RawConditionalFormatFill, RawConditionalFormatStyle, parseDxfStyle, readCondFmtGroup };
@@ -1,2 +1,2 @@
1
- import { a as parseDxfStyle, i as RawConditionalFormatStyle, n as RawConditionalFormat, o as readCondFmtGroup, r as RawConditionalFormatFill, t as CondFmtGroupResult } from "../conditional-format-DOdazxWe.js";
1
+ import { a as parseDxfStyle, i as RawConditionalFormatStyle, n as RawConditionalFormat, o as readCondFmtGroup, r as RawConditionalFormatFill, t as CondFmtGroupResult } from "../conditional-format-Cqcjnm7O.js";
2
2
  export { CondFmtGroupResult, RawConditionalFormat, RawConditionalFormatFill, RawConditionalFormatStyle, parseDxfStyle, readCondFmtGroup };
@@ -1,2 +1,2 @@
1
- import { n as readDv, t as RawDataValidation } from "../data-validation-DfpjUN-N.cjs";
1
+ import { n as readDv, t as RawDataValidation } from "../data-validation-lJWM9-AP.cjs";
2
2
  export { RawDataValidation, readDv };
@@ -1,2 +1,2 @@
1
- import { n as readDv, t as RawDataValidation } from "../data-validation-BXvIVU0e.js";
1
+ import { n as readDv, t as RawDataValidation } from "../data-validation-BeYpL3Nb.js";
2
2
  export { RawDataValidation, readDv };