@office-kit/xlsx 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/cell/cell.d.ts +12 -19
- package/dist/{cell-Df3cKRIl.mjs → cell-B5OUUdfI.mjs} +13 -7
- package/dist/cell-B5OUUdfI.mjs.map +1 -0
- package/dist/{cell-style-CNsET6WU.mjs → cell-style-DjKKPWDL.mjs} +2 -2
- package/dist/{cell-style-CNsET6WU.mjs.map → cell-style-DjKKPWDL.mjs.map} +1 -1
- package/dist/cell.mjs +1 -1
- package/dist/{coordinate-Bt5Gni2I.mjs → coordinate-CxC88uBk.mjs} +31 -2
- package/dist/coordinate-CxC88uBk.mjs.map +1 -0
- package/dist/{defined-names-Ctu3F6ls.mjs → defined-names-Cmp8rbvI.mjs} +2 -2
- package/dist/{defined-names-Ctu3F6ls.mjs.map → defined-names-Cmp8rbvI.mjs.map} +1 -1
- package/dist/{differential-BPKa7wXi.mjs → differential-7KGzbliB.mjs} +2 -2
- package/dist/{differential-BPKa7wXi.mjs.map → differential-7KGzbliB.mjs.map} +1 -1
- package/dist/{drawing-ZJ3h4VHD.mjs → drawing-Cv6UtInY.mjs} +2 -2
- package/dist/{drawing-ZJ3h4VHD.mjs.map → drawing-Cv6UtInY.mjs.map} +1 -1
- package/dist/drawing.mjs +1 -1
- package/dist/{escape-rnWSPpWY.mjs → escape-rA5UpibT.mjs} +26 -3
- package/dist/escape-rA5UpibT.mjs.map +1 -0
- package/dist/io/load.d.ts +28 -0
- package/dist/io.mjs +2 -2
- package/dist/{load-B1sK-LjT.mjs → load-DIdQ_zum.mjs} +66 -39
- package/dist/{load-B1sK-LjT.mjs.map → load-DIdQ_zum.mjs.map} +1 -1
- package/dist/{manifest-pLmx7KYh.mjs → manifest-BHUYpjUG.mjs} +3 -3
- package/dist/{manifest-pLmx7KYh.mjs.map → manifest-BHUYpjUG.mjs.map} +1 -1
- package/dist/node.mjs +1 -1
- package/dist/packaging.mjs +1 -1
- package/dist/{reader-DHMxLBQV.mjs → reader-pC7bxYAs.mjs} +30 -7
- package/dist/reader-pC7bxYAs.mjs.map +1 -0
- package/dist/{save-DmdWwxmw.mjs → save-ax11Gsw0.mjs} +7 -7
- package/dist/{save-DmdWwxmw.mjs.map → save-ax11Gsw0.mjs.map} +1 -1
- package/dist/schema.mjs +1 -1
- package/dist/{serialize-BC2Wu3bR.mjs → serialize-Dmb6Vtt9.mjs} +23 -6
- package/dist/serialize-Dmb6Vtt9.mjs.map +1 -0
- package/dist/{serializer-C6nm0mRJ.mjs → serializer-dhv07Z6F.mjs} +2 -2
- package/dist/{serializer-C6nm0mRJ.mjs.map → serializer-dhv07Z6F.mjs.map} +1 -1
- package/dist/streaming.mjs +103 -68
- package/dist/streaming.mjs.map +1 -1
- package/dist/styles.mjs +3 -3
- package/dist/{stylesheet-writer-oXSuGnJy.mjs → stylesheet-writer-BBYjNSMA.mjs} +184 -113
- package/dist/stylesheet-writer-BBYjNSMA.mjs.map +1 -0
- package/dist/{table-BrP0RwUd.mjs → table-BFi2WmgG.mjs} +2 -2
- package/dist/{table-BrP0RwUd.mjs.map → table-BFi2WmgG.mjs.map} +1 -1
- package/dist/utils/cell-number.d.ts +10 -0
- package/dist/utils/coordinate.d.ts +11 -0
- package/dist/utils/escape.d.ts +17 -0
- package/dist/utils/xsd-boolean.d.ts +9 -0
- package/dist/utils.mjs +2 -2
- package/dist/{workbook-DOTFzCpz.mjs → workbook-CMel6UcI.mjs} +7 -7
- package/dist/{workbook-DOTFzCpz.mjs.map → workbook-CMel6UcI.mjs.map} +1 -1
- package/dist/workbook.mjs +2 -2
- package/dist/{worksheet-B2NOQ6dM.mjs → worksheet-Cxn2c-jz.mjs} +3 -3
- package/dist/{worksheet-B2NOQ6dM.mjs.map → worksheet-Cxn2c-jz.mjs.map} +1 -1
- package/dist/worksheet.mjs +2 -2
- package/dist/xml.mjs +2 -2
- package/dist/zip.mjs +1 -1
- package/package.json +1 -1
- package/dist/cell-Df3cKRIl.mjs.map +0 -1
- package/dist/coordinate-Bt5Gni2I.mjs.map +0 -1
- package/dist/escape-rnWSPpWY.mjs.map +0 -1
- package/dist/reader-DHMxLBQV.mjs.map +0 -1
- package/dist/serialize-BC2Wu3bR.mjs.map +0 -1
- package/dist/stylesheet-writer-oXSuGnJy.mjs.map +0 -1
package/dist/streaming.mjs
CHANGED
|
@@ -1,42 +1,20 @@
|
|
|
1
1
|
import { i as OpenXmlIoError, o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
|
-
import { s as coordinateToTuple } from "./coordinate-
|
|
2
|
+
import { _ as rowNumberFromAttr, c as derivedRowNumber, s as coordinateToTuple } from "./coordinate-CxC88uBk.mjs";
|
|
3
3
|
import { t as ERROR_CODES } from "./inference-BMvv9cUY.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { _ as ARC_WORKBOOK_RELS,
|
|
6
|
-
import { t as stylesheetToBytes, v as serializeCell } from "./stylesheet-writer-
|
|
4
|
+
import { a as unescapeCellString, n as escapeXmlAttr } from "./escape-rA5UpibT.mjs";
|
|
5
|
+
import { _ as ARC_WORKBOOK_RELS, c as ARC_CONTENT_TYPES, f as ARC_ROOT_RELS, ft as SHEET_MAIN_NS, g as ARC_WORKBOOK, lt as REL_NS, m as ARC_STYLE, p as ARC_SHARED_STRINGS, pt as STYLES_TYPE, ut as SHARED_STRINGS_TYPE, wt as XLSX_TYPE, yt as WORKSHEET_TYPE } from "./tree-BX-sRRVp.mjs";
|
|
6
|
+
import { t as stylesheetToBytes, v as serializeCell, x as parseCellNumber } from "./stylesheet-writer-BBYjNSMA.mjs";
|
|
7
7
|
import { t as parseXml } from "./parser-By6RWZVW.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { t as
|
|
8
|
+
import { r as parseXsdBoolean } from "./serialize-Dmb6Vtt9.mjs";
|
|
9
|
+
import { $ as findByType, Q as findById, a as makeManifest, n as addOverride, nt as relsFromBytes, o as manifestFromBytes, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships } from "./manifest-BHUYpjUG.mjs";
|
|
10
|
+
import { ct as buildXfPatch, ht as makeStylesheet, it as addCellXf, lt as defaultCellXf } from "./cell-style-DjKKPWDL.mjs";
|
|
11
|
+
import { A as serializeRichString, D as makeSharedStrings, S as validateSheetTitle, k as parseSharedStringsXml } from "./workbook-CMel6UcI.mjs";
|
|
12
|
+
import { a as parseDate1904, c as resolveRelTarget, l as parseStylesheetXml, n as SHARED_STRINGS_PART, o as parseSheetEntries, r as STYLES_PART, s as readOptionalWorkbookPart, t as OFFICE_DOC_REL_TYPE } from "./load-DIdQ_zum.mjs";
|
|
13
|
+
import { t as openZip } from "./reader-pC7bxYAs.mjs";
|
|
13
14
|
import { t as utf8ByteLength } from "./utf8-OAkCDG5g.mjs";
|
|
14
15
|
import { t as createZipWriter } from "./writer-C38RBZCy.mjs";
|
|
15
16
|
import { t as iterParse } from "./iterparse-DZE0zy2M.mjs";
|
|
16
17
|
//#region src/streaming/read-only.ts
|
|
17
|
-
const SHEET_TAG = `{${SHEET_MAIN_NS}}sheet`;
|
|
18
|
-
const SHEETS_TAG = `{${SHEET_MAIN_NS}}sheets`;
|
|
19
|
-
const parseSheetList = (root, workbookPath, archive) => {
|
|
20
|
-
const sheetsEl = findChild(root, SHEETS_TAG);
|
|
21
|
-
if (!sheetsEl) return [];
|
|
22
|
-
const wbRelsPath = relsPathFor(workbookPath);
|
|
23
|
-
const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : { rels: [] };
|
|
24
|
-
const out = [];
|
|
25
|
-
for (const sheet of findChildren(sheetsEl, SHEET_TAG)) {
|
|
26
|
-
const name = sheet.attrs["name"];
|
|
27
|
-
const rId = sheet.attrs[`{${REL_NS}}id`];
|
|
28
|
-
if (!name || !rId) continue;
|
|
29
|
-
const rel = findById(wbRels, rId);
|
|
30
|
-
if (!rel) continue;
|
|
31
|
-
const partPath = resolveRelTarget(workbookPath, rel.target);
|
|
32
|
-
out.push({
|
|
33
|
-
name,
|
|
34
|
-
rId,
|
|
35
|
-
partPath
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return out;
|
|
39
|
-
};
|
|
40
18
|
const relsPathFor = (partPath) => {
|
|
41
19
|
const i = partPath.lastIndexOf("/");
|
|
42
20
|
if (i < 0) return `_rels/${partPath}.rels`;
|
|
@@ -46,16 +24,16 @@ const localName = (qname) => {
|
|
|
46
24
|
const i = qname.lastIndexOf("}");
|
|
47
25
|
return i < 0 ? qname : qname.slice(i + 1);
|
|
48
26
|
};
|
|
49
|
-
const decodeCellValue = (t, vText, inlineText, sst) => {
|
|
27
|
+
const decodeCellValue = (t, vText, inlineText, sst, sheet, col, row) => {
|
|
50
28
|
switch (t) {
|
|
51
|
-
case "n": return vText
|
|
29
|
+
case "n": return parseCellNumber(vText, sheet, col, row);
|
|
52
30
|
case "s": {
|
|
53
31
|
if (vText === void 0) return null;
|
|
54
32
|
const idx = Number.parseInt(vText, 10);
|
|
55
33
|
if (!Number.isInteger(idx) || idx < 0 || idx >= sst.length) return null;
|
|
56
34
|
return sst[idx] ?? null;
|
|
57
35
|
}
|
|
58
|
-
case "b": return vText
|
|
36
|
+
case "b": return parseXsdBoolean(vText) ?? null;
|
|
59
37
|
case "e":
|
|
60
38
|
if (!vText || !ERROR_CODES.has(vText)) return null;
|
|
61
39
|
return {
|
|
@@ -72,14 +50,28 @@ const decodeCellValue = (t, vText, inlineText, sst) => {
|
|
|
72
50
|
* stream that yields them), yielding one `ReadOnlyCell[]` per row that matches
|
|
73
51
|
* `opts`.
|
|
74
52
|
*/
|
|
75
|
-
async function* iterSheetRows(sheetInput, sst, opts) {
|
|
53
|
+
async function* iterSheetRows(title, sheetInput, sst, opts) {
|
|
76
54
|
const minRow = opts.minRow ?? 1;
|
|
77
55
|
const maxRow = opts.maxRow ?? Number.POSITIVE_INFINITY;
|
|
78
56
|
const minCol = opts.minCol ?? 1;
|
|
79
57
|
const maxCol = opts.maxCol ?? Number.POSITIVE_INFINITY;
|
|
80
58
|
let inSheetData = false;
|
|
81
59
|
let currentRow = -1;
|
|
60
|
+
let nextRow = 1;
|
|
82
61
|
let currentCells = [];
|
|
62
|
+
let nextCol = 1;
|
|
63
|
+
let pendingCells = [];
|
|
64
|
+
const settleRow = (row) => {
|
|
65
|
+
currentRow = row;
|
|
66
|
+
nextRow = Math.max(nextRow, row + 1);
|
|
67
|
+
if (row >= minRow && row <= maxRow) for (const cell of pendingCells) currentCells.push({
|
|
68
|
+
row,
|
|
69
|
+
col: cell.col,
|
|
70
|
+
value: decodeCellValue(cell.type, cell.text, cell.inline, sst, title, cell.col, row),
|
|
71
|
+
styleId: cell.styleId
|
|
72
|
+
});
|
|
73
|
+
pendingCells = [];
|
|
74
|
+
};
|
|
83
75
|
let cellOpen = false;
|
|
84
76
|
let cellRow = 0;
|
|
85
77
|
let cellCol = 0;
|
|
@@ -101,28 +93,35 @@ async function* iterSheetRows(sheetInput, sst, opts) {
|
|
|
101
93
|
}
|
|
102
94
|
switch (local) {
|
|
103
95
|
case "row": {
|
|
104
|
-
e.attrs;
|
|
105
96
|
const rRaw = e.attrs["r"];
|
|
106
|
-
|
|
97
|
+
if (rRaw === void 0) currentRow = 0;
|
|
98
|
+
else {
|
|
99
|
+
currentRow = rowNumberFromAttr(rRaw, "loadWorkbookStream");
|
|
100
|
+
nextRow = Math.max(nextRow, currentRow + 1);
|
|
101
|
+
}
|
|
107
102
|
currentCells = [];
|
|
103
|
+
pendingCells = [];
|
|
104
|
+
nextCol = 1;
|
|
108
105
|
break;
|
|
109
106
|
}
|
|
110
107
|
case "c": {
|
|
111
108
|
if (currentRow < 0) break;
|
|
112
|
-
|
|
109
|
+
const ref = e.attrs["r"];
|
|
110
|
+
if (currentRow === 0 && ref) settleRow(coordinateToTuple(ref).row);
|
|
111
|
+
if (currentRow !== 0 && (currentRow < minRow || currentRow > maxRow)) break;
|
|
113
112
|
cellOpen = true;
|
|
114
113
|
cellType = e.attrs["t"] ?? "n";
|
|
115
114
|
const sRaw = e.attrs["s"];
|
|
116
115
|
cellStyleId = sRaw ? Number.parseInt(sRaw, 10) || 0 : 0;
|
|
117
|
-
const ref = e.attrs["r"];
|
|
118
116
|
if (ref) {
|
|
119
117
|
const tup = coordinateToTuple(ref);
|
|
120
118
|
cellRow = tup.row;
|
|
121
119
|
cellCol = tup.col;
|
|
122
120
|
} else {
|
|
123
121
|
cellRow = currentRow;
|
|
124
|
-
cellCol =
|
|
122
|
+
cellCol = nextCol;
|
|
125
123
|
}
|
|
124
|
+
nextCol = cellCol + 1;
|
|
126
125
|
vText = "";
|
|
127
126
|
isText = "";
|
|
128
127
|
break;
|
|
@@ -155,6 +154,7 @@ async function* iterSheetRows(sheetInput, sst, opts) {
|
|
|
155
154
|
inSheetData = false;
|
|
156
155
|
return;
|
|
157
156
|
case "row":
|
|
157
|
+
if (currentRow === 0) settleRow(derivedRowNumber(nextRow, "loadWorkbookStream"));
|
|
158
158
|
if (currentRow >= minRow && currentRow <= maxRow && currentCells.length > 0) yield currentCells;
|
|
159
159
|
if (currentRow > maxRow) {
|
|
160
160
|
inSheetData = false;
|
|
@@ -164,8 +164,15 @@ async function* iterSheetRows(sheetInput, sst, opts) {
|
|
|
164
164
|
currentCells = [];
|
|
165
165
|
break;
|
|
166
166
|
case "c":
|
|
167
|
-
if (cellOpen &&
|
|
168
|
-
|
|
167
|
+
if (cellOpen && cellRow === 0 && cellCol >= minCol && cellCol <= maxCol) pendingCells.push({
|
|
168
|
+
col: cellCol,
|
|
169
|
+
type: cellType,
|
|
170
|
+
text: vText,
|
|
171
|
+
inline: isText,
|
|
172
|
+
styleId: cellStyleId
|
|
173
|
+
});
|
|
174
|
+
else if (cellOpen && cellCol >= minCol && cellCol <= maxCol && cellRow >= minRow && cellRow <= maxRow) {
|
|
175
|
+
const value = decodeCellValue(cellType, vText, isText, sst, title, cellCol, cellRow);
|
|
169
176
|
currentCells.push({
|
|
170
177
|
row: cellRow,
|
|
171
178
|
col: cellCol,
|
|
@@ -194,7 +201,9 @@ async function* iterSheetRows(sheetInput, sst, opts) {
|
|
|
194
201
|
const isXmlSpace = (b) => b === 32 || b === 9 || b === 10 || b === 13;
|
|
195
202
|
/**
|
|
196
203
|
* Read the `r="N"` row number out of a `<row …>` attribute region, scanning
|
|
197
|
-
* bytes directly. Returns -1 when the attribute is absent or
|
|
204
|
+
* bytes directly. Returns -1 when the attribute is absent, or holds anything
|
|
205
|
+
* `parseRowNumberAttr` rejects: the two accept the same shapes, so the index
|
|
206
|
+
* can never seek by a number the SAX walk reads differently.
|
|
198
207
|
*
|
|
199
208
|
* Decoding the region to a string and running a regex instead costs one
|
|
200
209
|
* TextDecoder, one string and one match array per row, which on a million-row
|
|
@@ -204,9 +213,11 @@ const readRowAttr = (bytes, from, to) => {
|
|
|
204
213
|
for (let p = from; p + 3 < to; p++) {
|
|
205
214
|
if (!isXmlSpace(bytes[p])) continue;
|
|
206
215
|
if (bytes[p + 1] !== 114 || bytes[p + 2] !== 61 || bytes[p + 3] !== 34) continue;
|
|
216
|
+
let q = p + 4;
|
|
217
|
+
while (q < to && isXmlSpace(bytes[q])) q++;
|
|
218
|
+
if (bytes[q] === 43) q++;
|
|
207
219
|
let value = 0;
|
|
208
220
|
let digits = 0;
|
|
209
|
-
let q = p + 4;
|
|
210
221
|
while (q < to) {
|
|
211
222
|
const d = bytes[q];
|
|
212
223
|
if (d === void 0 || d < 48 || d > 57) break;
|
|
@@ -214,7 +225,8 @@ const readRowAttr = (bytes, from, to) => {
|
|
|
214
225
|
digits++;
|
|
215
226
|
q++;
|
|
216
227
|
}
|
|
217
|
-
|
|
228
|
+
while (q < to && isXmlSpace(bytes[q])) q++;
|
|
229
|
+
if (digits > 0 && value >= 1 && value <= 1048576 && q < to && bytes[q] === 34) return value;
|
|
218
230
|
}
|
|
219
231
|
return -1;
|
|
220
232
|
};
|
|
@@ -277,9 +289,14 @@ const findSheetDataTagEnd = (bytes) => {
|
|
|
277
289
|
* `sheetDataEnd` is the byte offset of `</sheetData>` so callers can clip the
|
|
278
290
|
* region that gets handed to saxes. `sheetDataTagEnd` includes the original
|
|
279
291
|
* namespace-bearing ancestor tags, reused by {@link replayFromRow}.
|
|
292
|
+
*
|
|
293
|
+
* `hasUnnumberedRow` reports a `<row>` this scan cannot number, which makes the
|
|
294
|
+
* whole sheet unseekable: a row without `@r` takes the row its first cell
|
|
295
|
+
* names, and reading cell refs is the SAX walk's job.
|
|
280
296
|
*/
|
|
281
297
|
const buildRowOffsetIndex = (bytes) => {
|
|
282
298
|
const out = [];
|
|
299
|
+
let hasUnnumberedRow = false;
|
|
283
300
|
let sheetDataEnd = -1;
|
|
284
301
|
let i = 0;
|
|
285
302
|
while (i < bytes.length) {
|
|
@@ -309,13 +326,15 @@ const buildRowOffsetIndex = (bytes) => {
|
|
|
309
326
|
row,
|
|
310
327
|
offset: start
|
|
311
328
|
});
|
|
329
|
+
else hasUnnumberedRow = true;
|
|
312
330
|
i = j + 1;
|
|
313
331
|
}
|
|
314
332
|
if (sheetDataEnd < 0) sheetDataEnd = bytes.length;
|
|
315
333
|
return {
|
|
316
334
|
index: out,
|
|
317
335
|
sheetDataEnd,
|
|
318
|
-
sheetDataTagEnd: findSheetDataTagEnd(bytes)
|
|
336
|
+
sheetDataTagEnd: findSheetDataTagEnd(bytes),
|
|
337
|
+
hasUnnumberedRow
|
|
319
338
|
};
|
|
320
339
|
};
|
|
321
340
|
/**
|
|
@@ -365,7 +384,9 @@ const replayFromRow = (bytes, sheetDataTagEnd, fromOffset, sheetDataEnd) => {
|
|
|
365
384
|
* `iterRows({ minRow > 1 })` needs random access instead, so the first band
|
|
366
385
|
* query inflates the part and indexes its row offsets, and holds both for the
|
|
367
386
|
* life of the worksheet handle or until the workbook closes. Subsequent band
|
|
368
|
-
* queries jump straight to the first matching row without inflating or scanning
|
|
387
|
+
* queries jump straight to the first matching row without inflating or scanning
|
|
388
|
+
* again. A sheet whose rows omit `@r` cannot be indexed by row number, so its
|
|
389
|
+
* band queries keep streaming and hold nothing.
|
|
369
390
|
*/
|
|
370
391
|
const makeStreamingReadOnlyWorksheet = (title, archive, partPath, sst, indexes) => {
|
|
371
392
|
const cacheKey = {};
|
|
@@ -373,9 +394,13 @@ const makeStreamingReadOnlyWorksheet = (title, archive, partPath, sst, indexes)
|
|
|
373
394
|
let cached = indexes.byWorksheet.get(cacheKey);
|
|
374
395
|
if (!cached) {
|
|
375
396
|
const bytes = archive.read(partPath);
|
|
376
|
-
|
|
397
|
+
const { hasUnnumberedRow, index, sheetDataEnd, sheetDataTagEnd } = buildRowOffsetIndex(bytes);
|
|
398
|
+
cached = hasUnnumberedRow ? { seekable: false } : {
|
|
399
|
+
seekable: true,
|
|
377
400
|
bytes,
|
|
378
|
-
|
|
401
|
+
index,
|
|
402
|
+
sheetDataEnd,
|
|
403
|
+
sheetDataTagEnd
|
|
379
404
|
};
|
|
380
405
|
indexes.byWorksheet.set(cacheKey, cached);
|
|
381
406
|
}
|
|
@@ -383,14 +408,16 @@ const makeStreamingReadOnlyWorksheet = (title, archive, partPath, sst, indexes)
|
|
|
383
408
|
};
|
|
384
409
|
const iterRows = (opts = {}) => {
|
|
385
410
|
const minRow = opts.minRow ?? 1;
|
|
386
|
-
if (minRow <= 1) return iterSheetRows(archive.readStream(partPath), sst, opts);
|
|
387
|
-
const
|
|
388
|
-
if (
|
|
411
|
+
if (minRow <= 1) return iterSheetRows(title, archive.readStream(partPath), sst, opts);
|
|
412
|
+
const seek = ensureIndexed();
|
|
413
|
+
if (!seek.seekable) return iterSheetRows(title, archive.readStream(partPath), sst, opts);
|
|
414
|
+
const { bytes, index, sheetDataEnd, sheetDataTagEnd } = seek;
|
|
415
|
+
if (index.length === 0 || sheetDataTagEnd < 0) return iterSheetRows(title, bytes, sst, opts);
|
|
389
416
|
const pos = firstRowAtOrAfter(index, minRow);
|
|
390
417
|
if (pos < 0) return (async function* () {})();
|
|
391
418
|
const target = index[pos];
|
|
392
|
-
if (!target) return iterSheetRows(bytes, sst, opts);
|
|
393
|
-
return iterSheetRows(replayFromRow(bytes, sheetDataTagEnd, target.offset, sheetDataEnd), sst, opts);
|
|
419
|
+
if (!target) return iterSheetRows(title, bytes, sst, opts);
|
|
420
|
+
return iterSheetRows(title, replayFromRow(bytes, sheetDataTagEnd, target.offset, sheetDataEnd), sst, opts);
|
|
394
421
|
};
|
|
395
422
|
const iterValues = async function* (opts = {}) {
|
|
396
423
|
for await (const row of iterRows(opts)) yield row.map((c) => c.value);
|
|
@@ -406,16 +433,16 @@ const makeStreamingReadOnlyWorksheet = (title, archive, partPath, sst, indexes)
|
|
|
406
433
|
* sheet list / styles / shared strings. Per the project-wide "no classes" rule
|
|
407
434
|
* (CLAUDE.md), the workbook is a plain object closing over the archive handle.
|
|
408
435
|
*/
|
|
409
|
-
const makeStreamingReadOnlyWorkbook = (sheetNames, styles, date1904, archive,
|
|
436
|
+
const makeStreamingReadOnlyWorkbook = (sheetNames, styles, date1904, archive, partPathByName, sst) => {
|
|
410
437
|
const indexes = { byWorksheet: /* @__PURE__ */ new WeakMap() };
|
|
411
438
|
return {
|
|
412
439
|
sheetNames,
|
|
413
440
|
styles,
|
|
414
441
|
date1904,
|
|
415
442
|
openWorksheet(name) {
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
return makeStreamingReadOnlyWorksheet(name, archive,
|
|
443
|
+
const partPath = partPathByName.get(name);
|
|
444
|
+
if (partPath === void 0) throw new OpenXmlSchemaError(`loadWorkbookStream: no worksheet named "${name}"`);
|
|
445
|
+
return makeStreamingReadOnlyWorksheet(name, archive, partPath, sst, indexes);
|
|
419
446
|
},
|
|
420
447
|
async close() {
|
|
421
448
|
archive.close();
|
|
@@ -429,19 +456,27 @@ async function loadWorkbookStream(source, opts = {}) {
|
|
|
429
456
|
if (!archive.has("[Content_Types].xml")) throw new OpenXmlSchemaError(`loadWorkbookStream: missing "${ARC_CONTENT_TYPES}"`);
|
|
430
457
|
manifestFromBytes(archive.read(ARC_CONTENT_TYPES));
|
|
431
458
|
if (!archive.has(ARC_ROOT_RELS)) throw new OpenXmlSchemaError(`loadWorkbookStream: missing "${ARC_ROOT_RELS}"`);
|
|
432
|
-
const officeDocRel = relsFromBytes(archive.read(ARC_ROOT_RELS))
|
|
459
|
+
const officeDocRel = findByType(relsFromBytes(archive.read(ARC_ROOT_RELS)), OFFICE_DOC_REL_TYPE);
|
|
433
460
|
if (!officeDocRel) throw new OpenXmlSchemaError(`loadWorkbookStream: no officeDocument relationship in root rels`);
|
|
434
461
|
const workbookPath = resolveRelTarget("", officeDocRel.target);
|
|
435
462
|
if (!archive.has(workbookPath)) throw new OpenXmlSchemaError(`loadWorkbookStream: workbook part "${workbookPath}" missing`);
|
|
436
463
|
const workbookRoot = parseXml(archive.read(workbookPath));
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
464
|
+
const declaredSheets = parseSheetEntries(workbookRoot);
|
|
465
|
+
const wbRelsPath = relsPathFor(workbookPath);
|
|
466
|
+
if (declaredSheets.length > 0 && !archive.has(wbRelsPath)) throw new OpenXmlSchemaError(`loadWorkbookStream: workbook has sheets but rels part "${wbRelsPath}" is missing`);
|
|
467
|
+
const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : makeRelationships();
|
|
468
|
+
const partPathByName = /* @__PURE__ */ new Map();
|
|
469
|
+
for (const declared of declaredSheets) {
|
|
470
|
+
if (partPathByName.has(declared.name)) throw new OpenXmlSchemaError(`loadWorkbookStream: duplicate sheet name "${declared.name}"`);
|
|
471
|
+
const rel = findById(wbRels, declared.rId);
|
|
472
|
+
if (!rel) throw new OpenXmlSchemaError(`loadWorkbookStream: sheet "${declared.name}" rId "${declared.rId}" has no matching rels entry`);
|
|
473
|
+
partPathByName.set(declared.name, resolveRelTarget(workbookPath, rel.target));
|
|
474
|
+
}
|
|
475
|
+
const sstBytes = readOptionalWorkbookPart(archive, workbookPath, wbRels, SHARED_STRINGS_PART);
|
|
476
|
+
const sst = sstBytes === void 0 ? makeSharedStrings() : parseSharedStringsXml(sstBytes);
|
|
477
|
+
const stylesBytes = readOptionalWorkbookPart(archive, workbookPath, wbRels, STYLES_PART);
|
|
478
|
+
const styles = stylesBytes === void 0 ? makeStylesheet() : parseStylesheetXml(stylesBytes);
|
|
479
|
+
return makeStreamingReadOnlyWorkbook(declaredSheets.map((e) => e.name), styles, parseDate1904(workbookRoot), archive, partPathByName, sst.entries.map((e) => typeof e === "string" ? e : e.runs.map((r) => r.text).join("")));
|
|
445
480
|
}
|
|
446
481
|
//#endregion
|
|
447
482
|
//#region src/streaming/string-table.ts
|