基础教程之导入学生数据

说明

本教程主要说明如果使用Magicodes.IE.Excel完成学生数据的Excel导入。

要点

  • 本教程使用Magicodes.IE.Excel来完成Excel数据导入
  • 需要通过创建Dto来完成导入
  • Magicodes.IE.Excel可以根据Dto以及特性设置来自动生成导入的Excel模板,数据验证(包括重复验证),模板验证,读取设置,值约束和映射,输出Excel验证标注

主要步骤

1.安装包Magicodes.IE.Excel

在本篇教程中,我们仅演示使用Excel来完成学生数据的导入。我们需要在已准备好的工程中安装以下包,参考命令如下所示:

Install-Package Magicodes.IE.Excel

2.创建导入Dto

主要代码如下所示:

  • 学生数据Dto

    /// <summary>
    /// 导入学生数据Dto
    /// IsLabelingError:是否标注数据错误
    /// </summary>
    [ExcelImporter(IsLabelingError = true)]
    public class ImportStudentDto
    {
    /// <summary>
    /// 序号
    /// </summary>
    [ImporterHeader(Name = "序号")]
    public long SerialNumber { get; set; } /// <summary>
    /// 学籍号
    /// </summary>
    [ImporterHeader(Name = "学籍号")]
    [MaxLength(, ErrorMessage = "学籍号字数超出最大限制,请修改!")]
    public string StudentCode { get; set; } /// <summary>
    /// 姓名
    /// </summary>
    [ImporterHeader(Name = "姓名")]
    [Required(ErrorMessage = "学生姓名不能为空")]
    [MaxLength(, ErrorMessage = "名称字数超出最大限制,请修改!")]
    public string Name { get; set; } /// <summary>
    /// 身份证号码
    /// </summary>
    [ImporterHeader(Name = "身份证号", IsAllowRepeat = false)]
    [Required(ErrorMessage = "身份证号不能为空")]
    [MaxLength(, ErrorMessage = "身份证字数超出最大限制,请修改!")]
    public string IdCard { get; set; } /// <summary>
    /// 性别
    /// </summary>
    [ImporterHeader(Name = "性别")]
    [Required(ErrorMessage = "性别不能为空")]
    [ValueMapping("男", )]
    [ValueMapping("女", )]
    public Genders Gender { get; set; } /// <summary>
    /// 家庭地址
    /// </summary>
    [ImporterHeader(Name = "家庭住址")]
    [Required(ErrorMessage = "家庭地址不能为空")]
    [MaxLength(, ErrorMessage = "家庭地址字数超出最大限制,请修改!")]
    public string Address { get; set; } /// <summary>
    /// 家长姓名
    /// </summary>
    [ImporterHeader(Name = "家长姓名")]
    [Required(ErrorMessage = "家长姓名不能为空")]
    [MaxLength(, ErrorMessage = "家长姓名数超出最大限制,请修改!")]
    public string Guardian { get; set; } /// <summary>
    /// 家长联系电话
    /// </summary>
    [ImporterHeader(Name = "家长联系电话")]
    [MaxLength(, ErrorMessage = "家长联系电话字数超出最大限制,请修改!")]
    public string GuardianPhone { get; set; } /// <summary>
    /// 学号
    /// </summary>
    [ImporterHeader(Name = "学号")]
    [MaxLength(, ErrorMessage = "学号字数超出最大限制,请修改!")]
    public string StudentNub { get; set; } /// <summary>
    /// 宿舍号
    /// </summary>
    [ImporterHeader(Name = "宿舍号")]
    [MaxLength(, ErrorMessage = "宿舍号字数超出最大限制,请修改!")]
    public string DormitoryNo { get; set; } /// <summary>
    /// QQ
    /// </summary>
    [ImporterHeader(Name = "QQ号")]
    [MaxLength(, ErrorMessage = "QQ号字数超出最大限制,请修改!")]
    public string QQ { get; set; } /// <summary>
    /// 民族
    /// </summary>
    [ImporterHeader(Name = "民族")]
    [MaxLength(, ErrorMessage = "民族字数超出最大限制,请修改!")]
    public string Nation { get; set; } /// <summary>
    /// 户口性质
    /// </summary>
    [ImporterHeader(Name = "户口性质")]
    [MaxLength(, ErrorMessage = "户口性质字数超出最大限制,请修改!")]
    public string HouseholdType { get; set; } /// <summary>
    /// 联系电话
    /// </summary>
    [ImporterHeader(Name = "学生联系电话")]
    [MaxLength(, ErrorMessage = "手机号码字数超出最大限制,请修改!")]
    public string Phone { get; set; } /// <summary>
    /// 状态
    /// 测试可为空的枚举类型
    /// </summary>
    [ImporterHeader(Name = "状态")]
    public StudentStatus? Status { get; set; } /// <summary>
    /// 备注
    /// </summary>
    [ImporterHeader(Name = "备注")]
    [MaxLength(, 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,主要注意事项如下:

    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 = , /// <summary>
    /// 女
    /// </summary>
    Female =
    }

    注意上文中的第7点。

  • 学生状态枚举
/// <summary>
/// 学生状态 正常、流失、休学、勤工俭学、顶岗实习、毕业、参军
/// </summary>
public enum StudentStatus
{
/// <summary>
/// 正常
/// </summary>
[Display(Name = "正常")] Normal = , /// <summary>
/// 流失
/// </summary>
[Description("流水")] PupilsAway = , /// <summary>
/// 休学
/// </summary>
[Display(Name = "休学")] Suspension = , /// <summary>
/// 勤工俭学
/// </summary>
[Display(Name = "勤工俭学")] WorkStudy = , /// <summary>
/// 顶岗实习
/// </summary>
[Display(Name = "顶岗实习")] PostPractice = , /// <summary>
/// 毕业
/// </summary>
[Display(Name = "毕业")] Graduation = , /// <summary>
/// 参军
/// </summary>
[Display(Name = "参军")] JoinTheArmy =
}

注意上文中的第7点。

3.生成导入模板并填充数据

导入之前是不是得准备一份模板?对于我们,手写模板?这是不存在的。Magicodes.IE.Excel封装了根据DTO自动生成Excel导入模板的方法,我们可以直接调用。这里我们来看下导入的相关方法:

/// <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) ?? ) > ||
    (RowErrors?.Count ?? ) > ;
    }

    其中,

    • 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 > ) _testOutputHelper.WriteLine(JsonConvert.SerializeObject(import.RowErrors));
    import.HasError.ShouldBeFalse();
    import.Data.ShouldNotBeNull();
    import.Data.Count.ShouldBe();
    }
  • 获取验证标注

