@shbernal/ts-xlsx 1.1.0 → 1.3.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 +26 -0
- package/dist/core/address.js +0 -33
- package/dist/core/autofilter.js +0 -9
- package/dist/core/cell.js +0 -131
- package/dist/core/color-resolution.js +0 -60
- package/dist/core/column.js +0 -60
- package/dist/core/comment-thread.js +0 -45
- package/dist/core/conditional-formatting-overlay.js +0 -11
- package/dist/core/conditional-formatting.js +0 -10
- package/dist/core/containers.js +0 -15
- package/dist/core/data-validation-overlay.js +0 -25
- package/dist/core/data-validation.js +0 -7
- package/dist/core/date.js +0 -39
- package/dist/core/formula.js +0 -117
- package/dist/core/grid-edits.js +0 -38
- package/dist/core/image.js +0 -25
- package/dist/core/internal.js +0 -27
- package/dist/core/limits.js +0 -45
- package/dist/core/merge.d.ts +18 -0
- package/dist/core/merge.js +22 -7
- package/dist/core/modern-functions.js +0 -17
- package/dist/core/page-setup.js +0 -5
- package/dist/core/pivot-table.d.ts +1 -1
- package/dist/core/pivot-table.js +0 -48
- package/dist/core/preserved.js +0 -4
- package/dist/core/protection.js +0 -26
- package/dist/core/range.js +0 -112
- package/dist/core/row-input.d.ts +24 -0
- package/dist/core/row-input.js +29 -0
- package/dist/core/row.js +0 -66
- package/dist/core/style.js +0 -26
- package/dist/core/table-style.js +0 -28
- package/dist/core/table.js +0 -97
- package/dist/core/text-metrics.js +0 -40
- package/dist/core/theme.js +0 -85
- package/dist/core/value.js +0 -94
- package/dist/core/workbook-protection.js +0 -13
- package/dist/core/workbook.d.ts +13 -1
- package/dist/core/workbook.js +0 -380
- package/dist/core/worksheet-model.js +2 -23
- package/dist/core/worksheet.d.ts +9 -0
- package/dist/core/worksheet.js +7 -506
- package/dist/customui/errors.js +0 -10
- package/dist/customui/index.js +0 -5
- package/dist/customui/ribbon.js +0 -43
- package/dist/entries/core.js +0 -6
- package/dist/entries/csv.js +0 -4
- package/dist/entries/customui.js +0 -2
- package/dist/entries/errors.js +0 -13
- package/dist/entries/vba.js +0 -5
- package/dist/entries/xlsb.js +0 -6
- package/dist/entries/xlsx.js +0 -13
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +5 -56
- package/dist/index.js +0 -12
- package/dist/io/csv/read.js +0 -18
- package/dist/io/csv/write.js +0 -18
- package/dist/io/opc/errors.js +0 -30
- package/dist/io/opc/inflate.js +0 -35
- package/dist/io/opc/namespaces.js +0 -15
- package/dist/io/opc/part-paths.js +0 -11
- package/dist/io/opc/read-opc.js +0 -31
- package/dist/io/opc/read-options.js +0 -6
- package/dist/io/opc/rels.js +0 -13
- package/dist/io/opc/sniff-format.js +0 -50
- package/dist/io/opc/zip-mtime.d.ts +5 -0
- package/dist/io/opc/zip-mtime.js +1 -0
- package/dist/io/style/xf-style.js +0 -31
- package/dist/io/xlsb/errors.js +0 -10
- package/dist/io/xlsb/formula.js +1 -99
- package/dist/io/xlsb/primitives.js +1 -83
- package/dist/io/xlsb/ptg-functions.js +0 -34
- package/dist/io/xlsb/read-shared-strings.js +0 -7
- package/dist/io/xlsb/read-styles.js +3 -66
- package/dist/io/xlsb/read-worksheet.js +4 -87
- package/dist/io/xlsb/read.js +2 -60
- package/dist/io/xlsb/record-stream.js +0 -28
- package/dist/io/xlsb/record-types.js +0 -19
- package/dist/io/xlsx/cell-accumulator.js +0 -32
- package/dist/io/xlsx/cell-value.js +0 -29
- package/dist/io/xlsx/color-xml.d.ts +6 -0
- package/dist/io/xlsx/color-xml.js +42 -0
- package/dist/io/xlsx/comments.js +0 -84
- package/dist/io/xlsx/conditional-formatting.d.ts +1 -1
- package/dist/io/xlsx/conditional-formatting.js +1 -97
- package/dist/io/xlsx/data-validation.js +0 -56
- package/dist/io/xlsx/edit-vba.js +2 -55
- package/dist/io/xlsx/errors.js +0 -12
- package/dist/io/xlsx/hyperlinks.js +0 -40
- package/dist/io/xlsx/images.js +0 -32
- package/dist/io/xlsx/namespaces.js +0 -42
- package/dist/io/xlsx/package-plan.js +0 -47
- package/dist/io/xlsx/pivot.js +0 -22
- package/dist/io/xlsx/{pivot-read.js → read-pivot.js} +0 -30
- package/dist/io/xlsx/read-rows.js +1 -83
- package/dist/io/xlsx/{shared-strings-read.js → read-shared-strings.js} +0 -11
- package/dist/io/xlsx/read-styles.d.ts +25 -1
- package/dist/io/xlsx/read-styles.js +61 -108
- package/dist/io/xlsx/read-worksheet.js +7 -88
- package/dist/io/xlsx/read.js +36 -213
- package/dist/io/xlsx/relationships.js +0 -11
- package/dist/io/xlsx/rich-runs.js +0 -16
- package/dist/io/xlsx/rich-text.js +0 -12
- package/dist/io/xlsx/shared-formulas.js +0 -7
- package/dist/io/xlsx/shared-strings.js +0 -21
- package/dist/io/xlsx/sheet-properties.js +4 -66
- package/dist/io/xlsx/styles.d.ts +1 -29
- package/dist/io/xlsx/styles.js +2 -366
- package/dist/io/xlsx/tables.js +5 -52
- package/dist/io/xlsx/threaded-comments.js +0 -103
- package/dist/io/xlsx/workbook-xml.d.ts +1 -1
- package/dist/io/xlsx/workbook-xml.js +6 -96
- package/dist/io/xlsx/worksheet-xml.js +0 -174
- package/dist/io/xlsx/write-stream.js +2 -137
- package/dist/io/xlsx/write.d.ts +5 -1
- package/dist/io/xlsx/write.js +5 -137
- package/dist/io/xlsx/x14-ext.js +0 -8
- package/dist/vba/cfb-writer.js +12 -59
- package/dist/vba/cfb.js +2 -32
- package/dist/vba/codepage.js +1 -23
- package/dist/vba/errors.js +0 -15
- package/dist/vba/index.js +0 -10
- package/dist/vba/ms-ovba.js +3 -46
- package/dist/vba/project-editor.js +4 -89
- package/dist/vba/project.js +2 -34
- package/dist/vba/vba-encoding.js +1 -17
- package/dist/xml/errors.js +0 -10
- package/dist/xml/xml-read.js +3 -82
- package/dist/xml/xml.js +0 -39
- package/package.json +8 -9
- package/skills/ts-xlsx-upstream/SKILL.md +178 -0
- /package/dist/io/xlsx/{pivot-read.d.ts → read-pivot.d.ts} +0 -0
- /package/dist/io/xlsx/{shared-strings-read.d.ts → read-shared-strings.d.ts} +0 -0
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// The worksheet-body reader: one `xl/worksheets/sheetN.xml` in, its cells/columns/rows/print-setup
|
|
2
|
-
// applied onto a {@link Worksheet}. It is a single streaming pass driving a handful of accumulators
|
|
3
|
-
// (the cell being read, shared-formula masters, an autofilter draft, the current page-break axis) so
|
|
4
|
-
// each element commits its state as it closes. Style indices resolve through the parsed style table.
|
|
5
1
|
import { decodeRange } from '../../core/address.js';
|
|
6
2
|
import { isCustomFilterOperator, } from '../../core/autofilter.js';
|
|
7
3
|
import { INTERNAL } from '../../core/internal.js';
|
|
@@ -9,15 +5,9 @@ import { SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
|
|
|
9
5
|
import { assignStyleFacets } from '../../core/style.js';
|
|
10
6
|
import { boolPresent, boolStrict, boolTristate, localName, parseXml, } from '../../xml/xml-read.js';
|
|
11
7
|
import { CellAccumulator } from './cell-accumulator.js';
|
|
12
|
-
import { parseColor } from './
|
|
8
|
+
import { parseColor } from './color-xml.js';
|
|
13
9
|
const MARGIN_SIDES = ['left', 'right', 'top', 'bottom', 'header', 'footer'];
|
|
14
|
-
// Worksheet elements that commit on their close: a formatted-but-empty `<c/>` and a criteria-free
|
|
15
|
-
// self-closing `<autoFilter/>` are expanded to open+close so each finalises once in onClose. The
|
|
16
|
-
// text-bearing `<f/>`/`<v/>`/`<t/>` are deliberately excluded — an empty one must not commit.
|
|
17
10
|
const WORKSHEET_EMPTY_CLOSES = new Set(['c', 'autoFilter']);
|
|
18
|
-
// Fold a filter column's accumulated `<filters>` or `<customFilters>` state into one criteria value,
|
|
19
|
-
// or null when it carried nothing filterable. A `<filters>` block with no values and no blank flag,
|
|
20
|
-
// or a `<customFilters>` with no predicates, is a no-op that would round-trip as noise, so it drops.
|
|
21
11
|
function pendingFilterCriteria(values, blank, predicates, and) {
|
|
22
12
|
if (values !== null && (values.length > 0 || blank)) {
|
|
23
13
|
return { kind: 'values', values, blank };
|
|
@@ -27,12 +17,6 @@ function pendingFilterCriteria(values, blank, predicates, and) {
|
|
|
27
17
|
}
|
|
28
18
|
return null;
|
|
29
19
|
}
|
|
30
|
-
// Read a <sheetProtection> element back into a SheetProtection — the deserialization mirror of the
|
|
31
|
-
// writer. `sheet="0"` (or "false") means the element records an *un*protected sheet, so nothing is
|
|
32
|
-
// restored. Each flag attribute is the INVERSE of the author's allow-flag ("1" forbids, "0" permits),
|
|
33
|
-
// and only attributes actually present are carried, so an omitted (default-valued) flag stays absent —
|
|
34
|
-
// exactly what the writer emitted. A password credential is preserved verbatim in its agile form
|
|
35
|
-
// (algorithm, hash, salt, spin count); there is no plaintext password to recover, so it is not re-hashed.
|
|
36
20
|
function parseSheetProtection(attrs) {
|
|
37
21
|
if (attrs.sheet === '0' || attrs.sheet === 'false')
|
|
38
22
|
return undefined;
|
|
@@ -60,9 +44,6 @@ function parseSheetProtection(attrs) {
|
|
|
60
44
|
}
|
|
61
45
|
return { flags };
|
|
62
46
|
}
|
|
63
|
-
// Autofilter accumulation. The sheet `<autoFilter ref>` seeds a draft; each `<filterColumn colId>`
|
|
64
|
-
// opens a column whose criteria (`<filters>` values or `<customFilters>` predicates) stream into the
|
|
65
|
-
// draft until `</filterColumn>`, and `</autoFilter>` commits the whole thing to the sheet.
|
|
66
47
|
class AutoFilterAccumulator {
|
|
67
48
|
#ref = null;
|
|
68
49
|
#columns = [];
|
|
@@ -71,14 +52,10 @@ class AutoFilterAccumulator {
|
|
|
71
52
|
#blank = false;
|
|
72
53
|
#predicates = null;
|
|
73
54
|
#and = false;
|
|
74
|
-
// Seed a draft from the range. (A table's own `<autoFilter>` also matches, but table sheets route
|
|
75
|
-
// through parseTable, so this only ever sees the sheet-level one.)
|
|
76
55
|
begin(attrs) {
|
|
77
56
|
this.#ref = attrs.ref !== undefined && attrs.ref !== '' ? attrs.ref : null;
|
|
78
57
|
this.#columns = [];
|
|
79
58
|
}
|
|
80
|
-
// Open a criteria block for one column, offset `colId` from the range's left edge. Reset the
|
|
81
|
-
// per-column accumulators; whichever child (`<filters>`/`<customFilters>`) opens fills one.
|
|
82
59
|
beginColumn(attrs) {
|
|
83
60
|
this.#colId = attrs.colId !== undefined ? Number(attrs.colId) : -1;
|
|
84
61
|
this.#values = null;
|
|
@@ -88,8 +65,6 @@ class AutoFilterAccumulator {
|
|
|
88
65
|
}
|
|
89
66
|
beginValues(attrs) {
|
|
90
67
|
this.#values = [];
|
|
91
|
-
// `blank` defaults off when absent, so presence is required first — then it reads as an
|
|
92
|
-
// on-when-present flag. (`boolPresent` alone would treat the absent attribute as on.)
|
|
93
68
|
this.#blank = attrs.blank !== undefined && boolPresent(attrs.blank);
|
|
94
69
|
}
|
|
95
70
|
addValue(attrs) {
|
|
@@ -100,8 +75,6 @@ class AutoFilterAccumulator {
|
|
|
100
75
|
this.#predicates = [];
|
|
101
76
|
this.#and = attrs.and !== undefined && boolPresent(attrs.and);
|
|
102
77
|
}
|
|
103
|
-
// The operator attribute defaults to `equal` when absent (per CT_CustomFilter); an operand is
|
|
104
|
-
// likewise optional. An unrecognised operator drops the predicate rather than guessing.
|
|
105
78
|
addCustom(attrs) {
|
|
106
79
|
if (this.#predicates === null)
|
|
107
80
|
return;
|
|
@@ -110,18 +83,12 @@ class AutoFilterAccumulator {
|
|
|
110
83
|
this.#predicates.push({ operator, val: attrs.val ?? '' });
|
|
111
84
|
}
|
|
112
85
|
}
|
|
113
|
-
// Assemble this column's criteria from whichever accumulator filled. A column whose colId is
|
|
114
|
-
// negative, or whose criteria are empty (no values, no blank, no predicates), carries nothing
|
|
115
|
-
// filterable and is dropped so a re-write stays clean — load-repair, not authoring.
|
|
116
86
|
endColumn() {
|
|
117
87
|
const criteria = pendingFilterCriteria(this.#values, this.#blank, this.#predicates, this.#and);
|
|
118
88
|
if (this.#colId >= 0 && criteria !== null) {
|
|
119
89
|
this.#columns.push({ colId: this.#colId, criteria });
|
|
120
90
|
}
|
|
121
91
|
}
|
|
122
|
-
// Commit the accumulated autofilter to the sheet. Runs on `</autoFilter>` — including the synthesized
|
|
123
|
-
// close of a criteria-free self-closing `<autoFilter/>`. Columns whose colId falls outside the range
|
|
124
|
-
// are dropped here so the strict setter never trips on hostile input.
|
|
125
92
|
commit(sheet) {
|
|
126
93
|
if (this.#ref === null)
|
|
127
94
|
return;
|
|
@@ -131,16 +98,11 @@ class AutoFilterAccumulator {
|
|
|
131
98
|
sheet.autoFilter = { ref: this.#ref, columns: this.#columns.filter((c) => c.colId < width) };
|
|
132
99
|
}
|
|
133
100
|
catch {
|
|
134
|
-
// unbounded or malformed autofilter range in the source file — ignore it
|
|
135
101
|
}
|
|
136
102
|
this.#ref = null;
|
|
137
103
|
this.#columns = [];
|
|
138
104
|
}
|
|
139
105
|
}
|
|
140
|
-
// Page-break accumulation. `<brk>` elements appear under both `<rowBreaks>` and `<colBreaks>`; a break
|
|
141
|
-
// container's open points the accumulator at that axis's list (null outside any container), so a
|
|
142
|
-
// `<brk>` lands on the right axis, and the matching close clears it. A self-closing
|
|
143
|
-
// `<rowBreaks/>`/`<colBreaks/>` fires no close, so a new open simply reassigns the target.
|
|
144
106
|
class PageBreakAccumulator {
|
|
145
107
|
#target = null;
|
|
146
108
|
begin(target) {
|
|
@@ -149,8 +111,6 @@ class PageBreakAccumulator {
|
|
|
149
111
|
end() {
|
|
150
112
|
this.#target = null;
|
|
151
113
|
}
|
|
152
|
-
// `id` is the row/column the layout splits before; a non-positive or non-integer id is hostile input
|
|
153
|
-
// and dropped rather than trusted. A `<brk>` outside any break container has no axis and is ignored.
|
|
154
114
|
add(attrs) {
|
|
155
115
|
if (this.#target === null)
|
|
156
116
|
return;
|
|
@@ -167,24 +127,15 @@ class PageBreakAccumulator {
|
|
|
167
127
|
}
|
|
168
128
|
}
|
|
169
129
|
export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
170
|
-
// The one `<c>` currently being read: its address/type/style, formula, value, inline text, rich
|
|
171
|
-
// runs, and the sheet-spanning shared-formula master map. Each `<c>` resets it and commits it.
|
|
172
130
|
const cell = new CellAccumulator();
|
|
173
131
|
let inInlineString = false;
|
|
174
132
|
let capture = false;
|
|
175
133
|
let text = '';
|
|
176
|
-
// A row with customFormat="1" supplies a default style for its cells that carry no `s`.
|
|
177
134
|
let rowStyle = -1;
|
|
178
135
|
let rowCustomFormat = false;
|
|
179
136
|
const autoFilter = new AutoFilterAccumulator();
|
|
180
137
|
const pageBreaks = new PageBreakAccumulator();
|
|
181
|
-
// A column's `style` is the default for its cells that carry no style of their own; this
|
|
182
|
-
// maps a column index to that style index so a bare cell can inherit it (as Excel does,
|
|
183
|
-
// without stamping every cell). Columns are parsed before any cell references them.
|
|
184
138
|
const columnStyle = new Map();
|
|
185
|
-
// Commit the cell held in the accumulator, resolving its style from its own `s`, then its row's
|
|
186
|
-
// (when customFormat), then its column's default — the order Excel applies. Runs on `</c>` close,
|
|
187
|
-
// including the synthesized close of a self-closing `<c/>` formatted-but-empty cell.
|
|
188
139
|
const finalizeCellFromState = () => {
|
|
189
140
|
const styleIndex = cell.styleIndex >= 0
|
|
190
141
|
? cell.styleIndex
|
|
@@ -216,12 +167,10 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
|
216
167
|
cell.beginInlineString();
|
|
217
168
|
break;
|
|
218
169
|
case 'r':
|
|
219
|
-
// A run inside a rich inline string. Its `<rPr>` (if any) and `<t>` follow.
|
|
220
170
|
if (inInlineString)
|
|
221
171
|
cell.runs.beginRun();
|
|
222
172
|
break;
|
|
223
173
|
case 'rPr':
|
|
224
|
-
// The run's formatting bundle; its self-closing children stream into the default branch.
|
|
225
174
|
cell.runs.beginProperties();
|
|
226
175
|
break;
|
|
227
176
|
case 'f':
|
|
@@ -238,26 +187,20 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
|
238
187
|
case 'evenFooter':
|
|
239
188
|
case 'firstHeader':
|
|
240
189
|
case 'firstFooter':
|
|
241
|
-
// A `<headerFooter>` child carries its header/footer definition as text (the `&`-prefixed
|
|
242
|
-
// section/format tokens, e.g. `&C&"Arial"&G`). Capture it verbatim so a round-trip preserves
|
|
243
|
-
// a header image's `&G` picture token and every other formatting directive.
|
|
244
190
|
capture = true;
|
|
245
191
|
break;
|
|
246
192
|
case 'mergeCell':
|
|
247
|
-
// A well-formed file never declares overlapping merges; a corrupt one might. Reject the
|
|
248
|
-
// bad range at the model boundary, but don't let one abort the whole parse — drop it and
|
|
249
|
-
// keep reading the valid geometry.
|
|
250
193
|
if (attrs.ref !== undefined && attrs.ref !== '') {
|
|
251
194
|
try {
|
|
252
195
|
sheet.mergeCells(attrs.ref);
|
|
253
196
|
}
|
|
254
197
|
catch {
|
|
255
|
-
// overlapping/malformed merge in the source file — skip it
|
|
256
198
|
}
|
|
257
199
|
}
|
|
258
200
|
break;
|
|
259
201
|
case 'tabColor':
|
|
260
202
|
case 'outlinePr':
|
|
203
|
+
case 'sheetView':
|
|
261
204
|
case 'pane':
|
|
262
205
|
case 'pageSetUpPr':
|
|
263
206
|
case 'printOptions':
|
|
@@ -299,8 +242,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
|
299
242
|
autoFilter.addCustom(attrs);
|
|
300
243
|
break;
|
|
301
244
|
default:
|
|
302
|
-
// A run's `<rPr>` child (`<b/>`, `<sz>`, `<color>`, `<rFont>`, …) sets one font facet; it
|
|
303
|
-
// is self-closing, so it is read here on open. Nothing else uses the default branch.
|
|
304
245
|
cell.runs.applyProperty(local, attrs);
|
|
305
246
|
break;
|
|
306
247
|
}
|
|
@@ -321,8 +262,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
|
321
262
|
cell.setValue(text);
|
|
322
263
|
break;
|
|
323
264
|
case 't':
|
|
324
|
-
// A `<t>` inside a run is that run's text; a bare `<t>` directly in the `<is>` is a plain
|
|
325
|
-
// inline string. A run takes precedence — a run is also inside the inline string.
|
|
326
265
|
cell.appendText(text, inInlineString);
|
|
327
266
|
break;
|
|
328
267
|
case 'r':
|
|
@@ -363,27 +302,23 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
|
|
|
363
302
|
},
|
|
364
303
|
}, { closeEmptyElements: WORKSHEET_EMPTY_CLOSES });
|
|
365
304
|
}
|
|
366
|
-
// Apply one `<sheetPr>` / `<sheetView>` / print-setup child to the sheet. These are the worksheet's
|
|
367
|
-
// layout and print metadata; grouping them here keeps the cell-reading switch a pure dispatch. Each
|
|
368
|
-
// records only what the source carried, so a file missing a facet leaves it unset and a re-write
|
|
369
|
-
// stays byte-clean. Every element here is self-closing (its state is all in attributes), so it is
|
|
370
|
-
// read on open.
|
|
371
305
|
function applySheetProperties(local, attrs, sheet) {
|
|
372
306
|
switch (local) {
|
|
373
307
|
case 'tabColor':
|
|
374
|
-
// A `<sheetPr>` child.
|
|
375
308
|
sheet.tabColor = parseColor(attrs);
|
|
376
309
|
break;
|
|
377
310
|
case 'outlinePr':
|
|
378
|
-
// A `<sheetPr>` child.
|
|
379
311
|
if (attrs.summaryBelow !== undefined)
|
|
380
312
|
sheet.outline.summaryBelow = boolPresent(attrs.summaryBelow);
|
|
381
313
|
if (attrs.summaryRight !== undefined)
|
|
382
314
|
sheet.outline.summaryRight = boolPresent(attrs.summaryRight);
|
|
383
315
|
break;
|
|
316
|
+
case 'sheetView':
|
|
317
|
+
if (attrs.showGridLines !== undefined && !boolPresent(attrs.showGridLines)) {
|
|
318
|
+
sheet.view.showGridLines = false;
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
384
321
|
case 'pane':
|
|
385
|
-
// A `<sheetView>` child recording a frozen (or split) pane. Only a frozen pane maps onto the
|
|
386
|
-
// model's view; a source without one leaves `view` empty, so a re-write emits no pane.
|
|
387
322
|
if (attrs.state === 'frozen' || attrs.state === 'frozenSplit') {
|
|
388
323
|
sheet.view.state = 'frozen';
|
|
389
324
|
if (attrs.xSplit !== undefined)
|
|
@@ -395,8 +330,6 @@ function applySheetProperties(local, attrs, sheet) {
|
|
|
395
330
|
}
|
|
396
331
|
break;
|
|
397
332
|
case 'pageSetUpPr':
|
|
398
|
-
// The fit-to-page flag, a `<sheetPr>` child. Recorded only when the attribute is present, so a
|
|
399
|
-
// `<pageSetUpPr>` present for other reasons (e.g. `autoPageBreaks`) leaves `fitToPage` unset.
|
|
400
333
|
if (attrs.fitToPage !== undefined)
|
|
401
334
|
sheet.pageSetup.fitToPage = boolPresent(attrs.fitToPage);
|
|
402
335
|
break;
|
|
@@ -419,8 +352,6 @@ function applyColumn(sheet, attrs, xfStyles, columnStyle) {
|
|
|
419
352
|
const width = attrs.width !== undefined ? Number(attrs.width) : undefined;
|
|
420
353
|
const hidden = boolStrict(attrs.hidden);
|
|
421
354
|
const styleIndex = attrs.style !== undefined ? Number(attrs.style) : -1;
|
|
422
|
-
// The column's style resolves to the same facet bundle a cell's does; mirror all of it onto the
|
|
423
|
-
// column model so `getColumn(i)` reflects the declared default, not just its number format.
|
|
424
355
|
const style = styleIndex >= 0 ? xfStyles[styleIndex] : undefined;
|
|
425
356
|
for (let index = min; index <= max; index++) {
|
|
426
357
|
const column = sheet.getColumn(index);
|
|
@@ -437,7 +368,6 @@ function applyColumn(sheet, attrs, xfStyles, columnStyle) {
|
|
|
437
368
|
column.collapsed = true;
|
|
438
369
|
if (style !== undefined)
|
|
439
370
|
assignStyleFacets(column, style);
|
|
440
|
-
// Record the column's style so a bare cell in it can inherit the full column format on read.
|
|
441
371
|
if (styleIndex >= 0)
|
|
442
372
|
columnStyle.set(index, styleIndex);
|
|
443
373
|
}
|
|
@@ -446,10 +376,6 @@ function applyRow(sheet, attrs) {
|
|
|
446
376
|
const number = Number(attrs.r);
|
|
447
377
|
if (!Number.isInteger(number) || number < 1)
|
|
448
378
|
return;
|
|
449
|
-
// A `<row>` that states no attribute at all leaves no format record behind — the handle creates
|
|
450
|
-
// one only when something is written through it. That is the right reading: a bare `<row r="5"/>`
|
|
451
|
-
// carries no formatting to round-trip, and fabricating an empty record for it would put row 5 in
|
|
452
|
-
// the used range on the strength of an element that says nothing.
|
|
453
379
|
const row = sheet.getRow(number);
|
|
454
380
|
if (attrs.ht !== undefined && attrs.customHeight !== '0') {
|
|
455
381
|
const height = Number(attrs.ht);
|
|
@@ -466,9 +392,6 @@ function applyRow(sheet, attrs) {
|
|
|
466
392
|
if (boolStrict(attrs.collapsed))
|
|
467
393
|
row.collapsed = true;
|
|
468
394
|
}
|
|
469
|
-
// Read the `<printOptions>` boolean toggles back onto the model, storing only the ones the source
|
|
470
|
-
// carried so a re-write stays byte-clean. An OOXML boolean is `1`/`true` for on and `0`/`false` for
|
|
471
|
-
// off; a present-but-unrecognised token is dropped rather than coerced.
|
|
472
395
|
function applyPrintOptions(printOptions, attrs) {
|
|
473
396
|
const horizontalCentered = boolTristate(attrs.horizontalCentered);
|
|
474
397
|
if (horizontalCentered !== undefined)
|
|
@@ -496,10 +419,6 @@ function applyMargins(margins, attrs) {
|
|
|
496
419
|
margins[side] = value;
|
|
497
420
|
}
|
|
498
421
|
}
|
|
499
|
-
// Read the `<pageSetup>` print-scaling attributes back onto the model, setting only those the
|
|
500
|
-
// source carried so a re-write stays byte-clean. Numeric attributes that fail to parse are
|
|
501
|
-
// dropped rather than stored as NaN; the enumerated ones are trusted verbatim (an unexpected token
|
|
502
|
-
// round-trips harmlessly as an unknown string).
|
|
503
422
|
function applyPageSetup(pageSetup, attrs) {
|
|
504
423
|
const num = (raw) => {
|
|
505
424
|
if (raw === undefined)
|