@niicojs/excel 0.1.0 → 0.2.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/dist/index.cjs +143 -9
- package/dist/index.d.cts +70 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +70 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +143 -9
- package/package.json +7 -7
- package/src/cell.ts +44 -9
- package/src/index.ts +3 -0
- package/src/types.ts +28 -0
- package/src/workbook.ts +130 -2
package/dist/index.cjs
CHANGED
|
@@ -152,6 +152,10 @@ const ERROR_TYPES = new Set([
|
|
|
152
152
|
}
|
|
153
153
|
switch(t){
|
|
154
154
|
case 'n':
|
|
155
|
+
// Check if this is actually a date stored as number
|
|
156
|
+
if (this._isDateFormat()) {
|
|
157
|
+
return 'date';
|
|
158
|
+
}
|
|
155
159
|
return 'number';
|
|
156
160
|
case 's':
|
|
157
161
|
case 'str':
|
|
@@ -164,7 +168,12 @@ const ERROR_TYPES = new Set([
|
|
|
164
168
|
return 'date';
|
|
165
169
|
default:
|
|
166
170
|
// If no type but has value, infer from value
|
|
167
|
-
if (typeof this._data.v === 'number')
|
|
171
|
+
if (typeof this._data.v === 'number') {
|
|
172
|
+
if (this._isDateFormat()) {
|
|
173
|
+
return 'date';
|
|
174
|
+
}
|
|
175
|
+
return 'number';
|
|
176
|
+
}
|
|
168
177
|
if (typeof this._data.v === 'string') return 'string';
|
|
169
178
|
if (typeof this._data.v === 'boolean') return 'boolean';
|
|
170
179
|
return 'empty';
|
|
@@ -180,7 +189,14 @@ const ERROR_TYPES = new Set([
|
|
|
180
189
|
}
|
|
181
190
|
switch(t){
|
|
182
191
|
case 'n':
|
|
183
|
-
|
|
192
|
+
{
|
|
193
|
+
const numVal = typeof v === 'number' ? v : parseFloat(String(v));
|
|
194
|
+
// Check if this is actually a date stored as number
|
|
195
|
+
if (this._isDateFormat()) {
|
|
196
|
+
return this._excelDateToJs(numVal);
|
|
197
|
+
}
|
|
198
|
+
return numVal;
|
|
199
|
+
}
|
|
184
200
|
case 's':
|
|
185
201
|
// Shared string reference
|
|
186
202
|
if (typeof v === 'number') {
|
|
@@ -242,9 +258,15 @@ const ERROR_TYPES = new Set([
|
|
|
242
258
|
this._data.v = val ? 1 : 0;
|
|
243
259
|
this._data.t = 'b';
|
|
244
260
|
} else if (val instanceof Date) {
|
|
245
|
-
// Store as
|
|
246
|
-
this._data.v =
|
|
247
|
-
this._data.t = '
|
|
261
|
+
// Store as Excel serial number with date format for maximum compatibility
|
|
262
|
+
this._data.v = this._jsDateToExcel(val);
|
|
263
|
+
this._data.t = 'n';
|
|
264
|
+
// Apply a default date format if no style is set
|
|
265
|
+
if (this._data.s === undefined) {
|
|
266
|
+
this._data.s = this._worksheet.workbook.styles.createStyle({
|
|
267
|
+
numberFormat: 'yyyy-mm-dd'
|
|
268
|
+
});
|
|
269
|
+
}
|
|
248
270
|
} else if ('error' in val) {
|
|
249
271
|
this._data.v = val.error;
|
|
250
272
|
this._data.t = 'e';
|
|
@@ -334,9 +356,16 @@ const ERROR_TYPES = new Set([
|
|
|
334
356
|
/**
|
|
335
357
|
* Check if this cell has a date number format
|
|
336
358
|
*/ _isDateFormat() {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
359
|
+
if (this._data.s === undefined) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
const style = this._worksheet.workbook.styles.getStyle(this._data.s);
|
|
363
|
+
if (!style.numberFormat) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
// Common date format patterns
|
|
367
|
+
const fmt = style.numberFormat.toLowerCase();
|
|
368
|
+
return fmt.includes('y') || fmt.includes('m') || fmt.includes('d') || fmt.includes('h') || fmt.includes('s') || fmt === 'general date' || fmt === 'short date' || fmt === 'long date';
|
|
340
369
|
}
|
|
341
370
|
/**
|
|
342
371
|
* Convert Excel serial date to JavaScript Date
|
|
@@ -2467,6 +2496,110 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
2467
2496
|
return copy;
|
|
2468
2497
|
}
|
|
2469
2498
|
/**
|
|
2499
|
+
* Create a new worksheet from an array of objects.
|
|
2500
|
+
*
|
|
2501
|
+
* The first row contains headers (object keys or custom column headers),
|
|
2502
|
+
* and subsequent rows contain the object values.
|
|
2503
|
+
*
|
|
2504
|
+
* @param config - Configuration for the sheet creation
|
|
2505
|
+
* @returns The created Worksheet
|
|
2506
|
+
*
|
|
2507
|
+
* @example
|
|
2508
|
+
* ```typescript
|
|
2509
|
+
* const data = [
|
|
2510
|
+
* { name: 'Alice', age: 30, city: 'Paris' },
|
|
2511
|
+
* { name: 'Bob', age: 25, city: 'London' },
|
|
2512
|
+
* { name: 'Charlie', age: 35, city: 'Berlin' },
|
|
2513
|
+
* ];
|
|
2514
|
+
*
|
|
2515
|
+
* // Simple usage - all object keys become columns
|
|
2516
|
+
* const sheet = wb.addSheetFromData({
|
|
2517
|
+
* name: 'People',
|
|
2518
|
+
* data: data,
|
|
2519
|
+
* });
|
|
2520
|
+
*
|
|
2521
|
+
* // With custom column configuration
|
|
2522
|
+
* const sheet2 = wb.addSheetFromData({
|
|
2523
|
+
* name: 'People Custom',
|
|
2524
|
+
* data: data,
|
|
2525
|
+
* columns: [
|
|
2526
|
+
* { key: 'name', header: 'Full Name' },
|
|
2527
|
+
* { key: 'age', header: 'Age (years)' },
|
|
2528
|
+
* ],
|
|
2529
|
+
* });
|
|
2530
|
+
* ```
|
|
2531
|
+
*/ addSheetFromData(config) {
|
|
2532
|
+
const { name, data, columns, headerStyle = true, startCell = 'A1' } = config;
|
|
2533
|
+
if (data.length === 0) {
|
|
2534
|
+
// Create empty sheet if no data
|
|
2535
|
+
return this.addSheet(name);
|
|
2536
|
+
}
|
|
2537
|
+
// Create the new sheet
|
|
2538
|
+
const sheet = this.addSheet(name);
|
|
2539
|
+
// Parse start cell
|
|
2540
|
+
const startAddr = parseAddress(startCell);
|
|
2541
|
+
let startRow = startAddr.row;
|
|
2542
|
+
const startCol = startAddr.col;
|
|
2543
|
+
// Determine columns to use
|
|
2544
|
+
const columnConfigs = columns ?? this._inferColumns(data[0]);
|
|
2545
|
+
// Write header row
|
|
2546
|
+
for(let colIdx = 0; colIdx < columnConfigs.length; colIdx++){
|
|
2547
|
+
const colConfig = columnConfigs[colIdx];
|
|
2548
|
+
const headerText = colConfig.header ?? String(colConfig.key);
|
|
2549
|
+
const cell = sheet.cell(startRow, startCol + colIdx);
|
|
2550
|
+
cell.value = headerText;
|
|
2551
|
+
// Apply header style if enabled
|
|
2552
|
+
if (headerStyle) {
|
|
2553
|
+
cell.style = {
|
|
2554
|
+
bold: true
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
// Move to data rows
|
|
2559
|
+
startRow++;
|
|
2560
|
+
// Write data rows
|
|
2561
|
+
for(let rowIdx = 0; rowIdx < data.length; rowIdx++){
|
|
2562
|
+
const rowData = data[rowIdx];
|
|
2563
|
+
for(let colIdx = 0; colIdx < columnConfigs.length; colIdx++){
|
|
2564
|
+
const colConfig = columnConfigs[colIdx];
|
|
2565
|
+
const value = rowData[colConfig.key];
|
|
2566
|
+
const cell = sheet.cell(startRow + rowIdx, startCol + colIdx);
|
|
2567
|
+
// Convert value to CellValue
|
|
2568
|
+
cell.value = this._toCellValue(value);
|
|
2569
|
+
// Apply column style if defined
|
|
2570
|
+
if (colConfig.style) {
|
|
2571
|
+
cell.style = colConfig.style;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
return sheet;
|
|
2576
|
+
}
|
|
2577
|
+
/**
|
|
2578
|
+
* Infer column configuration from the first data object
|
|
2579
|
+
*/ _inferColumns(sample) {
|
|
2580
|
+
return Object.keys(sample).map((key)=>({
|
|
2581
|
+
key
|
|
2582
|
+
}));
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Convert an unknown value to a CellValue
|
|
2586
|
+
*/ _toCellValue(value) {
|
|
2587
|
+
if (value === null || value === undefined) {
|
|
2588
|
+
return null;
|
|
2589
|
+
}
|
|
2590
|
+
if (typeof value === 'number' || typeof value === 'string' || typeof value === 'boolean') {
|
|
2591
|
+
return value;
|
|
2592
|
+
}
|
|
2593
|
+
if (value instanceof Date) {
|
|
2594
|
+
return value;
|
|
2595
|
+
}
|
|
2596
|
+
if (typeof value === 'object' && 'error' in value) {
|
|
2597
|
+
return value;
|
|
2598
|
+
}
|
|
2599
|
+
// Convert other types to string
|
|
2600
|
+
return String(value);
|
|
2601
|
+
}
|
|
2602
|
+
/**
|
|
2470
2603
|
* Create a pivot table from source data.
|
|
2471
2604
|
*
|
|
2472
2605
|
* @param config - Pivot table configuration
|
|
@@ -2677,7 +2810,8 @@ const builder = new fastXmlParser.XMLBuilder(builderOptions);
|
|
|
2677
2810
|
Type: rel.type,
|
|
2678
2811
|
Target: rel.target
|
|
2679
2812
|
}, []));
|
|
2680
|
-
|
|
2813
|
+
// Calculate next available relationship ID based on existing max ID
|
|
2814
|
+
let nextRelId = Math.max(0, ...this._relationships.map((r)=>parseInt(r.id.replace('rId', ''), 10) || 0)) + 1;
|
|
2681
2815
|
// Add shared strings relationship if needed
|
|
2682
2816
|
if (this._sharedStrings.count > 0) {
|
|
2683
2817
|
const hasSharedStrings = this._relationships.some((r)=>r.type === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings');
|
package/dist/index.d.cts
CHANGED
|
@@ -130,6 +130,32 @@ interface PivotCacheField {
|
|
|
130
130
|
* Pivot field axis assignment
|
|
131
131
|
*/
|
|
132
132
|
type PivotFieldAxis = 'row' | 'column' | 'filter' | 'value';
|
|
133
|
+
/**
|
|
134
|
+
* Configuration for creating a sheet from an array of objects
|
|
135
|
+
*/
|
|
136
|
+
interface SheetFromDataConfig<T extends object = Record<string, unknown>> {
|
|
137
|
+
/** Name of the sheet to create */
|
|
138
|
+
name: string;
|
|
139
|
+
/** Array of objects with the same structure */
|
|
140
|
+
data: T[];
|
|
141
|
+
/** Column definitions (optional - defaults to all keys from first object) */
|
|
142
|
+
columns?: ColumnConfig<T>[];
|
|
143
|
+
/** Apply header styling (bold text) (default: true) */
|
|
144
|
+
headerStyle?: boolean;
|
|
145
|
+
/** Starting cell address (default: 'A1') */
|
|
146
|
+
startCell?: string;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Column configuration for sheet data
|
|
150
|
+
*/
|
|
151
|
+
interface ColumnConfig<T = Record<string, unknown>> {
|
|
152
|
+
/** Key from the object to use for this column */
|
|
153
|
+
key: keyof T;
|
|
154
|
+
/** Header text (optional - defaults to key name) */
|
|
155
|
+
header?: string;
|
|
156
|
+
/** Cell style for data cells in this column */
|
|
157
|
+
style?: CellStyle;
|
|
158
|
+
}
|
|
133
159
|
|
|
134
160
|
/**
|
|
135
161
|
* Represents a single cell in a worksheet
|
|
@@ -665,6 +691,49 @@ declare class Workbook {
|
|
|
665
691
|
* Copy a worksheet
|
|
666
692
|
*/
|
|
667
693
|
copySheet(sourceName: string, newName: string): Worksheet;
|
|
694
|
+
/**
|
|
695
|
+
* Create a new worksheet from an array of objects.
|
|
696
|
+
*
|
|
697
|
+
* The first row contains headers (object keys or custom column headers),
|
|
698
|
+
* and subsequent rows contain the object values.
|
|
699
|
+
*
|
|
700
|
+
* @param config - Configuration for the sheet creation
|
|
701
|
+
* @returns The created Worksheet
|
|
702
|
+
*
|
|
703
|
+
* @example
|
|
704
|
+
* ```typescript
|
|
705
|
+
* const data = [
|
|
706
|
+
* { name: 'Alice', age: 30, city: 'Paris' },
|
|
707
|
+
* { name: 'Bob', age: 25, city: 'London' },
|
|
708
|
+
* { name: 'Charlie', age: 35, city: 'Berlin' },
|
|
709
|
+
* ];
|
|
710
|
+
*
|
|
711
|
+
* // Simple usage - all object keys become columns
|
|
712
|
+
* const sheet = wb.addSheetFromData({
|
|
713
|
+
* name: 'People',
|
|
714
|
+
* data: data,
|
|
715
|
+
* });
|
|
716
|
+
*
|
|
717
|
+
* // With custom column configuration
|
|
718
|
+
* const sheet2 = wb.addSheetFromData({
|
|
719
|
+
* name: 'People Custom',
|
|
720
|
+
* data: data,
|
|
721
|
+
* columns: [
|
|
722
|
+
* { key: 'name', header: 'Full Name' },
|
|
723
|
+
* { key: 'age', header: 'Age (years)' },
|
|
724
|
+
* ],
|
|
725
|
+
* });
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
addSheetFromData<T extends object>(config: SheetFromDataConfig<T>): Worksheet;
|
|
729
|
+
/**
|
|
730
|
+
* Infer column configuration from the first data object
|
|
731
|
+
*/
|
|
732
|
+
private _inferColumns;
|
|
733
|
+
/**
|
|
734
|
+
* Convert an unknown value to a CellValue
|
|
735
|
+
*/
|
|
736
|
+
private _toCellValue;
|
|
668
737
|
/**
|
|
669
738
|
* Create a pivot table from source data.
|
|
670
739
|
*
|
|
@@ -741,5 +810,5 @@ declare const parseRange: (range: string) => RangeAddress;
|
|
|
741
810
|
declare const toRange: (range: RangeAddress) => string;
|
|
742
811
|
|
|
743
812
|
export { Cell, PivotCache, PivotTable, Range, SharedStrings, Styles, Workbook, Worksheet, parseAddress, parseRange, toAddress, toRange };
|
|
744
|
-
export type { AggregationType, Alignment, BorderStyle, BorderType, CellAddress, CellError, CellStyle, CellType, CellValue, ErrorType, PivotFieldAxis, PivotTableConfig, PivotValueConfig, RangeAddress };
|
|
813
|
+
export type { AggregationType, Alignment, BorderStyle, BorderType, CellAddress, CellError, CellStyle, CellType, CellValue, ColumnConfig, ErrorType, PivotFieldAxis, PivotTableConfig, PivotValueConfig, RangeAddress, SheetFromDataConfig };
|
|
745
814
|
//# sourceMappingURL=index.d.cts.map
|