.xls (HSSF) 與 .xlsx (XSSF) 格式。Install-Package NPOI
// 或 .NET Core CLI
dotnet add package NPOI
using NPOI.HSSF.UserModel; // .xls
using NPOI.XSSF.UserModel; // .xlsx
using NPOI.SS.UserModel;
using System.Data;
using System.IO;
public byte[] ExportStudentsToExcel(DataTable dt, bool xlsx = true) {
IWorkbook workbook = xlsx ? (IWorkbook)new XSSFWorkbook() : new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet(\"學生名單\");
// 樣式:表頭加粗、置中、邊框
ICellStyle headerStyle = workbook.CreateCellStyle();
IFont headerFont = workbook.CreateFont(); headerFont.IsBold = true; headerStyle.SetFont(headerFont);
headerStyle.Alignment = HorizontalAlignment.Center;
headerStyle.BorderBottom = BorderStyle.Thin; headerStyle.BorderTop = BorderStyle.Thin;
headerStyle.BorderLeft = BorderStyle.Thin; headerStyle.BorderRight = BorderStyle.Thin;
ICellStyle dataStyle = workbook.CreateCellStyle();
dataStyle.BorderBottom = BorderStyle.Thin; dataStyle.BorderTop = BorderStyle.Thin;
dataStyle.BorderLeft = BorderStyle.Thin; dataStyle.BorderRight = BorderStyle.Thin;
// 寫入表頭
IRow headerRow = sheet.CreateRow(0);
for (int c = 0; c < dt.Columns.Count; c++) {
ICell cell = headerRow.CreateCell(c);
cell.SetCellValue(dt.Columns[c].ColumnName);
cell.CellStyle = headerStyle;
}
// 寫入資料
for (int r = 0; r < dt.Rows.Count; r++) {
IRow row = sheet.CreateRow(r + 1);
for (int c = 0; c < dt.Columns.Count; c++) {
ICell cell = row.CreateCell(c);
object val = dt.Rows[r][c];
if (val is DateTime) cell.SetCellValue((DateTime)val);
else if (val is double || val is float || val is decimal) cell.SetCellValue(Convert.ToDouble(val));
else if (val is int || val is long) cell.SetCellValue(Convert.ToInt64(val));
else cell.SetCellValue(val?.ToString() ?? \"\");
cell.CellStyle = dataStyle;
}
}
// 自動欄寬
for (int c = 0; c < dt.Columns.Count; c++) sheet.AutoSizeColumn(c);
using (MemoryStream ms = new MemoryStream()) {
workbook.Write(ms);
return ms.ToArray();
}
}
// 呼叫範例(WinForm/Web API 均適用)
// byte[] excelBytes = ExportStudentsToExcel(dataTable);
// File.WriteAllBytes(\"students.xlsx\", excelBytes); // 或回傳 FileStreamResult
| 問題 | 解決方案 |
|---|---|
| 大數據量 ( > 10 萬行) 記憶體溢位 | 使用 SXSSFWorkbook (僅 .xlsx) 流式寫入,定期 flush 到磁碟 |
| 日期/數字格式不正確 | 建立 ICellStyle 設定 DataFormat (如 yyyy-mm-dd, #,##0.00) |
| 中文欄名亂碼 | 確保專案編碼 UTF-8,NPOI 內部使用 Unicode,無亂碼問題 |
| 合併儲存格 | sheet.AddMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol)) |
**NPOI 是 C# 導出 Excel 的最佳選擇**:無依賴、跨平台、功能完整。配合 DataTable 或實體列表,十幾行代碼即可生成專業格式試算表。