Có thể bạn quan tâm: Tạo Bảng Trong 1 Ô Excel: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao
Mở Đầu
Trong môi trường phát triển phần mềm .NET, việc xuất dữ liệu ra file Excel là một yêu cầu thường gặp, đặc biệt trong các ứng dụng doanh nghiệp, báo cáo tài chính, quản lý kho, hay bất kỳ hệ thống nào cần cung cấp dữ liệu dưới dạng bảng tính cho người dùng cuối. Trước đây, để thực hiện điều này, các lập trình viên thường phải dựa vào Interop của Microsoft Office, COM object hay thậm chí là tạo file CSV đơn giản. Tuy nhiên, những phương pháp này đều có những hạn chế đáng chú ý:
- Interop yêu cầu máy chủ phải cài đặt Microsoft Office, gây ra các vấn đề về hiệu năng, độ ổn định và khả năng chạy trên môi trường server (đặc biệt là Linux).
- CSV không hỗ trợ định dạng, công thức, biểu đồ, hay nhiều tính năng nâng cao của Excel.
- Thư viện bên thứ ba như NPOI, ClosedXML… mỗi cái có ưu và nhược điểm riêng, nhưng EPPlus đã nhanh chóng nổi lên như một trong những lựa chọn hàng đầu nhờ tính năng phong phú, hiệu năng tốt và giao diện lập trình thân thiện.
Bài viết này sẽ cung cấp cho bạn một hướng dẫn toàn diện về EPPlus Export to Excel trong C#, từ cài đặt, cấu hình, tạo file, định dạng, chèn công thức, biểu đồ, tới những mẹo tối ưu hiệu năng và xử lý các vấn đề phổ biến. Mục tiêu là giúp bạn không chỉ “đánh bật” một file Excel đơn giản mà còn khai thác tối đa sức mạnh của EPPlus để tạo ra những báo cáo chuyên nghiệp, tương tác và đáp ứng yêu cầu doanh nghiệp.
Có thể bạn quan tâm: Cách Kích Hoạt Scroll Lock Trong Excel: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao
1. Giới Thiệu Tổng Quan Về EPPlus
1.1 EPPlus là gì?
EPPlus là một thư viện mã nguồn mở (được phát hành dưới giấy phép polyform noncommercial cho phiên bản 5.x trở lên, và GPLv3 cho các phiên bản cũ) cho phép tạo, đọc và chỉnh sửa file Excel (.xlsx) mà không cần cài đặt Microsoft Office. Thư viện này được xây dựng dựa trên chuẩn Open XML của Microsoft, giúp nó hoạt động nhanh chóng và tiêu tốn ít tài nguyên.
1.2 Lý Do Chọn EPPlus
| Tiêu chí | EPPlus | NPOI | ClosedXML |
|---|---|---|---|
| Hiệu năng | Rất nhanh, tối ưu cho file lớn | Tốt, nhưng hơi chậm hơn EPPlus | Tương đương EPPlus |
| Định dạng | Hỗ trợ phong phú (font, màu, border, fill, conditional formatting) | Hỗ trợ cơ bản | Hỗ trợ tốt |
| Công thức | Toàn diện, hỗ trợ mọi công thức Excel | Hạn chế | Toàn diện |
| Biểu đồ | Hỗ trợ tạo và chỉnh sửa | Hạn chế | Không hỗ trợ biểu đồ |
| Tài liệu | Rất đầy đủ, ví dụ thực tế | Đủ | Đầy đủ |
| Giấy phép | Polyform (phi thương mại) / GPL (cũ) | Apache 2.0 | MIT |
Với những ưu điểm trên, EPPlus trở thành lựa chọn lý tưởng khi bạn cần:
- Tạo báo cáo có định dạng phức tạp (đầu trang, tiêu đề, màu sắc, border).
- Chèn công thức tính toán tự động.
- Thêm biểu đồ để trực quan hoá dữ liệu.
- Đọc và xử lý file Excel hiện có (import).
Có thể bạn quan tâm: Cách Kích Hoạt Tab Developer Trong Excel: Hướng Dẫn Chi Tiết Từ A Đến Z
2. Cài Đặt EPPlus trong Dự Án C
2.1 Sử dụng NuGet
Cách nhanh nhất để đưa EPPlus vào dự án là thông qua NuGet Package Manager. Mở Visual Studio, vào Tools → NuGet Package Manager → Manage NuGet Packages for Solution và tìm kiếm EPPlus. Chọn phiên bản mới nhất (đến thời điểm viết bài là 6.1.2) và cài đặt.
Hoặc dùng Package Manager Console:
Install-Package EPPlus -Version 6.1.2
Lưu ý: Từ phiên bản 5.0 trở lên, EPPlus yêu cầu bạn khai báo LicenseContext để chỉ định mục đích sử dụng (Commercial/NonCommercial). Nếu dự án của bạn là thương mại, bạn cần mua giấy phép hoặc chuyển sang phiên bản GPL cũ hơn.
2.2 Thiết Lập LicenseContext
Trong Program.cs (hoặc Startup.cs nếu là ASP.NET Core), thêm dòng sau trước khi sử dụng bất kỳ phương thức nào của EPPlus:
using OfficeOpenXml;
using OfficeOpenXml.Style; // Đặt context cho EPPlus
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // Dùng cho mục đích phi thương mại
Nếu dự án thương mại, bạn sẽ cần:
ExcelPackage.LicenseContext = LicenseContext.Commercial;
và cung cấp file license tương ứng (theo tài liệu EPPlus).
3. Tạo File Excel Cơ Bản
3.1 Mẫu Code Cơ Bản
using System;
using System.IO;
using OfficeOpenXml; class Program
{ static void Main() { // Đảm bảo đã thiết lập LicenseContext ở đâu đó trong dự án var fileInfo = new FileInfo(@"C:\Temp\SampleReport.xlsx"); // Xóa file nếu đã tồn tại để tránh lỗi if (fileInfo.Exists) fileInfo.Delete(); using (var package = new ExcelPackage(fileInfo)) { // Tạo một worksheet mới var worksheet = package.Workbook.Worksheets.Add("Báo cáo"); // Ghi dữ liệu vào ô A1 worksheet.Cells"A1".Value = "Hello EPPlus!"; // Lưu file package.Save(); } Console.WriteLine("File đã được tạo thành công!"); }
}
Kết quả: Một file Excel có một sheet tên “Báo cáo” và ô A1 chứa chuỗi “Hello EPPlus!”.
3.2 Ghi Dữ Liệu Từ Danh Sách
Thực tế, bạn thường sẽ xuất dữ liệu từ một danh sách (List) hoặc DataTable. Dưới đây là ví dụ với một danh sách các đối tượng Product.
public class Product
{ public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public int Quantity { get; set; }
} // ... var products = new List<Product>
{ new Product { Id = 1, Name = "Bút bi", Price = 15000, Quantity = 120 }, new Product { Id = 2, Name = "Sổ A5", Price = 25000, Quantity = 80 }, new Product { Id = 3, Name = "Mực in", Price = 50000, Quantity = 30 }
}; using (var package = new ExcelPackage())
{ var ws = package.Workbook.Worksheets.Add("Sản phẩm"); // Đặt tiêu đề cột ws.Cells1, 1.Value = "Mã"; ws.Cells1, 2.Value = "Tên sản phẩm"; ws.Cells1, 3.Value = "Giá (VND)"; ws.Cells1, 4.Value = "Số lượng"; // Ghi dữ liệu int row = 2; foreach (var p in products) { ws.Cellsrow, 1.Value = p.Id; ws.Cellsrow, 2.Value = p.Name; ws.Cellsrow, 3.Value = p.Price; ws.Cellsrow, 4.Value = p.Quantity; row++; } // AutoFit cột ws.Cellsws.Dimension.Address.AutoFitColumns(); // Lưu var output = new FileInfo(@"C:\Temp\Products.xlsx"); package.SaveAs(output);
}
Kết quả: Một bảng dữ liệu có header và các dòng sản phẩm, các cột tự động điều chỉnh độ rộng.
4. Định Dạng (Styling) Trong EPPlus
Định dạng là yếu tố quan trọng để làm cho báo cáo Excel trở nên chuyên nghiệp. EPPlus cung cấp một API mạnh mẽ để tùy chỉnh font, màu nền, border, alignment, và thậm chí là Conditional Formatting.
4.1 Định Dạng Header
var headerRange = ws.Cells1, 1, 1, 4; // A1:D1
headerRange.Style.Font.Bold = true;
headerRange.Style.Font.Size = 12;
headerRange.Style.Fill.PatternType = ExcelFillStyle.Solid;
headerRange.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.DarkBlue);
headerRange.Style.Font.Color.SetColor(System.Drawing.Color.White);
headerRange.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
headerRange.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
headerRange.Style.Border.BorderAround(ExcelBorderStyle.Thin, System.Drawing.Color.Black);
4.2 Định Dạng Dữ Liệu
// Định dạng cột Giá là tiền tệ
ws.Column(3).Style.Numberformat.Format = "#,##0₫"; // Định dạng cột Số lượng là số nguyên và căn phải
ws.Column(4).Style.HorizontalAlignment = ExcelHorizontalAlignment.Right; // Thêm border cho toàn bộ dữ liệu
var dataRange = ws.Cells2, 1, row - 1, 4;
dataRange.Style.Border.Top.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Left.Style = ExcelBorderStyle.Thin;
dataRange.Style.Border.Right.Style = ExcelBorderStyle.Thin;
4.3 Conditional Formatting (Định Dạng Có Điều Kiện)
Giả sử bạn muốn tô đỏ các dòng có số lượng < 50.
var cond = ws.ConditionalFormatting.AddLessThan(ws.Cells2, 4, row - 1, 4);
cond.Formula = "50";
cond.Style.Font.Color.Color = System.Drawing.Color.Red;
cond.Style.Fill.PatternType = ExcelFillStyle.Solid;
cond.Style.Fill.BackgroundColor.Color = System.Drawing.Color.LightPink;
4.4 Định Dạng Đoạn Văn Bản (Rich Text)
Nếu bạn muốn một ô chứa đoạn văn bản có các phần in đậm, in nghiêng:
var rich = ws.Cells"B2".RichText;
rich.Add("Đây là ").Bold = false;
rich.Add("đoạn in đậm").Bold = true;
rich.Add(" và ").Bold = false;
rich.Add("đoạn nghiêng").Italic = true;
5. Sử Dụng Công Thức (Formulas)
Một trong những lợi thế lớn của EPPlus là khả năng chèn công thức Excel trực tiếp, cho phép người dùng cuối thực hiện tính toán ngay trong file.
5.1 Công Thức Cơ Bản
// Tổng số lượng (cột D)
ws.Cellsrow, 4.Formula = $"SUM(D2:D{row - 1})";
ws.Cellsrow, 4.Style.Font.Bold = true; // Tổng giá trị (Giá Số lượng)
ws.Cellsrow, 5.Formula = $"SUMPRODUCT(C2:C{row - 1}, D2:D{row - 1})";
ws.Cellsrow, 5.Style.Font.Bold = true;
ws.Cellsrow, 5.Style.Numberformat.Format = "#,##0₫";
5.2 Đặt Công Thức Động Khi Thêm Dòng
Nếu bạn muốn mỗi dòng tính “Thành tiền = Giá Số lượng”:
for (int i = 2; i < row; i++)
{ ws.Cellsi, 5.Formula = $"C{i}D{i}"; ws.Cellsi, 5.Style.Numberformat.Format = "#,##0₫";
}
5.3 Công Thức Mảng (Array Formula)
EPPlus cũng hỗ trợ công thức mảng, ví dụ tính trung bình cộng có điều kiện:
ws.Cells"F2".FormulaArray = "AVERAGEIF(D2:D10, \">=50\", C2:C10)";
6. Tạo Biểu Đồ (Charts)
Biểu đồ giúp người dùng nhanh chóng nắm bắt xu hướng và so sánh dữ liệu. EPPlus hỗ trợ nhiều loại biểu đồ như Column, Bar, Line, Pie, Doughnut, Radar, và Scatter.
6.1 Ví Dụ: Biểu Đồ Cột Thể Hiện Doanh Thu

