导出数据到Excel表格以及从Excel表格中读取数据是我们日常开发很多情况都会遇到的,这里或许只是导出一些简单的数据到excel,这里或许会按照一定的模板导出数据到excel,这里也可能需要从Excel中读取数据。为了避免重复性的劳动,这里本人结合开发中遇到情况,在基于Npoi操作Excel的情况进一步对Excel的操作进行封装,旨在更方便的开发,开箱即用,只需要短短几行代码即可实现。如果您需要使用这个包,可以在NuGet上搜索OpenDeepSpace.Npoi进行使用。
本人采用基于特性,以及基于Excel模板的方式实现了:
1.无模板数据导出到Excel
2.基于模板导出数据到Excel
3.从Excel读取数据

以下我将通过代码的形式来告诉你该如何使用他。由于以下所有的案列都是基于同一个输出对象。
首先将为大家介绍ExcelColumn特性的使用。如果某一个类的某些数据需要导出到Excel中,你就需要在类上打上ExcelColumn特性。
ExcelColumn特性有两个参数可以进行设置。

参数名 含义
colName 列名(输出到Excel中的列名)
colOrder 列顺序(该列在Excel中顺序)

源码见github:OpenDeepSpace.Npoi

例如下面这个输出对象 本文所有导出到Excel的数据都采用该对象

/// <summary>/// 泛指ExcelData数据输出对象/// </summary>public class ExcelDataOutDto{[ExcelColumn("唯一标识",1)]//通过ExcelColumn特性指定为需要输出到Excel的列,参数分别为列名,列排序/// <summary>/// Id/// </summary>public string Id { get; set; }[ExcelColumn("姓名", 2)]/// <summary>/// 姓名/// </summary>public string Name { get; set; }[ExcelColumn("年龄", 3)]/// <summary>/// 年龄/// </summary>public int Age { get; set; }[ExcelColumn("出生日期",4)]/// <summary>/// 出生日期/// </summary>public DateTime BirthDate { get; set; }/// <summary>/// 其他信息/// </summary>public string OtherInfo { get; set; }}

这是我定义的一些初始数据

List<ExcelDataOutDto> excelDataOutDtos = new List<ExcelDataOutDto>() {new ExcelDataOutDto(){Id=Guid.NewGuid().ToString(),Name="小张",Age=20,BirthDate=DateTime.Today.AddYears(-20),OtherInfo="我是小张,我不嚣张"},new ExcelDataOutDto(){Id=Guid.NewGuid().ToString(),Name="小李",Age=24,BirthDate=DateTime.Today.AddYears(-24),OtherInfo="面对疾风吧"},new ExcelDataOutDto(){Id=Guid.NewGuid().ToString(),Name="小吴",Age=27,BirthDate=DateTime.Today.AddYears(-27),OtherInfo="哈哈哈笑而不语"},};

无模板导出数据到Excel

无模板导出数据到指定路径

这里你只需简单的两行代码即可完成最简单数据导出到Excel

ExcelHandler excelHandler = new ExcelHandler();//构造一个ExcelHandler处理对象
excelHandler.exportObjectToExcel($@"D:\excelexport\{Guid.NewGuid().ToString("N")}.xlsx", excelDataOutDtos);//导出数据

导出的结果以及说明如下:

如果你不需要序号以及需要设置导出的日期格式

excelHandler.setIsSetOrder(false);//不设置序列号
excelHandler.getExcelDatePattern().setDatePattern("yyyy/MM/dd");//指定日期的格式化模式

如果需要进一步筛选需要导出的字段,即打了ExcelColumn特性的列不需要全部导出,可以加入如下代码:

 //指定导出列 默认只要写了ExcelColumn特性的都会导出,这里可以对ExcelColumn进行进一步筛选List<string> colNames = new List<string>();colNames.Add("姓名");colNames.Add("出生日期");ExcelHandler excelHandler = new ExcelHandler();excelHandler.exportObjectToExcel($@"D:\excelexport\{Guid.NewGuid().ToString("N")}.xlsx", excelDataOutDtos,colNames);

无模板导出到流

