基於EPPlus和NPOI實現的Excel導入導出
基於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);
- excel 文件流將會轉為
- 導出
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
Field0 | Field1 | Field2 | Field3 |
---|---|---|---|
233 | 23 | Male | 233.33 |
1122 | 12 | Female | 123.23 |
233 | 23 | Male | 233.33 |
1122 | 12 | Female | 123.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
EPPlus
的ExcelPackage
, 一般需要手動創建
ExcelWorksheet sheet
EPPlus
的ExcelWorksheet
, 一般需要手動創建
導出(Export/…)
有的時候總是會有人需要把系統裏面的列表數據導出成 Excel
然後像個傻逼一樣再導回到系統裏面去
所以相對導入又做了個導出功能, 兩者相似度比較高
1.BuildExportConfig
建個導出配置 ExportConfig
// datas 為 ExcelTestDto集合
var config = new ExportConfig<ExcelTestDto>(datas);
由於導出比較簡單粗暴, 所以提供了一個 GenDefaultConfig
可以直接 根據泛型生成 Config (大概不算好用)
2.AddCellOption
由於導出比較簡單粗暴, 所以就只有一個 Add
和 AddIf
方法添加單元格設置(雖然是兩個)
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生成配置
- 可以可存入一般關係型數據庫的數據生成配置