@niicojs/excel 0.2.0 → 0.2.2

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.js CHANGED
@@ -2339,8 +2339,6 @@ const builder = new XMLBuilder(builderOptions);
2339
2339
  */ static create() {
2340
2340
  const workbook = new Workbook();
2341
2341
  workbook._dirty = true;
2342
- // Add default sheet
2343
- workbook.addSheet('Sheet1');
2344
2342
  return workbook;
2345
2343
  }
2346
2344
  /**
@@ -2525,13 +2523,20 @@ const builder = new XMLBuilder(builderOptions);
2525
2523
  * { key: 'age', header: 'Age (years)' },
2526
2524
  * ],
2527
2525
  * });
2526
+ *
2527
+ * // With rich cell values (value, formula, style)
2528
+ * const dataWithFormulas = [
2529
+ * { product: 'Widget', price: 10, qty: 5, total: { formula: 'B2*C2', style: { bold: true } } },
2530
+ * { product: 'Gadget', price: 20, qty: 3, total: { formula: 'B3*C3', style: { bold: true } } },
2531
+ * ];
2532
+ * const sheet3 = wb.addSheetFromData({
2533
+ * name: 'With Formulas',
2534
+ * data: dataWithFormulas,
2535
+ * });
2528
2536
  * ```
2529
2537
  */ addSheetFromData(config) {
2530
2538
  const { name, data, columns, headerStyle = true, startCell = 'A1' } = config;
2531
- if (data.length === 0) {
2532
- // Create empty sheet if no data
2533
- return this.addSheet(name);
2534
- }
2539
+ if (!data?.length) return this.addSheet(name);
2535
2540
  // Create the new sheet
2536
2541
  const sheet = this.addSheet(name);
2537
2542
  // Parse start cell
@@ -2562,17 +2567,41 @@ const builder = new XMLBuilder(builderOptions);
2562
2567
  const colConfig = columnConfigs[colIdx];
2563
2568
  const value = rowData[colConfig.key];
2564
2569
  const cell = sheet.cell(startRow + rowIdx, startCol + colIdx);
2565
- // Convert value to CellValue
2566
- cell.value = this._toCellValue(value);
2567
- // Apply column style if defined
2570
+ // Check if value is a rich cell definition
2571
+ if (this._isRichCellValue(value)) {
2572
+ const richValue = value;
2573
+ if (richValue.value !== undefined) cell.value = richValue.value;
2574
+ if (richValue.formula !== undefined) cell.formula = richValue.formula;
2575
+ if (richValue.style !== undefined) cell.style = richValue.style;
2576
+ } else {
2577
+ // Convert value to CellValue
2578
+ cell.value = this._toCellValue(value);
2579
+ }
2580
+ // Apply column style if defined (merged with cell style)
2568
2581
  if (colConfig.style) {
2569
- cell.style = colConfig.style;
2582
+ cell.style = {
2583
+ ...cell.style,
2584
+ ...colConfig.style
2585
+ };
2570
2586
  }
2571
2587
  }
2572
2588
  }
2573
2589
  return sheet;
2574
2590
  }