ExcelHandler excelHandler = new ExcelHandler();NpoiMemoryStream npoiMemoryStream=new NpoiMemoryStream();excelHandler.exportObjectToExcel(npoiMemoryStream, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"{Guid.NewGuid()}.xlsx");

根据模板导出到Excel

Excel模板的制作需要的一些规则:

Excel模板中的占位符 含义
datas 填在Excel的单元格表示数据开始位置
styles 填在Excel的单元格表示该列所有单元格的样式
defaultStyles 填在Excel的单元格表示单元格的默认样式
# 以#号开头紧接着包含英文 表示非规则的信息填充 一般用在头部或底部 例如#datetime
order 填在excel单元格中 指定序号占位符 可以以此来自定义序号列的名称

例如如下三个模板:
无头部底部模板:

有头部底部的模板:

有头部底部带序号的模板

模板不包含头部底部信息的导出

模板如下:

存在空列这里如果不设置空列数将整体先前移动,即会自动移动到A列开始

根据模板文件导出不包含头部底部信息到指定路径

ExcelHandler excelHandler = new ExcelHandler();
excelHandler.getExcelTemplate().setExcelColNums(4);//设置excel的列数
excelHandler.getExcelTemplate().setDataStartColNum(2);//设置数据开始列
excelHandler.exportObjectToExcelByTemplate(Path.Combine(@"ExcelTemplates/导出的数据模板无头部底部.xlsx"), $@"D:\excelexporttemplate\指定路径模板{Guid.NewGuid().ToString("N")}.xlsx", excelDataOutDtos);//Path.Combine表示模板文件是放在工程启动项目所在文件夹下面

根据模板文件导出不包含头部底部信息到流

ExcelHandler excelHandler = new ExcelHandler();
excelHandler.getExcelTemplate().setExcelColNums(4 );//设置excel的列数
//导出到流文件
NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();            excelHandler.exportObjectToExcelByTemplate(Path.Combine(@"ExcelTemplates/导出的数据模板无头部底部.xlsx"), npoiMemoryStream, excelDataOutDtos);
npoiMemoryStream.Seek(0, SeekOrigin.Begin);
return File(npoiMemoryStream, "application/stream", $"模板流文件无头部底部{Guid.NewGuid()}.xlsx");

根据模板文件流导出不包含头部底部信息到指定路径

public async Task<FileResult> ExportObjectToExcelByTemplate(IFormFile templateFormFile){var streamone=templateFormFile.OpenReadStream();ExcelHandler excelHandler = new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.getExcelTemplate().setDataStartColNum(2);//导出到指定路径excelHandler.exportObjectToExcelByTemplate(streamone, $@"D:\excelexportstreamtemplate\指定路径模板{Guid.NewGuid().ToString("N")}.xlsx", excelDataOutDtos);}

根据模板文件流导出不包含头部底部信息到流

public async Task<FileResult> ExportObjectToExcelByTemplate(IFormFile templateFormFile){var streamone=templateFormFile.OpenReadStream();//导出到流ExcelHandler excelHandler=new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.getExcelTemplate().setDataStartColNum(2);NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();excelHandler.exportObjectToExcelByTemplate(streamThree, npoiMemoryStream, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"模板流文件无头部底部{Guid.NewGuid()}.xlsx");}

导出数据结果如下:

模板包含头部底部信息的导出

模板如下:

根据模板导出包含头部底部信息到指定路径

 ExcelHandler excelHandler=new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4 );Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();//头部底部信息 key为#号后面的部分headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);excelHandler.exportObjectToExcelByTemplate(@"C:\Users\lenovo\Desktop\导出的数据模板含头部底部.xlsx", $@"D:\excelexporthftemplate\指定路径带头部底部模板{Guid.NewGuid().ToString("N")}.xlsx",headerAndFooterMaps,excelDataOutDtos);

根据模板导出包含头部底部信息到流

ExcelHandler excelHandler = new ExcelHandler();NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.exportObjectToExcelByTemplate(@"C:\Users\lenovo\Desktop\导出的数据模板含头部底部.xlsx",npoiMemoryStream, headerAndFooterMaps, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"模板流文件有头部底部{Guid.NewGuid()}.xlsx");}

