基于EPPlus和NPOI实现的Excel导入导出

x33g5p2x  于2021-11-16 转载在 其他  
字(3.7k)|赞(0)|评价(0)|浏览(267)

基于EPPlus和NPOI实现的Excel导入导出

CollapseNav.Net.Tool.Excel(NuGet地址)

太长不看

  • 导入

  • excel 文件流将会转为 ExcelTestDto 类型的集合

var config = new ReadConfig<ExcelTestDto>()
.Default(item => item.Field0, "233")
.Require("Field1", item => item.Field1)
.Add("Field3", item => item.Field3);
IEnumerable<ExcelTestDto> data = await config.EPPlusExcelToEntityAsync(excelStream);
  • 导出

  • ExcelTestDto 类型的集合将会转为 excel 文件流

var config = new ExportConfig<ExcelTestDto>(datas);
.Add("Field0", item => item.Field0)
.Add("Field1", item => item.Field1)
.Add("Field2", item => item.Field2 ? "Male" : "Female")
.Add("Field3", item => item.Field3);
Stream stream = await exportConfig.EPPlusExportAsync();

简单的使用方式就是上面那样, 至少在我需要的使用场景下是work的

NuGet包在上面

前言

为了方便自己处理一些有关 excel 的导入导出功能, 所以花了更长时间做了这个包

主要是我觉得计算各个未知的下标位置, 计算那些 0 1 2 3 4 5 实在是太麻烦

而且每换一个模板就要再搞一次, 可读性巨差

我想摆脱这样的地狱, 然后奋力挣扎了几下

思路可以看一下之前的文章

本章就讲怎么用这个包

Excel Data

使用的表格数据Demo, 暂时只能处理单行表头的简单excel

Field0Field1Field2Field3
23323Male233.33
112212Female123.23
23323Male233.33
112212Female123.23
............

How To Use

导入(Import/Read/...)

我碰到的使用场景中, 一般需要将Excel的数据转为系统中的某个实体

比如导入一个商品列表Excel,将这个列表转为 Goods 对象, 然后使用现成的 AddRange(IEnumerable<Goods> datas) 方法存到数据库中

基于以上这种 Excel-->Entitys 的使用场景设计了这一套东西

性能怎么样我就没测试了, 可能很拉了

假设我的实体长这样

public class ExcelTestDto
{
    public string Field0 { get; set; }
    public int Field1 { get; set; }
    public bool Field2 { get; set; }
    public double Field3 { get; set; }
}
1.BuildReadConfig

第一步先创建一个 ReadConfig 作为excel的读取配置

var config = new ReadConfig<ExcelTestDto>();

这个配置决定了之后将以什么方式读取哪些列

2.AddCellOptions

有了 ReadConfig 之后就需要添加具体的配置了

暂时提供了 Default``Require``Add 添加对 单个实体字段 的读取设置

  • Default

  • 不依赖表格数据,对 ExcelTestDto 中的属性统一添加默认值

config.Default(item => item.Field0, "233");
  • Require

  • 被 Require 的单元格不可为空, 否则在读取时会主动抛出异常

config.Require("Field1", item => item.Field1);
  • Add

  • 普通的添加单元格设置, 相对来说更加灵活一些

config.Add("Field3", item => item.Field3)

所有的excel单元格都会被读成 string

Require``Add 都可以使用 Func<string, object> 委托自定义对读取单元格的处理

由于是委托, 你可以做很多操作, 但比较容易影响性能, 最好不要写复杂的耗时的委托

config.Add("Field1", item => item.Field1, item =>
{
    var numCellData = int.Parse(item);
    numCellData += 2333;
    return numCellData;
});

以上操作都会返回 ReadConfig , 所以 强烈推荐 写成以下的调用

var config = new ReadConfig<ExcelTestDto>()
.Default(item => item.Field0, "233")
.Require("Field1", item => item.Field1)
.Add("Field3", item => item.Field3)
;

同时提供了对应的 DefaultIf``RequireIf``AddIf 方法, 用来根据不同的条件添加不同的配置

3.AddInit

偶尔会有在一行数据读取完之后计算点什么的需求, 比如综合学生的各科成绩打个等第, 所以提供一个 AddInit 方法, 通过传入一个 Func<T, T> 来搞点事情

config.AddInit(item =>
{
    item.Field0 += "23333";
    // 一些属性的初始化也可以在这边做,代替 Default 也是可以的
    item.Field2 = false;
    return item;
});
4.ConvertExcel

配置完成之后就可以使用 EPPlusExcelToEntityAsync 将对应的excel转为实体集合

// 如果excel是个文件流
IEnumerable<ExcelTestDto> data = await config.EPPlusExcelToEntityAsync(excelStream);

除了流, 也支持其他的参数

  • string filepath

  • 简单质朴的物理文件路径, 将直接读取物理路径上的excel文件

  • ExcelPackage pack

  • EPPlusExcelPackage, 一般需要手动创建

  • ExcelWorksheet sheet

  • EPPlusExcelWorksheet, 一般需要手动创建

导出(Export/...)

有的时候总是会有人需要把系统里面的列表数据导出成 Excel

然后像个傻逼一样再导回到系统里面去

所以相对导入又做了个导出功能, 两者相似度比较高

1.BuildExportConfig

建个导出配置 ExportConfig

// datas 为 ExcelTestDto集合
var config = new ExportConfig<ExcelTestDto>(datas);

由于导出比较简单粗暴, 所以提供了一个 GenDefaultConfig 可以直接 根据泛型生成 Config (大概不算好用)

2.AddCellOption

由于导出比较简单粗暴, 所以就只有一个 AddAddIf 方法添加单元格设置(虽然是两个)

config
.Add("Field0", item => item.Field0)
.Add("Field1", item => item.Field1)
.Add("Field2", item => item.Field2 ? "Male" : "Female")
.Add("Field3", item => item.Field3);
3.GenerateExcel

使用 EPPlusExportAsync 生成 Excel

// 新版本应该已经支持无参导出为流
// Stream stream = await exportConfig.EPPlusExportAsync();
Stream stream = await exportConfig.EPPlusExportAsync(someStream);

方法会返回一个流, 拿到流之后可以去做你们想做的事情...

也可以传入一个物理路径(string 类型), 这样就会在指定的位置生成excel

TODO

  • [x] 无参导出

  • [ ] 合并相同的导入配置

  • [ ] 考虑添加错误处理

  • [ ] 测试性能问题

  • [ ] 根据配置生成导入导出配置

  • 根据泛型的属性生成配置

  • 根据attribute生成配置

  • 可以可存入一般关系型数据库的数据生成配置

相关文章