@niicojs/excel 0.3.4 → 0.3.5
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/LICENSE +20 -20
- package/README.md +8 -2
- package/dist/index.cjs +1187 -1265
- package/dist/index.d.cts +171 -324
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +171 -324
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1187 -1266
- package/package.json +4 -4
- package/src/index.ts +8 -10
- package/src/pivot-table.ts +619 -524
- package/src/shared-strings.ts +33 -9
- package/src/styles.ts +38 -9
- package/src/types.ts +295 -323
- package/src/utils/address.ts +48 -0
- package/src/utils/format.ts +8 -7
- package/src/utils/xml.ts +1 -1
- package/src/utils/zip.ts +153 -11
- package/src/workbook.ts +330 -350
- package/src/worksheet.ts +1003 -935
- package/src/pivot-cache.ts +0 -449
package/src/shared-strings.ts
CHANGED
|
@@ -18,21 +18,38 @@ export class SharedStrings {
|
|
|
18
18
|
private stringToIndex: Map<string, number> = new Map();
|
|
19
19
|
private _dirty = false;
|
|
20
20
|
private _totalCount = 0;
|
|
21
|
+
private _rawXml: string | null = null;
|
|
22
|
+
private _parsed = false;
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* Parse shared strings from XML content
|
|
24
26
|
*/
|
|
25
27
|
static parse(xml: string): SharedStrings {
|
|
26
28
|
const ss = new SharedStrings();
|
|
27
|
-
|
|
29
|
+
ss._rawXml = xml;
|
|
30
|
+
ss._parse();
|
|
31
|
+
return ss;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private _parse(): void {
|
|
35
|
+
if (this._parsed) return;
|
|
36
|
+
if (!this._rawXml) {
|
|
37
|
+
this._parsed = true;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const parsed = parseXml(this._rawXml);
|
|
28
42
|
const sst = findElement(parsed, 'sst');
|
|
29
|
-
if (!sst)
|
|
43
|
+
if (!sst) {
|
|
44
|
+
this._parsed = true;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
30
47
|
|
|
31
48
|
const countAttr = getAttr(sst, 'count');
|
|
32
49
|
if (countAttr) {
|
|
33
50
|
const total = parseInt(countAttr, 10);
|
|
34
51
|
if (Number.isFinite(total) && total >= 0) {
|
|
35
|
-
|
|
52
|
+
this._totalCount = total;
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
55
|
|
|
@@ -40,17 +57,17 @@ export class SharedStrings {
|
|
|
40
57
|
for (const child of children) {
|
|
41
58
|
if ('si' in child) {
|
|
42
59
|
const siChildren = getChildren(child, 'si');
|
|
43
|
-
const text =
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
const text = this.extractText(siChildren);
|
|
61
|
+
this.entries.push({ text, node: child });
|
|
62
|
+
this.stringToIndex.set(text, this.entries.length - 1);
|
|
46
63
|
}
|
|
47
64
|
}
|
|
48
65
|
|
|
49
|
-
if (
|
|
50
|
-
|
|
66
|
+
if (this._totalCount === 0 && this.entries.length > 0) {
|
|
67
|
+
this._totalCount = this.entries.length;
|
|
51
68
|
}
|
|
52
69
|
|
|
53
|
-
|
|
70
|
+
this._parsed = true;
|
|
54
71
|
}
|
|
55
72
|
|
|
56
73
|
/**
|
|
@@ -90,6 +107,7 @@ export class SharedStrings {
|
|
|
90
107
|
* Get a string by index
|
|
91
108
|
*/
|
|
92
109
|
getString(index: number): string | undefined {
|
|
110
|
+
this._parse();
|
|
93
111
|
return this.entries[index]?.text;
|
|
94
112
|
}
|
|
95
113
|
|
|
@@ -98,6 +116,7 @@ export class SharedStrings {
|
|
|
98
116
|
* If the string already exists, returns the existing index
|
|
99
117
|
*/
|
|
100
118
|
addString(str: string): number {
|
|
119
|
+
this._parse();
|
|
101
120
|
const existing = this.stringToIndex.get(str);
|
|
102
121
|
if (existing !== undefined) {
|
|
103
122
|
this._totalCount++;
|
|
@@ -120,6 +139,7 @@ export class SharedStrings {
|
|
|
120
139
|
* Check if the shared strings table has been modified
|
|
121
140
|
*/
|
|
122
141
|
get dirty(): boolean {
|
|
142
|
+
this._parse();
|
|
123
143
|
return this._dirty;
|
|
124
144
|
}
|
|
125
145
|
|
|
@@ -127,6 +147,7 @@ export class SharedStrings {
|
|
|
127
147
|
* Get the count of strings
|
|
128
148
|
*/
|
|
129
149
|
get count(): number {
|
|
150
|
+
this._parse();
|
|
130
151
|
return this.entries.length;
|
|
131
152
|
}
|
|
132
153
|
|
|
@@ -134,6 +155,7 @@ export class SharedStrings {
|
|
|
134
155
|
* Get total usage count of shared strings
|
|
135
156
|
*/
|
|
136
157
|
get totalCount(): number {
|
|
158
|
+
this._parse();
|
|
137
159
|
return Math.max(this._totalCount, this.entries.length);
|
|
138
160
|
}
|
|
139
161
|
|
|
@@ -141,6 +163,7 @@ export class SharedStrings {
|
|
|
141
163
|
* Get all unique shared strings in insertion order.
|
|
142
164
|
*/
|
|
143
165
|
getAllStrings(): string[] {
|
|
166
|
+
this._parse();
|
|
144
167
|
return this.entries.map((entry) => entry.text);
|
|
145
168
|
}
|
|
146
169
|
|
|
@@ -148,6 +171,7 @@ export class SharedStrings {
|
|
|
148
171
|
* Generate XML for the shared strings table
|
|
149
172
|
*/
|
|
150
173
|
toXml(): string {
|
|
174
|
+
this._parse();
|
|
151
175
|
const siElements: XmlNode[] = [];
|
|
152
176
|
for (const entry of this.entries) {
|
|
153
177
|
if (entry.node) {
|
package/src/styles.ts
CHANGED
|
@@ -80,6 +80,8 @@ export class Styles {
|
|
|
80
80
|
private _borders: StyleBorder[] = [];
|
|
81
81
|
private _cellXfs: CellXf[] = []; // Cell formats (combined style index)
|
|
82
82
|
private _xmlNodes: XmlNode[] | null = null;
|
|
83
|
+
private _rawXml: string | null = null;
|
|
84
|
+
private _parsed = false;
|
|
83
85
|
private _dirty = false;
|
|
84
86
|
|
|
85
87
|
// Cache for style deduplication
|
|
@@ -146,10 +148,30 @@ export class Styles {
|
|
|
146
148
|
*/
|
|
147
149
|
static parse(xml: string): Styles {
|
|
148
150
|
const styles = new Styles();
|
|
149
|
-
styles.
|
|
151
|
+
styles._rawXml = xml;
|
|
152
|
+
styles._parse();
|
|
153
|
+
return styles;
|
|
154
|
+
}
|
|
150
155
|
|
|
151
|
-
|
|
152
|
-
if (
|
|
156
|
+
private _parse(): void {
|
|
157
|
+
if (this._parsed) return;
|
|
158
|
+
if (!this._rawXml) {
|
|
159
|
+
this._parsed = true;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this._xmlNodes = parseXml(this._rawXml);
|
|
164
|
+
|
|
165
|
+
if (!this._xmlNodes) {
|
|
166
|
+
this._parsed = true;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const styleSheet = findElement(this._xmlNodes, 'styleSheet');
|
|
171
|
+
if (!styleSheet) {
|
|
172
|
+
this._parsed = true;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
153
175
|
|
|
154
176
|
const children = getChildren(styleSheet, 'styleSheet');
|
|
155
177
|
|
|
@@ -160,7 +182,7 @@ export class Styles {
|
|
|
160
182
|
if ('numFmt' in child) {
|
|
161
183
|
const id = parseInt(getAttr(child, 'numFmtId') || '0', 10);
|
|
162
184
|
const code = getAttr(child, 'formatCode') || '';
|
|
163
|
-
|
|
185
|
+
this._numFmts.set(id, code);
|
|
164
186
|
}
|
|
165
187
|
}
|
|
166
188
|
}
|
|
@@ -170,7 +192,7 @@ export class Styles {
|
|
|
170
192
|
if (fonts) {
|
|
171
193
|
for (const child of getChildren(fonts, 'fonts')) {
|
|
172
194
|
if ('font' in child) {
|
|
173
|
-
|
|
195
|
+
this._fonts.push(this._parseFont(child));
|
|
174
196
|
}
|
|
175
197
|
}
|
|
176
198
|
}
|
|
@@ -180,7 +202,7 @@ export class Styles {
|
|
|
180
202
|
if (fills) {
|
|
181
203
|
for (const child of getChildren(fills, 'fills')) {
|
|
182
204
|
if ('fill' in child) {
|
|
183
|
-
|
|
205
|
+
this._fills.push(this._parseFill(child));
|
|
184
206
|
}
|
|
185
207
|
}
|
|
186
208
|
}
|
|
@@ -190,7 +212,7 @@ export class Styles {
|
|
|
190
212
|
if (borders) {
|
|
191
213
|
for (const child of getChildren(borders, 'borders')) {
|
|
192
214
|
if ('border' in child) {
|
|
193
|
-
|
|
215
|
+
this._borders.push(this._parseBorder(child));
|
|
194
216
|
}
|
|
195
217
|
}
|
|
196
218
|
}
|
|
@@ -200,12 +222,12 @@ export class Styles {
|
|
|
200
222
|
if (cellXfs) {
|
|
201
223
|
for (const child of getChildren(cellXfs, 'cellXfs')) {
|
|
202
224
|
if ('xf' in child) {
|
|
203
|
-
|
|
225
|
+
this._cellXfs.push(this._parseCellXf(child));
|
|
204
226
|
}
|
|
205
227
|
}
|
|
206
228
|
}
|
|
207
229
|
|
|
208
|
-
|
|
230
|
+
this._parsed = true;
|
|
209
231
|
}
|
|
210
232
|
|
|
211
233
|
/**
|
|
@@ -213,6 +235,7 @@ export class Styles {
|
|
|
213
235
|
*/
|
|
214
236
|
static createDefault(): Styles {
|
|
215
237
|
const styles = new Styles();
|
|
238
|
+
styles._parsed = true;
|
|
216
239
|
|
|
217
240
|
// Default font (Calibri 11)
|
|
218
241
|
styles._fonts.push({
|
|
@@ -366,6 +389,7 @@ export class Styles {
|
|
|
366
389
|
* Get a style by index
|
|
367
390
|
*/
|
|
368
391
|
getStyle(index: number): CellStyle {
|
|
392
|
+
this._parse();
|
|
369
393
|
const cached = this._styleObjectCache.get(index);
|
|
370
394
|
if (cached) return { ...cached };
|
|
371
395
|
|
|
@@ -440,6 +464,7 @@ export class Styles {
|
|
|
440
464
|
* Uses caching to deduplicate identical styles
|
|
441
465
|
*/
|
|
442
466
|
createStyle(style: CellStyle): number {
|
|
467
|
+
this._parse();
|
|
443
468
|
const key = this._getStyleKey(style);
|
|
444
469
|
const cached = this._styleCache.get(key);
|
|
445
470
|
if (cached !== undefined) {
|
|
@@ -489,6 +514,7 @@ export class Styles {
|
|
|
489
514
|
* Clone an existing style by index, optionally overriding fields.
|
|
490
515
|
*/
|
|
491
516
|
cloneStyle(index: number, overrides: Partial<CellStyle> = {}): number {
|
|
517
|
+
this._parse();
|
|
492
518
|
const baseStyle = this.getStyle(index);
|
|
493
519
|
return this.createStyle({ ...baseStyle, ...overrides });
|
|
494
520
|
}
|
|
@@ -602,6 +628,7 @@ export class Styles {
|
|
|
602
628
|
* @param format - The number format string (e.g., '0.00', '#,##0', '$#,##0.00')
|
|
603
629
|
*/
|
|
604
630
|
getOrCreateNumFmtId(format: string): number {
|
|
631
|
+
this._parse();
|
|
605
632
|
this._dirty = true;
|
|
606
633
|
return this._findOrCreateNumFmt(format);
|
|
607
634
|
}
|
|
@@ -610,6 +637,7 @@ export class Styles {
|
|
|
610
637
|
* Check if styles have been modified
|
|
611
638
|
*/
|
|
612
639
|
get dirty(): boolean {
|
|
640
|
+
this._parse();
|
|
613
641
|
return this._dirty;
|
|
614
642
|
}
|
|
615
643
|
|
|
@@ -617,6 +645,7 @@ export class Styles {
|
|
|
617
645
|
* Generate XML for styles
|
|
618
646
|
*/
|
|
619
647
|
toXml(): string {
|
|
648
|
+
this._parse();
|
|
620
649
|
const children: XmlNode[] = [];
|
|
621
650
|
|
|
622
651
|
// Number formats
|