根据模板文件流导出包含头部底部信息到指定路径

public async Task<FileResult> ExportObjectToExcelByTemplateIncludeHeaderAndFooter(IFormFile templateFormFile){var streamone = templateFormFile.OpenReadStream();Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);excelHandler.exportObjectToExcelByTemplate(streamone, $@"D:\excelexporthftemplate\指定路径模板{Guid.NewGuid().ToString("N")}.xlsx",headerAndFooterMaps, excelDataOutDtos);}

根据模板文件流导出包含头部底部信息到流

public async Task<FileResult> ExportObjectToExcelByTemplateIncludeHeaderAndFooter(IFormFile templateFormFile){var streamone = templateFormFile.OpenReadStream();Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);//导出到流excelHandler = new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();excelHandler.exportObjectToExcelByTemplate(streamone, npoiMemoryStream,headerAndFooterMaps, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"模板流文件有头部底部{Guid.NewGuid()}.xlsx");}

导出结果如下:

模板已经存在列名的导出

如果模板中已经存在列名,将不会使用ExcelColumn特性中的colName作为列名
模板如下:

根据模板导出存在列名包含头部底部信息到指定路径

ExcelHandler excelHandler = new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.setIsClasspath(false);//指定模板是否在工程路径下excelHandler.getExcelTemplate().setIsOrder(true);excelHandler.getExcelTemplate().setOrderName("排序号");//给序号列设置名称Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);excelHandler.exportObjectToExcelByTemplateHasColName(@"C:\Users\lenovo\Desktop\导出的数据模板含头部底部有列名.xlsx", $@"D:\excelexporthftemplate\指定路径带头部底部模板{Guid.NewGuid().ToString("N")}.xlsx", headerAndFooterMaps, excelDataOutDtos);

根据模板导出存在列名包含头部底部信息到流

ExcelHandler excelHandler = new ExcelHandler();NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.getExcelTemplate().insertOrder();excelHandler.getExcelTemplate().setOrderName("排序号");excelHandler.exportObjectToExcelByTemplateHasColName(@"C:\Users\lenovo\Desktop\导出的数据模板含头部底部有列名.xlsx", npoiMemoryStream, headerAndFooterMaps, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"模板流文件有头部底部{Guid.NewGuid()}.xlsx");

根据模板文件流导出存在列名包含头部底部信息到指定路径

