@niicojs/excel 0.2.5 → 0.2.6
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/dist/index.cjs +168 -9
- package/dist/index.d.cts +14 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +168 -9
- package/package.json +1 -1
- package/src/pivot-table.ts +40 -15
- package/src/styles.ts +64 -4
- package/src/workbook.ts +4 -0
package/dist/index.cjs
CHANGED
|
@@ -1117,6 +1117,129 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1117
1117
|
}
|
|
1118
1118
|
}
|
|
1119
1119
|
|
|
1120
|
+
/**
|
|
1121
|
+
* Excel built-in number format IDs (0-163 are reserved).
|
|
1122
|
+
* These formats don't need to be defined in the numFmts element.
|
|
1123
|
+
*/ const BUILTIN_NUM_FMTS = new Map([
|
|
1124
|
+
[
|
|
1125
|
+
'General',
|
|
1126
|
+
0
|
|
1127
|
+
],
|
|
1128
|
+
[
|
|
1129
|
+
'0',
|
|
1130
|
+
1
|
|
1131
|
+
],
|
|
1132
|
+
[
|
|
1133
|
+
'0.00',
|
|
1134
|
+
2
|
|
1135
|
+
],
|
|
1136
|
+
[
|
|
1137
|
+
'#,##0',
|
|
1138
|
+
3
|
|
1139
|
+
],
|
|
1140
|
+
[
|
|
1141
|
+
'#,##0.00',
|
|
1142
|
+
4
|
|
1143
|
+
],
|
|
1144
|
+
[
|
|
1145
|
+
'0%',
|
|
1146
|
+
9
|
|
1147
|
+
],
|
|
1148
|
+
[
|
|
1149
|
+
'0.00%',
|
|
1150
|
+
10
|
|
1151
|
+
],
|
|
1152
|
+
[
|
|
1153
|
+
'0.00E+00',
|
|
1154
|
+
11
|
|
1155
|
+
],
|
|
1156
|
+
[
|
|
1157
|
+
'# ?/?',
|
|
1158
|
+
12
|
|
1159
|
+
],
|
|
1160
|
+
[
|
|
1161
|
+
'# ??/??',
|
|
1162
|
+
13
|
|
1163
|
+
],
|
|
1164
|
+
[
|
|
1165
|
+
'mm-dd-yy',
|
|
1166
|
+
14
|
|
1167
|
+
],
|
|
1168
|
+
[
|
|
1169
|
+
'd-mmm-yy',
|
|
1170
|
+
15
|
|
1171
|
+
],
|
|
1172
|
+
[
|
|
1173
|
+
'd-mmm',
|
|
1174
|
+
16
|
|
1175
|
+
],
|
|
1176
|
+
[
|
|
1177
|
+
'mmm-yy',
|
|
1178
|
+
17
|
|
1179
|
+
],
|
|
1180
|
+
[
|
|
1181
|
+
'h:mm AM/PM',
|
|
1182
|
+
18
|
|
1183
|
+
],
|
|
1184
|
+
[
|
|
1185
|
+
'h:mm:ss AM/PM',
|
|
1186
|
+
19
|
|
1187
|
+
],
|
|
1188
|
+
[
|
|
1189
|
+
'h:mm',
|
|
1190
|
+
20
|
|
1191
|
+
],
|
|
1192
|
+
[
|
|
1193
|
+
'h:mm:ss',
|
|
1194
|
+
21
|
|
1195
|
+
],
|
|
1196
|
+
[
|
|
1197
|
+
'm/d/yy h:mm',
|
|
1198
|
+
22
|
|
1199
|
+
],
|
|
1200
|
+
[
|
|
1201
|
+
'#,##0 ;(#,##0)',
|
|
1202
|
+
37
|
|
1203
|
+
],
|
|
1204
|
+
[
|
|
1205
|
+
'#,##0 ;[Red](#,##0)',
|
|
1206
|
+
38
|
|
1207
|
+
],
|
|
1208
|
+
[
|
|
1209
|
+
'#,##0.00;(#,##0.00)',
|
|
1210
|
+
39
|
|
1211
|
+
],
|
|
1212
|
+
[
|
|
1213
|
+
'#,##0.00;[Red](#,##0.00)',
|
|
1214
|
+
40
|
|
1215
|
+
],
|
|
1216
|
+
[
|
|
1217
|
+
'mm:ss',
|
|
1218
|
+
45
|
|
1219
|
+
],
|
|
1220
|
+
[
|
|
1221
|
+
'[h]:mm:ss',
|
|
1222
|
+
46
|
|
1223
|
+
],
|
|
1224
|
+
[
|
|
1225
|
+
'mmss.0',
|
|
1226
|
+
47
|
|
1227
|
+
],
|
|
1228
|
+
[
|
|
1229
|
+
'##0.0E+0',
|
|
1230
|
+
48
|
|
1231
|
+
],
|
|
1232
|
+
[
|
|
1233
|
+
'@',
|
|
1234
|
+
49
|
|
1235
|
+
]
|
|
1236
|
+
]);
|
|
1237
|
+
/**
|
|
1238
|
+
* Reverse lookup: built-in format ID -> format code
|
|
1239
|
+
*/ const BUILTIN_NUM_FMT_CODES = new Map(Array.from(BUILTIN_NUM_FMTS.entries()).map(([code, id])=>[
|
|
1240
|
+
id,
|
|
1241
|
+
code
|
|
1242
|
+
]));
|
|
1120
1243
|
/**
|
|
1121
1244
|
* Normalize a color to ARGB format (8 hex chars).
|
|
1122
1245
|
* Accepts: "#RGB", "#RRGGBB", "RGB", "RRGGBB", "AARRGGBB", "#AARRGGBB"
|
|
@@ -1307,7 +1430,8 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1307
1430
|
const font = this._fonts[xf.fontId];
|
|
1308
1431
|
const fill = this._fills[xf.fillId];
|
|
1309
1432
|
const border = this._borders[xf.borderId];
|
|
1310
|
-
|
|
1433
|
+
// Check custom formats first, then fall back to built-in format codes
|
|
1434
|
+
const numFmt = this._numFmts.get(xf.numFmtId) ?? BUILTIN_NUM_FMT_CODES.get(xf.numFmtId);
|
|
1311
1435
|
const style = {};
|
|
1312
1436
|
if (font) {
|
|
1313
1437
|
if (font.bold) style.bold = true;
|
|
@@ -1439,16 +1563,30 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1439
1563
|
return this._borders.length - 1;
|
|
1440
1564
|
}
|
|
1441
1565
|
_findOrCreateNumFmt(format) {
|
|
1442
|
-
// Check
|
|
1566
|
+
// Check built-in formats first (IDs 0-163)
|
|
1567
|
+
const builtinId = BUILTIN_NUM_FMTS.get(format);
|
|
1568
|
+
if (builtinId !== undefined) {
|
|
1569
|
+
return builtinId;
|
|
1570
|
+
}
|
|
1571
|
+
// Check if already exists in custom formats
|
|
1443
1572
|
for (const [id, code] of this._numFmts){
|
|
1444
1573
|
if (code === format) return id;
|
|
1445
1574
|
}
|
|
1446
|
-
// Create new
|
|
1447
|
-
const
|
|
1575
|
+
// Create new custom format (IDs 164+)
|
|
1576
|
+
const existingIds = Array.from(this._numFmts.keys());
|
|
1577
|
+
const id = existingIds.length > 0 ? Math.max(...existingIds) + 1 : 164;
|
|
1448
1578
|
this._numFmts.set(id, format);
|
|
1449
1579
|
return id;
|
|
1450
1580
|
}
|
|
1451
1581
|
/**
|
|
1582
|
+
* Get or create a number format ID for the given format string.
|
|
1583
|
+
* Returns built-in IDs (0-163) for standard formats, or creates custom IDs (164+).
|
|
1584
|
+
* @param format - The number format string (e.g., '0.00', '#,##0', '$#,##0.00')
|
|
1585
|
+
*/ getOrCreateNumFmtId(format) {
|
|
1586
|
+
this._dirty = true;
|
|
1587
|
+
return this._findOrCreateNumFmt(format);
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1452
1590
|
* Check if styles have been modified
|
|
1453
1591
|
*/ get dirty() {
|
|
1454
1592
|
return this._dirty;
|
|
@@ -1628,6 +1766,7 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1628
1766
|
this._columnFields = [];
|
|
1629
1767
|
this._valueFields = [];
|
|
1630
1768
|
this._filterFields = [];
|
|
1769
|
+
this._styles = null;
|
|
1631
1770
|
this._name = name;
|
|
1632
1771
|
this._cache = cache;
|
|
1633
1772
|
this._targetSheet = targetSheet;
|
|
@@ -1662,6 +1801,13 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1662
1801
|
return this._pivotTableIndex;
|
|
1663
1802
|
}
|
|
1664
1803
|
/**
|
|
1804
|
+
* Set the styles reference for number format resolution
|
|
1805
|
+
* @internal
|
|
1806
|
+
*/ setStyles(styles) {
|
|
1807
|
+
this._styles = styles;
|
|
1808
|
+
return this;
|
|
1809
|
+
}
|
|
1810
|
+
/**
|
|
1665
1811
|
* Add a field to the row area
|
|
1666
1812
|
* @param fieldName - Name of the source field (column header)
|
|
1667
1813
|
*/ addRowField(fieldName) {
|
|
@@ -1696,7 +1842,8 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1696
1842
|
* @param fieldName - Name of the source field (column header)
|
|
1697
1843
|
* @param aggregation - Aggregation function (sum, count, average, min, max)
|
|
1698
1844
|
* @param displayName - Optional display name (defaults to "Sum of FieldName")
|
|
1699
|
-
|
|
1845
|
+
* @param numberFormat - Optional number format (e.g., '$#,##0.00', '0.00%')
|
|
1846
|
+
*/ addValueField(fieldName, aggregation = 'sum', displayName, numberFormat) {
|
|
1700
1847
|
const fieldIndex = this._cache.getFieldIndex(fieldName);
|
|
1701
1848
|
if (fieldIndex < 0) {
|
|
1702
1849
|
throw new Error(`Field not found in source data: ${fieldName}`);
|
|
@@ -1707,7 +1854,8 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1707
1854
|
fieldIndex,
|
|
1708
1855
|
axis: 'value',
|
|
1709
1856
|
aggregation,
|
|
1710
|
-
displayName: displayName || defaultName
|
|
1857
|
+
displayName: displayName || defaultName,
|
|
1858
|
+
numberFormat
|
|
1711
1859
|
});
|
|
1712
1860
|
return this;
|
|
1713
1861
|
}
|
|
@@ -1830,17 +1978,26 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1830
1978
|
}
|
|
1831
1979
|
// Data fields (values)
|
|
1832
1980
|
if (this._valueFields.length > 0) {
|
|
1833
|
-
const dataFieldNodes = this._valueFields.map((f)=>
|
|
1981
|
+
const dataFieldNodes = this._valueFields.map((f)=>{
|
|
1982
|
+
const attrs = {
|
|
1834
1983
|
name: f.displayName || f.fieldName,
|
|
1835
1984
|
fld: String(f.fieldIndex),
|
|
1836
1985
|
baseField: '0',
|
|
1837
1986
|
baseItem: '0',
|
|
1838
1987
|
subtotal: f.aggregation || 'sum'
|
|
1839
|
-
}
|
|
1988
|
+
};
|
|
1989
|
+
// Add numFmtId if format specified and styles available
|
|
1990
|
+
if (f.numberFormat && this._styles) {
|
|
1991
|
+
attrs.numFmtId = String(this._styles.getOrCreateNumFmtId(f.numberFormat));
|
|
1992
|
+
}
|
|
1993
|
+
return createElement('dataField', attrs, []);
|
|
1994
|
+
});
|
|
1840
1995
|
children.push(createElement('dataFields', {
|
|
1841
1996
|
count: String(dataFieldNodes.length)
|
|
1842
1997
|
}, dataFieldNodes));
|
|
1843
1998
|
}
|
|
1999
|
+
// Check if any value field has a number format
|
|
2000
|
+
const hasNumberFormats = this._valueFields.some((f)=>f.numberFormat);
|
|
1844
2001
|
// Pivot table style
|
|
1845
2002
|
children.push(createElement('pivotTableStyleInfo', {
|
|
1846
2003
|
name: 'PivotStyleMedium9',
|
|
@@ -1855,7 +2012,7 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
1855
2012
|
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
|
1856
2013
|
name: this._name,
|
|
1857
2014
|
cacheId: String(this._cache.cacheId),
|
|
1858
|
-
applyNumberFormats: '0',
|
|
2015
|
+
applyNumberFormats: hasNumberFormats ? '1' : '0',
|
|
1859
2016
|
applyBorderFormats: '0',
|
|
1860
2017
|
applyFontFormats: '0',
|
|
1861
2018
|
applyPatternFormats: '0',
|
|
@@ -2789,6 +2946,8 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
2789
2946
|
// Create pivot table
|
|
2790
2947
|
const pivotTableIndex = this._pivotTables.length + 1;
|
|
2791
2948
|
const pivotTable = new PivotTable(config.name, cache, targetSheet, targetCell, targetAddr.row + 1, targetAddr.col, pivotTableIndex);
|
|
2949
|
+
// Set styles reference for number format resolution
|
|
2950
|
+
pivotTable.setStyles(this._styles);
|
|
2792
2951
|
this._pivotTables.push(pivotTable);
|
|
2793
2952
|
return pivotTable;
|
|
2794
2953
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -521,6 +521,12 @@ declare class Styles {
|
|
|
521
521
|
private _findOrCreateFill;
|
|
522
522
|
private _findOrCreateBorder;
|
|
523
523
|
private _findOrCreateNumFmt;
|
|
524
|
+
/**
|
|
525
|
+
* Get or create a number format ID for the given format string.
|
|
526
|
+
* Returns built-in IDs (0-163) for standard formats, or creates custom IDs (164+).
|
|
527
|
+
* @param format - The number format string (e.g., '0.00', '#,##0', '$#,##0.00')
|
|
528
|
+
*/
|
|
529
|
+
getOrCreateNumFmtId(format: string): number;
|
|
524
530
|
/**
|
|
525
531
|
* Check if styles have been modified
|
|
526
532
|
*/
|
|
@@ -620,6 +626,7 @@ declare class PivotTable {
|
|
|
620
626
|
private _valueFields;
|
|
621
627
|
private _filterFields;
|
|
622
628
|
private _pivotTableIndex;
|
|
629
|
+
private _styles;
|
|
623
630
|
constructor(name: string, cache: PivotCache, targetSheet: string, targetCell: string, targetRow: number, targetCol: number, pivotTableIndex: number);
|
|
624
631
|
/**
|
|
625
632
|
* Get the pivot table name
|
|
@@ -641,6 +648,11 @@ declare class PivotTable {
|
|
|
641
648
|
* Get the pivot table index (for file naming)
|
|
642
649
|
*/
|
|
643
650
|
get index(): number;
|
|
651
|
+
/**
|
|
652
|
+
* Set the styles reference for number format resolution
|
|
653
|
+
* @internal
|
|
654
|
+
*/
|
|
655
|
+
setStyles(styles: Styles): this;
|
|
644
656
|
/**
|
|
645
657
|
* Add a field to the row area
|
|
646
658
|
* @param fieldName - Name of the source field (column header)
|
|
@@ -656,8 +668,9 @@ declare class PivotTable {
|
|
|
656
668
|
* @param fieldName - Name of the source field (column header)
|
|
657
669
|
* @param aggregation - Aggregation function (sum, count, average, min, max)
|
|
658
670
|
* @param displayName - Optional display name (defaults to "Sum of FieldName")
|
|
671
|
+
* @param numberFormat - Optional number format (e.g., '$#,##0.00', '0.00%')
|
|
659
672
|
*/
|
|
660
|
-
addValueField(fieldName: string, aggregation?: AggregationType, displayName?: string): this;
|
|
673
|
+
addValueField(fieldName: string, aggregation?: AggregationType, displayName?: string, numberFormat?: string): this;
|
|
661
674
|
/**
|
|
662
675
|
* Add a field to the filter (page) area
|
|
663
676
|
* @param fieldName - Name of the source field (column header)
|