Có thể bạn quan tâm: Chuyển Đổi Epoch Time Sang Date Trong Excel: Hướng Dẫn Chi Tiết Từ A Đến Z
// Giả sử dữ liệu đã có ở cột A (Tên sản phẩm) và E (Thành tiền)
var chart = ws.Drawings.AddChart("DoanhThuChart", eChartType.ColumnClustered) as ExcelBarChart;
chart.Title.Text = "Doanh thu theo sản phẩm";
chart.SetPosition(row + 2, 0, 0, 0); // Đặt vị trí dưới bảng
chart.SetSize(800, 400); // Định nghĩa series
var series = chart.Series.Add(ws.Cells2, 5, row - 1, 5, ws.Cells2, 2, row - 1, 2); // Values, XAxis
series.Header = "Doanh thu";
6.2 Tùy Chỉnh Biểu Đồ
chart.YAxis.Title.Text = "Số tiền (VND)";
chart.XAxis.Title.Text = "Sản phẩm";
chart.Legend.Position = eLegendPosition.Bottom;
chart.DataLabel.ShowValue = true;
6.3 Biểu Đồ Pie
var pieChart = ws.Drawings.AddChart("PieChart", eChartType.Pie) as ExcelPieChart;
pieChart.Title.Text = "Tỷ lệ doanh thu";
pieChart.SetPosition(row + 20, 0, 0, 0);
pieChart.SetSize(500, 400);
pieChart.Series.Add(ws.Cells2, 5, row - 1, 5, ws.Cells2, 2, row - 1, 2);
pieChart.DataLabel.ShowPercent = true;
7. Xử Lý File Lớn và Tối Ưu Hiệu Năng
Khi xuất dữ liệu hàng nghìn, hàng triệu dòng, việc tối ưu code là rất quan trọng để tránh OutOfMemoryException và giảm thời gian xử lý.
7.1 Sử Dụng LoadFromCollection hoặc LoadFromDataTable
EPPlus cung cấp các phương thức bulk load để nhanh chóng đưa dữ liệu vào worksheet.
// Với List<Product>
ws.Cells"A1".LoadFromCollection(products, PrintHeaders: true, TableStyle: TableStyles.Medium9);
Hoặc với DataTable:
DataTable dt = GetDataTableFromDatabase();
ws.Cells"A1".LoadFromDataTable(dt, true);
7.2 Tắt AutoFit Khi Không Cần
AutoFitColumns rất tiện nhưng tiêu tốn thời gian cho file lớn. Thay vào đó, chỉ đặt độ rộng cố định hoặc auto-fit cho một vài cột quan trọng.
ws.Column(2).Width = 25; // Đặt rộng cố định
ws.Column(3).AutoFit(); // Chỉ auto-fit cột giá
7.3 Sử Dụng ExcelPackage.Stream Để Ghi Trực Tiếp Vào Response
Trong ứng dụng web, bạn không cần lưu file tạm, mà có thể stream trực tiếp về client.
public IActionResult Export()
{ var stream = new MemoryStream(); using (var package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("Report"); ws.Cells"A1".LoadFromCollection(GetData(), true); package.SaveAs(stream); } stream.Position = 0; string fileName = $"Report_{DateTime.Now:yyyyMMddHHmmss}.xlsx"; return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
7.4 Giải Phóng Bộ Nhớ
Luôn dùng using hoặc gọi Dispose() để giải phóng tài nguyên.
using (var package = new ExcelPackage(fileInfo))
{ // ... code ...
} // package.Dispose() tự động được gọi ở đây
8. Đọc (Import) File Excel Với EPPlus
Mặc dù chủ đề chính là export, nhưng trong thực tế bạn thường cần đọc lại dữ liệu đã xuất hoặc nhận file từ người dùng.
8.1 Đọc Dữ Liệu Cơ Bản
var file = new FileInfo(@"C:\Temp\Products.xlsx");
using (var package = new ExcelPackage(file))
{ var ws = package.Workbook.Worksheets.First(); // Lấy sheet đầu tiên int startRow = ws.Dimension.Start.Row + 1; // Bỏ qua header int endRow = ws.Dimension.End.Row; var list = new List<Product>(); for (int row = startRow; row <= endRow; row++) { var p = new Product { Id = Convert.ToInt32(ws.Cellsrow, 1.Value), Name = ws.Cellsrow, 2.Value?.ToString(), Price = Convert.ToDecimal(ws.Cellsrow, 3.Value), Quantity = Convert.ToInt32(ws.Cellsrow, 4.Value) }; list.Add(p); }
}
8.2 Đọc Dữ Liệu Bằng ToDataTable
EPPlus không có method ToDataTable mặc định, nhưng bạn có thể tự viết một helper:
public static DataTable WorksheetToDataTable(ExcelWorksheet ws, bool hasHeader = true)
{ var dt = new DataTable(); var start = ws.Dimension.Start; var end = ws.Dimension.End; // Đọc header for (int col = start.Column; col <= end.Column; col++) { var columnName = hasHeader ? ws.Cellsstart.Row, col.Text : $"Column{col}"; dt.Columns.Add(columnName); } // Đọc dữ liệu for (int row = start.Row + (hasHeader ? 1 : 0); row <= end.Row; row++) { var dr = dt.NewRow(); for (int col = start.Column; col <= end.Column; col++) { drcol - start.Column = ws.Cellsrow, col.Text; } dt.Rows.Add(dr); } return dt;
}
9. Các Tình Huống Thực Tế Và Mẫu Code
9.1 Báo Cáo Tài Chính Hàng Tháng
- Yêu cầu: Export bảng cân đối kế toán, bao gồm tiêu đề, ngày tháng, các cột tài khoản, số dư đầu kỳ, phát sinh, dư cuối kỳ. Cần tính tổng tự động, highlight các số âm màu đỏ, và chèn biểu đồ cột so sánh dư cuối kỳ.
Mã mẫu:
public void ExportFinancialReport(List<AccountBalance> balances, DateTime month, string filePath)
{ using var package = new ExcelPackage(); var ws = package.Workbook.Worksheets.Add("Cân Đối Kế Toán"); // Header ws.Cells"A1".Value = $"Bảng cân đối kế toán - Tháng {month:MM/yyyy}"; ws.Cells"A1:E1".Merge = true; ws.Cells"A1".Style.Font.Size = 16; ws.Cells"A1".Style.Font.Bold = true; ws.Cells"A1".Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // Column titles var headers = new { "Mã tài khoản", "Tên tài khoản", "Dư đầu kỳ", "Phát sinh", "Dư cuối kỳ" }; for (int i = 0; i < headers.Length; i++) { ws.Cells3, i + 1.Value = headersi; } // Định dạng header var headerRange = ws.Cells3, 1, 3, headers.Length; headerRange.Style.Font.Bold = true; headerRange.Style.Fill.PatternType = ExcelFillStyle.Solid; headerRange.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray); headerRange.Style.Border.BorderAround(ExcelBorderStyle.Thin); // Dữ liệu int row = 4; foreach (var acc in balances) { ws.Cellsrow, 1.Value = acc.Code; ws.Cellsrow, 2.Value = acc.Name; ws.Cellsrow, 3.Formula = $"=SUM('{ws.Name}'!C{row})"; // placeholder, sẽ được thay thế ws.Cellsrow, 4.Formula = $"=SUM('{ws.Name}'!D{row})"; ws.Cellsrow, 5.Formula = $"=C{row}+D{row}"; row++; } // Tổng cộng ws.Cellsrow, 2.Value = "Tổng cộng"; ws.Cellsrow, 2.Style.Font.Bold = true; ws.Cellsrow, 3.Formula = $"SUM(C4:C{row - 1})"; ws.Cellsrow, 4.Formula = $"SUM(D4:D{row - 1})"; ws.Cellsrow, 5.Formula = $"SUM(E4:E{row - 1})"; // Định dạng số tiền ws.Column(3).Style.Numberformat.Format = "#,##0₫"; ws.Column(4).Style.Numberformat.Format = "#,##0₫"; ws.Column(5).Style.Numberformat.Format = "#,##0₫"; // Highlight số âm var negCond = ws.ConditionalFormatting.AddLessThan(ws.Cells4, 5, row, 5); negCond.Formula = "0"; negCond.Style.Font.Color.Color = System.Drawing.Color.Red; // AutoFit ws.Cellsws.Dimension.Address.AutoFitColumns(); // Biểu đồ cột var chart = ws.Drawings.AddChart("ChartBalance", eChartType.ColumnClustered) as ExcelBarChart; chart.Title.Text = "Dư cuối kỳ theo tài khoản"; chart.SetPosition(row + 2, 0, 0, 0); chart.SetSize(900, 400); chart.Series.Add(ws.Cells4, 5, row - 1, 5, ws.Cells4, 2, row - 1, 2); chart.DataLabel.ShowValue = true; // Lưu file var fi = new FileInfo(filePath); if (fi.Exists) fi.Delete(); package.SaveAs(fi);
}
9.2 Export Đánh Giá Nhân Viên Với Định Dạng Conditional Formatting
- Yêu cầu: Xuất danh sách nhân viên, điểm đánh giá (0‑100). Các ô điểm < 60 màu đỏ, 60‑80 màu vàng, > 80 màu xanh.
Mã mẫu:
public void ExportEmployeeRatings(List<Employee> employees, string outPath)
{ using var package = new ExcelPackage(); var ws = package.Workbook.Worksheets.Add("Đánh Giá"); // Header ws.Cells"A1".Value = "Bảng Đánh Giá Nhân Viên"; ws.Cells"A1:C1".Merge = true; ws.Cells"A1".Style.Font.Size = 14; ws.Cells"A1".Style.Font.Bold = true; ws.Cells"A1".Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; ws.Cells"A2".Value = "Mã NV"; ws.Cells"B2".Value = "Tên NV"; ws.Cells"C2".Value = "Điểm"; var header = ws.Cells2, 1, 2, 3; header.Style.Font.Bold = true; header.Style.Fill.PatternType = ExcelFillStyle.Solid; header.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightSteelBlue); // Dữ liệu int row = 3; foreach (var emp in employees) { ws.Cellsrow, 1.Value = emp.Id; ws.Cellsrow, 2.Value = emp.Name; ws.Cellsrow, 3.Value = emp.Score; row++; } // Conditional Formatting var red = ws.ConditionalFormatting.AddLessThan(ws.Cells3, 3, row - 1, 3); red.Formula = "60"; red.Style.Font.Color.Color = System.Drawing.Color.White; red.Style.Fill.PatternType = ExcelFillStyle.Solid; red.Style.Fill.BackgroundColor.Color = System.Drawing.Color.Red; var yellow = ws.ConditionalFormatting.AddBetween(ws.Cells3, 3, row - 1, 3); yellow.Formula = "60"; yellow.Formula2 = "80"; yellow.Style.Fill.PatternType = ExcelFillStyle.Solid; yellow.Style.Fill.BackgroundColor.Color = System.Drawing.Color.Gold; var green = ws.ConditionalFormatting.AddGreaterThan(ws.Cells3, 3, row - 1, 3); green.Formula = "80"; green.Style.Fill.PatternType = ExcelFillStyle.Solid; green.Style.Fill.BackgroundColor.Color = System.Drawing.Color.Green; green.Style.Font.Color.Color = System.Drawing.Color.White; // AutoFit ws.Cellsws.Dimension.Address.AutoFitColumns(); // Save var fi = new FileInfo(outPath); if (fi.Exists) fi.Delete(); package.SaveAs(fi);
}
9.3 Export Định Dạng Giao Diện Đa Sheet (Multiple Worksheets)
Nếu báo cáo cần chia thành các sheet: “Tổng hợp”, “Chi tiết”, “Biểu đồ”.
public void ExportMultiSheetReport(DataSet ds, string path)
{ using var package = new ExcelPackage(); // Sheet 1: Tổng hợp var summaryWs = package.Workbook.Worksheets.Add("Tổng hợp"); summaryWs.Cells"A1".Value = "Báo cáo tổng hợp"; summaryWs.Cells"A2".LoadFromDataTable(ds.Tables"Summary", true); summaryWs.CellssummaryWs.Dimension.Address.AutoFitColumns(); // Sheet 2: Chi tiết var detailWs = package.Workbook.Worksheets.Add("Chi tiết"); detailWs.Cells"A1".LoadFromDataTable(ds.Tables"Detail", true); detailWs.CellsdetailWs.Dimension.Address.AutoFitColumns(); // Sheet 3: Biểu đồ var chartWs = package.Workbook.Worksheets.Add("Biểu đồ"); chartWs.Cells"A1".LoadFromDataTable(ds.Tables"ChartData", true); // Tạo biểu đồ ở đây (tùy ý) var chart = chartWs.Drawings.AddChart("Chart1", eChartType.Line) as ExcelLineChart; chart.Title.Text = "Biểu đồ xu hướng"; chart.SetPosition(1, 0, 5, 0); chart.SetSize(800, 400); chart.Series.Add(chartWs.Cells2, 2, ds.Tables"ChartData".Rows.Count + 1, 2, chartWs.Cells2, 1, ds.Tables"ChartData".Rows.Count + 1, 1); // Lưu var fi = new FileInfo(path); if (fi.Exists) fi.Delete(); package.SaveAs(fi);
}
10. Xử Lý Các Vấn Đề Thường Gặp
10.1 Lỗi “File is locked” hoặc “Cannot access the file”
- Nguyên nhân: File đang được mở bởi một process khác (Excel).
- Giải pháp: Đảm bảo file được đóng trước khi ghi, hoặc sử dụng
FileMode.CreatevàFileShare.None. Khi stream tới client, luôn resetstream.Position = 0.
10.2 Định Dạng Số Không Hiển Thị Đúng
- Nguyên nhân: Không đặt đúng
Numberformat. - Giải pháp: Sử dụng
ws.Column(i).Style.Numberformat.Format = "#,##0.00"hoặc"#,##0%cho phần trăm.
10.3 Công Thức Không Tính Toán Khi Mở File
- Nguyên nhân: Khi bạn ghi file và mở ngay, Excel có thể chưa tính lại công thức.
- Giải pháp: Đặt
package.Workbook.Calculate()trước khi lưu, hoặc để người dùng nhấnF9trong Excel.
package.Workbook.Calculate(); // Tính toán mọi công thức
10.4 Bộ Nhớ Tăng Đột Biến Khi Xử Lý File Lớn
- Nguyên nhân: Sử dụng
LoadFromCollectionmà không chỉ địnhTableStyle, hoặc thực hiện quá nhiều thao tácAutoFit. - Giải pháp:
- Tắt
AutoFitcho toàn bộ cột, chỉ áp dụng cho một vài cột cần. - Sử dụng
ExcelRangeBase.LoadFromDataReadernếu dữ liệu đến từ database. - Chạy trong môi trường 64‑bit để có địa chỉ bộ nhớ lớn hơn.
10.5 Cảnh Báo “LicenseContext is not set”
- Nguyên nhân: Bỏ qua việc khai báo
ExcelPackage.LicenseContext. - Giải pháp: Đặt trong
MainhoặcStartupnhư đã mô tả ở mục 2.2.
11. Các Mẫu Thư Viện Hỗ Trợ và Tích Hợp
11.1 EPPlus + AutoMapper
Khi bạn có DTO và muốn tự động map sang Excel:
var config = new MapperConfiguration(cfg => cfg.CreateMap<ProductDto, Product>());
var mapper = config.CreateMapper();
var products = mapper.Map<List<Product>>(productDtos);
ws.Cells"A1".LoadFromCollection(products, true);
11.2 EPPlus + ASP.NET Core FileResult
public async Task<IActionResult> DownloadReport()
{ var stream = new MemoryStream(); using (var package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("Report"); ws.Cells"A1".LoadFromCollection(await _service.GetReportDataAsync(), true); await package.SaveAsAsync(stream); } stream.Position = 0; return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Report.xlsx");
}
11.3 EPPlus + Hangfire (Export Background Job)
public void EnqueueExportJob(int userId)
{ BackgroundJob.Enqueue(() => ExportUserReport(userId));
} public void ExportUserReport(int userId)
{ var data = _repo.GetUserData(userId); var filePath = Path.Combine(_env.WebRootPath, $"Reports\\User_{userId}_{DateTime.Now:yyyyMMdd}.xlsx"); ExportToExcel(data, filePath); // Gửi email thông báo, v.v...
}
12. Kết Luận
Việc export to Excel bằng EPPlus trong C# không chỉ là một kỹ thuật đơn giản mà còn mở ra một loạt khả năng mạnh mẽ để tạo ra các báo cáo doanh nghiệp chuyên nghiệp, tương tác và dễ dàng bảo trì. Từ việc cài đặt, định dạng, chèn công thức, biểu đồ, cho tới tối ưu hiệu năng với dữ liệu lớn, EPPlus cung cấp một API nhất quán, dễ học và hiệu quả.
Bạn có thể áp dụng các mẫu code trên vào:
- Ứng dụng desktop (WinForms, WPF) để tạo báo cáo offline.
- Web API hoặc ASP.NET Core MVC để cung cấp file Excel qua HTTP.
- Nền tảng serverless (Azure Functions, AWS Lambda) – chỉ cần lưu trữ file vào Blob Storage hoặc S3.
Cuối cùng, hãy luôn nhớ:
- Thiết lập LicenseContext đúng cách để tránh lỗi runtime.
- Tối ưu hoá khi dữ liệu lớn – dùng
LoadFromCollection, tránhAutoFitkhông cần. - Sử dụng Conditional Formatting để tăng tính trực quan.
- Kiểm tra và xử lý ngoại lệ (file lock, memory) để ứng dụng luôn ổn định.
Với kiến thức và các mẫu code chi tiết trong bài viết này, bạn hoàn toàn có thể tự tin triển khai giải pháp EPPlus Export to Excel cho bất kỳ dự án C# nào, đáp ứng yêu cầu báo cáo của doanh nghiệp một cách nhanh chóng và chuyên nghiệp. Chúc bạn thành công!

Tiến sĩ Lê Thống Nhất sinh năm 1955 tại Nghệ An, là nhà giáo, nhà báo và doanh nhân trong lĩnh vực giáo dục. Ông từng giảng dạy Toán học tại Trường THPT Chuyên Phan Bội Châu và đảm nhiệm nhiều vai trò trong ngành giáo dục, từ viết sách, biên soạn tài liệu đến sáng lập các dự án hỗ trợ học tập trực tuyến.
Ông là người sáng lập BigSchool – nền tảng giáo dục trực tuyến kết nối giáo viên và học sinh cả nước. Ngoài ra, ông còn nổi tiếng với vai trò tác giả, diễn giả truyền cảm hứng và khách mời trên nhiều chương trình truyền hình, trong đó có “Ai là triệu phú” trên truyền hình VTV.
Trong suốt sự nghiệp, Tiến sĩ Lê Thống Nhất đã nhận nhiều giải thưởng giáo dục và được biết đến như một người luôn đổi mới, ứng dụng công nghệ vào dạy và học, góp phần lan tỏa tri thức và niềm say mê học tập cho thế hệ trẻ.
