xls-codec 4.12.5 → 4.13.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 +3 -1
- package/dist/biff/font.cjs +127 -0
- package/dist/biff/font.d.cts +2 -0
- package/dist/biff/font.d.ts +2 -0
- package/dist/biff/font.js +119 -0
- package/dist/biff/ptg-writer.cjs +1 -1
- package/dist/biff/ptg-writer.js +1 -1
- package/dist/biff/string-writer.cjs +1 -1
- package/dist/biff/string-writer.js +1 -1
- package/dist/biff/xf-writer.cjs +1 -22
- package/dist/biff/xf-writer.d.cts +1 -2
- package/dist/biff/xf-writer.d.ts +1 -2
- package/dist/biff/xf-writer.js +2 -22
- package/dist/{conditional-format-12-C3nwy1f8.d.ts → conditional-format-12-BTN59oHJ.d.ts} +2 -2
- package/dist/{conditional-format-12-D65-ruTq.d.cts → conditional-format-12-ZkrPfAP4.d.cts} +2 -2
- package/dist/{conditional-format-Cth_afMy.d.cts → conditional-format-BzTJe8Fm.d.cts} +1 -1
- package/dist/{conditional-format-BRMUTRP1.d.ts → conditional-format-D4U0eLcY.d.ts} +1 -1
- package/dist/content.cjs +52 -6
- package/dist/content.js +52 -6
- package/dist/{data-validation-BgUt8CbE.d.cts → data-validation-CTeIudWM.d.cts} +1 -1
- package/dist/{data-validation-Cq6iD8lB.d.ts → data-validation-Cjdk9imN.d.ts} +1 -1
- package/dist/defined-names-CqBJJmOJ.d.cts +39 -0
- package/dist/defined-names-DJZ27hRp.d.ts +39 -0
- package/dist/font-CBvAGxD8.d.cts +45 -0
- package/dist/font-DcXHYgZ2.d.ts +45 -0
- package/dist/index.cjs +5 -6
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +7 -7
- package/dist/workbook/chart.d.cts +1 -1
- package/dist/workbook/chart.d.ts +1 -1
- package/dist/workbook/comment-writer.cjs +1 -1
- package/dist/workbook/comment-writer.js +1 -1
- package/dist/workbook/conditional-format-12.d.cts +1 -1
- package/dist/workbook/conditional-format-12.d.ts +1 -1
- package/dist/workbook/conditional-format-ex.d.cts +3 -3
- package/dist/workbook/conditional-format-ex.d.ts +3 -3
- package/dist/workbook/conditional-format-write.cjs +1 -1
- package/dist/workbook/conditional-format-write.js +1 -1
- package/dist/workbook/conditional-format.cjs +1 -1
- package/dist/workbook/conditional-format.d.cts +1 -1
- package/dist/workbook/conditional-format.d.ts +1 -1
- package/dist/workbook/conditional-format.js +1 -1
- package/dist/workbook/data-validation-write.cjs +1 -1
- package/dist/workbook/data-validation-write.js +1 -1
- package/dist/workbook/data-validation.d.cts +1 -1
- package/dist/workbook/data-validation.d.ts +1 -1
- package/dist/workbook/defined-names.cjs +186 -0
- package/dist/workbook/defined-names.d.cts +2 -0
- package/dist/workbook/defined-names.d.ts +2 -0
- package/dist/workbook/defined-names.js +182 -0
- package/dist/workbook/drawing.d.cts +1 -1
- package/dist/workbook/drawing.d.ts +1 -1
- package/dist/workbook/globals-writer.cjs +7 -7
- package/dist/workbook/globals-writer.d.cts +9 -2
- package/dist/workbook/globals-writer.d.ts +9 -2
- package/dist/workbook/globals-writer.js +8 -8
- package/dist/workbook/globals.cjs +8 -2
- package/dist/workbook/globals.d.cts +6 -1
- package/dist/workbook/globals.d.ts +6 -1
- package/dist/workbook/globals.js +8 -2
- package/dist/workbook/print-names.cjs +1 -1
- package/dist/workbook/print-names.js +1 -1
- package/dist/workbook/sheet-writer.cjs +4 -4
- package/dist/workbook/sheet-writer.js +4 -4
- package/dist/workbook/sheet.cjs +1 -1
- package/dist/workbook/sheet.d.cts +4 -4
- package/dist/workbook/sheet.d.ts +4 -4
- package/dist/workbook/sheet.js +1 -1
- package/dist/write.cjs +56 -12
- package/dist/write.js +57 -13
- package/dist/written-cells.cjs +4 -2
- package/dist/written-cells.d.cts +2 -2
- package/dist/written-cells.d.ts +2 -2
- package/dist/written-cells.js +4 -2
- package/package.json +3 -3
|
@@ -1,10 +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 require_biff_substreams = require("../biff/substreams.cjs");
|
|
5
|
-
const require_biff_xf_colors = require("../biff/xf-colors.cjs");
|
|
6
4
|
const require_biff_cursor = require("../biff/cursor.cjs");
|
|
7
5
|
const require_biff_strings = require("../biff/strings.cjs");
|
|
6
|
+
const require_biff_xf_colors = require("../biff/xf-colors.cjs");
|
|
7
|
+
const require_biff_font = require("../biff/font.cjs");
|
|
8
|
+
const require_biff_substreams = require("../biff/substreams.cjs");
|
|
8
9
|
const require_workbook_print_names = require("./print-names.cjs");
|
|
9
10
|
let excel_number_format = require("excel-number-format");
|
|
10
11
|
//#region src/workbook/globals.ts
|
|
@@ -19,6 +20,7 @@ const MIN_SST_ENTRY_BYTES = 3;
|
|
|
19
20
|
function readWorkbookGlobals(records) {
|
|
20
21
|
const sheets = [];
|
|
21
22
|
const cellFormats = [];
|
|
23
|
+
const fonts = [];
|
|
22
24
|
const customFormats = /* @__PURE__ */ new Map();
|
|
23
25
|
const supBooks = [];
|
|
24
26
|
let sharedStrings = [];
|
|
@@ -40,6 +42,9 @@ function readWorkbookGlobals(records) {
|
|
|
40
42
|
case 224:
|
|
41
43
|
cellFormats.push(readCellFormat(record));
|
|
42
44
|
break;
|
|
45
|
+
case 49:
|
|
46
|
+
fonts.push(require_biff_font.readFontRecord(record));
|
|
47
|
+
break;
|
|
43
48
|
case 34:
|
|
44
49
|
date1904 = readDate1904(record);
|
|
45
50
|
break;
|
|
@@ -58,6 +63,7 @@ function readWorkbookGlobals(records) {
|
|
|
58
63
|
sheets,
|
|
59
64
|
sharedStrings,
|
|
60
65
|
cellFormats,
|
|
66
|
+
fonts,
|
|
61
67
|
numberFormats,
|
|
62
68
|
date1904,
|
|
63
69
|
sheetRanges,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as SheetRange, t as ExternalSheetLabel } from "../ptg-75v7MhaA.cjs";
|
|
2
1
|
import { t as RecordGroup } from "../substreams-XDNgDvRJ.cjs";
|
|
2
|
+
import { r as XfFontFields } from "../font-CBvAGxD8.cjs";
|
|
3
|
+
import { a as SheetRange, t as ExternalSheetLabel } from "../ptg-75v7MhaA.cjs";
|
|
3
4
|
import { E as XfDecorationFields, w as XfAlignmentFields } from "../xf-colors-aeH9Ax3Q.cjs";
|
|
4
5
|
import { n as SheetPrintNames } from "../print-names-B2OR0fvs.cjs";
|
|
5
6
|
import { Color } from "document-schema.js";
|
|
@@ -36,6 +37,10 @@ interface WorkbookGlobals {
|
|
|
36
37
|
readonly sharedStrings: readonly string[];
|
|
37
38
|
/** The XF table, indexed by a cell's own ixfe. */
|
|
38
39
|
readonly cellFormats: readonly CellFormat[];
|
|
40
|
+
/**
|
|
41
|
+
* The font table, indexed by an XF record's own ifnt ([MS-XLS] 2.4.122). Entry 0 is the Normal style's font -- the workbook's own default, which content.ts diffs each cell's font against to decide which of its properties the cell genuinely states (a cell has no way to say "no font", only an index into this table, so entry 0 is what "the format's default" concretely means here).
|
|
42
|
+
*/
|
|
43
|
+
readonly fonts: readonly XfFontFields[];
|
|
39
44
|
/** Number-format codes by identifier: the file's own Format records laid over the built-in table. */
|
|
40
45
|
readonly numberFormats: ReadonlyMap<number, string>;
|
|
41
46
|
/** Whether serials count from the 1904 epoch rather than the 1900 one ([MS-XLS] 2.4.77). */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as SheetRange, t as ExternalSheetLabel } from "../ptg-75v7MhaA.js";
|
|
2
1
|
import { t as RecordGroup } from "../substreams-CgTHx5kX.js";
|
|
2
|
+
import { r as XfFontFields } from "../font-DcXHYgZ2.js";
|
|
3
|
+
import { a as SheetRange, t as ExternalSheetLabel } from "../ptg-75v7MhaA.js";
|
|
3
4
|
import { E as XfDecorationFields, w as XfAlignmentFields } from "../xf-colors-kdNsiNYt.js";
|
|
4
5
|
import { n as SheetPrintNames } from "../print-names-BXcmmwVi.js";
|
|
5
6
|
import { Color } from "document-schema.js";
|
|
@@ -36,6 +37,10 @@ interface WorkbookGlobals {
|
|
|
36
37
|
readonly sharedStrings: readonly string[];
|
|
37
38
|
/** The XF table, indexed by a cell's own ixfe. */
|
|
38
39
|
readonly cellFormats: readonly CellFormat[];
|
|
40
|
+
/**
|
|
41
|
+
* The font table, indexed by an XF record's own ifnt ([MS-XLS] 2.4.122). Entry 0 is the Normal style's font -- the workbook's own default, which content.ts diffs each cell's font against to decide which of its properties the cell genuinely states (a cell has no way to say "no font", only an index into this table, so entry 0 is what "the format's default" concretely means here).
|
|
42
|
+
*/
|
|
43
|
+
readonly fonts: readonly XfFontFields[];
|
|
39
44
|
/** Number-format codes by identifier: the file's own Format records laid over the built-in table. */
|
|
40
45
|
readonly numberFormats: ReadonlyMap<number, string>;
|
|
41
46
|
/** Whether serials count from the 1904 epoch rather than the 1900 one ([MS-XLS] 2.4.77). */
|
package/dist/workbook/globals.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { RECORD_FORMAT } from "../biff/record-types.js";
|
|
2
2
|
import { BiffFormatError } from "../biff/records.js";
|
|
3
|
-
import { recordByteLength } from "../biff/substreams.js";
|
|
4
|
-
import { readLongRgbColor, unpackXfAlignment, unpackXfDecoration } from "../biff/xf-colors.js";
|
|
5
3
|
import { BlockCursor } from "../biff/cursor.js";
|
|
6
4
|
import { readRichExtendedString, readShortXLUnicodeString, readXLUnicodeString, readXLUnicodeStringNoCch } from "../biff/strings.js";
|
|
5
|
+
import { readLongRgbColor, unpackXfAlignment, unpackXfDecoration } from "../biff/xf-colors.js";
|
|
6
|
+
import { readFontRecord } from "../biff/font.js";
|
|
7
|
+
import { recordByteLength } from "../biff/substreams.js";
|
|
7
8
|
import { readPrintNames } from "./print-names.js";
|
|
8
9
|
import { BUILTIN_NUMBER_FORMATS } from "excel-number-format";
|
|
9
10
|
//#region src/workbook/globals.ts
|
|
@@ -18,6 +19,7 @@ const MIN_SST_ENTRY_BYTES = 3;
|
|
|
18
19
|
function readWorkbookGlobals(records) {
|
|
19
20
|
const sheets = [];
|
|
20
21
|
const cellFormats = [];
|
|
22
|
+
const fonts = [];
|
|
21
23
|
const customFormats = /* @__PURE__ */ new Map();
|
|
22
24
|
const supBooks = [];
|
|
23
25
|
let sharedStrings = [];
|
|
@@ -39,6 +41,9 @@ function readWorkbookGlobals(records) {
|
|
|
39
41
|
case 224:
|
|
40
42
|
cellFormats.push(readCellFormat(record));
|
|
41
43
|
break;
|
|
44
|
+
case 49:
|
|
45
|
+
fonts.push(readFontRecord(record));
|
|
46
|
+
break;
|
|
42
47
|
case 34:
|
|
43
48
|
date1904 = readDate1904(record);
|
|
44
49
|
break;
|
|
@@ -57,6 +62,7 @@ function readWorkbookGlobals(records) {
|
|
|
57
62
|
sheets,
|
|
58
63
|
sharedStrings,
|
|
59
64
|
cellFormats,
|
|
65
|
+
fonts,
|
|
60
66
|
numberFormats,
|
|
61
67
|
date1904,
|
|
62
68
|
sheetRanges,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../biff/record-types.cjs");
|
|
3
|
-
const require_biff_cursor = require("../biff/cursor.cjs");
|
|
4
3
|
const require_biff_builder = require("../biff/builder.cjs");
|
|
4
|
+
const require_biff_cursor = require("../biff/cursor.cjs");
|
|
5
5
|
const require_biff_record_writer = require("../biff/record-writer.cjs");
|
|
6
6
|
//#region src/workbook/print-names.ts
|
|
7
7
|
/** The built-in name index a Print_Area Lbl carries in place of a name ([MS-XLS] 2.4.150's own built-in name table). */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../biff/record-types.js";
|
|
2
|
-
import { BlockCursor } from "../biff/cursor.js";
|
|
3
2
|
import { RecordBuilder } from "../biff/builder.js";
|
|
3
|
+
import { BlockCursor } from "../biff/cursor.js";
|
|
4
4
|
import { writeRecord } from "../biff/record-writer.js";
|
|
5
5
|
//#region src/workbook/print-names.ts
|
|
6
6
|
/** The built-in name index a Print_Area Lbl carries in place of a name ([MS-XLS] 2.4.150's own built-in name table). */
|
|
@@ -2,13 +2,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_biff_record_types = require("../biff/record-types.cjs");
|
|
3
3
|
const require_units = require("../units.cjs");
|
|
4
4
|
const require_biff_print_setup = require("../biff/print-setup.cjs");
|
|
5
|
-
const require_biff_errors = require("../biff/errors.cjs");
|
|
6
|
-
const require_biff_write_errors = require("../biff/write-errors.cjs");
|
|
7
|
-
const require_serial = require("../serial.cjs");
|
|
8
5
|
const require_biff_builder = require("../biff/builder.cjs");
|
|
6
|
+
const require_biff_write_errors = require("../biff/write-errors.cjs");
|
|
9
7
|
const require_biff_record_writer = require("../biff/record-writer.cjs");
|
|
10
|
-
const
|
|
8
|
+
const require_biff_errors = require("../biff/errors.cjs");
|
|
11
9
|
const require_biff_string_writer = require("../biff/string-writer.cjs");
|
|
10
|
+
const require_serial = require("../serial.cjs");
|
|
11
|
+
const require_biff_bof_writer = require("../biff/bof-writer.cjs");
|
|
12
12
|
const require_workbook_globals_writer = require("./globals-writer.cjs");
|
|
13
13
|
const require_biff_ptg_writer = require("../biff/ptg-writer.cjs");
|
|
14
14
|
const require_written_cells = require("../written-cells.cjs");
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { RECORD_BOF } from "../biff/record-types.js";
|
|
2
2
|
import { pointsToColumnWidth, pointsToInches, pointsToTwips } from "../units.js";
|
|
3
3
|
import { packSetupFlags, paperSelectionFor } from "../biff/print-setup.js";
|
|
4
|
-
import { errorCodeOf } from "../biff/errors.js";
|
|
5
|
-
import { BiffWriteError } from "../biff/write-errors.js";
|
|
6
|
-
import { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial } from "../serial.js";
|
|
7
4
|
import { RecordBuilder } from "../biff/builder.js";
|
|
5
|
+
import { BiffWriteError } from "../biff/write-errors.js";
|
|
8
6
|
import { concatRecords, writeRecord } from "../biff/record-writer.js";
|
|
9
|
-
import {
|
|
7
|
+
import { errorCodeOf } from "../biff/errors.js";
|
|
10
8
|
import { writeXLUnicodeString } from "../biff/string-writer.js";
|
|
9
|
+
import { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial } from "../serial.js";
|
|
10
|
+
import { writeBofData } from "../biff/bof-writer.js";
|
|
11
11
|
import { GENERAL_CELL_XF_INDEX } from "./globals-writer.js";
|
|
12
12
|
import { compileFormulaText } from "../biff/ptg-writer.js";
|
|
13
13
|
import { cellCarriesFormatting, writesCellRecord } from "../written-cells.js";
|
package/dist/workbook/sheet.cjs
CHANGED
|
@@ -3,9 +3,9 @@ const require_biff_record_types = require("../biff/record-types.cjs");
|
|
|
3
3
|
const require_biff_records = require("../biff/records.cjs");
|
|
4
4
|
const require_units = require("../units.cjs");
|
|
5
5
|
const require_biff_print_setup = require("../biff/print-setup.cjs");
|
|
6
|
-
const require_biff_substreams = require("../biff/substreams.cjs");
|
|
7
6
|
const require_biff_cursor = require("../biff/cursor.cjs");
|
|
8
7
|
const require_biff_strings = require("../biff/strings.cjs");
|
|
8
|
+
const require_biff_substreams = require("../biff/substreams.cjs");
|
|
9
9
|
const require_biff_errors = require("../biff/errors.cjs");
|
|
10
10
|
const require_biff_ptg = require("../biff/ptg.cjs");
|
|
11
11
|
const require_biff_rk = require("../biff/rk.cjs");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { t as RecordGroup } from "../substreams-XDNgDvRJ.cjs";
|
|
1
2
|
import { n as SetupFields } from "../print-setup-B_ihDvm5.cjs";
|
|
2
3
|
import { r as FormulaSheetContext } from "../ptg-75v7MhaA.cjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { t as RawDataValidation } from "../data-validation-BgUt8CbE.cjs";
|
|
4
|
+
import { r as RawConditionalFormat } from "../conditional-format-BzTJe8Fm.cjs";
|
|
5
|
+
import { a as RawConditionalFormat12 } from "../conditional-format-12-ZkrPfAP4.cjs";
|
|
6
|
+
import { t as RawDataValidation } from "../data-validation-CTeIudWM.cjs";
|
|
7
7
|
//#region src/workbook/sheet.d.ts
|
|
8
8
|
/** A cell's value as its own record carries it, before number-format classification decides whether a number is really a date, a percentage, or an amount of money. */
|
|
9
9
|
type RawCellValue = {
|
package/dist/workbook/sheet.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { t as RecordGroup } from "../substreams-CgTHx5kX.js";
|
|
1
2
|
import { n as SetupFields } from "../print-setup-B_ihDvm5.js";
|
|
2
3
|
import { r as FormulaSheetContext } from "../ptg-75v7MhaA.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { t as RawDataValidation } from "../data-validation-Cq6iD8lB.js";
|
|
4
|
+
import { r as RawConditionalFormat } from "../conditional-format-D4U0eLcY.js";
|
|
5
|
+
import { a as RawConditionalFormat12 } from "../conditional-format-12-BTN59oHJ.js";
|
|
6
|
+
import { t as RawDataValidation } from "../data-validation-Cjdk9imN.js";
|
|
7
7
|
//#region src/workbook/sheet.d.ts
|
|
8
8
|
/** A cell's value as its own record carries it, before number-format classification decides whether a number is really a date, a percentage, or an amount of money. */
|
|
9
9
|
type RawCellValue = {
|
package/dist/workbook/sheet.js
CHANGED
|
@@ -2,9 +2,9 @@ import { RECORD_CFEX, RECORD_CONDFMT12 } from "../biff/record-types.js";
|
|
|
2
2
|
import { BiffFormatError } from "../biff/records.js";
|
|
3
3
|
import { columnWidthToPoints, inchesToPoints, twipsToPoints } from "../units.js";
|
|
4
4
|
import { unpackSetupFlags } from "../biff/print-setup.js";
|
|
5
|
-
import { recordByteLength } from "../biff/substreams.js";
|
|
6
5
|
import { BlockCursor } from "../biff/cursor.js";
|
|
7
6
|
import { readXLUnicodeString } from "../biff/strings.js";
|
|
7
|
+
import { recordByteLength } from "../biff/substreams.js";
|
|
8
8
|
import { errorTextOf } from "../biff/errors.js";
|
|
9
9
|
import { parseFormulaText, readPtgExpBase } from "../biff/ptg.js";
|
|
10
10
|
import { decodeRkNumber } from "../biff/rk.js";
|
package/dist/write.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_container = require("./container.cjs");
|
|
3
|
-
const require_biff_xf_colors = require("./biff/xf-colors.cjs");
|
|
4
3
|
const require_biff_write_errors = require("./biff/write-errors.cjs");
|
|
4
|
+
const require_biff_xf_colors = require("./biff/xf-colors.cjs");
|
|
5
|
+
const require_biff_font = require("./biff/font.cjs");
|
|
6
|
+
const require_workbook_defined_names = require("./workbook/defined-names.cjs");
|
|
5
7
|
const require_workbook_print_names = require("./workbook/print-names.cjs");
|
|
6
8
|
const require_metadata = require("./metadata.cjs");
|
|
7
9
|
const require_workbook_globals_writer = require("./workbook/globals-writer.cjs");
|
|
@@ -41,8 +43,16 @@ function defaultFormatIdForKind(kind) {
|
|
|
41
43
|
case "empty": return GENERAL_FORMAT_ID;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* The number-format code a cell resolves through -- its own explicit numberFormatCode, a `[$USD]#,##0.00`-shaped code for a currency cell that names an ISO 4217 code of its own (see below), or the built-in code for its value kind's own default identifier. This is called identically during the workbook-wide format scan and later per cell, so the two can never resolve a cell to different codes.
|
|
48
|
+
*
|
|
49
|
+
* The ISO-code bracket is the one carrier a currency code survives the round trip through: the format string IS where BIFF8 states a cell's currency, and the classifier this package's own reader reads it back through recovers the code from exactly that bracket -- writing the symbol instead would render identically and lose the code permanently, since no faithful symbol-to-code mapping exists on the way back ('$' alone is USD, CAD, AUD and a dozen others). That is the identical encoding ooxml.js's own typed/xlsx/number-format.ts currencyNumberFormat already states for the same schema field, so an amount round-trips through either legacy format under the same spelling. A currency string that is not an ISO-code shape (a display symbol like "£") cannot go inside that bracket without producing a malformed format code, so it falls back to the plain built-in currency format -- the value kind preserved, the code honestly lost, since inventing a code for a symbol would state a currency the cell never named.
|
|
50
|
+
*/
|
|
45
51
|
function formatCodeForCell(cell) {
|
|
52
|
+
if (cell.numberFormatCode === void 0 && cell.value.kind === "currency") {
|
|
53
|
+
const currency = cell.value.currency;
|
|
54
|
+
if (currency !== void 0 && (0, excel_number_format.isIsoCurrencyCodeShape)(currency)) return `[$${currency.toUpperCase()}]#,##0.00`;
|
|
55
|
+
}
|
|
46
56
|
return cell.numberFormatCode ?? builtinCode(defaultFormatIdForKind(cell.value.kind));
|
|
47
57
|
}
|
|
48
58
|
/** Scans every sheet's cells once, assigning each distinct number-format code a formatId: reusing a built-in id for a code matching one of excel-number-format's own BUILTIN_NUMBER_FORMATS strings exactly, minting a new custom id from FIRST_CUSTOM_FORMAT_ID otherwise. Cell XF index assignment is a separate, later pass (buildCellXfPlan below) -- a formatId alone no longer determines a cell's XF index once decoration exists, since two cells sharing a format but differing in background/borders need two distinct XFs. */
|
|
@@ -103,6 +113,7 @@ function buildPalettePlan(sheets) {
|
|
|
103
113
|
for (const cell of sheet.cells) {
|
|
104
114
|
if (!require_written_cells.writesCellRecord(cell)) continue;
|
|
105
115
|
recordFill(cell.background);
|
|
116
|
+
record(cell.font?.color);
|
|
106
117
|
record(cell.borders?.left?.color);
|
|
107
118
|
record(cell.borders?.right?.color);
|
|
108
119
|
record(cell.borders?.top?.color);
|
|
@@ -201,33 +212,63 @@ function resolveDecorationForCell(cell, icvOf) {
|
|
|
201
212
|
bottom: resolveWriteEdge(cell.borders?.bottom, icvOf)
|
|
202
213
|
};
|
|
203
214
|
}
|
|
204
|
-
/** A deterministic signature for one cell XF's own (formatId, alignment, verticalAlignment, decoration) tuple, so two cells sharing all
|
|
205
|
-
function signatureOfCellXf(formatId, alignment, verticalAlignment, decoration) {
|
|
206
|
-
let signature = `f${formatId}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
|
|
215
|
+
/** A deterministic signature for one cell XF's own (formatId, fontIndex, alignment, verticalAlignment, decoration) tuple, so two cells sharing all five share one XF record -- the interning key buildCellXfPlan below dedupes on, mirroring how CellFormatTable in ooxml.js's typed/xlsx/styles.ts dedupes an <xf> on (number format, decoration) together rather than on format alone, widened here by the cell's own font and alignment. */
|
|
216
|
+
function signatureOfCellXf(formatId, fontIndex, alignment, verticalAlignment, decoration) {
|
|
217
|
+
let signature = `f${formatId}|n${fontIndex}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
|
|
207
218
|
if (decoration === void 0) return signature;
|
|
208
219
|
signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}:${decoration.fillBackgroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
|
|
209
220
|
return signature;
|
|
210
221
|
}
|
|
222
|
+
/** A deterministic signature for one font-table entry, the interning key below dedupes on -- name, height, the four flags, and the colour index, since those are the whole record as far as this package's reader is concerned. */
|
|
223
|
+
function signatureOfFont(fields) {
|
|
224
|
+
return `${fields.name}|${fields.heightTwips}|${fields.bold ? 1 : 0}${fields.italic ? 1 : 0}${fields.strikeout ? 1 : 0}${fields.underline ? 1 : 0}|${fields.colorIcv}`;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Scans every sheet's cells once, interning each distinct cell font into its own font-table entry: the Normal font is always entry 0 (every style XF and the implicit General cell XF reference it, whether or not any cell states a font of its own), and each distinct ContentFont the workbook's cells resolve to mints one further entry the first time it is seen. A ContentFont that normalises back to the Normal font's own fields -- absent, empty, or restating only default values -- resolves to entry 0 and mints nothing, the write-side mirror of the reader's own diff against entry 0.
|
|
228
|
+
*/
|
|
229
|
+
function buildFontPlan(sheets, palettePlan) {
|
|
230
|
+
const fontEntries = [require_biff_font.NORMAL_FONT_FIELDS];
|
|
231
|
+
const indexBySignature = /* @__PURE__ */ new Map([[signatureOfFont(require_biff_font.NORMAL_FONT_FIELDS), 0]]);
|
|
232
|
+
const fieldsOf = (cell) => require_biff_font.xfFontFieldsOf(cell.font, palettePlan.icvOf);
|
|
233
|
+
for (const sheet of sheets) for (const cell of sheet.cells) {
|
|
234
|
+
if (!require_written_cells.writesCellRecord(cell)) continue;
|
|
235
|
+
const fields = fieldsOf(cell);
|
|
236
|
+
const signature = signatureOfFont(fields);
|
|
237
|
+
if (indexBySignature.has(signature)) continue;
|
|
238
|
+
indexBySignature.set(signature, fontEntries.length);
|
|
239
|
+
fontEntries.push(fields);
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
fontEntries,
|
|
243
|
+
fontIndexForCell: (cell) => {
|
|
244
|
+
const index = indexBySignature.get(signatureOfFont(fieldsOf(cell)));
|
|
245
|
+
if (index === void 0) throw new require_biff_write_errors.BiffWriteError(`internal error: the cell at row ${cell.row}, column ${cell.column} resolves to a font the workbook-wide font scan never saw -- the writer's own "does this cell get a record" predicate and its font-interning pass disagree about this cell`);
|
|
246
|
+
return index;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
211
250
|
/**
|
|
212
|
-
* Scans every sheet's cells once, interning each distinct (number format, decoration) combination into its own cell XF index -- a cell with General formatting and no decoration resolves to the workbook's own implicit GENERAL_CELL_XF_INDEX with no new XF record at all, exactly as before; every other combination mints one XF record the first time it is seen and is reused by every later cell sharing it.
|
|
251
|
+
* Scans every sheet's cells once, interning each distinct (number format, font, alignment, decoration) combination into its own cell XF index -- a cell with General formatting, the Normal font, and no decoration resolves to the workbook's own implicit GENERAL_CELL_XF_INDEX with no new XF record at all, exactly as before; every other combination mints one XF record the first time it is seen and is reused by every later cell sharing it.
|
|
213
252
|
*
|
|
214
253
|
* The returned xfIndexForCell only ever LOOKS UP -- it cannot mint an entry, and refuses a signature this scan never saw. buildWorkbookGlobals is handed cellXfEntries before any sheet's records are built, so an entry minted later than this scan would be one no XF record was written for, and the cell record naming its index would point past the end of the workbook's XF table. Nothing about the resulting bytes says so: a reader resolves that index to whatever XF happens to sit there, or to none, and the cell's format is silently wrong either way. Refusing the lookup is the only place that divergence can still be caught.
|
|
215
254
|
*/
|
|
216
|
-
function buildCellXfPlan(sheets, formatPlan, palettePlan) {
|
|
255
|
+
function buildCellXfPlan(sheets, formatPlan, palettePlan, fontPlan) {
|
|
217
256
|
const cellXfEntries = [];
|
|
218
|
-
const xfIndexBySignature = /* @__PURE__ */ new Map([[signatureOfCellXf(GENERAL_FORMAT_ID, void 0, void 0, void 0), require_workbook_globals_writer.GENERAL_CELL_XF_INDEX]]);
|
|
257
|
+
const xfIndexBySignature = /* @__PURE__ */ new Map([[signatureOfCellXf(GENERAL_FORMAT_ID, 0, void 0, void 0, void 0), require_workbook_globals_writer.GENERAL_CELL_XF_INDEX]]);
|
|
219
258
|
let nextXfIndex = require_workbook_globals_writer.GENERAL_CELL_XF_INDEX + 1;
|
|
220
|
-
const signatureOf = (cell) => signatureOfCellXf(formatPlan.formatIdOf(formatCodeForCell(cell)), cell.alignment, cell.verticalAlignment, resolveDecorationForCell(cell, palettePlan.icvOf));
|
|
259
|
+
const signatureOf = (cell) => signatureOfCellXf(formatPlan.formatIdOf(formatCodeForCell(cell)), fontPlan.fontIndexForCell(cell), cell.alignment, cell.verticalAlignment, resolveDecorationForCell(cell, palettePlan.icvOf));
|
|
221
260
|
for (const sheet of sheets) for (const cell of sheet.cells) {
|
|
222
261
|
if (!require_written_cells.writesCellRecord(cell)) continue;
|
|
223
262
|
const formatId = formatPlan.formatIdOf(formatCodeForCell(cell));
|
|
263
|
+
const fontIndex = fontPlan.fontIndexForCell(cell);
|
|
224
264
|
const decoration = resolveDecorationForCell(cell, palettePlan.icvOf);
|
|
225
|
-
const signature = signatureOfCellXf(formatId, cell.alignment, cell.verticalAlignment, decoration);
|
|
265
|
+
const signature = signatureOfCellXf(formatId, fontIndex, cell.alignment, cell.verticalAlignment, decoration);
|
|
226
266
|
if (xfIndexBySignature.has(signature)) continue;
|
|
227
267
|
xfIndexBySignature.set(signature, nextXfIndex);
|
|
228
268
|
nextXfIndex += 1;
|
|
229
269
|
cellXfEntries.push({
|
|
230
270
|
formatId,
|
|
271
|
+
fontIndex,
|
|
231
272
|
alignment: cell.alignment,
|
|
232
273
|
verticalAlignment: cell.verticalAlignment,
|
|
233
274
|
decoration
|
|
@@ -297,15 +338,18 @@ function buildWorkbookStream(content) {
|
|
|
297
338
|
const formatPlan = buildFormatPlan(content.sheets);
|
|
298
339
|
const sstPlan = buildSstPlan(content.sheets);
|
|
299
340
|
const palettePlan = buildPalettePlan(content.sheets);
|
|
300
|
-
const
|
|
341
|
+
const fontPlan = buildFontPlan(content.sheets, palettePlan);
|
|
342
|
+
const cellXfPlan = buildCellXfPlan(content.sheets, formatPlan, palettePlan, fontPlan);
|
|
301
343
|
const globalsPlan = {
|
|
302
344
|
sheetNames: content.sheets.map((sheet) => sheet.name),
|
|
345
|
+
fonts: fontPlan.fontEntries,
|
|
303
346
|
customFormats: formatPlan.customFormats,
|
|
304
347
|
cellXfEntries: cellXfPlan.cellXfEntries,
|
|
305
348
|
sharedStrings: sstPlan.strings,
|
|
306
349
|
sharedStringTotalCount: sstPlan.totalCount,
|
|
307
350
|
paletteColors: palettePlan.paletteColors,
|
|
308
|
-
printNames: buildPrintNamePlan(content.sheets)
|
|
351
|
+
printNames: buildPrintNamePlan(content.sheets),
|
|
352
|
+
definedNames: require_workbook_defined_names.definedNameEntriesFor(content.names ?? [], content.sheets)
|
|
309
353
|
};
|
|
310
354
|
const globals = require_workbook_globals_writer.buildWorkbookGlobals(globalsPlan);
|
|
311
355
|
const sheetContext = {
|
package/dist/write.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SUMMARY_INFORMATION_STREAM } from "./container.js";
|
|
2
|
-
import { DEFAULT_PALETTE_HEX_TO_ICV, PATTERN_TYPE_TO_FILL_PATTERN, borderStyleTokenFor } from "./biff/xf-colors.js";
|
|
3
2
|
import { BiffWriteError } from "./biff/write-errors.js";
|
|
3
|
+
import { DEFAULT_PALETTE_HEX_TO_ICV, PATTERN_TYPE_TO_FILL_PATTERN, borderStyleTokenFor } from "./biff/xf-colors.js";
|
|
4
|
+
import { NORMAL_FONT_FIELDS, xfFontFieldsOf } from "./biff/font.js";
|
|
5
|
+
import { definedNameEntriesFor } from "./workbook/defined-names.js";
|
|
4
6
|
import { printNameEntriesFor } from "./workbook/print-names.js";
|
|
5
7
|
import { layoutMetadataToSummaryInformation as layoutMetadataToSummaryInformation$1 } from "./metadata.js";
|
|
6
8
|
import { GENERAL_CELL_XF_INDEX, buildWorkbookGlobals } from "./workbook/globals-writer.js";
|
|
@@ -8,7 +10,7 @@ import { cellCarriesFormatting, writesCellRecord } from "./written-cells.js";
|
|
|
8
10
|
import { buildWorksheetSubstream } from "./workbook/sheet-writer.js";
|
|
9
11
|
import { hasSummaryInformationFields, writeCompoundFile, writeSummaryInformationStream } from "archive-codec";
|
|
10
12
|
import { colorToRgbHex, flattenTree, unrecognizedFillKind } from "document-schema.js";
|
|
11
|
-
import { BUILTIN_NUMBER_FORMATS } from "excel-number-format";
|
|
13
|
+
import { BUILTIN_NUMBER_FORMATS, isIsoCurrencyCodeShape } from "excel-number-format";
|
|
12
14
|
//#region src/write.ts
|
|
13
15
|
const WORKBOOK_STREAM_NAME = "Workbook";
|
|
14
16
|
/** [MS-XLS] 2.4.126: a Format record's own ifmt is constrained to the ranges 5-8, 23-26, 41-44, 63-66, and 164-382 for a custom (non-built-in) code; 164 is the first identifier every real producer actually uses for a custom code, and this writer follows suit, incrementing sequentially and refusing to exceed the range's own ceiling. */
|
|
@@ -40,8 +42,16 @@ function defaultFormatIdForKind(kind) {
|
|
|
40
42
|
case "empty": return GENERAL_FORMAT_ID;
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* The number-format code a cell resolves through -- its own explicit numberFormatCode, a `[$USD]#,##0.00`-shaped code for a currency cell that names an ISO 4217 code of its own (see below), or the built-in code for its value kind's own default identifier. This is called identically during the workbook-wide format scan and later per cell, so the two can never resolve a cell to different codes.
|
|
47
|
+
*
|
|
48
|
+
* The ISO-code bracket is the one carrier a currency code survives the round trip through: the format string IS where BIFF8 states a cell's currency, and the classifier this package's own reader reads it back through recovers the code from exactly that bracket -- writing the symbol instead would render identically and lose the code permanently, since no faithful symbol-to-code mapping exists on the way back ('$' alone is USD, CAD, AUD and a dozen others). That is the identical encoding ooxml.js's own typed/xlsx/number-format.ts currencyNumberFormat already states for the same schema field, so an amount round-trips through either legacy format under the same spelling. A currency string that is not an ISO-code shape (a display symbol like "£") cannot go inside that bracket without producing a malformed format code, so it falls back to the plain built-in currency format -- the value kind preserved, the code honestly lost, since inventing a code for a symbol would state a currency the cell never named.
|
|
49
|
+
*/
|
|
44
50
|
function formatCodeForCell(cell) {
|
|
51
|
+
if (cell.numberFormatCode === void 0 && cell.value.kind === "currency") {
|
|
52
|
+
const currency = cell.value.currency;
|
|
53
|
+
if (currency !== void 0 && isIsoCurrencyCodeShape(currency)) return `[$${currency.toUpperCase()}]#,##0.00`;
|
|
54
|
+
}
|
|
45
55
|
return cell.numberFormatCode ?? builtinCode(defaultFormatIdForKind(cell.value.kind));
|
|
46
56
|
}
|
|
47
57
|
/** Scans every sheet's cells once, assigning each distinct number-format code a formatId: reusing a built-in id for a code matching one of excel-number-format's own BUILTIN_NUMBER_FORMATS strings exactly, minting a new custom id from FIRST_CUSTOM_FORMAT_ID otherwise. Cell XF index assignment is a separate, later pass (buildCellXfPlan below) -- a formatId alone no longer determines a cell's XF index once decoration exists, since two cells sharing a format but differing in background/borders need two distinct XFs. */
|
|
@@ -102,6 +112,7 @@ function buildPalettePlan(sheets) {
|
|
|
102
112
|
for (const cell of sheet.cells) {
|
|
103
113
|
if (!writesCellRecord(cell)) continue;
|
|
104
114
|
recordFill(cell.background);
|
|
115
|
+
record(cell.font?.color);
|
|
105
116
|
record(cell.borders?.left?.color);
|
|
106
117
|
record(cell.borders?.right?.color);
|
|
107
118
|
record(cell.borders?.top?.color);
|
|
@@ -200,33 +211,63 @@ function resolveDecorationForCell(cell, icvOf) {
|
|
|
200
211
|
bottom: resolveWriteEdge(cell.borders?.bottom, icvOf)
|
|
201
212
|
};
|
|
202
213
|
}
|
|
203
|
-
/** A deterministic signature for one cell XF's own (formatId, alignment, verticalAlignment, decoration) tuple, so two cells sharing all
|
|
204
|
-
function signatureOfCellXf(formatId, alignment, verticalAlignment, decoration) {
|
|
205
|
-
let signature = `f${formatId}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
|
|
214
|
+
/** A deterministic signature for one cell XF's own (formatId, fontIndex, alignment, verticalAlignment, decoration) tuple, so two cells sharing all five share one XF record -- the interning key buildCellXfPlan below dedupes on, mirroring how CellFormatTable in ooxml.js's typed/xlsx/styles.ts dedupes an <xf> on (number format, decoration) together rather than on format alone, widened here by the cell's own font and alignment. */
|
|
215
|
+
function signatureOfCellXf(formatId, fontIndex, alignment, verticalAlignment, decoration) {
|
|
216
|
+
let signature = `f${formatId}|n${fontIndex}|a${alignment ?? ""}|v${verticalAlignment ?? ""}`;
|
|
206
217
|
if (decoration === void 0) return signature;
|
|
207
218
|
signature += `|p${decoration.fillPattern}:${decoration.fillForegroundIcv}:${decoration.fillBackgroundIcv}|l${decoration.left.style}:${decoration.left.icv}|r${decoration.right.style}:${decoration.right.icv}|t${decoration.top.style}:${decoration.top.icv}|b${decoration.bottom.style}:${decoration.bottom.icv}`;
|
|
208
219
|
return signature;
|
|
209
220
|
}
|
|
221
|
+
/** A deterministic signature for one font-table entry, the interning key below dedupes on -- name, height, the four flags, and the colour index, since those are the whole record as far as this package's reader is concerned. */
|
|
222
|
+
function signatureOfFont(fields) {
|
|
223
|
+
return `${fields.name}|${fields.heightTwips}|${fields.bold ? 1 : 0}${fields.italic ? 1 : 0}${fields.strikeout ? 1 : 0}${fields.underline ? 1 : 0}|${fields.colorIcv}`;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Scans every sheet's cells once, interning each distinct cell font into its own font-table entry: the Normal font is always entry 0 (every style XF and the implicit General cell XF reference it, whether or not any cell states a font of its own), and each distinct ContentFont the workbook's cells resolve to mints one further entry the first time it is seen. A ContentFont that normalises back to the Normal font's own fields -- absent, empty, or restating only default values -- resolves to entry 0 and mints nothing, the write-side mirror of the reader's own diff against entry 0.
|
|
227
|
+
*/
|
|
228
|
+
function buildFontPlan(sheets, palettePlan) {
|
|
229
|
+
const fontEntries = [NORMAL_FONT_FIELDS];
|
|
230
|
+
const indexBySignature = /* @__PURE__ */ new Map([[signatureOfFont(NORMAL_FONT_FIELDS), 0]]);
|
|
231
|
+
const fieldsOf = (cell) => xfFontFieldsOf(cell.font, palettePlan.icvOf);
|
|
232
|
+
for (const sheet of sheets) for (const cell of sheet.cells) {
|
|
233
|
+
if (!writesCellRecord(cell)) continue;
|
|
234
|
+
const fields = fieldsOf(cell);
|
|
235
|
+
const signature = signatureOfFont(fields);
|
|
236
|
+
if (indexBySignature.has(signature)) continue;
|
|
237
|
+
indexBySignature.set(signature, fontEntries.length);
|
|
238
|
+
fontEntries.push(fields);
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
fontEntries,
|
|
242
|
+
fontIndexForCell: (cell) => {
|
|
243
|
+
const index = indexBySignature.get(signatureOfFont(fieldsOf(cell)));
|
|
244
|
+
if (index === void 0) throw new BiffWriteError(`internal error: the cell at row ${cell.row}, column ${cell.column} resolves to a font the workbook-wide font scan never saw -- the writer's own "does this cell get a record" predicate and its font-interning pass disagree about this cell`);
|
|
245
|
+
return index;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
210
249
|
/**
|
|
211
|
-
* Scans every sheet's cells once, interning each distinct (number format, decoration) combination into its own cell XF index -- a cell with General formatting and no decoration resolves to the workbook's own implicit GENERAL_CELL_XF_INDEX with no new XF record at all, exactly as before; every other combination mints one XF record the first time it is seen and is reused by every later cell sharing it.
|
|
250
|
+
* Scans every sheet's cells once, interning each distinct (number format, font, alignment, decoration) combination into its own cell XF index -- a cell with General formatting, the Normal font, and no decoration resolves to the workbook's own implicit GENERAL_CELL_XF_INDEX with no new XF record at all, exactly as before; every other combination mints one XF record the first time it is seen and is reused by every later cell sharing it.
|
|
212
251
|
*
|
|
213
252
|
* The returned xfIndexForCell only ever LOOKS UP -- it cannot mint an entry, and refuses a signature this scan never saw. buildWorkbookGlobals is handed cellXfEntries before any sheet's records are built, so an entry minted later than this scan would be one no XF record was written for, and the cell record naming its index would point past the end of the workbook's XF table. Nothing about the resulting bytes says so: a reader resolves that index to whatever XF happens to sit there, or to none, and the cell's format is silently wrong either way. Refusing the lookup is the only place that divergence can still be caught.
|
|
214
253
|
*/
|
|
215
|
-
function buildCellXfPlan(sheets, formatPlan, palettePlan) {
|
|
254
|
+
function buildCellXfPlan(sheets, formatPlan, palettePlan, fontPlan) {
|
|
216
255
|
const cellXfEntries = [];
|
|
217
|
-
const xfIndexBySignature = /* @__PURE__ */ new Map([[signatureOfCellXf(GENERAL_FORMAT_ID, void 0, void 0, void 0), GENERAL_CELL_XF_INDEX]]);
|
|
256
|
+
const xfIndexBySignature = /* @__PURE__ */ new Map([[signatureOfCellXf(GENERAL_FORMAT_ID, 0, void 0, void 0, void 0), GENERAL_CELL_XF_INDEX]]);
|
|
218
257
|
let nextXfIndex = GENERAL_CELL_XF_INDEX + 1;
|
|
219
|
-
const signatureOf = (cell) => signatureOfCellXf(formatPlan.formatIdOf(formatCodeForCell(cell)), cell.alignment, cell.verticalAlignment, resolveDecorationForCell(cell, palettePlan.icvOf));
|
|
258
|
+
const signatureOf = (cell) => signatureOfCellXf(formatPlan.formatIdOf(formatCodeForCell(cell)), fontPlan.fontIndexForCell(cell), cell.alignment, cell.verticalAlignment, resolveDecorationForCell(cell, palettePlan.icvOf));
|
|
220
259
|
for (const sheet of sheets) for (const cell of sheet.cells) {
|
|
221
260
|
if (!writesCellRecord(cell)) continue;
|
|
222
261
|
const formatId = formatPlan.formatIdOf(formatCodeForCell(cell));
|
|
262
|
+
const fontIndex = fontPlan.fontIndexForCell(cell);
|
|
223
263
|
const decoration = resolveDecorationForCell(cell, palettePlan.icvOf);
|
|
224
|
-
const signature = signatureOfCellXf(formatId, cell.alignment, cell.verticalAlignment, decoration);
|
|
264
|
+
const signature = signatureOfCellXf(formatId, fontIndex, cell.alignment, cell.verticalAlignment, decoration);
|
|
225
265
|
if (xfIndexBySignature.has(signature)) continue;
|
|
226
266
|
xfIndexBySignature.set(signature, nextXfIndex);
|
|
227
267
|
nextXfIndex += 1;
|
|
228
268
|
cellXfEntries.push({
|
|
229
269
|
formatId,
|
|
270
|
+
fontIndex,
|
|
230
271
|
alignment: cell.alignment,
|
|
231
272
|
verticalAlignment: cell.verticalAlignment,
|
|
232
273
|
decoration
|
|
@@ -296,15 +337,18 @@ function buildWorkbookStream(content) {
|
|
|
296
337
|
const formatPlan = buildFormatPlan(content.sheets);
|
|
297
338
|
const sstPlan = buildSstPlan(content.sheets);
|
|
298
339
|
const palettePlan = buildPalettePlan(content.sheets);
|
|
299
|
-
const
|
|
340
|
+
const fontPlan = buildFontPlan(content.sheets, palettePlan);
|
|
341
|
+
const cellXfPlan = buildCellXfPlan(content.sheets, formatPlan, palettePlan, fontPlan);
|
|
300
342
|
const globalsPlan = {
|
|
301
343
|
sheetNames: content.sheets.map((sheet) => sheet.name),
|
|
344
|
+
fonts: fontPlan.fontEntries,
|
|
302
345
|
customFormats: formatPlan.customFormats,
|
|
303
346
|
cellXfEntries: cellXfPlan.cellXfEntries,
|
|
304
347
|
sharedStrings: sstPlan.strings,
|
|
305
348
|
sharedStringTotalCount: sstPlan.totalCount,
|
|
306
349
|
paletteColors: palettePlan.paletteColors,
|
|
307
|
-
printNames: buildPrintNamePlan(content.sheets)
|
|
350
|
+
printNames: buildPrintNamePlan(content.sheets),
|
|
351
|
+
definedNames: definedNameEntriesFor(content.names ?? [], content.sheets)
|
|
308
352
|
};
|
|
309
353
|
const globals = buildWorkbookGlobals(globalsPlan);
|
|
310
354
|
const sheetContext = {
|
package/dist/written-cells.cjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_biff_font = require("./biff/font.cjs");
|
|
2
3
|
//#region src/written-cells.ts
|
|
3
4
|
/**
|
|
4
|
-
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated: a background fill, a border on at least one side, a non-default horizontal alignment,
|
|
5
|
+
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated/default-font: a background fill, a border on at least one side, a non-default horizontal alignment, a non-default vertical alignment, or a font that differs from the workbook's own Normal font.
|
|
5
6
|
*
|
|
6
|
-
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means.
|
|
7
|
+
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means. A font is held to the identical standard through biff/font.ts's cellFontDiffersFromNormal, so a ContentFont that merely restates a default value (fontFamily "Arial", sizePt 10, bold false) is none either, for the same reason.
|
|
7
8
|
*/
|
|
8
9
|
function cellCarriesFormatting(cell) {
|
|
9
10
|
if (cell.background !== void 0) return true;
|
|
10
11
|
if (cell.alignment !== void 0) return true;
|
|
11
12
|
if (cell.verticalAlignment !== void 0) return true;
|
|
13
|
+
if (cell.font !== void 0 && require_biff_font.cellFontDiffersFromNormal(cell.font)) return true;
|
|
12
14
|
const { borders } = cell;
|
|
13
15
|
if (borders === void 0) return false;
|
|
14
16
|
return borders.left !== void 0 || borders.right !== void 0 || borders.top !== void 0 || borders.bottom !== void 0;
|
package/dist/written-cells.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ContentSheetCell } from "document-schema.js";
|
|
2
2
|
//#region src/written-cells.d.ts
|
|
3
3
|
/**
|
|
4
|
-
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated: a background fill, a border on at least one side, a non-default horizontal alignment,
|
|
4
|
+
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated/default-font: a background fill, a border on at least one side, a non-default horizontal alignment, a non-default vertical alignment, or a font that differs from the workbook's own Normal font.
|
|
5
5
|
*
|
|
6
|
-
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means.
|
|
6
|
+
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means. A font is held to the identical standard through biff/font.ts's cellFontDiffersFromNormal, so a ContentFont that merely restates a default value (fontFamily "Arial", sizePt 10, bold false) is none either, for the same reason.
|
|
7
7
|
*/
|
|
8
8
|
declare function cellCarriesFormatting(cell: ContentSheetCell): boolean;
|
|
9
9
|
/**
|
package/dist/written-cells.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ContentSheetCell } from "document-schema.js";
|
|
2
2
|
//#region src/written-cells.d.ts
|
|
3
3
|
/**
|
|
4
|
-
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated: a background fill, a border on at least one side, a non-default horizontal alignment,
|
|
4
|
+
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated/default-font: a background fill, a border on at least one side, a non-default horizontal alignment, a non-default vertical alignment, or a font that differs from the workbook's own Normal font.
|
|
5
5
|
*
|
|
6
|
-
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means.
|
|
6
|
+
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means. A font is held to the identical standard through biff/font.ts's cellFontDiffersFromNormal, so a ContentFont that merely restates a default value (fontFamily "Arial", sizePt 10, bold false) is none either, for the same reason.
|
|
7
7
|
*/
|
|
8
8
|
declare function cellCarriesFormatting(cell: ContentSheetCell): boolean;
|
|
9
9
|
/**
|
package/dist/written-cells.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { cellFontDiffersFromNormal } from "./biff/font.js";
|
|
1
2
|
//#region src/written-cells.ts
|
|
2
3
|
/**
|
|
3
|
-
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated: a background fill, a border on at least one side, a non-default horizontal alignment,
|
|
4
|
+
* Whether a cell carries real formatting beyond General/bottom-aligned/undecorated/default-font: a background fill, a border on at least one side, a non-default horizontal alignment, a non-default vertical alignment, or a font that differs from the workbook's own Normal font.
|
|
4
5
|
*
|
|
5
|
-
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means.
|
|
6
|
+
* A present `borders` object is not enough on its own -- one with no side set describes no border at all, and treating it as formatting would mint an XF byte-identical to the undecorated one and, for an empty cell, a Blank record the reader would then correctly drop again. write.ts's own resolveDecorationForCell answers "no decoration" for exactly this set through this same predicate, so the two cannot disagree about what an empty-but-present borders object means. A font is held to the identical standard through biff/font.ts's cellFontDiffersFromNormal, so a ContentFont that merely restates a default value (fontFamily "Arial", sizePt 10, bold false) is none either, for the same reason.
|
|
6
7
|
*/
|
|
7
8
|
function cellCarriesFormatting(cell) {
|
|
8
9
|
if (cell.background !== void 0) return true;
|
|
9
10
|
if (cell.alignment !== void 0) return true;
|
|
10
11
|
if (cell.verticalAlignment !== void 0) return true;
|
|
12
|
+
if (cell.font !== void 0 && cellFontDiffersFromNormal(cell.font)) return true;
|
|
11
13
|
const { borders } = cell;
|
|
12
14
|
if (borders === void 0) return false;
|
|
13
15
|
return borders.left !== void 0 || borders.right !== void 0 || borders.top !== void 0 || borders.bottom !== void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xls-codec",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.0",
|
|
4
4
|
"description": "Hand-written reader for the legacy Excel Binary File Format (.xls, BIFF8) as specified by [MS-XLS], mapping a workbook's record stream onto the shared document-schema.js spreadsheet model - the .xls codec for the documents.js family.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
},
|
|
71
71
|
"packageManager": "pnpm@11.6.0",
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"archive-codec": "1.10.
|
|
74
|
-
"document-schema.js": "7.
|
|
73
|
+
"archive-codec": "1.10.8",
|
|
74
|
+
"document-schema.js": "7.10.0",
|
|
75
75
|
"excel-number-format": "1.1.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|