基於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生成配置
- 可以可存入一般關係型資料庫的資料生成配置