2575
2591
  /**
2592
+ * Check if a value is a rich cell value object with value, formula, or style fields
2593
+ */ _isRichCellValue(value) {
2594
+ if (value === null || value === undefined) {
2595
+ return false;
2596
+ }
2597
+ if (typeof value !== 'object' || value instanceof Date) {
2598
+ return false;
2599
+ }
2600
+ // Check if it has at least one of the rich cell properties
2601
+ const obj = value;
2602
+ return 'value' in obj || 'formula' in obj || 'style' in obj;
2603
+ }
2604
+ /**
2576
2605
  * Infer column configuration from the first data object
2577
2606
  */ _inferColumns(sample) {
2578
2607
  return Object.keys(sample).map((key)=>({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@niicojs/excel",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "typescript library to manipulate excel files",
5
5
  "homepage": "https://github.com/niicojs/excel#readme",
6
6
  "bugs": {
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ export type {
28
28
  // Sheet from data types
29
29
  SheetFromDataConfig,
30
30
  ColumnConfig,
31
+ RichCellValue,
31
32
  } from './types';
32
33
 
33
34
  // Utility exports
package/src/types.ts CHANGED
@@ -191,3 +191,16 @@ export interface ColumnConfig<T = Record<string, unknown>> {
191
191
  /** Cell style for data cells in this column */
192
192
  style?: CellStyle;
193
193
  }
194
+
195
+ /**
196
+ * Rich cell value with optional formula and style.
197
+ * Use this when you need to set value, formula, or style for individual cells.
198
+ */
199
+ export interface RichCellValue {
200
+ /** Cell value */
201
+ value?: CellValue;
202
+ /** Formula (without leading '=') */
203
+ formula?: string;
204
+ /** Cell style */
205
+ style?: CellStyle;
206
+ }
package/src/workbook.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  CellValue,
7
7
  SheetFromDataConfig,
8
8
  ColumnConfig,
9
+ RichCellValue,
9
10
  } from './types';
10
11
  import { Worksheet } from './worksheet';
11
12
  import { SharedStrings } from './shared-strings';
@@ -87,9 +88,6 @@ export class Workbook {
87
88
  const workbook = new Workbook();
88
89
  workbook._dirty = true;
89
90
 
90
- // Add default sheet
91
- workbook.addSheet('Sheet1');
92
-
93
91
  return workbook;
94
92
  }
95
93
 
@@ -315,15 +313,22 @@ export class Workbook {
315
313
  * { key: 'age', header: 'Age (years)' },
316
314
  * ],
317
315
  * });
316
+ *
317
+ * // With rich cell values (value, formula, style)
318
+ * const dataWithFormulas = [
319
+ * { product: 'Widget', price: 10, qty: 5, total: { formula: 'B2*C2', style: { bold: true } } },
320
+ * { product: 'Gadget', price: 20, qty: 3, total: { formula: 'B3*C3', style: { bold: true } } },
321
+ * ];
322
+ * const sheet3 = wb.addSheetFromData({
323
+ * name: 'With Formulas',
324
+ * data: dataWithFormulas,
325
+ * });
318
326
  * ```
319
327
  */
320
328
  addSheetFromData<T extends object>(config: SheetFromDataConfig<T>): Worksheet {
321
329
  const { name, data, columns, headerStyle = true, startCell = 'A1' } = config;
322
330
 
323
- if (data.length === 0) {
324
- // Create empty sheet if no data
325
- return this.addSheet(name);
326
- }
331
+ if (!data?.length) return this.addSheet(name);
327
332
 
328
333
  // Create the new sheet
329
334
  const sheet = this.addSheet(name);
@@ -361,12 +366,20 @@ export class Workbook {
361
366
  const value = rowData[colConfig.key];
362
367
  const cell = sheet.cell(startRow + rowIdx, startCol + colIdx);
363
368
 
364
- // Convert value to CellValue
365
- cell.value = this._toCellValue(value);
369
+ // Check if value is a rich cell definition
370
+ if (this._isRichCellValue(value)) {
371
+ const richValue = value as RichCellValue;
372
+ if (richValue.value !== undefined) cell.value = richValue.value;
373
+ if (richValue.formula !== undefined) cell.formula = richValue.formula;
374
+ if (richValue.style !== undefined) cell.style = richValue.style;
375
+ } else {
376
+ // Convert value to CellValue
377
+ cell.value = this._toCellValue(value);
378
+ }
366
379
 
367
- // Apply column style if defined
380
+ // Apply column style if defined (merged with cell style)
368
381
  if (colConfig.style) {
369
- cell.style = colConfig.style;
382
+ cell.style = { ...cell.style, ...colConfig.style };
370
383
  }
371
384
  }
372
385
  }
@@ -374,6 +387,21 @@ export class Workbook {
374
387
  return sheet;
375
388
  }
376
389
 
390
+ /**
391
+ * Check if a value is a rich cell value object with value, formula, or style fields
392
+ */
393
+ private _isRichCellValue(value: unknown): value is RichCellValue {
394
+ if (value === null || value === undefined) {
395
+ return false;
396
+ }
397
+ if (typeof value !== 'object' || value instanceof Date) {
398
+ return false;
399
+ }
400
+ // Check if it has at least one of the rich cell properties
401
+ const obj = value as Record<string, unknown>;
402
+ return 'value' in obj || 'formula' in obj || 'style' in obj;
403
+ }
404
+
377
405
  /**
378
406
  * Infer column configuration from the first data object
379
407
  */