cilog-lib 1.13.0 → 1.13.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.
@@ -491,70 +491,70 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
491
491
  }], propDecorators: { cell: [{ type: i0.Input, args: [{ isSignal: true, alias: "cell", required: false }] }] } });
492
492
 
493
493
  class ExportService {
494
+ colorCache = {};
494
495
  constructor() { }
495
496
  exportExcel(values, columns, byFiltre, withColors) {
496
- // Workbook
497
497
  let wb = new Excel.Workbook();
498
- // Worksheet
499
498
  let ws = wb.addWorksheet('Export', {
500
499
  properties: { defaultColWidth: 20 },
501
500
  });
502
- // Colonnes
501
+ const activeColumns = columns.filter(col => !col.invisible && (!byFiltre || col.exportable === true));
502
+ // Génération des colonnes Excel
503
503
  let cols = [];
504
- columns = columns.filter(col => !col.invisible);
505
- columns.forEach(col => {
506
- if (!byFiltre || col.exportable == true) {
507
- let colExcel = {
508
- header: col.libelle,
509
- key: col.id,
510
- style: this.getStyleByType(col.type)
511
- };
512
- if (col.width != null && col.width.toString().includes('px')) {
513
- const px = parseInt(col.width.toString().replace('px', '').trim(), 10);
514
- const excelWidth = px / 7;
515
- colExcel.width = parseFloat(excelWidth.toFixed(2));
516
- }
517
- cols.push(colExcel);
504
+ activeColumns.forEach(col => {
505
+ let colExcel = {
506
+ header: col.libelle,
507
+ key: col.id,
508
+ style: this.getStyleByType(col.type)
509
+ };
510
+ if (col.width != null && col.width.toString().includes('px')) {
511
+ const px = parseInt(col.width.toString().replace('px', '').trim(), 10);
512
+ colExcel.width = parseFloat((px / 7).toFixed(2));
518
513
  }
514
+ cols.push(colExcel);
519
515
  });
520
516
  ws.columns = cols;
521
- // Lignes
522
- values.forEach(row => {
523
- if (!byFiltre || row.exportable == true) {
524
- let rowExcel = {};
525
- columns.filter(obj => !byFiltre || obj.exportable == true).forEach(col => {
526
- if (row[col.id].excelSubstitution != null) {
527
- rowExcel[col.id] = row[col.id].excelSubstitution;
528
- }
529
- else {
530
- rowExcel[col.id] = this.getValueByType(row[col.id], col);
531
- }
532
- });
533
- // Application du style de chaque cellule
534
- let result = ws.addRow(rowExcel);
535
- columns.filter(obj => !byFiltre || obj.exportable == true).forEach((col, index) => {
517
+ const activeRows = byFiltre ? values.filter(row => row.exportable === true) : values;
518
+ // Traitement des lignes
519
+ activeRows.forEach(row => {
520
+ let rowExcel = {};
521
+ // Remplissage rapide des données
522
+ activeColumns.forEach(col => {
523
+ const cellData = row[col.id];
524
+ if (cellData) {
525
+ rowExcel[col.id] = cellData.excelSubstitution != null
526
+ ? cellData.excelSubstitution
527
+ : this.getValueByType(cellData, col);
528
+ }
529
+ });
530
+ let result = ws.addRow(rowExcel);
531
+ // Application des styles par cellule (uniquement si nécessaire)
532
+ activeColumns.forEach((col, index) => {
533
+ const cellData = row[col.id];
534
+ if (!cellData)
535
+ return;
536
+ // On ne récupère la cellule Excel que si on a vraiment un style à lui appliquer
537
+ if (cellData.bold || (withColors && (row.color || cellData.color))) {
536
538
  const cell = result.getCell(index + 1);
537
- if (row[col.id].bold) {
539
+ if (cellData.bold) {
538
540
  cell.font = { bold: true };
539
541
  }
540
542
  if (withColors) {
541
- if ((row.color != null && row.color != '') || (row[col.id].color != null && row[col.id].color != '')) {
542
- cell.style.fill = {
543
+ const targetColor = cellData.color || row.color;
544
+ if (targetColor) {
545
+ const hexaColor = this.getHexaColor(targetColor);
546
+ cell.fill = {
543
547
  type: "pattern",
544
548
  pattern: "solid",
545
- fgColor: {
546
- argb: row[col.id].color != null ? this.getHexaColor(row[col.id].color) : this.getHexaColor(row.color)
547
- },
548
- bgColor: {
549
- argb: row[col.id].color != null ? this.getHexaColor(row[col.id].color) : this.getHexaColor(row.color)
550
- }
549
+ fgColor: { argb: hexaColor },
550
+ bgColor: { argb: hexaColor }
551
551
  };
552
552
  }
553
553
  }
554
- });
555
- }
554
+ }
555
+ });
556
556
  });
557
- // Style
557
+ // Style Global
558
558
  this.setStyleGlobalGrille(ws);
559
559
  // Sauvegarde
560
560
  wb.xlsx.writeBuffer().then(function (buffer) {
@@ -565,85 +565,86 @@ class ExportService {
565
565
  });
566
566
  }
567
567
  getHexaColor(color) {
568
- var ctx = document.createElement('canvas').getContext('2d');
568
+ if (!color)
569
+ return '';
570
+ // Si la couleur est déjà au format #hex, on nettoie directement sans créer de canvas
571
+ if (color.startsWith('#')) {
572
+ return color.replace('#', '');
573
+ }
574
+ // Si c'est un nom de couleur (ex: 'red', 'blue') ou du rgb(), on utilise le cache ou le canvas
575
+ if (this.colorCache[color]) {
576
+ return this.colorCache[color];
577
+ }
578
+ const ctx = document.createElement('canvas').getContext('2d');
579
+ if (!ctx)
580
+ return color;
569
581
  ctx.fillStyle = color;
570
- return ctx.fillStyle.replace('#', '');
582
+ const hexa = ctx.fillStyle.replace('#', '');
583
+ this.colorCache[color] = hexa; // On s'en rappelle pour la prochaine fois !
584
+ return hexa;
571
585
  }
572
586
  setStyleGlobalGrille(ws) {
573
- ws.views = [
574
- { state: 'frozen', ySplit: 1 }
575
- ];
587
+ ws.views = [{ state: 'frozen', ySplit: 1 }];
588
+ const totalColumns = ws.columnCount;
589
+ const lastColumnLetter = this.columnIndexToColumnLetter(totalColumns);
576
590
  ws.eachRow((row, rowNumber) => {
577
- row.eachCell({ includeEmpty: true }, (cell, number) => {
578
- if (rowNumber == 1) {
591
+ if (rowNumber === 1) {
592
+ // En-tête : Inclure les cellules vides, fond vert, texte blanc/gras centré
593
+ row.eachCell({ includeEmpty: true }, (cell) => {
579
594
  cell.fill = {
580
595
  pattern: 'solid',
581
596
  type: 'pattern',
582
- fgColor: {
583
- argb: '2fab49',
584
- },
585
- };
586
- cell.alignment = { horizontal: 'center' };
587
- cell.alignment.vertical = 'middle';
588
- cell.font = {
589
- name: 'Arial',
590
- size: 10,
591
- bold: true
597
+ fgColor: { argb: '2fab49' },
592
598
  };
599
+ cell.alignment = { horizontal: 'center', vertical: 'middle' };
600
+ cell.font = { name: 'Arial', size: 10, bold: true, color: { argb: 'FFFFFF' } };
593
601
  cell.border = {
594
- bottom: { style: 'thin' },
595
- top: { style: 'thin' },
596
- left: { style: 'thin' },
597
- right: { style: 'thin' },
602
+ bottom: { style: 'thin' }, top: { style: 'thin' },
603
+ left: { style: 'thin' }, right: { style: 'thin' },
598
604
  };
599
- }
600
- else {
605
+ });
606
+ }
607
+ else {
608
+ row.eachCell({ includeEmpty: true }, (cell) => {
601
609
  cell.border = {
602
- bottom: { style: 'thin' },
603
- top: { style: 'thin' },
604
- left: { style: 'thin' },
605
- right: { style: 'thin' },
610
+ bottom: { style: 'thin' }, top: { style: 'thin' },
611
+ left: { style: 'thin' }, right: { style: 'thin' },
606
612
  };
607
- }
608
- });
613
+ });
614
+ }
609
615
  });
610
- ws.autoFilter = {
611
- from: 'A1',
612
- to: this.columnIndexToColumnLetter(ws.columnCount).toString() + '1',
613
- };
616
+ ws.autoFilter = { from: 'A1', to: `${lastColumnLetter}1` };
614
617
  }
615
618
  columnIndexToColumnLetter(column) {
616
- var temp, letter = '';
619
+ let letter = '';
617
620
  while (column > 0) {
618
- temp = (column - 1) % 26;
621
+ let temp = (column - 1) % 26;
619
622
  letter = String.fromCharCode(temp + 65) + letter;
620
- column = (column - temp - 1) / 26;
623
+ column = Math.floor((column - temp - 1) / 26); // Math.floor pour éviter les flottants
621
624
  }
622
625
  return letter;
623
626
  }
624
627
  getValueByType(cell, col) {
628
+ if (cell.value == null)
629
+ return null;
625
630
  switch (col.type) {
626
631
  case ColType.MultiSelect:
627
- let optionLabelMulti = cell.options != null && cell.options.optionLabel != null ? cell.options.optionLabel : col.options.optionLabel;
628
- return cell.value.map(val => val[optionLabelMulti]).join(', ');
632
+ const optionLabelMulti = cell.options?.optionLabel || col.options?.optionLabel;
633
+ return Array.isArray(cell.value) ? cell.value.map(val => val[optionLabelMulti]).join(', ') : '';
629
634
  case ColType.SelectButton:
630
635
  case ColType.Dropdown:
631
636
  case ColType.State:
632
- let optionLabel = cell.options != null && cell.options.optionLabel != null ? cell.options.optionLabel : col.options.optionLabel;
633
- return cell.value != null ? cell.value[optionLabel] : null;
637
+ const optionLabel = cell.options?.optionLabel || col.options?.optionLabel;
638
+ return cell.value[optionLabel] || null;
634
639
  case ColType.Image:
635
640
  case ColType.Button:
636
641
  return null;
637
642
  case ColType.Switch:
638
- return cell.value == true ? 'Oui' : 'Non';
643
+ return cell.value === true ? 'Oui' : 'Non';
639
644
  case ColType.Date:
640
- if (cell.value != null) {
641
- let dateStr = cell.value.getFullYear() + '-' + ((cell.value.getMonth() + 1 < 10) ? '0' + (cell.value.getMonth() + 1) : (cell.value.getMonth() + 1)) + '-' + (cell.value.getDate() < 10 ? '0' + cell.value.getDate() : cell.value.getDate()) + 'T00:00:00.000Z';
642
- return new Date(dateStr);
643
- }
644
- else {
645
- return null;
646
- }
645
+ // Correction du parsing de date plus propre
646
+ const d = new Date(cell.value);
647
+ return isNaN(d.getTime()) ? null : d;
647
648
  default:
648
649
  return cell.value;
649
650
  }