客户说虽然你提示了,但是我还是不知道哪里错了!!怎么办?!!

我们贴心的为你准备了导入数据的Excel文件的标注:

如何开启这个【史诗剧情】呢?仅需:

[ExcelImporter(IsLabelingError = true)]

开启后,我们将自动保存“{目标文件名称}_.xlsx”的标注文件到目标位置。

  • 获取导入数据

没有错误了?也就是HasError为false,那么我们就可以直接拿到Data为所欲为了!

最后

整个学生数据的导入教程就此结束了。相关库会一直更新,在功能体验上有可能会和本文教程有细微的出入,请以相关具体代码、版本日志、单元测试示例为准。

Magicodes.IE之导入学生数据教程的更多相关文章

  1. Magicodes.IE之导入导出筛选器

    总体设计   Magicodes.IE是一个导入导出通用库,支持Dto导入导出以及动态导出,支持Excel.Word.Pdf.Csv和Html.在本篇教程,笔者将讲述如何使用Magicodes.IE的 ...

  2. CRL快速开发框架系列教程九(导入/导出数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  3. Magicodes.IE 在100万数据量下导入导出性能测试

    原文作者:HueiFeng 前言 目前Magicodes.IE更新到了2.2.3,感谢大家的支持,同时建议大家在使用过程中如果遇到一些问题或者说需要一些额外的功能可以直接提issues,当然更建议大家 ...

  4. mysql导出csv/excel文件的几种方法,mysql的load导入csv数据

    方法一 php教程用mysql的命令和shell select * into outfile './bestlovesky.xls' from bestlovesky where 1 order by ...

  5. Mysql错误积累001-load data导入文件数据出现1290错误

    错误出现情景 在cmd中使用mysql命令,学生信息表添加数据.使用load data方式简单批量导入数据. 准备好文本数据: xueshengxinxi.txt 文件  数据之间以tab键进行分割 ...

  6. 用Python的pandas框架操作Excel文件中的数据教程

    用Python的pandas框架操作Excel文件中的数据教程 本文的目的,是向您展示如何使用pandas 来执行一些常见的Excel任务.有些例子比较琐碎,但我觉得展示这些简单的东西与那些你可以在其 ...

  7. c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出

    c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出 using NPOI.HSSF.UserModel;using NPOI.SS.UserModel;using S ...

  8. BCP导出导入大容量数据实践

    前言 SQL SERVER提供多种不同的数据导出导入的工具,也可以编写SQL脚本,使用存储过程,生成所需的数据文件,甚至可以生成包含SQL语句和数据的脚本文件.各有优缺点,以适用不同的需求.下面介绍大 ...

  9. SQL Server服务器上需要导入Excel数据的必要条件

    SQL Server服务器上需要导入Excel数据,必须安装2007 Office system 驱动程序:数据连接组件,或者Access2010的数据库引擎可再发行程序包,这样就不必在服务器上装Ex ...

随机推荐

  1. JSP HTML 各种 乱码 解决方法|jsp include html乱码|include 乱码|MyEclipse 中文乱码

    笔者花了一整天研究这个问题 .最终解决了所有的中文乱码问题. 不用 写 过滤器,不用改 tomcat 的配置文件 笔者使用的 软件是  MyEclipse2013 professional 版 JSP ...

  2. JVM(2) Java内存溢出异常

    在Java虚拟机运行时数据区中,除了程序计数器之外,虚拟机栈.本地方法栈.方法区和Java堆都有发生OutOfMemoryError(简称OOM)异常的可能. 一.Java堆溢出 Java堆用于存储对 ...

  3. Java多线程编程(四)Lock的使用

    一.使用ReentrantLock类 在Java多线程中,可以使用synchronized关键字来实现线程之间的同步互斥,但ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大, ...

  4. Spring(二)装配Spring Bean

    控制反转的概念:控制反转是一种通过描述(在Java中或者是XML或者注解)并通过第三方去产生或获取特定对象的方式. 在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependenc ...

  5. StackView在Android的应用

    StackView是AdapterViewAnimator的子类,它用于显示Adapter提供的一系列View.StackView将会以“堆叠”的方式来显示多个列表项.为了控制StackView现实的 ...

  6. django-URL匹配(二)

    1.新建django项目 django-admin startproject newwebsite 2.建立app 在newwebsite目录下:python manage.py startapp b ...

  7. Python调试工具

    1. 日志 通过日志或者print来打印变量.必要时可以打印locals()和globals() 建议使用logging.debug()来代替print,这样到了正式环境,就可以统一删除这些日志. 2 ...

  8. malloc面试题目(转) - [C++]

    试题4: void GetMemory( char *p ){ p = (char *) malloc( 100 );} void Test( void ) { char *str = NULL; G ...

  9. 论RSA算法的重要性 -RSA 简介

    地球上最重要的算法 (这个说法似乎有点夸张了,但是当你了解了RSA算法后,就觉得不夸张了.) 如果没有 RSA 算法,现在的网络世界毫无安全可言,也不可能有现在的网上交易.上一篇文章 ssh 协议为什 ...

  10. Linux系统 multitail 同时跟踪查看多个日志文件

    一.问题描述: 平时我们在排查问题的时候往往需要查看日志文件来定位问题,有些程序可能关联的多个程序,因此需要打开多个窗口使用 tailf 或者tail -f 方式查看日志 但是需要不停的切换窗口来看不 ...