xls-codec 1.0.2 → 2.0.1
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 +128 -23
- package/dist/biff/bof-writer.cjs +18 -0
- package/dist/biff/bof-writer.d.cts +5 -0
- package/dist/biff/bof-writer.d.ts +5 -0
- package/dist/biff/bof-writer.js +17 -0
- package/dist/biff/builder.cjs +48 -0
- package/dist/biff/builder.d.cts +17 -0
- package/dist/biff/builder.d.ts +17 -0
- package/dist/biff/builder.js +47 -0
- package/dist/biff/cursor.cjs +4 -0
- package/dist/biff/cursor.d.cts +1 -27
- package/dist/biff/cursor.d.ts +1 -27
- package/dist/biff/cursor.js +4 -0
- package/dist/biff/errors.cjs +7 -0
- package/dist/biff/errors.d.cts +3 -1
- package/dist/biff/errors.d.ts +3 -1
- package/dist/biff/errors.js +7 -1
- package/dist/biff/print-setup.cjs +108 -0
- package/dist/biff/print-setup.d.cts +2 -0
- package/dist/biff/print-setup.d.ts +2 -0
- package/dist/biff/print-setup.js +103 -0
- package/dist/biff/ptg-functions.cjs +383 -0
- package/dist/biff/ptg-functions.d.cts +7 -0
- package/dist/biff/ptg-functions.d.ts +7 -0
- package/dist/biff/ptg-functions.js +381 -0
- package/dist/biff/ptg.cjs +319 -0
- package/dist/biff/ptg.d.cts +2 -0
- package/dist/biff/ptg.d.ts +2 -0
- package/dist/biff/ptg.js +318 -0
- package/dist/biff/record-types.cjs +60 -0
- package/dist/biff/record-types.d.cts +41 -1
- package/dist/biff/record-types.d.ts +41 -1
- package/dist/biff/record-types.js +41 -1
- package/dist/biff/record-writer.cjs +29 -0
- package/dist/biff/record-writer.d.cts +7 -0
- package/dist/biff/record-writer.d.ts +7 -0
- package/dist/biff/record-writer.js +27 -0
- package/dist/biff/string-writer.cjs +58 -0
- package/dist/biff/string-writer.d.cts +13 -0
- package/dist/biff/string-writer.d.ts +13 -0
- package/dist/biff/string-writer.js +55 -0
- package/dist/biff/strings.d.cts +1 -1
- package/dist/biff/strings.d.ts +1 -1
- package/dist/biff/substreams.d.cts +1 -20
- package/dist/biff/substreams.d.ts +1 -20
- package/dist/biff/write-errors.cjs +10 -0
- package/dist/biff/write-errors.d.cts +6 -0
- package/dist/biff/write-errors.d.ts +6 -0
- package/dist/biff/write-errors.js +9 -0
- package/dist/biff/xf-colors.cjs +374 -0
- package/dist/biff/xf-colors.d.cts +2 -0
- package/dist/biff/xf-colors.d.ts +2 -0
- package/dist/biff/xf-colors.js +339 -0
- package/dist/biff/xf-writer.cjs +96 -0
- package/dist/biff/xf-writer.d.cts +29 -0
- package/dist/biff/xf-writer.d.ts +29 -0
- package/dist/biff/xf-writer.js +90 -0
- package/dist/container.cjs +13 -4
- package/dist/container.d.cts +10 -3
- package/dist/container.d.ts +10 -3
- package/dist/container.js +12 -4
- package/dist/content.cjs +123 -18
- package/dist/content.js +123 -18
- package/dist/cursor-VMtw9uVP.d.cts +30 -0
- package/dist/cursor-VMtw9uVP.d.ts +30 -0
- package/dist/index.cjs +71 -5
- package/dist/index.d.cts +20 -10
- package/dist/index.d.ts +20 -10
- package/dist/index.js +17 -7
- package/dist/metadata.cjs +14 -0
- package/dist/metadata.d.cts +6 -0
- package/dist/metadata.d.ts +6 -0
- package/dist/metadata.js +13 -0
- package/dist/print-names-D-njuzVw.d.cts +41 -0
- package/dist/print-names-DUlpVE00.d.ts +41 -0
- package/dist/print-setup-B_ihDvm5.d.cts +57 -0
- package/dist/print-setup-B_ihDvm5.d.ts +57 -0
- package/dist/ptg-B2K8t3js.d.cts +21 -0
- package/dist/ptg-B2K8t3js.d.ts +21 -0
- package/dist/serial.cjs +41 -0
- package/dist/serial.d.cts +7 -1
- package/dist/serial.d.ts +7 -1
- package/dist/serial.js +39 -1
- package/dist/substreams-D7dQiJbp.d.ts +21 -0
- package/dist/substreams-Ddtvn_Vr.d.cts +21 -0
- package/dist/units.cjs +37 -0
- package/dist/units.d.cts +15 -1
- package/dist/units.d.ts +15 -1
- package/dist/units.js +33 -1
- package/dist/workbook/globals-writer.cjs +122 -0
- package/dist/workbook/globals-writer.d.cts +39 -0
- package/dist/workbook/globals-writer.d.ts +39 -0
- package/dist/workbook/globals-writer.js +120 -0
- package/dist/workbook/globals.cjs +72 -8
- package/dist/workbook/globals.d.cts +26 -2
- package/dist/workbook/globals.d.ts +26 -2
- package/dist/workbook/globals.js +71 -7
- package/dist/workbook/print-names.cjs +241 -0
- package/dist/workbook/print-names.d.cts +2 -0
- package/dist/workbook/print-names.d.ts +2 -0
- package/dist/workbook/print-names.js +238 -0
- package/dist/workbook/sheet-writer.cjs +277 -0
- package/dist/workbook/sheet-writer.d.cts +12 -0
- package/dist/workbook/sheet-writer.d.ts +12 -0
- package/dist/workbook/sheet-writer.js +276 -0
- package/dist/workbook/sheet.cjs +125 -17
- package/dist/workbook/sheet.d.cts +38 -4
- package/dist/workbook/sheet.d.ts +38 -4
- package/dist/workbook/sheet.js +125 -17
- package/dist/write.cjs +311 -0
- package/dist/write.d.cts +13 -0
- package/dist/write.d.ts +13 -0
- package/dist/write.js +309 -0
- package/dist/written-cells.cjs +26 -0
- package/dist/written-cells.d.cts +16 -0
- package/dist/written-cells.d.ts +16 -0
- package/dist/written-cells.js +24 -0
- package/dist/xf-colors-CehHZtBy.d.cts +91 -0
- package/dist/xf-colors-CpykR3B9.d.ts +91 -0
- package/package.json +4 -3
- package/dist/number-format.cjs +0 -298
- package/dist/number-format.d.cts +0 -32
- package/dist/number-format.d.ts +0 -32
- package/dist/number-format.js +0 -296
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { RECORD_BOF } from "../biff/record-types.js";
|
|
2
|
+
import { RecordBuilder } from "../biff/builder.js";
|
|
3
|
+
import { concatRecords, writeRecord } from "../biff/record-writer.js";
|
|
4
|
+
import { writePrintNameRecords } from "./print-names.js";
|
|
5
|
+
import { writeBofData } from "../biff/bof-writer.js";
|
|
6
|
+
import { writeRichExtendedString, writeShortXLUnicodeString } from "../biff/string-writer.js";
|
|
7
|
+
import { writeCellXfRecord, writeFontRecord, writeFormatRecord, writePaletteRecord, writeStyleRecord, writeStyleXfRecord } from "../biff/xf-writer.js";
|
|
8
|
+
//#region src/workbook/globals-writer.ts
|
|
9
|
+
const GENERAL_FORMAT_ID = 0;
|
|
10
|
+
const NORMAL_FONT_INDEX = 0;
|
|
11
|
+
const NORMAL_FONT_NAME = "Arial";
|
|
12
|
+
/** Excel 97-2003's own Normal-style default: 10pt, in twips (dyHeight's own unit, [MS-XLS] 2.4.122). */
|
|
13
|
+
const NORMAL_FONT_HEIGHT_TWIPS = 200;
|
|
14
|
+
/** [MS-XLS] "BuiltInStyle" istyBuiltIn values (ECMA-376 Part 1 18.8.7's cellStyle builtinId table): 0 Normal, 1 RowLevel, 2 ColLevel -- the only three this writer emits, since it never groups rows/columns into an outline. */
|
|
15
|
+
const BUILTIN_STYLE_NORMAL = 0;
|
|
16
|
+
const BUILTIN_STYLE_ROW_LEVEL = 1;
|
|
17
|
+
const BUILTIN_STYLE_COL_LEVEL = 2;
|
|
18
|
+
/** BuiltInStyle's own iLevel sentinel for a style other than RowLevel/ColLevel: "otherwise, this value MUST be 0xFF". */
|
|
19
|
+
const NO_OUTLINE_LEVEL = 255;
|
|
20
|
+
/** RowLevel/ColLevel each cover seven outline depths ([MS-XLS] "BuiltInStyle"'s own 0x00-0x06 iLevel table). */
|
|
21
|
+
const OUTLINE_LEVEL_COUNT = 7;
|
|
22
|
+
/** The fifteen built-in cell styles, XF index 0 through 14, in the order every real Excel-written workbook carries them: Normal, then RowLevel_1..7, then ColLevel_1..7. */
|
|
23
|
+
const BUILTIN_STYLES = [
|
|
24
|
+
{
|
|
25
|
+
istyBuiltIn: BUILTIN_STYLE_NORMAL,
|
|
26
|
+
iLevel: NO_OUTLINE_LEVEL
|
|
27
|
+
},
|
|
28
|
+
...Array.from({ length: OUTLINE_LEVEL_COUNT }, (_unused, level) => ({
|
|
29
|
+
istyBuiltIn: BUILTIN_STYLE_ROW_LEVEL,
|
|
30
|
+
iLevel: level
|
|
31
|
+
})),
|
|
32
|
+
...Array.from({ length: OUTLINE_LEVEL_COUNT }, (_unused, level) => ({
|
|
33
|
+
istyBuiltIn: BUILTIN_STYLE_COL_LEVEL,
|
|
34
|
+
iLevel: level
|
|
35
|
+
}))
|
|
36
|
+
];
|
|
37
|
+
/** [MS-XLS] 2.1.7.20.3's own XFS production requires at least sixteen XF records before any cell can reference one: BUILTIN_STYLES.length built-in cell styles, then at least one cell XF -- the "General, no declared format" one every workbook needs unconditionally, written immediately after them. Derived from BUILTIN_STYLES's own length rather than restated as a literal, so the two can never drift apart. */
|
|
38
|
+
const GENERAL_CELL_XF_INDEX = BUILTIN_STYLES.length;
|
|
39
|
+
/** BoundSheet8 ([MS-XLS] 2.4.28) with lbPlyPos left at 0: a placeholder the caller patches in place, since the real value -- the byte offset of this sheet's own BOF within the finished workbook stream -- is only known once every substream's length has been measured. */
|
|
40
|
+
function writeBoundSheet8Placeholder(name) {
|
|
41
|
+
const data = new RecordBuilder().u32(0).u8(0).u8(0).bytes(writeShortXLUnicodeString(name)).build();
|
|
42
|
+
return writeRecord(133, data);
|
|
43
|
+
}
|
|
44
|
+
/** [MS-XLS] 2.4.271's own cch table: the value a self-referencing SupBook -- this workbook itself, rather than another workbook, a DDE/OLE data source, or an add-in -- carries in place of a virtual path. The one kind of supporting link this package writes, and the one kind workbook/globals.ts's own reader resolves a 3D reference through. */
|
|
45
|
+
const SUPBOOK_SELF_REFERENCING_CCH = 1025;
|
|
46
|
+
/** SupBook ([MS-XLS] 2.4.271), self-referencing: a two-byte sheet count then that cch sentinel, and nothing else -- the virtPath/rgst payload a real external link would carry has no meaning for a link that names this same workbook. */
|
|
47
|
+
function writeSupBookRecord(sheetCount) {
|
|
48
|
+
return writeRecord(430, new RecordBuilder().u16(sheetCount).u16(SUPBOOK_SELF_REFERENCING_CCH).build());
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* ExternSheet ([MS-XLS] 2.4.106): a two-byte cXTI then that many XTI structures ([MS-XLS] 2.5.344), each an iSupBook and a signed itabFirst/itabLast sheet-scope pair -- the write-side mirror of workbook/globals.ts's own readSheetRanges.
|
|
52
|
+
*
|
|
53
|
+
* One XTI per sheet, each scoped to that one sheet and pointing at the single self-referencing SupBook above, so a print name's own PtgArea3d can name its sheet by using that sheet's index as its ixti. The 3D reference machinery exists here purely because [MS-XLS] gives a defined name no other way to say which sheet its range is on.
|
|
54
|
+
*/
|
|
55
|
+
function writeExternSheetRecord(sheetCount) {
|
|
56
|
+
const builder = new RecordBuilder().u16(sheetCount);
|
|
57
|
+
for (let sheetIndex = 0; sheetIndex < sheetCount; sheetIndex += 1) builder.u16(0).u16(sheetIndex).u16(sheetIndex);
|
|
58
|
+
return writeRecord(23, builder.build());
|
|
59
|
+
}
|
|
60
|
+
/** SST ([MS-XLS] 2.4.265): a total reference count, a unique-string count, then that many XLUnicodeRichExtendedStrings, packed with no offsets -- the write-side mirror of workbook/globals.ts's own readSharedStrings. */
|
|
61
|
+
function writeSstRecord(strings, totalCount) {
|
|
62
|
+
const builder = new RecordBuilder().i32(totalCount).i32(strings.length);
|
|
63
|
+
for (const text of strings) builder.bytes(writeRichExtendedString(text));
|
|
64
|
+
return writeRecord(252, builder.build());
|
|
65
|
+
}
|
|
66
|
+
function buildWorkbookGlobals(plan) {
|
|
67
|
+
const pieces = [];
|
|
68
|
+
let offset = 0;
|
|
69
|
+
const push = (piece) => {
|
|
70
|
+
pieces.push(piece);
|
|
71
|
+
offset += piece.length;
|
|
72
|
+
};
|
|
73
|
+
push(writeRecord(RECORD_BOF, writeBofData(5)));
|
|
74
|
+
push(writeFontRecord(NORMAL_FONT_NAME, NORMAL_FONT_HEIGHT_TWIPS));
|
|
75
|
+
for (const code of plan.customFormats) push(writeFormatRecord(code.id, code.code));
|
|
76
|
+
BUILTIN_STYLES.forEach(() => {
|
|
77
|
+
push(writeStyleXfRecord({
|
|
78
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
79
|
+
formatId: GENERAL_FORMAT_ID
|
|
80
|
+
}));
|
|
81
|
+
});
|
|
82
|
+
push(writeCellXfRecord({
|
|
83
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
84
|
+
formatId: GENERAL_FORMAT_ID
|
|
85
|
+
}));
|
|
86
|
+
for (const entry of plan.cellXfEntries) push(writeCellXfRecord({
|
|
87
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
88
|
+
formatId: entry.formatId,
|
|
89
|
+
alignment: entry.alignment,
|
|
90
|
+
verticalAlignment: entry.verticalAlignment,
|
|
91
|
+
decoration: entry.decoration
|
|
92
|
+
}));
|
|
93
|
+
BUILTIN_STYLES.forEach((builtin, index) => {
|
|
94
|
+
push(writeStyleRecord({
|
|
95
|
+
xfIndex: index,
|
|
96
|
+
istyBuiltIn: builtin.istyBuiltIn,
|
|
97
|
+
iLevel: builtin.iLevel
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
100
|
+
if (plan.paletteColors !== void 0) push(writePaletteRecord(plan.paletteColors));
|
|
101
|
+
const lbPlyPosOffsets = [];
|
|
102
|
+
for (const name of plan.sheetNames) {
|
|
103
|
+
const recordStart = offset;
|
|
104
|
+
lbPlyPosOffsets.push(recordStart + 4);
|
|
105
|
+
push(writeBoundSheet8Placeholder(name));
|
|
106
|
+
}
|
|
107
|
+
if (plan.printNames.length > 0) {
|
|
108
|
+
push(writeSupBookRecord(plan.sheetNames.length));
|
|
109
|
+
push(writeExternSheetRecord(plan.sheetNames.length));
|
|
110
|
+
for (const record of writePrintNameRecords(plan.printNames)) push(record);
|
|
111
|
+
}
|
|
112
|
+
if (plan.sharedStrings.length > 0) push(writeSstRecord(plan.sharedStrings, plan.sharedStringTotalCount));
|
|
113
|
+
push(writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
114
|
+
return {
|
|
115
|
+
bytes: concatRecords(...pieces),
|
|
116
|
+
lbPlyPosOffsets
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { GENERAL_CELL_XF_INDEX, buildWorkbookGlobals };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_biff_record_types = require("../biff/record-types.cjs");
|
|
3
3
|
const require_biff_records = require("../biff/records.cjs");
|
|
4
|
-
const
|
|
4
|
+
const require_biff_xf_colors = require("../biff/xf-colors.cjs");
|
|
5
5
|
const require_biff_cursor = require("../biff/cursor.cjs");
|
|
6
6
|
const require_biff_strings = require("../biff/strings.cjs");
|
|
7
|
+
const require_workbook_print_names = require("./print-names.cjs");
|
|
8
|
+
let excel_number_format = require("excel-number-format");
|
|
7
9
|
//#region src/workbook/globals.ts
|
|
8
10
|
/** [MS-XLS] 2.4.28's own hsState values; 0x01 is Hidden and 0x02 Very Hidden. */
|
|
9
11
|
const HIDDEN_STATE_MASK = 3;
|
|
@@ -17,8 +19,11 @@ function readWorkbookGlobals(records) {
|
|
|
17
19
|
const sheets = [];
|
|
18
20
|
const cellFormats = [];
|
|
19
21
|
const customFormats = /* @__PURE__ */ new Map();
|
|
22
|
+
const supBookSelfReferencing = [];
|
|
20
23
|
let sharedStrings = [];
|
|
21
24
|
let date1904 = false;
|
|
25
|
+
let externSheet;
|
|
26
|
+
let palette;
|
|
22
27
|
for (const record of records) switch (record.type) {
|
|
23
28
|
case 133:
|
|
24
29
|
sheets.push(readBoundSheet(record));
|
|
@@ -34,18 +39,55 @@ function readWorkbookGlobals(records) {
|
|
|
34
39
|
case 224:
|
|
35
40
|
cellFormats.push(readCellFormat(record));
|
|
36
41
|
break;
|
|
37
|
-
case 34:
|
|
42
|
+
case 34:
|
|
43
|
+
date1904 = readDate1904(record);
|
|
44
|
+
break;
|
|
45
|
+
case 430:
|
|
46
|
+
supBookSelfReferencing.push(isSelfReferencingSupBook(record));
|
|
47
|
+
break;
|
|
48
|
+
case 23:
|
|
49
|
+
externSheet = record;
|
|
50
|
+
break;
|
|
51
|
+
case 146: palette = readPalette(record);
|
|
38
52
|
}
|
|
39
|
-
const numberFormats = new Map(
|
|
53
|
+
const numberFormats = new Map(excel_number_format.BUILTIN_NUMBER_FORMATS);
|
|
40
54
|
for (const [id, code] of customFormats) numberFormats.set(id, code);
|
|
55
|
+
const sheetRanges = externSheet === void 0 ? [] : readSheetRanges(externSheet, supBookSelfReferencing);
|
|
41
56
|
return {
|
|
42
57
|
sheets,
|
|
43
58
|
sharedStrings,
|
|
44
59
|
cellFormats,
|
|
45
60
|
numberFormats,
|
|
46
|
-
date1904
|
|
61
|
+
date1904,
|
|
62
|
+
sheetRanges,
|
|
63
|
+
palette,
|
|
64
|
+
printNames: require_workbook_print_names.readPrintNames(records)
|
|
47
65
|
};
|
|
48
66
|
}
|
|
67
|
+
/** [MS-XLS] 2.4.271's own cch table: a SupBook whose cch is exactly this value is a self-referencing supporting link -- this workbook itself -- rather than another workbook, a DDE/OLE data source, or an add-in. This is the only kind of supporting link a 3D reference resolves through here; every other kind genuinely needs bytes from outside this file. */
|
|
68
|
+
const SUPBOOK_SELF_REFERENCING_CCH = 1025;
|
|
69
|
+
/** SupBook ([MS-XLS] 2.4.271): a two-byte ctab then a two-byte cch. Only cch is read here -- ctab is undefined for a self-referencing SupBook and unused for every other kind this reader does not resolve, and the virtPath/rgst payload that would follow for a non-self-referencing link is never reached. */
|
|
70
|
+
function isSelfReferencingSupBook(record) {
|
|
71
|
+
const cursor = new require_biff_cursor.BlockCursor(record.blocks);
|
|
72
|
+
cursor.skip(2);
|
|
73
|
+
return cursor.u16() === SUPBOOK_SELF_REFERENCING_CCH;
|
|
74
|
+
}
|
|
75
|
+
/** ExternSheet ([MS-XLS] 2.4.106): a two-byte cXTI then that many XTI structures ([MS-XLS] 2.5.344) -- a two-byte iSupBook and two signed 16-bit sheet-scope bounds each. iSupBook indexes the SupBook collection positionally, in the order those records appeared. */
|
|
76
|
+
function readSheetRanges(record, supBookSelfReferencing) {
|
|
77
|
+
const cursor = new require_biff_cursor.BlockCursor(record.blocks);
|
|
78
|
+
const count = cursor.u16();
|
|
79
|
+
const ranges = [];
|
|
80
|
+
for (let index = 0; index < count; index += 1) {
|
|
81
|
+
const iSupBook = cursor.u16();
|
|
82
|
+
const itabFirst = cursor.i16();
|
|
83
|
+
const itabLast = cursor.i16();
|
|
84
|
+
ranges.push((supBookSelfReferencing[iSupBook] ?? false) && itabFirst >= 0 && itabLast >= 0 ? {
|
|
85
|
+
firstSheetIndex: itabFirst,
|
|
86
|
+
lastSheetIndex: itabLast
|
|
87
|
+
} : void 0);
|
|
88
|
+
}
|
|
89
|
+
return ranges;
|
|
90
|
+
}
|
|
49
91
|
/** BoundSheet8 ([MS-XLS] 2.4.28): a four-byte stream position, a byte of hidden state, a byte of sheet type, then the name as a ShortXLUnicodeString. */
|
|
50
92
|
function readBoundSheet(record) {
|
|
51
93
|
const cursor = new require_biff_cursor.BlockCursor(record.blocks);
|
|
@@ -79,15 +121,37 @@ function readFormat(record) {
|
|
|
79
121
|
code: require_biff_strings.readXLUnicodeString(cursor)
|
|
80
122
|
};
|
|
81
123
|
}
|
|
82
|
-
/** XF ([MS-XLS] 2.4.353): a font index, a number-format identifier,
|
|
124
|
+
/** XF ([MS-XLS] 2.4.353): a font index, a number-format identifier, a flags field whose fStyle bit says whether the trailing payload is a CellXF or a StyleXF, then that 14-byte trailing payload itself -- the leading alignment word xf-colors.ts's unpackXfAlignment resolves into this format's own `alignment`, then the border word, fill-pattern word, and fill-colour word its unpackXfDecoration resolves into this format's own `decoration`. CellXF and StyleXF share the identical alignment/border/fill bit layout ([MS-XLS] 2.4.353's own field table), so this reads both shapes uniformly regardless of isStyle -- a cell only ever references a CellXF entry by its own ixfe (workbook/sheet.ts's cell reading), so a StyleXF's alignment/decoration are parsed but never consulted downstream. */
|
|
83
125
|
function readCellFormat(record) {
|
|
84
126
|
const cursor = new require_biff_cursor.BlockCursor(record.blocks);
|
|
127
|
+
const fontIndex = cursor.u16();
|
|
128
|
+
const formatId = cursor.u16();
|
|
129
|
+
const flags = cursor.u16();
|
|
130
|
+
const word1 = cursor.u32();
|
|
131
|
+
const word2 = cursor.u32();
|
|
132
|
+
const word3 = cursor.u32();
|
|
133
|
+
const word4 = cursor.u16();
|
|
85
134
|
return {
|
|
86
|
-
fontIndex
|
|
87
|
-
formatId
|
|
88
|
-
isStyle: (
|
|
135
|
+
fontIndex,
|
|
136
|
+
formatId,
|
|
137
|
+
isStyle: (flags & XF_FLAG_STYLE) !== 0,
|
|
138
|
+
alignment: require_biff_xf_colors.unpackXfAlignment(word1),
|
|
139
|
+
decoration: require_biff_xf_colors.unpackXfDecoration(word2, word3, word4)
|
|
89
140
|
};
|
|
90
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Palette ([MS-XLS] 2.4.188): ccv, a signed colour count the spec states "MUST be 56", then that many LongRGB entries -- the write-side mirror is xf-writer.ts's own writePaletteRecord.
|
|
144
|
+
*
|
|
145
|
+
* A ccv that is not 56 is refused rather than honoured. This reader resolves every icv 8-63 positionally through this table, so a short (or zero, or negative) one does not degrade gracefully: every colour past its end silently becomes unresolvable, and a workbook's fills and borders all vanish at once with nothing to say why. A file declaring a count its own spec forbids is malformed, and saying so is the only honest answer.
|
|
146
|
+
*/
|
|
147
|
+
function readPalette(record) {
|
|
148
|
+
const cursor = new require_biff_cursor.BlockCursor(record.blocks);
|
|
149
|
+
const count = cursor.i16();
|
|
150
|
+
if (count !== 56) throw new require_biff_records.BiffFormatError(`Palette declares ${count} colour entries, but [MS-XLS] 2.4.188's own ccv field MUST be 56`);
|
|
151
|
+
const colors = [];
|
|
152
|
+
for (let index = 0; index < count; index += 1) colors.push(require_biff_xf_colors.readLongRgbColor(cursor));
|
|
153
|
+
return colors;
|
|
154
|
+
}
|
|
91
155
|
/** Date1904 ([MS-XLS] 2.4.77): a two-byte boolean. */
|
|
92
156
|
function readDate1904(record) {
|
|
93
157
|
return new require_biff_cursor.BlockCursor(record.blocks).u16() !== 0;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as SheetRange } from "../ptg-B2K8t3js.cjs";
|
|
2
|
+
import { t as RecordGroup } from "../substreams-Ddtvn_Vr.cjs";
|
|
3
|
+
import { C as XfAlignmentFields, T as XfDecorationFields } from "../xf-colors-CehHZtBy.cjs";
|
|
4
|
+
import { n as SheetPrintNames } from "../print-names-D-njuzVw.cjs";
|
|
5
|
+
import { Color } from "document-schema.js";
|
|
2
6
|
//#region src/workbook/globals.d.ts
|
|
3
7
|
/** One sheet, as its BoundSheet8 record describes it ([MS-XLS] 2.4.28). */
|
|
4
8
|
interface SheetEntry {
|
|
@@ -11,7 +15,7 @@ interface SheetEntry {
|
|
|
11
15
|
/** lbPlyPos: the byte offset, within the workbook stream, of this sheet's own BOF record. */
|
|
12
16
|
readonly bofPosition: number;
|
|
13
17
|
}
|
|
14
|
-
/** One XF record's fixed prefix ([MS-XLS] 2.4.353)
|
|
18
|
+
/** One XF record's fixed prefix ([MS-XLS] 2.4.353) plus its trailing CellXF/StyleXF payload's own alignment and fill/border fields. */
|
|
15
19
|
interface CellFormat {
|
|
16
20
|
/** ifnt: the index of the Font record this format uses. */
|
|
17
21
|
readonly fontIndex: number;
|
|
@@ -19,6 +23,10 @@ interface CellFormat {
|
|
|
19
23
|
readonly formatId: number;
|
|
20
24
|
/** fStyle: true when this record describes a cell STYLE rather than a cell format. */
|
|
21
25
|
readonly isStyle: boolean;
|
|
26
|
+
/** The trailing payload's own leading word, resolved into document-schema.js's Alignment/verticalAlignment members directly (undefined already means what an absent ContentSheetCell.alignment/verticalAlignment means, so content.ts consumes this without a further resolution step). */
|
|
27
|
+
readonly alignment: XfAlignmentFields;
|
|
28
|
+
/** The trailing payload's own fill pattern/colour and per-side border fields, raw -- resolved into document-schema.js's Color/ContentCellBorders by content.ts, through this same globals object's own `palette`. */
|
|
29
|
+
readonly decoration: XfDecorationFields;
|
|
22
30
|
}
|
|
23
31
|
/** Everything the globals substream contributes to reading the sheets that follow it. */
|
|
24
32
|
interface WorkbookGlobals {
|
|
@@ -32,6 +40,22 @@ interface WorkbookGlobals {
|
|
|
32
40
|
readonly numberFormats: ReadonlyMap<number, string>;
|
|
33
41
|
/** Whether serials count from the 1904 epoch rather than the 1900 one ([MS-XLS] 2.4.77). */
|
|
34
42
|
readonly date1904: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* A PtgRef3d/PtgArea3d's own ixti, resolved to the sheet range it names -- one entry per XTI in the EXTERNSHEET record's rgXTI array, in that array's own order (an ixti is an index into it).
|
|
45
|
+
*
|
|
46
|
+
* An entry is undefined when this reader does not resolve it: the XTI's own SupBook is not this same, self-referencing workbook (a genuine external-workbook, DDE, OLE, or add-in reference -- [MS-XLS] 2.4.271's own cch table, `0x0401` being the one this reader treats as resolvable), or its itabFirst/itabLast do not name a real sheet (`-1`, "sheet could not be found"). A formula whose 3D reference lands on an undefined entry is left with `formula` absent for that cell, exactly like the other unsupported-token cases -- this reader never resolves a genuinely external workbook's own sheet names, since that needs the external workbook's own bytes, not this one's.
|
|
47
|
+
*/
|
|
48
|
+
readonly sheetRanges: readonly (SheetRange | undefined)[];
|
|
49
|
+
/**
|
|
50
|
+
* The workbook's own custom colour table, from a Palette record ([MS-XLS] 2.4.188) -- 56 entries, index 0 being icv 8. Undefined when the file carries no Palette record at all, which is common: a real file relying purely on the fixed default 8-colour-plus-56-entry table (this package's own `resolveIcvColor` falls back to that same default table, matching [MS-XLS] "Icv"'s own documented fallback) never needs one.
|
|
51
|
+
*/
|
|
52
|
+
readonly palette: readonly Color[] | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The print range and repeated header bands each sheet's own built-in Print_Area/Print_Titles defined names declare, keyed by zero-based sheet index -- see workbook/print-names.ts for why a sheet's print settings are split between here and its own substream.
|
|
55
|
+
*
|
|
56
|
+
* A sheet with no entry declares neither, which is the common case: a workbook nobody has set a print area on carries no Lbl record at all.
|
|
57
|
+
*/
|
|
58
|
+
readonly printNames: ReadonlyMap<number, SheetPrintNames>;
|
|
35
59
|
}
|
|
36
60
|
/** Reads the globals substream's records into the tables the sheet reader needs. */
|
|
37
61
|
declare function readWorkbookGlobals(records: readonly RecordGroup[]): WorkbookGlobals;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as SheetRange } from "../ptg-B2K8t3js.js";
|
|
2
|
+
import { t as RecordGroup } from "../substreams-D7dQiJbp.js";
|
|
3
|
+
import { C as XfAlignmentFields, T as XfDecorationFields } from "../xf-colors-CpykR3B9.js";
|
|
4
|
+
import { n as SheetPrintNames } from "../print-names-DUlpVE00.js";
|
|
5
|
+
import { Color } from "document-schema.js";
|
|
2
6
|
//#region src/workbook/globals.d.ts
|
|
3
7
|
/** One sheet, as its BoundSheet8 record describes it ([MS-XLS] 2.4.28). */
|
|
4
8
|
interface SheetEntry {
|
|
@@ -11,7 +15,7 @@ interface SheetEntry {
|
|
|
11
15
|
/** lbPlyPos: the byte offset, within the workbook stream, of this sheet's own BOF record. */
|
|
12
16
|
readonly bofPosition: number;
|
|
13
17
|
}
|
|
14
|
-
/** One XF record's fixed prefix ([MS-XLS] 2.4.353)
|
|
18
|
+
/** One XF record's fixed prefix ([MS-XLS] 2.4.353) plus its trailing CellXF/StyleXF payload's own alignment and fill/border fields. */
|
|
15
19
|
interface CellFormat {
|
|
16
20
|
/** ifnt: the index of the Font record this format uses. */
|
|
17
21
|
readonly fontIndex: number;
|
|
@@ -19,6 +23,10 @@ interface CellFormat {
|
|
|
19
23
|
readonly formatId: number;
|
|
20
24
|
/** fStyle: true when this record describes a cell STYLE rather than a cell format. */
|
|
21
25
|
readonly isStyle: boolean;
|
|
26
|
+
/** The trailing payload's own leading word, resolved into document-schema.js's Alignment/verticalAlignment members directly (undefined already means what an absent ContentSheetCell.alignment/verticalAlignment means, so content.ts consumes this without a further resolution step). */
|
|
27
|
+
readonly alignment: XfAlignmentFields;
|
|
28
|
+
/** The trailing payload's own fill pattern/colour and per-side border fields, raw -- resolved into document-schema.js's Color/ContentCellBorders by content.ts, through this same globals object's own `palette`. */
|
|
29
|
+
readonly decoration: XfDecorationFields;
|
|
22
30
|
}
|
|
23
31
|
/** Everything the globals substream contributes to reading the sheets that follow it. */
|
|
24
32
|
interface WorkbookGlobals {
|
|
@@ -32,6 +40,22 @@ interface WorkbookGlobals {
|
|
|
32
40
|
readonly numberFormats: ReadonlyMap<number, string>;
|
|
33
41
|
/** Whether serials count from the 1904 epoch rather than the 1900 one ([MS-XLS] 2.4.77). */
|
|
34
42
|
readonly date1904: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* A PtgRef3d/PtgArea3d's own ixti, resolved to the sheet range it names -- one entry per XTI in the EXTERNSHEET record's rgXTI array, in that array's own order (an ixti is an index into it).
|
|
45
|
+
*
|
|
46
|
+
* An entry is undefined when this reader does not resolve it: the XTI's own SupBook is not this same, self-referencing workbook (a genuine external-workbook, DDE, OLE, or add-in reference -- [MS-XLS] 2.4.271's own cch table, `0x0401` being the one this reader treats as resolvable), or its itabFirst/itabLast do not name a real sheet (`-1`, "sheet could not be found"). A formula whose 3D reference lands on an undefined entry is left with `formula` absent for that cell, exactly like the other unsupported-token cases -- this reader never resolves a genuinely external workbook's own sheet names, since that needs the external workbook's own bytes, not this one's.
|
|
47
|
+
*/
|
|
48
|
+
readonly sheetRanges: readonly (SheetRange | undefined)[];
|
|
49
|
+
/**
|
|
50
|
+
* The workbook's own custom colour table, from a Palette record ([MS-XLS] 2.4.188) -- 56 entries, index 0 being icv 8. Undefined when the file carries no Palette record at all, which is common: a real file relying purely on the fixed default 8-colour-plus-56-entry table (this package's own `resolveIcvColor` falls back to that same default table, matching [MS-XLS] "Icv"'s own documented fallback) never needs one.
|
|
51
|
+
*/
|
|
52
|
+
readonly palette: readonly Color[] | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The print range and repeated header bands each sheet's own built-in Print_Area/Print_Titles defined names declare, keyed by zero-based sheet index -- see workbook/print-names.ts for why a sheet's print settings are split between here and its own substream.
|
|
55
|
+
*
|
|
56
|
+
* A sheet with no entry declares neither, which is the common case: a workbook nobody has set a print area on carries no Lbl record at all.
|
|
57
|
+
*/
|
|
58
|
+
readonly printNames: ReadonlyMap<number, SheetPrintNames>;
|
|
35
59
|
}
|
|
36
60
|
/** Reads the globals substream's records into the tables the sheet reader needs. */
|
|
37
61
|
declare function readWorkbookGlobals(records: readonly RecordGroup[]): WorkbookGlobals;
|
package/dist/workbook/globals.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { RECORD_FORMAT } from "../biff/record-types.js";
|
|
2
2
|
import { BiffFormatError } from "../biff/records.js";
|
|
3
|
-
import {
|
|
3
|
+
import { readLongRgbColor, unpackXfAlignment, unpackXfDecoration } from "../biff/xf-colors.js";
|
|
4
4
|
import { BlockCursor } from "../biff/cursor.js";
|
|
5
5
|
import { readRichExtendedString, readShortXLUnicodeString, readXLUnicodeString } from "../biff/strings.js";
|
|
6
|
+
import { readPrintNames } from "./print-names.js";
|
|
7
|
+
import { BUILTIN_NUMBER_FORMATS } from "excel-number-format";
|
|
6
8
|
//#region src/workbook/globals.ts
|
|
7
9
|
/** [MS-XLS] 2.4.28's own hsState values; 0x01 is Hidden and 0x02 Very Hidden. */
|
|
8
10
|
const HIDDEN_STATE_MASK = 3;
|
|
@@ -16,8 +18,11 @@ function readWorkbookGlobals(records) {
|
|
|
16
18
|
const sheets = [];
|
|
17
19
|
const cellFormats = [];
|
|
18
20
|
const customFormats = /* @__PURE__ */ new Map();
|
|
21
|
+
const supBookSelfReferencing = [];
|
|
19
22
|
let sharedStrings = [];
|
|
20
23
|
let date1904 = false;
|
|
24
|
+
let externSheet;
|
|
25
|
+
let palette;
|
|
21
26
|
for (const record of records) switch (record.type) {
|
|
22
27
|
case 133:
|
|
23
28
|
sheets.push(readBoundSheet(record));
|
|
@@ -33,18 +38,55 @@ function readWorkbookGlobals(records) {
|
|
|
33
38
|
case 224:
|
|
34
39
|
cellFormats.push(readCellFormat(record));
|
|
35
40
|
break;
|
|
36
|
-
case 34:
|
|
41
|
+
case 34:
|
|
42
|
+
date1904 = readDate1904(record);
|
|
43
|
+
break;
|
|
44
|
+
case 430:
|
|
45
|
+
supBookSelfReferencing.push(isSelfReferencingSupBook(record));
|
|
46
|
+
break;
|
|
47
|
+
case 23:
|
|
48
|
+
externSheet = record;
|
|
49
|
+
break;
|
|
50
|
+
case 146: palette = readPalette(record);
|
|
37
51
|
}
|
|
38
52
|
const numberFormats = new Map(BUILTIN_NUMBER_FORMATS);
|
|
39
53
|
for (const [id, code] of customFormats) numberFormats.set(id, code);
|
|
54
|
+
const sheetRanges = externSheet === void 0 ? [] : readSheetRanges(externSheet, supBookSelfReferencing);
|
|
40
55
|
return {
|
|
41
56
|
sheets,
|
|
42
57
|
sharedStrings,
|
|
43
58
|
cellFormats,
|
|
44
59
|
numberFormats,
|
|
45
|
-
date1904
|
|
60
|
+
date1904,
|
|
61
|
+
sheetRanges,
|
|
62
|
+
palette,
|
|
63
|
+
printNames: readPrintNames(records)
|
|
46
64
|
};
|
|
47
65
|
}
|
|
66
|
+
/** [MS-XLS] 2.4.271's own cch table: a SupBook whose cch is exactly this value is a self-referencing supporting link -- this workbook itself -- rather than another workbook, a DDE/OLE data source, or an add-in. This is the only kind of supporting link a 3D reference resolves through here; every other kind genuinely needs bytes from outside this file. */
|
|
67
|
+
const SUPBOOK_SELF_REFERENCING_CCH = 1025;
|
|
68
|
+
/** SupBook ([MS-XLS] 2.4.271): a two-byte ctab then a two-byte cch. Only cch is read here -- ctab is undefined for a self-referencing SupBook and unused for every other kind this reader does not resolve, and the virtPath/rgst payload that would follow for a non-self-referencing link is never reached. */
|
|
69
|
+
function isSelfReferencingSupBook(record) {
|
|
70
|
+
const cursor = new BlockCursor(record.blocks);
|
|
71
|
+
cursor.skip(2);
|
|
72
|
+
return cursor.u16() === SUPBOOK_SELF_REFERENCING_CCH;
|
|
73
|
+
}
|
|
74
|
+
/** ExternSheet ([MS-XLS] 2.4.106): a two-byte cXTI then that many XTI structures ([MS-XLS] 2.5.344) -- a two-byte iSupBook and two signed 16-bit sheet-scope bounds each. iSupBook indexes the SupBook collection positionally, in the order those records appeared. */
|
|
75
|
+
function readSheetRanges(record, supBookSelfReferencing) {
|
|
76
|
+
const cursor = new BlockCursor(record.blocks);
|
|
77
|
+
const count = cursor.u16();
|
|
78
|
+
const ranges = [];
|
|
79
|
+
for (let index = 0; index < count; index += 1) {
|
|
80
|
+
const iSupBook = cursor.u16();
|
|
81
|
+
const itabFirst = cursor.i16();
|
|
82
|
+
const itabLast = cursor.i16();
|
|
83
|
+
ranges.push((supBookSelfReferencing[iSupBook] ?? false) && itabFirst >= 0 && itabLast >= 0 ? {
|
|
84
|
+
firstSheetIndex: itabFirst,
|
|
85
|
+
lastSheetIndex: itabLast
|
|
86
|
+
} : void 0);
|
|
87
|
+
}
|
|
88
|
+
return ranges;
|
|
89
|
+
}
|
|
48
90
|
/** BoundSheet8 ([MS-XLS] 2.4.28): a four-byte stream position, a byte of hidden state, a byte of sheet type, then the name as a ShortXLUnicodeString. */
|
|
49
91
|
function readBoundSheet(record) {
|
|
50
92
|
const cursor = new BlockCursor(record.blocks);
|
|
@@ -78,15 +120,37 @@ function readFormat(record) {
|
|
|
78
120
|
code: readXLUnicodeString(cursor)
|
|
79
121
|
};
|
|
80
122
|
}
|
|
81
|
-
/** XF ([MS-XLS] 2.4.353): a font index, a number-format identifier,
|
|
123
|
+
/** XF ([MS-XLS] 2.4.353): a font index, a number-format identifier, a flags field whose fStyle bit says whether the trailing payload is a CellXF or a StyleXF, then that 14-byte trailing payload itself -- the leading alignment word xf-colors.ts's unpackXfAlignment resolves into this format's own `alignment`, then the border word, fill-pattern word, and fill-colour word its unpackXfDecoration resolves into this format's own `decoration`. CellXF and StyleXF share the identical alignment/border/fill bit layout ([MS-XLS] 2.4.353's own field table), so this reads both shapes uniformly regardless of isStyle -- a cell only ever references a CellXF entry by its own ixfe (workbook/sheet.ts's cell reading), so a StyleXF's alignment/decoration are parsed but never consulted downstream. */
|
|
82
124
|
function readCellFormat(record) {
|
|
83
125
|
const cursor = new BlockCursor(record.blocks);
|
|
126
|
+
const fontIndex = cursor.u16();
|
|
127
|
+
const formatId = cursor.u16();
|
|
128
|
+
const flags = cursor.u16();
|
|
129
|
+
const word1 = cursor.u32();
|
|
130
|
+
const word2 = cursor.u32();
|
|
131
|
+
const word3 = cursor.u32();
|
|
132
|
+
const word4 = cursor.u16();
|
|
84
133
|
return {
|
|
85
|
-
fontIndex
|
|
86
|
-
formatId
|
|
87
|
-
isStyle: (
|
|
134
|
+
fontIndex,
|
|
135
|
+
formatId,
|
|
136
|
+
isStyle: (flags & XF_FLAG_STYLE) !== 0,
|
|
137
|
+
alignment: unpackXfAlignment(word1),
|
|
138
|
+
decoration: unpackXfDecoration(word2, word3, word4)
|
|
88
139
|
};
|
|
89
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Palette ([MS-XLS] 2.4.188): ccv, a signed colour count the spec states "MUST be 56", then that many LongRGB entries -- the write-side mirror is xf-writer.ts's own writePaletteRecord.
|
|
143
|
+
*
|
|
144
|
+
* A ccv that is not 56 is refused rather than honoured. This reader resolves every icv 8-63 positionally through this table, so a short (or zero, or negative) one does not degrade gracefully: every colour past its end silently becomes unresolvable, and a workbook's fills and borders all vanish at once with nothing to say why. A file declaring a count its own spec forbids is malformed, and saying so is the only honest answer.
|
|
145
|
+
*/
|
|
146
|
+
function readPalette(record) {
|
|
147
|
+
const cursor = new BlockCursor(record.blocks);
|
|
148
|
+
const count = cursor.i16();
|
|
149
|
+
if (count !== 56) throw new BiffFormatError(`Palette declares ${count} colour entries, but [MS-XLS] 2.4.188's own ccv field MUST be 56`);
|
|
150
|
+
const colors = [];
|
|
151
|
+
for (let index = 0; index < count; index += 1) colors.push(readLongRgbColor(cursor));
|
|
152
|
+
return colors;
|
|
153
|
+
}
|
|
90
154
|
/** Date1904 ([MS-XLS] 2.4.77): a two-byte boolean. */
|
|
91
155
|
function readDate1904(record) {
|
|
92
156
|
return new BlockCursor(record.blocks).u16() !== 0;
|