Introduction à NPOI
NPOI est une bibliothèque .NET qui permet de lire et d'écrire des fichiers Office sans avoir besoin d'installer Microsoft Office. Elle supporte les formats tels que .xls, .doc et .ppt. Vous pouvez l'obtenir via NuGet pour une intégration facile.
Génération d'un fichier Excel
Voici un exemple de code pour créer un fichier Excel simple avec NPOI. Le code génère un classeur, une feuille de calcul et remplit des celllules avec des données simulées.
using NPOI.HSSF.UserModel;
using System.IO;
var classeur = new HSSFWorkbook();
var feuille = classeur.CreateSheet("Feuille1");
for (int ligne = 0; ligne < 15; ligne++)
{
var rangee = feuille.CreateRow(ligne);
for (int colonne = 0; colonne < 10; colonne++)
{
var cellule = rangee.CreateCell(colonne);
cellule.SetCellValue($"Valeur_{ligne}_{colonne}");
}
}
using (var flux = File.Create(@"C:\donnees.xlsx"))
{
classeur.Write(flux);
}
Lecture d'un fichier Excel
Pour lire un fichier Excel existant, utilisez le code ci-dessous. Il parcourt les feuilles et les cellules pour afficher le contenu.
using NPOI.HSSF.UserModel;
using System.IO;
using (var flux = File.OpenRead(@"C:\donnees.xlsx"))
{
var classeur = new HSSFWorkbook(flux);
for (int idx = 0; idx < classeur.NumberOfSheets; idx++)
{
var feuille = classeur.GetSheetAt(idx);
for (int ligne = 0; ligne <= feuille.LastRowNum; ligne++)
{
var rangee = feuille.GetRow(ligne);
if (rangee != null)
{
for (int col = 0; col < rangee.LastCellNum; col++)
{
var cellule = rangee.GetCell(col);
if (cellule != null)
{
Console.Write($"{cellule} ");
}
}
}
Console.WriteLine();
}
}
}
Gestion des grandes quantités de données
Les versions anciennes de NPOI, comme la 1.2.5, liimtent le nombre de lignes à 65 536 par feuille, car elles s'appuient sur le format .xls d'Excel 2003. Pour contourner cette limitation, vous pouvez répartir les données sur plusieurs feuilles ou utiliser la classe XSSFWorkbook pour le format .xlsx.
Solution avec plusieurs feuilles
using NPOI.HSSF.UserModel;
using System.Data;
public static HSSFWorkbook CreerClasseurMultiple(DataTable donnees)
{
var classeur = new HSSFWorkbook();
var feuille1 = classeur.CreateSheet("Feuille1");
var feuille2 = classeur.CreateSheet("Feuille2");
for (int i = 0; i < donnees.Rows.Count; i++)
{
ISheet feuilleCible = i < 65536 ? feuille1 : feuille2;
int indexRangee = i < 65536 ? i : i - 65536;
IRow rangee = feuilleCible.CreateRow(indexRangee);
for (int j = 0; j < donnees.Columns.Count; j++)
{
ICell cellule = rangee.CreateCell(j, CellType.String);
cellule.SetCellValue(donnees.Rows[i][j].ToString());
}
}
for (int i = 0; i < donnees.Columns.Count; i++)
{
feuille1.AutoSizeColumn(i, true);
feuille2.AutoSizeColumn(i, true);
}
return classeur;
}
Solution avec le format .xlsx
using NPOI.XSSF.UserModel;
using System.Data;
public static XSSFWorkbook CreerClasseurXlsx(DataTable donnees)
{
var classeur = new XSSFWorkbook();
var feuille = classeur.CreateSheet("Feuille1");
for (int i = 0; i < donnees.Rows.Count; i++)
{
IRow rangee = feuille.CreateRow(i);
for (int j = 0; j < donnees.Columns.Count; j++)
{
ICell cellule = rangee.CreateCell(j, CellType.String);
cellule.SetCellValue(donnees.Rows[i][j].ToString());
}
}
for (int i = 0; i < donnees.Columns.Count; i++)
{
feuille.AutoSizeColumn(i, true);
}
return classeur;
}
Exportation dans une application web
Pour exporter un fichier Excel à partir d'une application web, générez le classeur et configurez la réponse HTTP pour le téléchargement.
using NPOI.SS.UserModel;
using System.Text;
using System.Web;
public static void ExporterExcelWeb(DataTable donnees, string nomFichier = "")
{
IWorkbook classeur = CreerClasseurMultiple(donnees); // Utilisez une des méthodes précédentes.
if (string.IsNullOrEmpty(nomFichier))
nomFichier = DateTime.Now.ToString("yyyyMMddHHmmss");
var reponse = HttpContext.Current.Response;
reponse.Clear();
reponse.Buffer = true;
reponse.Charset = Encoding.UTF8.BodyName;
reponse.AppendHeader("Content-Disposition", $"attachment;filename={nomFichier}.xls");
reponse.ContentEncoding = Encoding.UTF8;
reponse.ContentType = "application/vnd.ms-excel";
classeur.Write(reponse.OutputStream);
reponse.End();
}