首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 使用 NPOI 讀取 Excel 模板並導出下載完整教學

     編輯:ASP.NET 基礎

前言

傳統 `Microsoft.Office.Interop.Excel` 需在伺服器安裝 Office、處理 COM 權限、進程殘留導致記憶體洩漏,且無法支援高併發。NPOI 是 Apache POI 的 .NET 移植版,純 managed code、無需安裝 Office、效能極佳、支援 .xls (HSSF) 與 .xlsx (XSSF)。本文示範「載入模板 → 填入資料 → 重新計算公式 → 串流輸出下載」的標準流程。

為何選擇 NPOI?

傳統 Interop 問題NPOI 優勢
需安裝 Office、修補漏洞純 .NET DLL,零依賴
COM 權限設定複雜 (DCOMCNFG)無權限問題,中信任環境可用
每次導出產生 EXCEL.EXE 進程,不自動釋放無進程,記憶體可控,支援高併發
自動轉換數字格式 (000123 → 123)可強制設定 CellType = String 保留前導零
公式/前 8 列型別推測導致科學記號完全由程式控制格式,無驚喜

準備工作

  1. NuGet 安裝:`Install-Package NPOI` (目前 2.6.x 支援 .NET Framework / .NET Core)
  2. 專案建立 `Template` 資料夾,放入 `Book1.xls` 模板檔 (預設 Sheet1、儲存格已設定格式、公式)。

核心導出程式碼

using NPOI.HSSF.UserModel;   // .xls
using NPOI.SS.UserModel;     // 介面層,支援 .xls/.xlsx 通用
using System.IO;
using System.Web;

public void ExportExcel()
{
    // 1. 載入模板到工作簿
    HSSFWorkbook workbook;
    string templatePath = HttpContext.Current.Request.PhysicalApplicationPath + @"Template\Book1.xls";
    using (FileStream fs = new FileStream(templatePath, FileMode.Open, FileAccess.Read))
    {
        workbook = new HSSFWorkbook(fs); // 自動解析模板樣式、公式、合併儲存格
    }

    // 2. 取得工作表並填入資料
    ISheet sheet = workbook.GetSheet("Sheet1"); // 或 workbook.GetSheetAt(0)

    // 模板第 2~13 列 (索引 1~12) 已預設格式,直接寫入數值
    sheet.GetRow(1).GetCell(1).SetCellValue(200200);
    sheet.GetRow(2).GetCell(1).SetCellValue(300);
    sheet.GetRow(3).GetCell(1).SetCellValue(500050);
    sheet.GetRow(4).GetCell(1).SetCellValue(8000);
    sheet.GetRow(5).GetCell(1).SetCellValue(110);
    sheet.GetRow(6).GetCell(1).SetCellValue(100);
    sheet.GetRow(7).GetCell(1).SetCellValue(200);
    sheet.GetRow(8).GetCell(1).SetCellValue(210);
    sheet.GetRow(9).GetCell(1).SetCellValue(2300);
    sheet.GetRow(10).GetCell(1).SetCellValue(240);
    sheet.GetRow(11).GetCell(1).SetCellValue(180123);
    sheet.GetRow(12).GetCell(1).SetCellValue(150);

    // 3. 強制重新計算所有公式 (模板若含 SUM/AVERAGE 等)
    sheet.ForceFormulaRecalculation = true;

    // 4. 設定回應標頭:觸發瀏覽器下載
    HttpResponse resp = HttpContext.Current.Response;
    resp.ContentType = "application/vnd.ms-excel"; // .xls MIME
    resp.AddHeader("Content-Disposition", "attachment;filename=ExportReport.xls");
    resp.Clear(); // 清除緩衝區 HTML,避免混雜

    // 5. 寫入 MemoryStream 並輸出二進位
    using (MemoryStream ms = new MemoryStream())
    {
        workbook.Write(ms);
        resp.BinaryWrite(ms.ToArray());
        resp.End(); // 結束回應
    }
}

關鍵技術細節

步驟關鍵 API注意事項
載入模板`new HSSFWorkbook(fs)`FileStream 需 `FileAccess.Read`,用完即 Dispose,避免鎖定檔案
存取儲存格`sheet.GetRow(i).GetCell(j)`若儲存格不存在會回傳 null,建議封裝安全取值擴充方法
寫入數值`cell.SetCellValue(val)`多載支援 string/double/bool/DateTime,自動對應 CellType
保留前導零`cell.SetCellValue("000123"); cell.CellType = CellType.String;`強制文字格式,防止自動轉數值
日期格式`cell.SetCellValue(DateTime.Now); cell.CellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("yyyy/mm/dd");`需建立/重用 CellStyle
公式重算`sheet.ForceFormulaRecalculation = true`僅支援 NPOI 內建函數,複雜 VBA/外部加載函數不支援
串流輸出`workbook.Write(ms)` → `Response.BinaryWrite`避免先存檔再傳輸,減少 I/O 與暫存檔清理

進階:支援 .xlsx (XSSFWorkbook)


// 依副檔名自動選擇
string ext = Path.GetExtension(templatePath).ToLower();
IWorkbook workbook = ext switch
{
    ".xls" => new HSSFWorkbook(fs),
    ".xlsx" => new XSSFWorkbook(fs),
    _ => throw new NotSupportedException("僅支援 .xls/.xlsx")
};
// 後續操作皆使用 IWorkbook/ISheet/ICell 介面,程式碼不變

常見問題與解決

  • 導出檔案損壞/為 0 bytes:確認 `Response.Clear()` 在 `BinaryWrite` 之前、無其他 `Response.Write` 輸出 HTML、`Response.End()` 結束。
  • 中文檔名亂碼:`filename*=UTF-8''" + HttpUtility.UrlEncode("報表.xlsx", Encoding.UTF8)` (RFC 5987)。
  • 大量資料記憶體不足:NPOI 需將整個工作簿載入記憶體。超過 5 萬列建議改用 `SXSSFWorkbook` (僅 .xlsx、串流寫入、低記憶體)。
  • 樣式大量重複建立導致檔案膨脹:建立 `CellStyle` 統一快取重用,勿在迴圈中 `new CellStyle()`。

總結

NPOI 是 ASP.NET 導出 Excel 的最佳選擇:零依賴、高效能、完整支援樣式/公式/合併儲存格。掌握「模板法」—— 先在 Excel 設計好版面與格式,程式只負責填資料、觸發公式重算、串流輸出 —— 可大幅降低維護成本,並完美解決 Interop 所有痛點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved