Magicodes.IE之導入學生數據教程

基礎教程之導入學生數據

說明

本教程主要說明若是使用Magicodes.IE.Excel完成學生數據的Excel導入。git

要點

  • 本教程使用Magicodes.IE.Excel來完成Excel數據導入
  • 須要經過建立Dto來完成導入
  • Magicodes.IE.Excel能夠根據Dto以及特性設置來自動生成導入的Excel模板,數據驗證(包括重複驗證),模板驗證,讀取設置,值約束和映射,輸出Excel驗證標註

主要步驟

1.安裝包Magicodes.IE.Excel

在本篇教程中,咱們僅演示使用Excel來完成學生數據的導入。咱們須要在已準備好的工程中安裝如下包,參考命令以下所示:github

Install-Package Magicodes.IE.Excel

2.建立導入Dto

主要代碼以下所示:shell

  • 學生數據Dtoapp

    /// <summary>
        /// 導入學生數據Dto
        /// IsLabelingError:是否標註數據錯誤
        /// </summary>
        [ExcelImporter(IsLabelingError = true)]
        public class ImportStudentDto
        {
            /// <summary>
            ///     序號
            /// </summary>
            [ImporterHeader(Name = "序號")]
            public long SerialNumber { get; set; }
    
            /// <summary>
            ///     學籍號
            /// </summary>
            [ImporterHeader(Name = "學籍號")]
            [MaxLength(30, ErrorMessage = "學籍號字數超出最大限制,請修改!")]
            public string StudentCode { get; set; }
    
            /// <summary>
            ///     姓名
            /// </summary>
            [ImporterHeader(Name = "姓名")]
            [Required(ErrorMessage = "學生姓名不能爲空")]
            [MaxLength(50, ErrorMessage = "名稱字數超出最大限制,請修改!")]
            public string Name { get; set; }
    
            /// <summary>
            ///     身份證號碼
            /// </summary>
            [ImporterHeader(Name = "身份證號", IsAllowRepeat = false)]
            [Required(ErrorMessage = "身份證號不能爲空")]
            [MaxLength(18, ErrorMessage = "身份證字數超出最大限制,請修改!")]
            public string IdCard { get; set; }
    
            /// <summary>
            ///     性別
            /// </summary>
            [ImporterHeader(Name = "性別")]
            [Required(ErrorMessage = "性別不能爲空")]
            [ValueMapping("", 0)]
            [ValueMapping("", 1)]
            public Genders Gender { get; set; }
    
            /// <summary>
            ///     家庭地址
            /// </summary>
            [ImporterHeader(Name = "家庭住址")]
            [Required(ErrorMessage = "家庭地址不能爲空")]
            [MaxLength(200, ErrorMessage = "家庭地址字數超出最大限制,請修改!")]
            public string Address { get; set; }
    
            /// <summary>
            ///     家長姓名
            /// </summary>
            [ImporterHeader(Name = "家長姓名")]
            [Required(ErrorMessage = "家長姓名不能爲空")]
            [MaxLength(50, ErrorMessage = "家長姓名數超出最大限制,請修改!")]
            public string Guardian { get; set; }
    
            /// <summary>
            ///     家長聯繫電話
            /// </summary>
            [ImporterHeader(Name = "家長聯繫電話")]
            [MaxLength(20, ErrorMessage = "家長聯繫電話字數超出最大限制,請修改!")]
            public string GuardianPhone { get; set; }
    
            /// <summary>
            ///     學號
            /// </summary>
            [ImporterHeader(Name = "學號")]
            [MaxLength(30, ErrorMessage = "學號字數超出最大限制,請修改!")]
            public string StudentNub { get; set; }
    
            /// <summary>
            ///     宿舍號
            /// </summary>
            [ImporterHeader(Name = "宿舍號")]
            [MaxLength(20, ErrorMessage = "宿舍號字數超出最大限制,請修改!")]
            public string DormitoryNo { get; set; }
    
            /// <summary>
            ///     QQ
            /// </summary>
            [ImporterHeader(Name = "QQ號")]
            [MaxLength(30, ErrorMessage = "QQ號字數超出最大限制,請修改!")]
            public string QQ { get; set; }
    
            /// <summary>
            ///     民族
            /// </summary>
            [ImporterHeader(Name = "民族")]
            [MaxLength(2, ErrorMessage = "民族字數超出最大限制,請修改!")]
            public string Nation { get; set; }
    
            /// <summary>
            ///     戶口性質
            /// </summary>
            [ImporterHeader(Name = "戶口性質")]
            [MaxLength(10, ErrorMessage = "戶口性質字數超出最大限制,請修改!")]
            public string HouseholdType { get; set; }
    
            /// <summary>
            ///     聯繫電話
            /// </summary>
            [ImporterHeader(Name = "學生聯繫電話")]
            [MaxLength(20, ErrorMessage = "手機號碼字數超出最大限制,請修改!")]
            public string Phone { get; set; }
    
            /// <summary>
            ///     狀態
            ///     測試可爲空的枚舉類型
            /// </summary>
            [ImporterHeader(Name = "狀態")]
            public StudentStatus? Status { get; set; }
    
            /// <summary>
            ///     備註
            /// </summary>
            [ImporterHeader(Name = "備註")]
            [MaxLength(200, ErrorMessage = "備註字數超出最大限制,請修改!")]
            public string Remark { get; set; }
    
            /// <summary>
            ///     是否住校(宿舍)
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public bool? IsBoarding { get; set; }
    
            /// <summary>
            ///     所屬班級id
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public Guid ClassId { get; set; }
    
            /// <summary>
            ///     學校Id
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public Guid? SchoolId { get; set; }
    
            /// <summary>
            ///     校區Id
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public Guid? CampusId { get; set; }
    
            /// <summary>
            ///     專業Id
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public Guid? MajorsId { get; set; }
    
            /// <summary>
            ///     年級Id
            /// </summary>
            [ImporterHeader(IsIgnore = true)]
            public Guid? GradeId { get; set; }
        }

    如上述代碼所示,咱們定義了以上學生數據Dto,主要注意事項以下:async

    1. ExcelImporter特性能夠設置一些導入的全局設置,好比是否標註錯誤、導入Sheet名稱(如不設置則自動獲取第一個)、截止讀取的列數、表頭位置。
    2. 支持經常使用的數據驗證設置,好比必填、最大長度。
    3. 支持數據重複校驗,好比身份證號碼。見ImporterHeader特性的IsAllowRepeat設置。
    4. 支持列頭設置,將ImporterHeader的Name屬性。除此以外,ImporterHeader還支持自動過濾空格(默認啓用)、處理掉全部的空格、列索引等。
    5. 對數據列啓用了忽略設置,見SchoolId的"[ImporterHeader(IsIgnore = true)]"。
    6. 使用了值映射,見「Gender」屬性。啓用值映射以後,將不會從枚舉定義中獲取值映射。
    7. 支持枚舉,支持從枚舉的Display、Description特性中獲取值映射。枚舉定義見下文。
  • 性別枚舉單元測試

    定義以下所示:測試

    /// <summary>
    ///     性別
    /// </summary>
    public enum Genders
    {
        /// <summary>
        ////// </summary>
        Man = 0,
    
        /// <summary>
        ////// </summary>
        Female = 1
    }

    注意上文中的第7點。ui

  • 學生狀態枚舉
