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

ASP.NET 實作 Excel (.xls/.xlsx) 匯入資料庫完整範例(含驗證、去重、錯誤處理)

     編輯:ASP.NET 基礎

功能需求

  • 前端上傳 .xls 或 .xlsx 檔案。
  • 後端使用 OLEDB 讀取工作表資料。
  • 逐筆對應實體類別,檢查重複鍵值(如學號)決定是否新增。
  • 完整的例外處理與使用者回饋。

前端上傳介面

<asp:FileUpload ID="FileUpload1" runat="server" Accept=".xls,.xlsx" />
<asp:Button ID="btnImport" runat="server" Text="匯入" OnClick="btnImport_Click" />
<asp:Label ID="lblMsg" runat="server" ForeColor="Red" />

後端核心邏輯

protected void btnImport_Click(object sender, EventArgs e)
{
    if (!FileUpload1.HasFile)
    {
        ShowAlert("請選擇 Excel 檔案");
        return;
    }

    string ext = Path.GetExtension(FileUpload1.FileName).ToLower();
    if (ext != ".xls" && ext != ".xlsx")
    {
        ShowAlert("僅支援 .xls 或 .xlsx 格式");
        return;
    }

    // 1. 儲存暫存檔
    string saveDir = Server.MapPath("~/UploadFiles/xls/");
    if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir);
    string savePath = Path.Combine(saveDir, Guid.NewGuid() + ext);
    FileUpload1.SaveAs(savePath);

    try
    {
        // 2. 讀取資料
        DataSet ds = ReadExcel(savePath, "Sheet1"); // 或動態取得第一個工作表名稱
        if (ds.Tables[0].Rows.Count == 0)
        {
            ShowAlert("Excel 內容為空");
            return;
        }

        // 3. 逐筆處理
        int success = 0, skip = 0, error = 0;
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            try
            {
                var student = new Student
                {
                    Stuid = row["學號"]?.ToString().Trim(),
                    Stuname = row["姓名"]?.ToString().Trim(),
                    // 其他欄位對應...
                };

                if (string.IsNullOrEmpty(student.Stuid))
                { error++; continue; }

                // 檢查重複
                if (StudentBLL.Exists(student.Stuid))
                { skip++; continue; }

                if (StudentBLL.Add(student)) success++;
                else error++;
            }
            catch (Exception ex)
            {
                error++;
                LogError(ex, row); // 記錄錯誤列內容供事後稽核
            }
        }

        ShowAlert($"匯入完成:成功 {success} 筆、略過重複 {skip} 筆、錯誤 {error} 筆");
    }
    finally
    {
        // 4. 清理暫存檔
        if (File.Exists(savePath)) File.Delete(savePath);
    }
}

private DataSet ReadExcel(string filePath, string sheetName)
{
    // .xls 使用 Jet OLEDB;.xlsx 需 ACE OLEDB (需安裝 Access Database Engine)
    string connStr = ext == ".xls"
        ? $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={filePath};Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'"
        : $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={filePath};Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'";

    using (var conn = new OleDbConnection(connStr))
    using (var adapter = new OleDbDataAdapter($"SELECT * FROM [{sheetName}$]", conn))
    {
        var ds = new DataSet();
        adapter.Fill(ds);
        return ds;
    }
}

private void ShowAlert(string msg)
{
    ScriptManager.RegisterStartupScript(this, GetType(), "alert", $"alert('{msg.Replace("'", "\\'")}');", true);
}

關鍵技術點解析

項目說明
IMEX=1混合資料型別欄位強制以文字讀取,避免數字欄位讀出 NULL。
HDR=YES第一列視為標題,不納入資料。
ACE vs Jet.xlsx 必須用 ACE OLEDB 12.0/16.0,伺服器需安裝 Access Database Engine (64 位元版)。
暫存檔命名使用 Guid 避免檔名衝突,匯入完成即刪除,不佔用空間。
去重策略以業務鍵 (學號) 判斷,若需更新既有資料可改用 Upsert 模式。

進階優化方向

  1. 大檔案分批:使用 OleDbDataReader 逐列讀取,避免一次載入整個 DataSet 佔記憶體。
  2. 非同步處理:搭配 Hangfire / Quartz / BackgroundService 將匯入放入背景工作,前端輪詢進度。
  3. 資料驗證框架:引入 FluentValidation 或 DataAnnotations,集中管理欄位規則。
  4. EPPlus / NPOI:不依賴 OLEDB Provider,支援 .xlsx 純 managed 程式碼讀寫,部署更輕鬆。

小結

Excel 匯入看似簡單,實際上涉及檔案格式相容性、資料型別推斷、業務規則驗證、併發與錯誤處理等多層面。建立標準化的匯入流程與共用元件,能大幅降低維護成本並提升系統穩定度。

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