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
package/dist/serial.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_biff_write_errors = require("./biff/write-errors.cjs");
|
|
2
3
|
//#region src/serial.ts
|
|
3
4
|
const MS_PER_DAY = 864e5;
|
|
4
5
|
const MS_PER_HOUR = 36e5;
|
|
@@ -56,7 +57,47 @@ function serialToIsoDateTime(serial, date1904) {
|
|
|
56
57
|
const date = isoDateOfDayCount(days, date1904);
|
|
57
58
|
return date === void 0 ? void 0 : `${date}T${isoTimeOfMsWithinDay(msWithinDay)}`;
|
|
58
59
|
}
|
|
60
|
+
const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
61
|
+
const ISO_TIME_PATTERN = /^(\d{2}):(\d{2}):(\d{2})$/;
|
|
62
|
+
/** The calendar day count a real date maps to, inverting isoDateOfDayCount: below the 1900 system's phantom leap day (1900-02-29) the day count is a plain offset from 1899-12-31; on or after it, one day is added to skip over the phantom date the calendar never had. The date1904 system has no such adjustment -- 1904 genuinely was a leap year, so its serial 0 origin needs no correction. */
|
|
63
|
+
function isoDateToDayCount(isoDate, date1904) {
|
|
64
|
+
const match = ISO_DATE_PATTERN.exec(isoDate);
|
|
65
|
+
if (match === null) throw new require_biff_write_errors.BiffWriteError(`date value ${JSON.stringify(isoDate)} is not an ISO 8601 calendar date (YYYY-MM-DD), which is the only spelling document-schema.js's 'date' cell value permits`);
|
|
66
|
+
const [, year, month, day] = match;
|
|
67
|
+
const utcMs = Date.UTC(Number(year), Number(month) - 1, Number(day));
|
|
68
|
+
if (date1904) return Math.round((utcMs - ORIGIN_1904_UTC_MS) / MS_PER_DAY);
|
|
69
|
+
const daysBelowPhantom = Math.round((utcMs - ORIGIN_1900_BELOW_PHANTOM_UTC_MS) / MS_PER_DAY);
|
|
70
|
+
const days = daysBelowPhantom < PHANTOM_LEAP_DAY_SERIAL ? daysBelowPhantom : daysBelowPhantom + 1;
|
|
71
|
+
if (days < 0) throw new require_biff_write_errors.BiffWriteError(`date value ${JSON.stringify(isoDate)} is before the epoch a BIFF8 serial can represent (1899-12-31)`);
|
|
72
|
+
return days;
|
|
73
|
+
}
|
|
74
|
+
/** The fraction-of-a-day a wall-clock time maps to, inverting isoTimeOfMsWithinDay. Exact for any whole-second HH:MM:SS input, which is the only shape document-schema.js's 'time'/'dateTime' cell values permit. */
|
|
75
|
+
function isoTimeToDayFraction(isoTime) {
|
|
76
|
+
const match = ISO_TIME_PATTERN.exec(isoTime);
|
|
77
|
+
if (match === null) throw new require_biff_write_errors.BiffWriteError(`time value ${JSON.stringify(isoTime)} is not an ISO 8601 wall-clock time (HH:MM:SS), which is the only spelling document-schema.js's 'time'/'dateTime' cell values permit`);
|
|
78
|
+
const [, hours, minutes, seconds] = match;
|
|
79
|
+
return (Number(hours) * MS_PER_HOUR + Number(minutes) * MS_PER_MINUTE + Number(seconds) * MS_PER_SECOND) / MS_PER_DAY;
|
|
80
|
+
}
|
|
81
|
+
function isoDateToSerial(isoDate, date1904) {
|
|
82
|
+
return isoDateToDayCount(isoDate, date1904);
|
|
83
|
+
}
|
|
84
|
+
function isoTimeToSerial(isoTime) {
|
|
85
|
+
return isoTimeToDayFraction(isoTime);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A combined ISO date-time back to its serial. Accepts a trailing fractional-seconds part and/or a 'Z'/offset suffix -- document-schema.js's own wire contract permits both when the source genuinely carried one -- but a BIFF8 serial has no timezone concept at all (see the read direction's own comment above), so any offset is dropped rather than applied: the wall-clock digits are taken as written, exactly as they would be typed into Excel directly.
|
|
89
|
+
*/
|
|
90
|
+
function isoDateTimeToSerial(isoDateTime, date1904) {
|
|
91
|
+
const separatorIndex = isoDateTime.indexOf("T");
|
|
92
|
+
if (separatorIndex !== 10) throw new require_biff_write_errors.BiffWriteError(`dateTime value ${JSON.stringify(isoDateTime)} is not an ISO 8601 combined date and time (YYYY-MM-DDTHH:MM:SS), which is the only spelling document-schema.js's 'dateTime' cell value permits`);
|
|
93
|
+
const datePart = isoDateTime.slice(0, separatorIndex);
|
|
94
|
+
const timePart = isoDateTime.slice(separatorIndex + 1).slice(0, 8);
|
|
95
|
+
return isoDateToDayCount(datePart, date1904) + isoTimeToDayFraction(timePart);
|
|
96
|
+
}
|
|
59
97
|
//#endregion
|
|
98
|
+
exports.isoDateTimeToSerial = isoDateTimeToSerial;
|
|
99
|
+
exports.isoDateToSerial = isoDateToSerial;
|
|
100
|
+
exports.isoTimeToSerial = isoTimeToSerial;
|
|
60
101
|
exports.serialToIsoDate = serialToIsoDate;
|
|
61
102
|
exports.serialToIsoDateTime = serialToIsoDateTime;
|
|
62
103
|
exports.serialToIsoTime = serialToIsoTime;
|
package/dist/serial.d.cts
CHANGED
|
@@ -3,5 +3,11 @@ declare function serialToIsoDate(serial: number, date1904: boolean): string | un
|
|
|
3
3
|
/** A time-of-day format renders only the fractional part -- a serial of 2.5 under `h:mm` displays as noon, not as "two days and twelve hours" -- so the day count is discarded here rather than made an error. Sub-second precision is discarded too: ContentCellValue's own 'time' spelling is fixed at HH:MM:SS. */
|
|
4
4
|
declare function serialToIsoTime(serial: number): string | undefined;
|
|
5
5
|
declare function serialToIsoDateTime(serial: number, date1904: boolean): string | undefined;
|
|
6
|
+
declare function isoDateToSerial(isoDate: string, date1904: boolean): number;
|
|
7
|
+
declare function isoTimeToSerial(isoTime: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* A combined ISO date-time back to its serial. Accepts a trailing fractional-seconds part and/or a 'Z'/offset suffix -- document-schema.js's own wire contract permits both when the source genuinely carried one -- but a BIFF8 serial has no timezone concept at all (see the read direction's own comment above), so any offset is dropped rather than applied: the wall-clock digits are taken as written, exactly as they would be typed into Excel directly.
|
|
10
|
+
*/
|
|
11
|
+
declare function isoDateTimeToSerial(isoDateTime: string, date1904: boolean): number;
|
|
6
12
|
//#endregion
|
|
7
|
-
export { serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
13
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
package/dist/serial.d.ts
CHANGED
|
@@ -3,5 +3,11 @@ declare function serialToIsoDate(serial: number, date1904: boolean): string | un
|
|
|
3
3
|
/** A time-of-day format renders only the fractional part -- a serial of 2.5 under `h:mm` displays as noon, not as "two days and twelve hours" -- so the day count is discarded here rather than made an error. Sub-second precision is discarded too: ContentCellValue's own 'time' spelling is fixed at HH:MM:SS. */
|
|
4
4
|
declare function serialToIsoTime(serial: number): string | undefined;
|
|
5
5
|
declare function serialToIsoDateTime(serial: number, date1904: boolean): string | undefined;
|
|
6
|
+
declare function isoDateToSerial(isoDate: string, date1904: boolean): number;
|
|
7
|
+
declare function isoTimeToSerial(isoTime: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* A combined ISO date-time back to its serial. Accepts a trailing fractional-seconds part and/or a 'Z'/offset suffix -- document-schema.js's own wire contract permits both when the source genuinely carried one -- but a BIFF8 serial has no timezone concept at all (see the read direction's own comment above), so any offset is dropped rather than applied: the wall-clock digits are taken as written, exactly as they would be typed into Excel directly.
|
|
10
|
+
*/
|
|
11
|
+
declare function isoDateTimeToSerial(isoDateTime: string, date1904: boolean): number;
|
|
6
12
|
//#endregion
|
|
7
|
-
export { serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
13
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
package/dist/serial.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BiffWriteError } from "./biff/write-errors.js";
|
|
1
2
|
//#region src/serial.ts
|
|
2
3
|
const MS_PER_DAY = 864e5;
|
|
3
4
|
const MS_PER_HOUR = 36e5;
|
|
@@ -55,5 +56,42 @@ function serialToIsoDateTime(serial, date1904) {
|
|
|
55
56
|
const date = isoDateOfDayCount(days, date1904);
|
|
56
57
|
return date === void 0 ? void 0 : `${date}T${isoTimeOfMsWithinDay(msWithinDay)}`;
|
|
57
58
|
}
|
|
59
|
+
const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
60
|
+
const ISO_TIME_PATTERN = /^(\d{2}):(\d{2}):(\d{2})$/;
|
|
61
|
+
/** The calendar day count a real date maps to, inverting isoDateOfDayCount: below the 1900 system's phantom leap day (1900-02-29) the day count is a plain offset from 1899-12-31; on or after it, one day is added to skip over the phantom date the calendar never had. The date1904 system has no such adjustment -- 1904 genuinely was a leap year, so its serial 0 origin needs no correction. */
|
|
62
|
+
function isoDateToDayCount(isoDate, date1904) {
|
|
63
|
+
const match = ISO_DATE_PATTERN.exec(isoDate);
|
|
64
|
+
if (match === null) throw new BiffWriteError(`date value ${JSON.stringify(isoDate)} is not an ISO 8601 calendar date (YYYY-MM-DD), which is the only spelling document-schema.js's 'date' cell value permits`);
|
|
65
|
+
const [, year, month, day] = match;
|
|
66
|
+
const utcMs = Date.UTC(Number(year), Number(month) - 1, Number(day));
|
|
67
|
+
if (date1904) return Math.round((utcMs - ORIGIN_1904_UTC_MS) / MS_PER_DAY);
|
|
68
|
+
const daysBelowPhantom = Math.round((utcMs - ORIGIN_1900_BELOW_PHANTOM_UTC_MS) / MS_PER_DAY);
|
|
69
|
+
const days = daysBelowPhantom < PHANTOM_LEAP_DAY_SERIAL ? daysBelowPhantom : daysBelowPhantom + 1;
|
|
70
|
+
if (days < 0) throw new BiffWriteError(`date value ${JSON.stringify(isoDate)} is before the epoch a BIFF8 serial can represent (1899-12-31)`);
|
|
71
|
+
return days;
|
|
72
|
+
}
|
|
73
|
+
/** The fraction-of-a-day a wall-clock time maps to, inverting isoTimeOfMsWithinDay. Exact for any whole-second HH:MM:SS input, which is the only shape document-schema.js's 'time'/'dateTime' cell values permit. */
|
|
74
|
+
function isoTimeToDayFraction(isoTime) {
|
|
75
|
+
const match = ISO_TIME_PATTERN.exec(isoTime);
|
|
76
|
+
if (match === null) throw new BiffWriteError(`time value ${JSON.stringify(isoTime)} is not an ISO 8601 wall-clock time (HH:MM:SS), which is the only spelling document-schema.js's 'time'/'dateTime' cell values permit`);
|
|
77
|
+
const [, hours, minutes, seconds] = match;
|
|
78
|
+
return (Number(hours) * MS_PER_HOUR + Number(minutes) * MS_PER_MINUTE + Number(seconds) * MS_PER_SECOND) / MS_PER_DAY;
|
|
79
|
+
}
|
|
80
|
+
function isoDateToSerial(isoDate, date1904) {
|
|
81
|
+
return isoDateToDayCount(isoDate, date1904);
|
|
82
|
+
}
|
|
83
|
+
function isoTimeToSerial(isoTime) {
|
|
84
|
+
return isoTimeToDayFraction(isoTime);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A combined ISO date-time back to its serial. Accepts a trailing fractional-seconds part and/or a 'Z'/offset suffix -- document-schema.js's own wire contract permits both when the source genuinely carried one -- but a BIFF8 serial has no timezone concept at all (see the read direction's own comment above), so any offset is dropped rather than applied: the wall-clock digits are taken as written, exactly as they would be typed into Excel directly.
|
|
88
|
+
*/
|
|
89
|
+
function isoDateTimeToSerial(isoDateTime, date1904) {
|
|
90
|
+
const separatorIndex = isoDateTime.indexOf("T");
|
|
91
|
+
if (separatorIndex !== 10) throw new BiffWriteError(`dateTime value ${JSON.stringify(isoDateTime)} is not an ISO 8601 combined date and time (YYYY-MM-DDTHH:MM:SS), which is the only spelling document-schema.js's 'dateTime' cell value permits`);
|
|
92
|
+
const datePart = isoDateTime.slice(0, separatorIndex);
|
|
93
|
+
const timePart = isoDateTime.slice(separatorIndex + 1).slice(0, 8);
|
|
94
|
+
return isoDateToDayCount(datePart, date1904) + isoTimeToDayFraction(timePart);
|
|
95
|
+
}
|
|
58
96
|
//#endregion
|
|
59
|
-
export { serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
97
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { n as BiffRecord } from "./records-DVIqXFKk.js";
|
|
2
|
+
//#region src/biff/substreams.d.ts
|
|
3
|
+
/** One logical record: its type, its data blocks -- the base record's, then one per Continue that followed it -- and the base record's own offset in the stream. */
|
|
4
|
+
interface RecordGroup {
|
|
5
|
+
readonly type: number;
|
|
6
|
+
readonly blocks: readonly Uint8Array<ArrayBuffer>[];
|
|
7
|
+
readonly offset: number;
|
|
8
|
+
}
|
|
9
|
+
/** One substream: the document type its BOF declared, the records between that BOF and its EOF, its ordinal position among the stream's substreams, and the stream offset of its own BOF -- which is what a BoundSheet8's lbPlyPos names. */
|
|
10
|
+
interface Substream {
|
|
11
|
+
readonly documentType: number;
|
|
12
|
+
readonly records: readonly RecordGroup[];
|
|
13
|
+
readonly index: number;
|
|
14
|
+
readonly offset: number;
|
|
15
|
+
}
|
|
16
|
+
/** Joins each record to the Continue records following it, keeping the blocks separate. */
|
|
17
|
+
declare function groupRecords(records: readonly BiffRecord[]): readonly RecordGroup[];
|
|
18
|
+
/** Splits a grouped record sequence into its substreams, verifying each BOF declares BIFF8. */
|
|
19
|
+
declare function splitSubstreams(groups: readonly RecordGroup[]): readonly Substream[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { splitSubstreams as i, Substream as n, groupRecords as r, RecordGroup as t };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { n as BiffRecord } from "./records-DVIqXFKk.cjs";
|
|
2
|
+
//#region src/biff/substreams.d.ts
|
|
3
|
+
/** One logical record: its type, its data blocks -- the base record's, then one per Continue that followed it -- and the base record's own offset in the stream. */
|
|
4
|
+
interface RecordGroup {
|
|
5
|
+
readonly type: number;
|
|
6
|
+
readonly blocks: readonly Uint8Array<ArrayBuffer>[];
|
|
7
|
+
readonly offset: number;
|
|
8
|
+
}
|
|
9
|
+
/** One substream: the document type its BOF declared, the records between that BOF and its EOF, its ordinal position among the stream's substreams, and the stream offset of its own BOF -- which is what a BoundSheet8's lbPlyPos names. */
|
|
10
|
+
interface Substream {
|
|
11
|
+
readonly documentType: number;
|
|
12
|
+
readonly records: readonly RecordGroup[];
|
|
13
|
+
readonly index: number;
|
|
14
|
+
readonly offset: number;
|
|
15
|
+
}
|
|
16
|
+
/** Joins each record to the Continue records following it, keeping the blocks separate. */
|
|
17
|
+
declare function groupRecords(records: readonly BiffRecord[]): readonly RecordGroup[];
|
|
18
|
+
/** Splits a grouped record sequence into its substreams, verifying each BOF declares BIFF8. */
|
|
19
|
+
declare function splitSubstreams(groups: readonly RecordGroup[]): readonly Substream[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { splitSubstreams as i, Substream as n, groupRecords as r, RecordGroup as t };
|
package/dist/units.cjs
CHANGED
|
@@ -5,6 +5,8 @@ const POINTS_PER_INCH = 72;
|
|
|
5
5
|
const PIXELS_PER_INCH = 96;
|
|
6
6
|
/** A twip is a twentieth of a point; a Row record's miyRw is in twips ([MS-XLS] 2.4.221). */
|
|
7
7
|
const TWIPS_PER_POINT = 20;
|
|
8
|
+
/** The inch's own definition in millimetres, which is what turns [MS-XLS] 2.4.257's metric paper sizes into points. */
|
|
9
|
+
const MILLIMETRES_PER_INCH = 25.4;
|
|
8
10
|
/**
|
|
9
11
|
* The "maximum digit width": the widest rendered width, in pixels, of the digits 0-9 in the workbook's Normal-style font, which is the unit a column width is expressed in multiples of.
|
|
10
12
|
*
|
|
@@ -15,6 +17,18 @@ const MAX_DIGIT_WIDTH_PX = 7;
|
|
|
15
17
|
function twipsToPoints(twips) {
|
|
16
18
|
return twips / TWIPS_PER_POINT;
|
|
17
19
|
}
|
|
20
|
+
/** A margin record's own Xnum ([MS-XLS] 2.4.151 and its three siblings), in inches, as points. */
|
|
21
|
+
function inchesToPoints(inches) {
|
|
22
|
+
return inches * POINTS_PER_INCH;
|
|
23
|
+
}
|
|
24
|
+
/** The inverse, for writing a margin back out. Exact for every value inchesToPoints produces, since the conversion is a single multiplication by an integer. */
|
|
25
|
+
function pointsToInches(points) {
|
|
26
|
+
return points / POINTS_PER_INCH;
|
|
27
|
+
}
|
|
28
|
+
/** A paper size [MS-XLS] 2.4.257's own code table states in millimetres, as points. */
|
|
29
|
+
function millimetresToPoints(millimetres) {
|
|
30
|
+
return millimetres / MILLIMETRES_PER_INCH * POINTS_PER_INCH;
|
|
31
|
+
}
|
|
18
32
|
/**
|
|
19
33
|
* A ColInfo record's coldx -- a width in 1/256ths of a character width ([MS-XLS] 2.4.53) -- as points.
|
|
20
34
|
*
|
|
@@ -25,6 +39,29 @@ function columnWidthToPoints(coldx) {
|
|
|
25
39
|
const digitWidthAllowance = Math.trunc(128 / MAX_DIGIT_WIDTH_PX);
|
|
26
40
|
return Math.trunc((256 * chars + digitWidthAllowance) / 256 * MAX_DIGIT_WIDTH_PX) / PIXELS_PER_INCH * POINTS_PER_INCH;
|
|
27
41
|
}
|
|
42
|
+
/** A Row record's own height field ([MS-XLS] 2.4.221 miyRw), in twips, rounded to the nearest whole twip and clamped to the field's own documented range (2-8192). The inverse of twipsToPoints, and exact for it: twipsToPoints(pointsToTwips(pt)) === pt for any pt this function does not clamp, since twips-per-point is an integer. */
|
|
43
|
+
function pointsToTwips(points) {
|
|
44
|
+
const MIN_ROW_HEIGHT_TWIPS = 2;
|
|
45
|
+
const MAX_ROW_HEIGHT_TWIPS = 8192;
|
|
46
|
+
const twips = Math.round(points * TWIPS_PER_POINT);
|
|
47
|
+
return Math.min(Math.max(twips, MIN_ROW_HEIGHT_TWIPS), MAX_ROW_HEIGHT_TWIPS);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The inverse of columnWidthToPoints: the smallest ColInfo coldx whose own forward pixel-quantized width is at least as wide as the given points. Because columnWidthToPoints truncates to a whole pixel, no coldx reproduces an arbitrary points value exactly; this picks the smallest coldx that rounds UP to (rather than under) the requested width, so a column written from a given widthPt and read back through columnWidthToPoints never comes back narrower than what was asked for -- the same "honestly approximate" contract columnWidthToPoints's own comment already documents for the read direction.
|
|
51
|
+
*
|
|
52
|
+
* Derived directly from columnWidthToPoints's own forward formula: pixels(coldx) = floor((coldx + digitWidthAllowance) * MAX_DIGIT_WIDTH_PX / 256). Solving for the smallest coldx with pixels(coldx) >= targetPixels gives coldx = ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX) - digitWidthAllowance.
|
|
53
|
+
*/
|
|
54
|
+
function pointsToColumnWidth(points) {
|
|
55
|
+
const digitWidthAllowance = Math.trunc(128 / MAX_DIGIT_WIDTH_PX);
|
|
56
|
+
const targetPixels = Math.round(points / POINTS_PER_INCH * PIXELS_PER_INCH);
|
|
57
|
+
const coldx = Math.ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX - digitWidthAllowance);
|
|
58
|
+
return Math.max(coldx, 0);
|
|
59
|
+
}
|
|
28
60
|
//#endregion
|
|
29
61
|
exports.columnWidthToPoints = columnWidthToPoints;
|
|
62
|
+
exports.inchesToPoints = inchesToPoints;
|
|
63
|
+
exports.millimetresToPoints = millimetresToPoints;
|
|
64
|
+
exports.pointsToColumnWidth = pointsToColumnWidth;
|
|
65
|
+
exports.pointsToInches = pointsToInches;
|
|
66
|
+
exports.pointsToTwips = pointsToTwips;
|
|
30
67
|
exports.twipsToPoints = twipsToPoints;
|
package/dist/units.d.cts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
//#region src/units.d.ts
|
|
2
2
|
/** A Row record's height, in twips, as points. */
|
|
3
3
|
declare function twipsToPoints(twips: number): number;
|
|
4
|
+
/** A margin record's own Xnum ([MS-XLS] 2.4.151 and its three siblings), in inches, as points. */
|
|
5
|
+
declare function inchesToPoints(inches: number): number;
|
|
6
|
+
/** The inverse, for writing a margin back out. Exact for every value inchesToPoints produces, since the conversion is a single multiplication by an integer. */
|
|
7
|
+
declare function pointsToInches(points: number): number;
|
|
8
|
+
/** A paper size [MS-XLS] 2.4.257's own code table states in millimetres, as points. */
|
|
9
|
+
declare function millimetresToPoints(millimetres: number): number;
|
|
4
10
|
/**
|
|
5
11
|
* A ColInfo record's coldx -- a width in 1/256ths of a character width ([MS-XLS] 2.4.53) -- as points.
|
|
6
12
|
*
|
|
7
13
|
* The pixel step reproduces Excel's own integer-pixel-grid truncation rather than smoothing it into a continuous formula, so a width read here matches the pixel count Excel itself would render, and matches what ooxml.js computes for the equivalent xlsx column.
|
|
8
14
|
*/
|
|
9
15
|
declare function columnWidthToPoints(coldx: number): number;
|
|
16
|
+
/** A Row record's own height field ([MS-XLS] 2.4.221 miyRw), in twips, rounded to the nearest whole twip and clamped to the field's own documented range (2-8192). The inverse of twipsToPoints, and exact for it: twipsToPoints(pointsToTwips(pt)) === pt for any pt this function does not clamp, since twips-per-point is an integer. */
|
|
17
|
+
declare function pointsToTwips(points: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* The inverse of columnWidthToPoints: the smallest ColInfo coldx whose own forward pixel-quantized width is at least as wide as the given points. Because columnWidthToPoints truncates to a whole pixel, no coldx reproduces an arbitrary points value exactly; this picks the smallest coldx that rounds UP to (rather than under) the requested width, so a column written from a given widthPt and read back through columnWidthToPoints never comes back narrower than what was asked for -- the same "honestly approximate" contract columnWidthToPoints's own comment already documents for the read direction.
|
|
20
|
+
*
|
|
21
|
+
* Derived directly from columnWidthToPoints's own forward formula: pixels(coldx) = floor((coldx + digitWidthAllowance) * MAX_DIGIT_WIDTH_PX / 256). Solving for the smallest coldx with pixels(coldx) >= targetPixels gives coldx = ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX) - digitWidthAllowance.
|
|
22
|
+
*/
|
|
23
|
+
declare function pointsToColumnWidth(points: number): number;
|
|
10
24
|
//#endregion
|
|
11
|
-
export { columnWidthToPoints, twipsToPoints };
|
|
25
|
+
export { columnWidthToPoints, inchesToPoints, millimetresToPoints, pointsToColumnWidth, pointsToInches, pointsToTwips, twipsToPoints };
|
package/dist/units.d.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
//#region src/units.d.ts
|
|
2
2
|
/** A Row record's height, in twips, as points. */
|
|
3
3
|
declare function twipsToPoints(twips: number): number;
|
|
4
|
+
/** A margin record's own Xnum ([MS-XLS] 2.4.151 and its three siblings), in inches, as points. */
|
|
5
|
+
declare function inchesToPoints(inches: number): number;
|
|
6
|
+
/** The inverse, for writing a margin back out. Exact for every value inchesToPoints produces, since the conversion is a single multiplication by an integer. */
|
|
7
|
+
declare function pointsToInches(points: number): number;
|
|
8
|
+
/** A paper size [MS-XLS] 2.4.257's own code table states in millimetres, as points. */
|
|
9
|
+
declare function millimetresToPoints(millimetres: number): number;
|
|
4
10
|
/**
|
|
5
11
|
* A ColInfo record's coldx -- a width in 1/256ths of a character width ([MS-XLS] 2.4.53) -- as points.
|
|
6
12
|
*
|
|
7
13
|
* The pixel step reproduces Excel's own integer-pixel-grid truncation rather than smoothing it into a continuous formula, so a width read here matches the pixel count Excel itself would render, and matches what ooxml.js computes for the equivalent xlsx column.
|
|
8
14
|
*/
|
|
9
15
|
declare function columnWidthToPoints(coldx: number): number;
|
|
16
|
+
/** A Row record's own height field ([MS-XLS] 2.4.221 miyRw), in twips, rounded to the nearest whole twip and clamped to the field's own documented range (2-8192). The inverse of twipsToPoints, and exact for it: twipsToPoints(pointsToTwips(pt)) === pt for any pt this function does not clamp, since twips-per-point is an integer. */
|
|
17
|
+
declare function pointsToTwips(points: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* The inverse of columnWidthToPoints: the smallest ColInfo coldx whose own forward pixel-quantized width is at least as wide as the given points. Because columnWidthToPoints truncates to a whole pixel, no coldx reproduces an arbitrary points value exactly; this picks the smallest coldx that rounds UP to (rather than under) the requested width, so a column written from a given widthPt and read back through columnWidthToPoints never comes back narrower than what was asked for -- the same "honestly approximate" contract columnWidthToPoints's own comment already documents for the read direction.
|
|
20
|
+
*
|
|
21
|
+
* Derived directly from columnWidthToPoints's own forward formula: pixels(coldx) = floor((coldx + digitWidthAllowance) * MAX_DIGIT_WIDTH_PX / 256). Solving for the smallest coldx with pixels(coldx) >= targetPixels gives coldx = ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX) - digitWidthAllowance.
|
|
22
|
+
*/
|
|
23
|
+
declare function pointsToColumnWidth(points: number): number;
|
|
10
24
|
//#endregion
|
|
11
|
-
export { columnWidthToPoints, twipsToPoints };
|
|
25
|
+
export { columnWidthToPoints, inchesToPoints, millimetresToPoints, pointsToColumnWidth, pointsToInches, pointsToTwips, twipsToPoints };
|
package/dist/units.js
CHANGED
|
@@ -4,6 +4,8 @@ const POINTS_PER_INCH = 72;
|
|
|
4
4
|
const PIXELS_PER_INCH = 96;
|
|
5
5
|
/** A twip is a twentieth of a point; a Row record's miyRw is in twips ([MS-XLS] 2.4.221). */
|
|
6
6
|
const TWIPS_PER_POINT = 20;
|
|
7
|
+
/** The inch's own definition in millimetres, which is what turns [MS-XLS] 2.4.257's metric paper sizes into points. */
|
|
8
|
+
const MILLIMETRES_PER_INCH = 25.4;
|
|
7
9
|
/**
|
|
8
10
|
* The "maximum digit width": the widest rendered width, in pixels, of the digits 0-9 in the workbook's Normal-style font, which is the unit a column width is expressed in multiples of.
|
|
9
11
|
*
|
|
@@ -14,6 +16,18 @@ const MAX_DIGIT_WIDTH_PX = 7;
|
|
|
14
16
|
function twipsToPoints(twips) {
|
|
15
17
|
return twips / TWIPS_PER_POINT;
|
|
16
18
|
}
|
|
19
|
+
/** A margin record's own Xnum ([MS-XLS] 2.4.151 and its three siblings), in inches, as points. */
|
|
20
|
+
function inchesToPoints(inches) {
|
|
21
|
+
return inches * POINTS_PER_INCH;
|
|
22
|
+
}
|
|
23
|
+
/** The inverse, for writing a margin back out. Exact for every value inchesToPoints produces, since the conversion is a single multiplication by an integer. */
|
|
24
|
+
function pointsToInches(points) {
|
|
25
|
+
return points / POINTS_PER_INCH;
|
|
26
|
+
}
|
|
27
|
+
/** A paper size [MS-XLS] 2.4.257's own code table states in millimetres, as points. */
|
|
28
|
+
function millimetresToPoints(millimetres) {
|
|
29
|
+
return millimetres / MILLIMETRES_PER_INCH * POINTS_PER_INCH;
|
|
30
|
+
}
|
|
17
31
|
/**
|
|
18
32
|
* A ColInfo record's coldx -- a width in 1/256ths of a character width ([MS-XLS] 2.4.53) -- as points.
|
|
19
33
|
*
|
|
@@ -24,5 +38,23 @@ function columnWidthToPoints(coldx) {
|
|
|
24
38
|
const digitWidthAllowance = Math.trunc(128 / MAX_DIGIT_WIDTH_PX);
|
|
25
39
|
return Math.trunc((256 * chars + digitWidthAllowance) / 256 * MAX_DIGIT_WIDTH_PX) / PIXELS_PER_INCH * POINTS_PER_INCH;
|
|
26
40
|
}
|
|
41
|
+
/** A Row record's own height field ([MS-XLS] 2.4.221 miyRw), in twips, rounded to the nearest whole twip and clamped to the field's own documented range (2-8192). The inverse of twipsToPoints, and exact for it: twipsToPoints(pointsToTwips(pt)) === pt for any pt this function does not clamp, since twips-per-point is an integer. */
|
|
42
|
+
function pointsToTwips(points) {
|
|
43
|
+
const MIN_ROW_HEIGHT_TWIPS = 2;
|
|
44
|
+
const MAX_ROW_HEIGHT_TWIPS = 8192;
|
|
45
|
+
const twips = Math.round(points * TWIPS_PER_POINT);
|
|
46
|
+
return Math.min(Math.max(twips, MIN_ROW_HEIGHT_TWIPS), MAX_ROW_HEIGHT_TWIPS);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The inverse of columnWidthToPoints: the smallest ColInfo coldx whose own forward pixel-quantized width is at least as wide as the given points. Because columnWidthToPoints truncates to a whole pixel, no coldx reproduces an arbitrary points value exactly; this picks the smallest coldx that rounds UP to (rather than under) the requested width, so a column written from a given widthPt and read back through columnWidthToPoints never comes back narrower than what was asked for -- the same "honestly approximate" contract columnWidthToPoints's own comment already documents for the read direction.
|
|
50
|
+
*
|
|
51
|
+
* Derived directly from columnWidthToPoints's own forward formula: pixels(coldx) = floor((coldx + digitWidthAllowance) * MAX_DIGIT_WIDTH_PX / 256). Solving for the smallest coldx with pixels(coldx) >= targetPixels gives coldx = ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX) - digitWidthAllowance.
|
|
52
|
+
*/
|
|
53
|
+
function pointsToColumnWidth(points) {
|
|
54
|
+
const digitWidthAllowance = Math.trunc(128 / MAX_DIGIT_WIDTH_PX);
|
|
55
|
+
const targetPixels = Math.round(points / POINTS_PER_INCH * PIXELS_PER_INCH);
|
|
56
|
+
const coldx = Math.ceil(targetPixels * 256 / MAX_DIGIT_WIDTH_PX - digitWidthAllowance);
|
|
57
|
+
return Math.max(coldx, 0);
|
|
58
|
+
}
|
|
27
59
|
//#endregion
|
|
28
|
-
export { columnWidthToPoints, twipsToPoints };
|
|
60
|
+
export { columnWidthToPoints, inchesToPoints, millimetresToPoints, pointsToColumnWidth, pointsToInches, pointsToTwips, twipsToPoints };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_biff_record_types = require("../biff/record-types.cjs");
|
|
3
|
+
const require_biff_builder = require("../biff/builder.cjs");
|
|
4
|
+
const require_biff_record_writer = require("../biff/record-writer.cjs");
|
|
5
|
+
const require_workbook_print_names = require("./print-names.cjs");
|
|
6
|
+
const require_biff_bof_writer = require("../biff/bof-writer.cjs");
|
|
7
|
+
const require_biff_string_writer = require("../biff/string-writer.cjs");
|
|
8
|
+
const require_biff_xf_writer = require("../biff/xf-writer.cjs");
|
|
9
|
+
//#region src/workbook/globals-writer.ts
|
|
10
|
+
const GENERAL_FORMAT_ID = 0;
|
|
11
|
+
const NORMAL_FONT_INDEX = 0;
|
|
12
|
+
const NORMAL_FONT_NAME = "Arial";
|
|
13
|
+
/** Excel 97-2003's own Normal-style default: 10pt, in twips (dyHeight's own unit, [MS-XLS] 2.4.122). */
|
|
14
|
+
const NORMAL_FONT_HEIGHT_TWIPS = 200;
|
|
15
|
+
/** [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. */
|
|
16
|
+
const BUILTIN_STYLE_NORMAL = 0;
|
|
17
|
+
const BUILTIN_STYLE_ROW_LEVEL = 1;
|
|
18
|
+
const BUILTIN_STYLE_COL_LEVEL = 2;
|
|
19
|
+
/** BuiltInStyle's own iLevel sentinel for a style other than RowLevel/ColLevel: "otherwise, this value MUST be 0xFF". */
|
|
20
|
+
const NO_OUTLINE_LEVEL = 255;
|
|
21
|
+
/** RowLevel/ColLevel each cover seven outline depths ([MS-XLS] "BuiltInStyle"'s own 0x00-0x06 iLevel table). */
|
|
22
|
+
const OUTLINE_LEVEL_COUNT = 7;
|
|
23
|
+
/** 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. */
|
|
24
|
+
const BUILTIN_STYLES = [
|
|
25
|
+
{
|
|
26
|
+
istyBuiltIn: BUILTIN_STYLE_NORMAL,
|
|
27
|
+
iLevel: NO_OUTLINE_LEVEL
|
|
28
|
+
},
|
|
29
|
+
...Array.from({ length: OUTLINE_LEVEL_COUNT }, (_unused, level) => ({
|
|
30
|
+
istyBuiltIn: BUILTIN_STYLE_ROW_LEVEL,
|
|
31
|
+
iLevel: level
|
|
32
|
+
})),
|
|
33
|
+
...Array.from({ length: OUTLINE_LEVEL_COUNT }, (_unused, level) => ({
|
|
34
|
+
istyBuiltIn: BUILTIN_STYLE_COL_LEVEL,
|
|
35
|
+
iLevel: level
|
|
36
|
+
}))
|
|
37
|
+
];
|
|
38
|
+
/** [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. */
|
|
39
|
+
const GENERAL_CELL_XF_INDEX = BUILTIN_STYLES.length;
|
|
40
|
+
/** 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. */
|
|
41
|
+
function writeBoundSheet8Placeholder(name) {
|
|
42
|
+
const data = new require_biff_builder.RecordBuilder().u32(0).u8(0).u8(0).bytes(require_biff_string_writer.writeShortXLUnicodeString(name)).build();
|
|
43
|
+
return require_biff_record_writer.writeRecord(133, data);
|
|
44
|
+
}
|
|
45
|
+
/** [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. */
|
|
46
|
+
const SUPBOOK_SELF_REFERENCING_CCH = 1025;
|
|
47
|
+
/** 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. */
|
|
48
|
+
function writeSupBookRecord(sheetCount) {
|
|
49
|
+
return require_biff_record_writer.writeRecord(430, new require_biff_builder.RecordBuilder().u16(sheetCount).u16(SUPBOOK_SELF_REFERENCING_CCH).build());
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 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.
|
|
53
|
+
*
|
|
54
|
+
* 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.
|
|
55
|
+
*/
|
|
56
|
+
function writeExternSheetRecord(sheetCount) {
|
|
57
|
+
const builder = new require_biff_builder.RecordBuilder().u16(sheetCount);
|
|
58
|
+
for (let sheetIndex = 0; sheetIndex < sheetCount; sheetIndex += 1) builder.u16(0).u16(sheetIndex).u16(sheetIndex);
|
|
59
|
+
return require_biff_record_writer.writeRecord(23, builder.build());
|
|
60
|
+
}
|
|
61
|
+
/** 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. */
|
|
62
|
+
function writeSstRecord(strings, totalCount) {
|
|
63
|
+
const builder = new require_biff_builder.RecordBuilder().i32(totalCount).i32(strings.length);
|
|
64
|
+
for (const text of strings) builder.bytes(require_biff_string_writer.writeRichExtendedString(text));
|
|
65
|
+
return require_biff_record_writer.writeRecord(252, builder.build());
|
|
66
|
+
}
|
|
67
|
+
function buildWorkbookGlobals(plan) {
|
|
68
|
+
const pieces = [];
|
|
69
|
+
let offset = 0;
|
|
70
|
+
const push = (piece) => {
|
|
71
|
+
pieces.push(piece);
|
|
72
|
+
offset += piece.length;
|
|
73
|
+
};
|
|
74
|
+
push(require_biff_record_writer.writeRecord(require_biff_record_types.RECORD_BOF, require_biff_bof_writer.writeBofData(5)));
|
|
75
|
+
push(require_biff_xf_writer.writeFontRecord(NORMAL_FONT_NAME, NORMAL_FONT_HEIGHT_TWIPS));
|
|
76
|
+
for (const code of plan.customFormats) push(require_biff_xf_writer.writeFormatRecord(code.id, code.code));
|
|
77
|
+
BUILTIN_STYLES.forEach(() => {
|
|
78
|
+
push(require_biff_xf_writer.writeStyleXfRecord({
|
|
79
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
80
|
+
formatId: GENERAL_FORMAT_ID
|
|
81
|
+
}));
|
|
82
|
+
});
|
|
83
|
+
push(require_biff_xf_writer.writeCellXfRecord({
|
|
84
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
85
|
+
formatId: GENERAL_FORMAT_ID
|
|
86
|
+
}));
|
|
87
|
+
for (const entry of plan.cellXfEntries) push(require_biff_xf_writer.writeCellXfRecord({
|
|
88
|
+
fontIndex: NORMAL_FONT_INDEX,
|
|
89
|
+
formatId: entry.formatId,
|
|
90
|
+
alignment: entry.alignment,
|
|
91
|
+
verticalAlignment: entry.verticalAlignment,
|
|
92
|
+
decoration: entry.decoration
|
|
93
|
+
}));
|
|
94
|
+
BUILTIN_STYLES.forEach((builtin, index) => {
|
|
95
|
+
push(require_biff_xf_writer.writeStyleRecord({
|
|
96
|
+
xfIndex: index,
|
|
97
|
+
istyBuiltIn: builtin.istyBuiltIn,
|
|
98
|
+
iLevel: builtin.iLevel
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
101
|
+
if (plan.paletteColors !== void 0) push(require_biff_xf_writer.writePaletteRecord(plan.paletteColors));
|
|
102
|
+
const lbPlyPosOffsets = [];
|
|
103
|
+
for (const name of plan.sheetNames) {
|
|
104
|
+
const recordStart = offset;
|
|
105
|
+
lbPlyPosOffsets.push(recordStart + 4);
|
|
106
|
+
push(writeBoundSheet8Placeholder(name));
|
|
107
|
+
}
|
|
108
|
+
if (plan.printNames.length > 0) {
|
|
109
|
+
push(writeSupBookRecord(plan.sheetNames.length));
|
|
110
|
+
push(writeExternSheetRecord(plan.sheetNames.length));
|
|
111
|
+
for (const record of require_workbook_print_names.writePrintNameRecords(plan.printNames)) push(record);
|
|
112
|
+
}
|
|
113
|
+
if (plan.sharedStrings.length > 0) push(writeSstRecord(plan.sharedStrings, plan.sharedStringTotalCount));
|
|
114
|
+
push(require_biff_record_writer.writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
115
|
+
return {
|
|
116
|
+
bytes: require_biff_record_writer.concatRecords(...pieces),
|
|
117
|
+
lbPlyPosOffsets
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
exports.GENERAL_CELL_XF_INDEX = GENERAL_CELL_XF_INDEX;
|
|
122
|
+
exports.buildWorkbookGlobals = buildWorkbookGlobals;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { T as XfDecorationFields } from "../xf-colors-CehHZtBy.cjs";
|
|
2
|
+
import { t as PrintNamePlanEntry } from "../print-names-D-njuzVw.cjs";
|
|
3
|
+
import { Alignment, Color } from "document-schema.js";
|
|
4
|
+
//#region src/workbook/globals-writer.d.ts
|
|
5
|
+
/** [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. */
|
|
6
|
+
declare const GENERAL_CELL_XF_INDEX: number;
|
|
7
|
+
/** One cell XF beyond the implicit General one at GENERAL_CELL_XF_INDEX: the number-format identifier it displays through, the cell's own horizontal/vertical alignment (general/bottom, this writer's own defaults, when omitted), and -- when the cell it serves carries a background or borders -- the fill/border fields its CellXF payload packs. Undefined decoration writes the same undecorated defaults this writer always wrote before decoration existed. */
|
|
8
|
+
interface CellXfPlanEntry {
|
|
9
|
+
readonly formatId: number;
|
|
10
|
+
readonly alignment?: Alignment;
|
|
11
|
+
readonly verticalAlignment?: "top" | "middle" | "bottom";
|
|
12
|
+
readonly decoration?: XfDecorationFields;
|
|
13
|
+
}
|
|
14
|
+
interface WorkbookGlobalsPlan {
|
|
15
|
+
readonly sheetNames: readonly string[];
|
|
16
|
+
/** Custom number-format codes needing their own Format record, each with the identifier already assigned to it (always >= 164, [MS-XLS] 2.4.126's own custom-identifier floor). A code equal to one of the built-in table's own strings needs no Format record here -- number-format.ts's BUILTIN_NUMBER_FORMATS already covers ids 0-49 for both this package's reader and any other. */
|
|
17
|
+
readonly customFormats: readonly {
|
|
18
|
+
readonly id: number;
|
|
19
|
+
readonly code: string;
|
|
20
|
+
}[];
|
|
21
|
+
/** Every cell XF beyond the implicit General one at GENERAL_CELL_XF_INDEX, in the order their XF records are written: index GENERAL_CELL_XF_INDEX + 1 + i is entry cellXfEntries[i]. write.ts's own cell-format interning pass assigns one entry to every distinct (number format, decoration) combination the workbook's cells actually use. */
|
|
22
|
+
readonly cellXfEntries: readonly CellXfPlanEntry[];
|
|
23
|
+
/** The shared string table, in SST order -- a LabelSst cell's own isst indexes into this array. */
|
|
24
|
+
readonly sharedStrings: readonly string[];
|
|
25
|
+
/** SST's own cstTotal: the total number of string-cell references across the whole workbook, not just the unique count. Not read by this package's own reader (which discards the field), but a real conformant value rather than a placeholder. */
|
|
26
|
+
readonly sharedStringTotalCount: number;
|
|
27
|
+
/** The workbook's own custom colour table (56 entries, icv 8 first), when write.ts's own palette-interning pass decided the workbook needs one -- undefined when every decoration colour the workbook's cells use already matches the fixed default table, in which case no Palette record is written at all and those colours resolve through the default table instead ([MS-XLS] "Icv"'s own documented fallback). */
|
|
28
|
+
readonly paletteColors?: readonly Color[];
|
|
29
|
+
/** The built-in Print_Area/Print_Titles defined names the workbook's sheets declare, one Lbl record each. Empty when no sheet declares a print range or a repeated header band, in which case no SupBook, ExternSheet, or Lbl record is written at all -- exactly like Palette above, a workbook that needs none stays as minimal as it always was. */
|
|
30
|
+
readonly printNames: readonly PrintNamePlanEntry[];
|
|
31
|
+
}
|
|
32
|
+
interface WorkbookGlobalsBuild {
|
|
33
|
+
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
34
|
+
/** Byte offset, within `bytes`, of each sheet's own BoundSheet8.lbPlyPos field ([MS-XLS] 2.4.28) -- a 4-byte little-endian integer the caller patches once every sheet substream's own length in the final workbook stream is known. In `plan.sheetNames` order. */
|
|
35
|
+
readonly lbPlyPosOffsets: readonly number[];
|
|
36
|
+
}
|
|
37
|
+
declare function buildWorkbookGlobals(plan: WorkbookGlobalsPlan): WorkbookGlobalsBuild;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { CellXfPlanEntry, GENERAL_CELL_XF_INDEX, WorkbookGlobalsBuild, WorkbookGlobalsPlan, buildWorkbookGlobals };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { T as XfDecorationFields } from "../xf-colors-CpykR3B9.js";
|
|
2
|
+
import { t as PrintNamePlanEntry } from "../print-names-DUlpVE00.js";
|
|
3
|
+
import { Alignment, Color } from "document-schema.js";
|
|
4
|
+
//#region src/workbook/globals-writer.d.ts
|
|
5
|
+
/** [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. */
|
|
6
|
+
declare const GENERAL_CELL_XF_INDEX: number;
|
|
7
|
+
/** One cell XF beyond the implicit General one at GENERAL_CELL_XF_INDEX: the number-format identifier it displays through, the cell's own horizontal/vertical alignment (general/bottom, this writer's own defaults, when omitted), and -- when the cell it serves carries a background or borders -- the fill/border fields its CellXF payload packs. Undefined decoration writes the same undecorated defaults this writer always wrote before decoration existed. */
|
|
8
|
+
interface CellXfPlanEntry {
|
|
9
|
+
readonly formatId: number;
|
|
10
|
+
readonly alignment?: Alignment;
|
|
11
|
+
readonly verticalAlignment?: "top" | "middle" | "bottom";
|
|
12
|
+
readonly decoration?: XfDecorationFields;
|
|
13
|
+
}
|
|
14
|
+
interface WorkbookGlobalsPlan {
|
|
15
|
+
readonly sheetNames: readonly string[];
|
|
16
|
+
/** Custom number-format codes needing their own Format record, each with the identifier already assigned to it (always >= 164, [MS-XLS] 2.4.126's own custom-identifier floor). A code equal to one of the built-in table's own strings needs no Format record here -- number-format.ts's BUILTIN_NUMBER_FORMATS already covers ids 0-49 for both this package's reader and any other. */
|
|
17
|
+
readonly customFormats: readonly {
|
|
18
|
+
readonly id: number;
|
|
19
|
+
readonly code: string;
|
|
20
|
+
}[];
|
|
21
|
+
/** Every cell XF beyond the implicit General one at GENERAL_CELL_XF_INDEX, in the order their XF records are written: index GENERAL_CELL_XF_INDEX + 1 + i is entry cellXfEntries[i]. write.ts's own cell-format interning pass assigns one entry to every distinct (number format, decoration) combination the workbook's cells actually use. */
|
|
22
|
+
readonly cellXfEntries: readonly CellXfPlanEntry[];
|
|
23
|
+
/** The shared string table, in SST order -- a LabelSst cell's own isst indexes into this array. */
|
|
24
|
+
readonly sharedStrings: readonly string[];
|
|
25
|
+
/** SST's own cstTotal: the total number of string-cell references across the whole workbook, not just the unique count. Not read by this package's own reader (which discards the field), but a real conformant value rather than a placeholder. */
|
|
26
|
+
readonly sharedStringTotalCount: number;
|
|
27
|
+
/** The workbook's own custom colour table (56 entries, icv 8 first), when write.ts's own palette-interning pass decided the workbook needs one -- undefined when every decoration colour the workbook's cells use already matches the fixed default table, in which case no Palette record is written at all and those colours resolve through the default table instead ([MS-XLS] "Icv"'s own documented fallback). */
|
|
28
|
+
readonly paletteColors?: readonly Color[];
|
|
29
|
+
/** The built-in Print_Area/Print_Titles defined names the workbook's sheets declare, one Lbl record each. Empty when no sheet declares a print range or a repeated header band, in which case no SupBook, ExternSheet, or Lbl record is written at all -- exactly like Palette above, a workbook that needs none stays as minimal as it always was. */
|
|
30
|
+
readonly printNames: readonly PrintNamePlanEntry[];
|
|
31
|
+
}
|
|
32
|
+
interface WorkbookGlobalsBuild {
|
|
33
|
+
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
34
|
+
/** Byte offset, within `bytes`, of each sheet's own BoundSheet8.lbPlyPos field ([MS-XLS] 2.4.28) -- a 4-byte little-endian integer the caller patches once every sheet substream's own length in the final workbook stream is known. In `plan.sheetNames` order. */
|
|
35
|
+
readonly lbPlyPosOffsets: readonly number[];
|
|
36
|
+
}
|
|
37
|
+
declare function buildWorkbookGlobals(plan: WorkbookGlobalsPlan): WorkbookGlobalsBuild;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { CellXfPlanEntry, GENERAL_CELL_XF_INDEX, WorkbookGlobalsBuild, WorkbookGlobalsPlan, buildWorkbookGlobals };
|