/// <summary>
///     學生狀態 正常、流失、休學、勤工儉學、頂崗實習、畢業、參軍
/// </summary>
public enum StudentStatus
{
    /// <summary>
    ///     正常
    /// </summary>
    [Display(Name = "正常")] Normal = 0,

    /// <summary>
    ///     流失
    /// </summary>
    [Description("流水")] PupilsAway = 1,

    /// <summary>
    ///     休學
    /// </summary>
    [Display(Name = "休學")] Suspension = 2,

    /// <summary>
    ///     勤工儉學
    /// </summary>
    [Display(Name = "勤工儉學")] WorkStudy = 3,

    /// <summary>
    ///     頂崗實習
    /// </summary>
    [Display(Name = "頂崗實習")] PostPractice = 4,

    /// <summary>
    ///     畢業
    /// </summary>
    [Display(Name = "畢業")] Graduation = 5,

    /// <summary>
    ///     參軍
    /// </summary>
    [Display(Name = "參軍")] JoinTheArmy = 6
}

注意上文中的第7點。spa

3.生成導入模板並填充數據

導入以前是否是得準備一份模板?對於咱們,手寫模板?這是不存在的。Magicodes.IE.Excel封裝了根據DTO自動生成Excel導入模板的方法,咱們能夠直接調用。這裏咱們來看下導入的相關方法:3d

/// <summary>
///     導入
/// </summary>
public interface IImporter
{
    /// <summary>
    ///     生成Excel導入模板
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    Task<TemplateFileInfo> GenerateTemplate<T>(string fileName) where T : class, new();

    /// <summary>
    ///     生成Excel導入模板
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns>二進制字節</returns>
    Task<byte[]> GenerateTemplateBytes<T>() where T : class, new();

    /// <summary>
    ///     導入模型驗證數據
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="filePath"></param>
    /// <returns></returns>
    Task<ImportResult<T>> Import<T>(string filePath) where T : class, new();
}