public async Task<FileResult> ExportObjectToExcelHasColNameByStream(IFormFile templateFormFile){var streamone = templateFormFile.OpenReadStream();ExcelHandler excelHandler = new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.setIsClasspath(false);excelHandler.getExcelTemplate().setIsOrder(true);excelHandler.getExcelTemplate().insertOrder();excelHandler.getExcelTemplate().setOrderName("排序号");//给序号列设置名称Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);excelHandler.exportObjectToExcelByTemplateHasColName(streamone, $@"D:\excelexporthftemplate\指定路径带头部底部模板{Guid.NewGuid().ToString("N")}.xlsx", headerAndFooterMaps, excelDataOutDtos);}

根据模板文件流导出存在列名包含头部底部信息到流

public async Task<FileResult> ExportObjectToExcelHasColNameByStream(IFormFile templateFormFile){var streamone = templateFormFile.OpenReadStream();ExcelHandler excelHandler = new ExcelHandler();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.setIsClasspath(false);excelHandler.getExcelTemplate().setIsOrder(true);excelHandler.getExcelTemplate().insertOrder();excelHandler.getExcelTemplate().setOrderName("排序号");//给序号列设置名称Dictionary<string, object> headerAndFooterMaps = new Dictionary<string, object>();headerAndFooterMaps.Add("datetime", DateTime.Now);headerAndFooterMaps.Add("exporter", "OpenDeepSpace管理员");headerAndFooterMaps.Add("count", excelDataOutDtos.Count);NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();excelHandler.getExcelTemplate().setExcelColNums(4);excelHandler.getExcelTemplate().insertOrder();excelHandler.getExcelTemplate().setOrderName("排序号");excelHandler.exportObjectToExcelByTemplateHasColName(streamone, npoiMemoryStream, headerAndFooterMaps, excelDataOutDtos);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"模板流文件有头部底部{Guid.NewGuid()}.xlsx");}

导出结果如下:

从Excel导出数据到对象集合

这个是根据Excel列名对应ExcelColumn特性来进行导入。
Excel数据截图如下:

从Excel文件导出数据

 ExcelHandler excelHandler = new ExcelHandler();var excelDatas = excelHandler.exportExcelToObject<ExcelDataOutDto>(@"C:\Users\lenovo\Desktop\Excel数据导出到对象.xlsx");

从Excel流文件导出数据

public void ExportExcelToObjectByStream(IFormFile formFile){ExcelHandler excelHandler = new ExcelHandler();var excelDatas = excelHandler.exportExcelToObject<ExcelDataOutDto>(formFile.OpenReadStream());}

导出图片到Excel中

暂未实现

多Sheet的导出

暂未实现

注意:从1.1.0版本开始ExcelHandler变为ExcelHandle,并且新增合并单元格操作以及为DateTime字段指定时间格式 1.1.2版本增加基于列的合并特性

合并相同列以及指定Datetime格式化

public class ExcelDataOutDto{[ExcelColumn("唯一标识",1,MergeColumn =true)]//通过ExcelColumn特性指定为需要输出到Excel的列,参数分别为列名,列排序/// <summary>/// Id/// </summary>public string Id { get; set; }[ExcelColumn("姓名", 2,IsBaselineCol =true,MergeColumn =true)]/// <summary>/// 姓名/// </summary>public string Name { get; set; }[ExcelColumn("年龄", 3,MergeColumn =true)]/// <summary>/// 年龄/// </summary>public int Age { get; set; }[ExcelColumn("出生日期",4,DatePattern ="yyyy-MM-dd HHmmss")]//指定日期/// <summary>/// 出生日期/// </summary>public DateTime BirthDate { get; set; }/// <summary>/// 其他信息/// </summary>public string OtherInfo { get; set; }}

Excel导出效果如下:

增加数据验证特性

这里如果你需要对导入或导出的数据验证,在1.1.3版本中可以通过继承DataValidationAttribute特性,实现IsValid方法来完成数据的验证.目前还没有提供一些默认的验证特性,后续考虑提供。
如下代码:
实现数据验证特性

//不为空
public class NotNullAttribute:DataValidationAttribute{public override DataValidationResult? IsValid(object data){if (data == null || string.IsNullOrWhiteSpace(data.ToString()))return new DataValidationResult(ErrorMessage);return DataValidationResult.Success;}}
//最大长度
public class MaxLengthAttribute : DataValidationAttribute{public int MaxLength { get; set; }public override DataValidationResult IsValid(object data){if (data.ToString().Length > MaxLength)return new DataValidationResult(ErrorMessage);return DataValidationResult.Success;}}

使用数据验证特性:

 [NotNull(ErrorMessage ="姓名不能为空")][MaxLength(MaxLength =100, ErrorMessage ="姓名最大长度不能超过100个字符")][ExcelColumn("姓名", 2,IsBaselineCol =true,MergeColumn =true)]/// <summary>/// 姓名/// </summary>public string Name { get; set; }

版本1.1.7中增加基于ExcelSheetAttribute特性以及基于父子级递归关联方式的多Sheet导出(仅限基于非模板方式的导出,且原则上支持无限级)

版本1.1.7增加ExcelSheetAttribute特性

ExcelSheetAttribute特性可以使用在类上和属性上,可以设置SheetName,即表示指定类输出到的Sheet的名称。
使用在类上:表示该类对应的数据输出的Sheet的名称
使用在属性上:表示该属性是一个关联的Sheet导出,建议采用List

结合ExcelSheetAttribute实现基于父子级递归关联方式的多Sheet导出

例子如下:
三级关联例子

/// <summary>/// 泛指ExcelData数据输出对象/// </summary>[ExcelSheet(SheetName = "主数据")]public class ExcelDataOutDto{[ExcelColumn("唯一标识", 1, MergeColumn = true)]//通过ExcelColumn特性指定为需要输出到Excel的列,参数分别为列名,列排序/// <summary>/// Id/// </summary>public string Id { get; set; }//[NotNull(ErrorMessage = "姓名不能为空")]s//[MaxLength(MaxLength = 100, ErrorMessage = "姓名最大长度不能超过100个字符")][ExcelColumn("姓名", 2, IsBaselineCol = true, MergeColumn = true)]/// <summary>/// 姓名/// </summary>public string Name { get; set; }[ExcelColumn("年龄", 3, MergeColumn = true)]/// <summary>/// 年龄/// </summary>public int Age { get; set; }[ExcelColumn("出生日期", 4, DatePattern = "yyyy-MM-dd HHmmss")]/// <summary>/// 出生日期/// </summary>public DateTime BirthDate { get; set; }/// <summary>/// 其他信息/// </summary>public string OtherInfo { get; set; }/// <summary>/// 关联数据/// </summary>[ExcelSheet]public List<ExcelRelationDataOutDto> ExcelRelationDataOutDtos { get; set; }}[ExcelSheet(SheetName = "关联数据")]public class ExcelRelationDataOutDto{[ExcelColumn(ColOrder =1,ColName ="名称",MergeColumn =true,IsBaselineCol =true)]public string Name { get; set; }/// <summary>/// 关联子数据/// </summary>[ExcelSheet]public List<ExcelRelationDataRelationOutDto> RelationData { get; set; }}
/// <summary>/// <see cref="ExcelRelationDataOutDto"/>的关联子数据/// </summary>[ExcelSheet(SheetName = "孙子数据")]public class ExcelRelationDataRelationOutDto{[ExcelColumn(ColOrder = 1, ColName = "名称", MergeColumn = true, IsBaselineCol = true)]public string Name { get; set; }}

三级关联的数据

List<ExcelDataOutDto> excelDataOutDtos = new List<ExcelDataOutDto>() {new ExcelDataOutDto(){Id=Guid.NewGuid().ToString(),Name="小张",Age=20,BirthDate=DateTime.Today.AddYears(-20),OtherInfo="我是小张,我不嚣张",ExcelRelationDataOutDtos=new List<ExcelRelationDataOutDto>(){ new ExcelRelationDataOutDto(){ Name="小张关联"},new ExcelRelationDataOutDto(){ Name="小张关联"},new ExcelRelationDataOutDto(){ Name="小张关联3",//子数据的子数据RelationData =new List<ExcelRelationDataRelationOutDto>(){ new ExcelRelationDataRelationOutDto(){ Name="小张孙子数据"}}},}},new ExcelDataOutDto(){Id="b66f90b7-178b-11ed-98e5-00155d562808",Name="小李",Age=24,BirthDate=DateTime.Today.AddYears(-24),OtherInfo="面对疾风吧"},new ExcelDataOutDto(){Id="b66f90b7-178b-11ed-98e5-00155d562808",Name="小李",Age=24,BirthDate=DateTime.Today.AddYears(-24),OtherInfo="面对疾风吧八八八",ExcelRelationDataOutDtos=new List<ExcelRelationDataOutDto>(){new ExcelRelationDataOutDto(){ Name="小李关联",//子数据的子数据RelationData =new List<ExcelRelationDataRelationOutDto>(){new ExcelRelationDataRelationOutDto(){ Name="小李孙子数据"},new ExcelRelationDataRelationOutDto(){ Name="小李孙子数据"},new ExcelRelationDataRelationOutDto(){ Name="小李孙子数据2"}}}}},/*new ExcelDataOutDto(){Id=Guid.NewGuid().ToString(),Name="小红",Age=24,BirthDate=DateTime.Today.AddYears(-24),OtherInfo="面对疾风吧八八八"},*/new ExcelDataOutDto(){Id="b66f90b7-178b-11ed-98e5-00155d5s2808",Name="小吴",Age=27,BirthDate=DateTime.Today.AddYears(-27),OtherInfo="哈哈哈笑而不语",ExcelRelationDataOutDtos=new List<ExcelRelationDataOutDto>(){new ExcelRelationDataOutDto(){ Name="小吴关联"},new ExcelRelationDataOutDto(){ Name="小吴关联3"}}},new ExcelDataOutDto(){Id="b66f90b7-178b-11ed-98e5-00155d5s2808",Name="小吴",Age=27,BirthDate=DateTime.Today.AddYears(-27),OtherInfo="哈哈哈笑笑笑"},new ExcelDataOutDto(){Id="b66f90b7-178b-11ed-98e5-00155d5s2809",Name="",Age=27,BirthDate=DateTime.Today.AddYears(-27),OtherInfo="哈哈哈笑笑笑"},};

导出例子:

 /// <summary>/// 无模板导出数据到excel并返回流文件供下载/// </summary>/// <returns></returns>[HttpGet]public async Task<FileResult> ExportObjectToExcelToStream(){ExcelHandle ExcelHandle = new ExcelHandle();NpoiMemoryStream npoiMemoryStream = new NpoiMemoryStream();List<ExcelDataOutDto> excelDataOutDtosOver = new List<ExcelDataOutDto>();for (int i = 0; i < 10000; i++){excelDataOutDtosOver.AddRange(excelDataOutDtos);}ExcelHandle.exportObjectToExcel(npoiMemoryStream, excelDataOutDtosOver);npoiMemoryStream.Seek(0, SeekOrigin.Begin);return File(npoiMemoryStream, "application/stream", $"{Guid.NewGuid()}.xlsx");}

导出结果如下:


版本1.1.8

修复部分错误。数据验证错误信息ErrorMessage中增加 {row} 占位符,来实现行下标的错误数据的提示。
比如:

/// <summary>/// 部门/// </summary>[ColumnNotNull(ErrorMessage = "第{row}行数据:部门不能为空")][ExcelColumn(ColOrder = 1, ColName = "部门")]public string Department { get; set; }

测试结果如下如果部门列下对应的数据为空,就会抛出如下异常:

当然如果你想自己处理异常,抛出你自己定义的友好异常可以try catch捕获这个异常然后处理。

版本1.1.9 异常处理优化

这里我分为两种异常,一种是数据异常,一种是列名表头异常。

/// <summary>/// Npoi异常码/// </summary>public class NpoiExceptionCode{/// <summary>/// 数据异常/// </summary>public const int DataException = 1000;/// <summary>/// 列名异常/// </summary>public const int ColumnNameException = 2000;}

数据异常就是:数据验证的时候出现异常,通过NpoiException包裹
列名异常就是:读取Excel中的数据时,如果对应列名查找不到那么就会通过NpoiException包裹 ColumnNameException。

你可以通过try catch捕获它,然后来实现用自己的异常抛出处理。比如这样:

//读取文件中数据ExcelHandle excelHandle = new ExcelHandle();List<EmergencyWorkerInDto> emergencyWorkerInDtos = new List<EmergencyWorkerInDto>();using (var stream = file.OpenReadStream()){try{var fileContent = excelHandle.exportExcelToObject<EmergencyWorkerInDto>(stream,IsAutoSkipNullRow:false);if (fileContent.Count == 0)throw new FriendlyException("Excel文件中没有任何数据");foreach (var item in fileContent){item.ResponseLevelId = ResponseLevelId;emergencyWorkerInDtos.Add(item);}}catch (Exception ex){if (ex is NpoiException npoiException){if (npoiException.ExceptionCode == NpoiExceptionCode.ColumnNameException)throw new FriendlyException("Excel文件与模板不符合");elsethrow new FriendlyException(npoiException.Message);}else{throw new FriendlyException(ex.Message);}}}

注意对于文件中除了表头没有数据有两种:第一种是除了表头,其他没有单元格没有任何填充(包括单元格背景设置),这种是需要自己判断处理,如上throw new FriendlyException(“Excel文件中没有任何数据”);
还有一种就是单元格有填充但无数据,这种就不是空,如果设置了数据验证就会抛出异常。

C#基于Npoi通过特性的方式导出简单数据到Excel或基于特性以及基于Excel模板导出数据到Excel以及从Excel中把数据导入到对象中相关推荐

  1. 如何将skp文件中的模型导入到UE4中

    首先,skp文件是不能直接导入到UE4中的. 解决方法:用SketchUp(草图大师)打开skp文件,在SketchUp中将模型转换成fbx格式,然后再将模型导入UE4中 目录 1.打开skp文件 2 ...

  2. js给对象添加变量属性 js 更改对象中的属性名 数组对象中每个对象添加一个字段-map用法和forEarch用法

    js给对象添加变量属性 & js 更改对象中的属性名 & 数组对象中每个对象添加一个字段-map用法和forEarch用法 1.js给对象添加变量属性 1.js创建一个对象或者在原有对 ...

  3. 将dblp中的文件导入到endnote中

    将dblp中的文件导入到endnote中 复制要导入的论文题目到dblp中搜索 点击第一个按钮的第一个链接 跳转后页面点击cite 点击1 Endnote,然后点击2下载. 此时并没有下载文件,页面跳 ...

  4. 网络编程8/17——将dict.txt中的内容导入到数据库中

    目录 代码 运行结果 dict.txt 作业:将dict.txt中的内容导入到数据库中 注意: 导入后检查解释意思是否完整,双词性 中间有空格的单词 o'clock 代码 #include<st ...

  5. python中使用什么导入模块-Python中使用语句导入模块或包的机制研究

    这篇文章讨论了Python的from import *和from import *,它们怎么执行以及为什么使用这种语法(也许)是一个坏主意. 从一个模块导入全部 from import * means ...

  6. python 中matplotlib 画图导入到word中如何保证分辨率

    python 中利用matplotlib 画图导入到word中如何保证分辨率 在写论文时,如果是菜鸟级别,可能不会花太多时间去学latex,直接用word去写,但是这有一个问题,当我们用其他工具画完实 ...

  7. java中id name_关于DOM对象中的id与name的区别

    例1: value="admin"> id="un" name="username" value="silas"& ...

  8. 关于python中requests模块导入问题-python中requests模块的使用方法

    本文实例讲述了python中requests模块的使用方法.分享给大家供大家参考.具体分析如下: 在HTTP相关处理中使用python是不必要的麻烦,这包括urllib2模块以巨大的复杂性代价获取综合 ...

  9. 如何将数据库中的记录表导入到VC中

    具体步骤如下: 首先新建一个基于对话框的工程,在对话框CConnectDatabaseDialog中添加按钮:IDC_ScoreSequery,Caption:导入表,双击"导入表" ...

最新文章

  1. 学习笔记TF065:TensorFlowOnSpark
  2. Linux内核分析 - 网络[四]:路由表
  3. Fiddler 自定义规则编写
  4. 146. LRU Cache
  5. shell中执行hive命令错误:delimited by end-of-file (wanted `EOF')
  6. 使用docker-compose搭建AspNetCore开发环境
  7. 微信小程序上传大于4m_微信定制小程序开发
  8. oracle linux 图形化,Linux7图形化安装Oracle11g教程,亲测实用有效!
  9. abap object-oriented–使用事件
  10. NYOJ96 - n-1位数
  11. 什么软件画er图方便_ER模型怎么画?必备入门级模型图绘制软件
  12. 同IP不同端口导致cookie冲突的解决方法
  13. Azure vNet
  14. sMRI影像数据3维CNN卷积
  15. centos 6.9部署svn服务器和客户端(客户端含windows、linux版本)
  16. JQuery对联广告
  17. 葫芦书笔记----CNN和RNN
  18. 王者荣耀的技术修炼之路
  19. 人民邮电报丨智链助力北大荒大米实现区块链全生命周期追溯
  20. 游戏自定义金币单位换算管理类

热门文章

  1. Nginx 服务安装搭建
  2. 电脑重启后黑屏一直转圈无法进入桌面怎么办?
  3. HTML如何做出分割线效果
  4. 设计模式中介者模式-备忘录模式-状态模式
  5. Drools入门系列
  6. 我想要这样的生活:天上无霾,地下无霜
  7. 史上最口语化Arduino入门教程——1.3模拟IO口
  8. matlab中input输入多个数_你可能不知道的MATLAB操作技巧#第二话
  9. 优化算法——拟牛顿法之BFGS算法
  10. python线程池并发_python 并发编程多线程之进程池/线程池