從Excel匯入

使用 OpenXml 匯入 Excel 檔案

這個功能的用途是把一個 Excel 檔案的內容匯到系統的資料庫裡面,以省去人員輸入資料的成本,它的程式邏輯為:
• 上傳要匯入的 Excel 檔案
• 檢查每1筆資料的正確性,如果有誤則寫入 log
• 將正確的資料寫入資料庫
• 產生 log,以供查詢
• 可將錯誤的資料匯出,供下次匯入

人事管理系統為例,它的 [匯入用戶資料] 功能的清單畫面如下圖,畫面上會顯示所有曾經匯入的紀錄,如果你點選 [失敗筆數] 這個欄位上面的數字,系統會下載這個匯入失敗的檔案,裡面包含失敗的原因說明;或是點選 [匯入檔案] 這個欄位來下載原始的匯入資料。

點擊上圖中的 [匯入Excel] 按鈕時,系統會出現以下的匯入畫面,匯入完成後,在清單畫面會增加這一筆匯入的紀錄。

匯入的功能除了為系統提供方便性之外,更重要的是它可以模組化,這表示你只要撰寫少許的程式碼就可以完成這個功能。以下是 [匯入用戶資料] 功能的controller,檔案為 UserImportController.cs:

1.繼承 XpImport controller,這個類別包含匯入功能的共用程式
2.設定匯入功能畫面所需要的4個變數,這些變數是公用的清單畫面需要的,它們定義在 XpImportController.cs
3.實作匯入功能,這也是需要撰寫的主要程式,UserImportService 的程式內容如下:

/// <summary>
/// import excel file
/// </summary>
/// <param name="file"></param>
/// <returns>result</returns>
public ResultImportDto Import(IFormFile file)
{
    var importDto = new ExcelImportDto<UserImportVo>()
    {
        ImportType = ImportTypeEstr.User,
        TplPath = _Xp.DirTpl + "UserImport.xlsx",
        SaveDir = _Xp.DirUserImport,
        FnSaveImportRows = SaveImportRows,
        CreatorName = _Fun.GetBaseUser().UserName,
    };
    return _WebExcel.ImportByFile(file, importDto);
}

private List<string> SaveImportRows(List<UserImportVo> okRows)
{
    var db = _Xp.GetDb();
    var deptIds = db.Dept.Select(a => a.Id).ToList();
    var results = new List<string>();
    foreach (var row in okRows)
    {
        //check deptId
        if (!deptIds.Contains(row.DeptId))
        {
            results.Add("DeptId有誤");
            continue;
        }

        db.User.Add(new User() { 
            Id = _Str.NewId(),
            Name = row.Name,
            Account = row.Account,
            Pwd = row.Pwd,
            DeptId = row.DeptId,
            Status = true,
        });

        try
        {
            db.SaveChanges();
            results.Add("");
        }
        catch (Exception ex)
        {
            results.Add(ex.InnerException.Message);
        }
    }
    return results;
}

在上面的 Import 函數中,你需要先建立一個 UserImportVo 類別,它用來定義要匯入的欄位清單,同時包含所要進行的驗証,部分內容如下:

public class UserImportVo
{
    [Required]
    [StringLength(20)]
    public string Name { get; set; }

    [Required]
    [StringLength(20)]
    public string Account { get; set; }