經過以上方法中的GenerateTemplate,咱們能夠獲得須要的導入模板。具體使用能夠參考如下單元測試:

public IImporter Importer = new ExcelImporter();

    [Fact(DisplayName = "生成學生數據導入模板(測試枚舉生成模板)")]
    public async Task GenerateStudentImportTemplate_Test()
    {
        var filePath = Path.Combine(Directory.GetCurrentDirectory(),
            nameof(GenerateStudentImportTemplate_Test) + ".xlsx");
        if (File.Exists(filePath)) File.Delete(filePath);

        var result = await Importer.GenerateTemplate<ImportStudentDto>(filePath);
        result.ShouldNotBeNull();
        File.Exists(filePath).ShouldBeTrue();

        //TODO:讀取Excel檢查表頭和格式
    }

以上DTO獲取模板並填充數據後以下圖所示:

注意:枚舉會自動生成下拉選擇,必填項列頭會標紅。

4.獲取學生導入驗證錯誤和數據

根據模板填充數據後,咱們就能夠進行數據導入了。一般狀況下,咱們有如下步驟:

  • 驗證導入數據

    經過Magicodes.IE.Excel導入數據會自動進行驗證,而且輸出驗證結果,以便於前臺顯示。具體咱們能夠經過其導入的結果類來了解:

    /// <summary>
    ///     導入結果
    /// </summary>
    public class ImportResult<T> where T : class
    {
        /// <summary>
        /// </summary>
        public ImportResult()
        {
            RowErrors = new List<DataRowErrorInfo>();
        }
    
        /// <summary>
        ///     導入數據
        /// </summary>
        public virtual ICollection<T> Data { get; set; }
    
        /// <summary>
        ///     驗證錯誤
        /// </summary>
        public virtual IList<DataRowErrorInfo> RowErrors { get; set; }
    
        /// <summary>
        ///     模板錯誤
        /// </summary>
        public virtual IList<TemplateErrorInfo> TemplateErrors { get; set; }
    
        /// <summary>
        ///     導入異常信息
        /// </summary>
        public virtual Exception Exception { get; set; }
    
        /// <summary>
        ///     是否存在導入錯誤
        /// </summary>
        public virtual bool HasError => Exception != null ||
                                        (TemplateErrors?.Count(p => p.ErrorLevel == ErrorLevels.Error) ?? 0) > 0 ||
                                        (RowErrors?.Count ?? 0) > 0;
    }

    其中,

    • Data爲數據結果

    • RowErrors爲驗證錯誤,好比必填、重複驗證、文本長度等等。會給出行號、字段以及字段錯誤集合

    • TemplateErrors爲模板錯誤,好比必填列缺失等錯誤信息。支持錯誤等級(警告、錯誤)

    • Exception爲導入異常信息

    • HasError爲是否存在錯誤(不包含警告)

    經過ImportResult,咱們就能夠很方便的拿到導入驗證錯誤而無須額外編寫代碼。一般在導入時咱們須要判斷HasError屬性並給前臺返回具體的錯誤結果。

    數據導入參考代碼以下所示:

    [Fact(DisplayName = "學生基礎數據導入")]
        public async Task StudentInfoImporter_Test()
        {
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "TestFiles", "Import", "學生基礎數據導入.xlsx");
            var import = await Importer.Import<ImportStudentDto>(filePath);
            import.ShouldNotBeNull();
            if (import.Exception != null) _testOutputHelper.WriteLine(import.Exception.ToString());
    
            if (import.RowErrors.Count > 0) _testOutputHelper.WriteLine(JsonConvert.SerializeObject(import.RowErrors));
            import.HasError.ShouldBeFalse();
            import.Data.ShouldNotBeNull();
            import.Data.Count.ShouldBe(16);
        }
  • 獲取驗證標註

客戶說雖然你提示了,可是我仍是不知道哪裏錯了!!怎麼辦?!!

咱們貼心的爲你準備了導入數據的Excel文件的標註:

如何開啓這個【史詩劇情】呢?僅需:

[ExcelImporter(IsLabelingError = true)]

開啓後,咱們將自動保存「{目標文件名稱}_.xlsx」的標註文件到目標位置。

  • 獲取導入數據

沒有錯誤了?也就是HasError爲false,那麼咱們就能夠直接拿到Data隨心所欲了!

最後

整個學生數據的導入教程就此結束了。相關庫會一直更新,在功能體驗上有可能會和本文教程有細微的出入,請以相關具體代碼、版本日誌、單元測試示例爲準。

相關文章
相關標籤/搜索