Epplus Export To Excel Trong C#: Hướng Dẫn Chi Tiết Từ A → Z

Mục lục bài viết

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.

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íEPPlusNPOIClosedXML
Hiệu năngRất nhanh, tối ưu cho file lớnTốt, nhưng hơi chậm hơn EPPlusTương đương EPPlus
Định dạngHỗ trợ phong phú (font, màu, border, fill, conditional formatting)Hỗ trợ cơ bảnHỗ trợ tốt
Công thứcToàn diện, hỗ trợ mọi công thức ExcelHạn chếToàn diện
Biểu đồHỗ trợ tạo và chỉnh sửaHạn chếKhông hỗ trợ biểu đồ
Tài liệuRất đầy đủ, ví dụ thực tếĐủĐầy đủ
Giấy phépPolyform (phi thương mại) / GPL (cũ)Apache 2.0MIT

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).

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

Epplus Export To Excel C#
Epplus Export To Excel C#
// 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.Create và FileShare.None. Khi stream tới client, luôn reset stream.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ấn F9 trong 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 LoadFromCollection mà không chỉ định TableStyle, hoặc thực hiện quá nhiều thao tác AutoFit.
  • Giải pháp:
  • Tắt AutoFit cho toàn bộ cột, chỉ áp dụng cho một vài cột cần.
  • Sử dụng ExcelRangeBase.LoadFromDataReader nế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 Main hoặc Startup như đã 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ớ:

  1. Thiết lập LicenseContext đúng cách để tránh lỗi runtime.
  2. Tối ưu hoá khi dữ liệu lớn – dùng LoadFromCollection, tránh AutoFit không cần.
  3. Sử dụng Conditional Formatting để tăng tính trực quan.
  4. 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!

⚠️
LƯU Ý QUAN TRỌNG: Miễn trừ trách nhiệm: Mặc dù chúng tôi luôn nỗ lực để đảm bảo tính chính xác và cập nhật của thông tin, nhưng các quy định về giáo dục và tuyển sinh có thể thay đổi theo thời gian. BigSchool không chịu trách nhiệm về bất kỳ sai sót nào hoặc kết quả phát sinh từ việc sử dụng thông tin trên trang này. Độc giả nên liên hệ trực tiếp với nhà trường hoặc cơ quan chức năng để có thông tin mới nhất. Ngoài ra, BigSchool tuyệt đối không bán sản phẩm, khóa học hay cung cấp dịch vụ được nhắc đến trong bài.

Viết một bình luận