應用系統開發中少不了跟Excel打交道,基於NPOI開發了ExcelPatternTool,與目前主流框架對比ExcelPatternTool著重單元格樣式的控制,對於初始資料匯入、報表匯出等簡單的Excel功能提升易用性。
ExcelPatternTool
開箱即用的Excel工具包。
Excel資料校驗,資料匯入,以及自定義樣式填充資料匯出到Excel文件。
功能
可設定列屬性,包括樣式,公式,註解;
可配置規則獨立設定單元格樣式;
可配置規則對Excel校驗,包括數值校驗和公式校驗,內建Lambda表示式和正規表示式兩個預設的校驗器;
可擴充套件的介面封裝和元件。
特點:
提供獨立Excel校驗工具;
提供Cli版本和帶UI(WPF)版本的程式;
提供ODBC擴充套件;
基於json檔案或型別+成員屬性(Attribute)的配置方式。
快速開始
在專案中引用ExcelPatternTool.Core
dotnet add package ExcelPatternTool.Core
從Excel匯入
Importer import = new Importer();
import.LoadXlsx(File.ReadAllBytes(filePath)); //匯入xlsx檔案
// or
import.LoadXls(File.ReadAllBytes(filePath)); //或匯入xls檔案
var importOption = new ImportOption<T>(0, 0);
var result = import.Process<T>(importOption).ToList()
Console.WriteLine(result); //匯入完成!
匯出Excel
IList<T> src = ... //準備資料
Exporter exporter = new Exporter();
exporter.DumpXlsx(filePath); //匯出xlsx檔案
// or
exporter.DumpXls(filePath); //或匯出xls檔案
var exportOption = new ExportOption<T>(0);
var issuccess = exporter.Process(src, exportOption); //匯出完成!
使用說明
編輯你的C#類,此類將作為ExcelPatternTool匯入匯出功能的承載實體型別,繼承自IExcelEntity
常規型別
常規型別是C#基本資料型別,直接輸出的為單元格值
可定義 string
, DateTime
,int
,double
,bool
高階型別
使用高階型別匯入時不光讀取資料,還將讀取單元格細節,匯出至Excel時,將保留這些細節。
高階型別是繼承自IAdvancedType的類,往往是一個泛型,它的型別引數為常規型別,對應實際的單元格值。
高階型別有:"包含註解","包含樣式","包含公式","全包含"型別。
- ICommentedType: 包含單元格註解;
- IStyledType: 包含單元格樣式;
- IFormulatedType: 包含單元格公式的物件;
- IFullAdvancedType: 包含了單元格註解,樣式,公式。
Importable註解
-
Order 列序號為此列在Excel中的編號,從0開始,即A列對應0,B列對應1 ...
-
Ignore 為True時將忽略這一列,等效於ExcelEntity無此屬性
Exportable註解
-
Order 列序號為此列在Excel中的編號,從0開始,即A列對應0,B列對應1 ...
-
Name 列名稱,將指定匯出時的該列第一行名稱
-
Ignore 為True時將忽略這一列,等效於ExcelEntity無此屬性
-
Format 指定單元格格式,格式約定請參考Excel 自定義單元格格式
-
Type: 單元格型別, Exportable中可指定Type型別的為
值 含義 Any
自定義 Text
文字 Numeric
數值 Date
時間 Bool
布林值 若不指定則根據屬性型別自動判斷
IImportOption匯入選項
- EntityType 指定一個實體型別,將使用此型別中的屬性作為匯入列
- SheetName 指定匯入的Sheet名稱,若不指定將匯入第SheetNumber個Sheet
- SheetNumber 指定匯入的Sheet編號,從0開始。
- SkipRows 指定跳過的行數,從0開始。
IExportOption匯出選項
- EntityType 指定一個實體型別,將使用此型別中的屬性作為匯出列
- SheetName 指定匯出的Sheet名稱,預設
Sheet1
- SkipRows 指定跳過的行數,從0開始。
- GenHeaderRow 指定是否生成表頭行,預設為False
- StyleMapperProvider 指定樣式對映器型別
單元格樣式
樣式支援文字顏色、背景顏色、邊框顏色、字型、字號、加粗、下劃線、斜體、刪除線等。
填充規則支援全域性樣式,列樣式,以及根據樣式對映器的規則填充單元格獨立樣式。
單元格透過StyleMetadata樣式後設資料定義樣式,樣式後設資料包括:
- FontColor 字型顏色
- FontName 字型名稱
- FontSize 字型大小(單位px)
- BorderColor 邊框顏色
- BackColor 背景顏色
- IsItalic 是否斜體
- IsBold 是否加粗
- IsStrikeout 是否刪除線
- FontUnderlineType 下劃線型別
- FontSuperScript 上標下標
StyleMapping樣式對映
樣式對映器用於將實體型別屬性對映為單元格樣式,可自定義實現,也可使用內建的樣式對映器。
- Target 指定樣式對映的目標屬性,可選Value單元格值或Formula單元格公式
- Convention 指定規則,預設的規則有
LambdaExpression
和RegularExpression
,分別對應Lambda表示式和正規表示式 - Expression 指定表示式內容
- MappingConfig 指定表示式結果對應的樣式後設資料
自定義樣式:
透過繼承StyleMapperProvider類,重寫GetStyleMappingContainers方法,返回的字典稱之為樣式對映容器
,作用是將規則對應的數值與樣式一一對應。
下面例子說明當“體溫”列中的資料超過36.5時,將字型顏色設定為紅色,否則為黑色。
public override Dictionary<string, StyleMapping> GetStyleMappingContainers()
{
return new Dictionary<string, StyleMapping>
{
"體溫",
new StyleMapping()
{
Target = Target.Value,
Convention = "LambdaExpression",
Expression = "{value}>36.5",
MappingConfig = new Dictionary<object, StyleMetadata>
{
{ true, new StyleMetadata(){ FontColor="Red"} } ,
{ false, new StyleMetadata(){ FontColor="Black"} }
}
}
}
}
建立後將匯出選項的StyleMapperProvider指定為該樣式對映器型別
使用資料庫作為資料來源
- 若涉及資料庫匯入匯出,請使用
Table
標籤指定表名稱, 使用Key
標籤指定主鍵型別,無鍵實體型別請使用Keyless
詳情請參考EFCore官方文件https://docs.microsoft.com/zh-cn/ef/core/modeling/
示例
Sample1:不同型別欄位匯出
假設某類中有如下欄位
public class WriteRowTestEntity : IExcelEntity
{
[Exportable(ignore: true)]
public long RowNumber { get; set; }
[Exportable("日期", Order = 1, Format = "yyyy\"年\"m\"月\"d\"日\";@")]
public DateTime DateTimeValue { get; set; }
[Exportable("整數", Order = 2)]
public int IntValue { get; set; }
[Exportable("小數", Order = 3)]
public double DoubleValue { get; set; }
[Exportable("布林值", Order = 4)]
public bool BoolValue { get; set; }
[Exportable("公式", Order = 7)]
public FormulatedType<int> IntWithFormula { get; set; }
}
匯出時日期按照給定格式生成,整數、小數、布林值根據型別自動判斷,公式將匯出公式內容。
Sample2:高階型別匯入和匯出
假設某類中有如下欄位
public class AdvancedTypeTestEntity : IExcelEntity
{
[Exportable(ignore: true)]
[Importable(ignore: true)]
public long RowNumber { get; set; }
[Exportable("全", Order = 4)]
[Importable(0)]
public FullAdvancedType<string> StringWithFullValue { get; set; }
}
StringWithFullValue將在匯入時儲存單元格的註解,樣式,公式,以及值。匯出時按照原樣匯出。
Sample3:員工健康體檢
假設某類中有如下欄位
public class EmployeeHealthEntity : IExcelEntity
{
[Exportable(Ignore = true)]
public long RowNumber { get; set; }
[Importable(0)]
[Exportable("姓名")]
public string ClientName { get; set; }
[Importable(1)]
[Exportable("收縮壓")]
public string BloodPressure2 { get; set; }
[Importable(2)]
[Exportable("舒張壓")]
public string BloodPressure1 { get; set; }
[Importable(3)]
[Exportable("體溫")]
public string Temperature { get; set; }
}
自定義樣式對映器EmployeeHealthEntityStyleMapperProvider類,重寫獲取樣式容器GetStyleMappingContainers方法,
內容如下:
public class EmployeeHealthEntityStyleMapperProvider : StyleMapperProvider
{
public override Dictionary<string, StyleMapping> GetStyleMappingContainers()
{
var result = new Dictionary<string, StyleMapping>
{
{
"體溫",
new StyleMapping()
{
Target = Target.Value,
Convention = "LambdaExpression",
Expression = "{value}>=36.5",
MappingConfig = new Dictionary<object, StyleMetadata>
{
{ true, new StyleMetadata(){ FontColor="Red"} } ,
{ false, new StyleMetadata(){ FontColor="Black"} }
}
}
},
{
"收縮壓",
new StyleMapping()
{
Target = Target.Value,
Convention = "BloodPressureResultExpression",
MappingConfig = new Dictionary<object, StyleMetadata>
{
{ "偏低異常", new StyleMetadata(){ FontColor="Orange"} } ,
{ "偏高異常", new StyleMetadata(){ FontColor="Red"} },
{ "正常", new StyleMetadata(){ FontColor="Black"} }
}
}
},
{
"舒張壓",
new StyleMapping()
{
Target = Target.Value,
Convention = "BloodPressureResultExpression",
MappingConfig = new Dictionary<object, StyleMetadata>
{
{ "偏低異常", new StyleMetadata(){ FontColor="Orange"} } ,
{ "偏高異常", new StyleMetadata(){ FontColor="Red"} },
{ "正常", new StyleMetadata(){ FontColor="Black"} }
}
}
},
};
return result;
}
重寫InitConventions將血壓的樣式對映規則定義為BloodPressureResultExpression,並新增到基類的樣式對映規則中,內容如下:
public override Dictionary<string, StyleConvention> InitConventions()
{
var baseOne = base.InitConventions();
baseOne.Add("BloodPressureResultExpression", new StyleConvention(new Func<string, StyleMapping, object, StyleMetadata>((key, c, e) =>
{
StyleMetadata result = null;
var lambdaParser = new LambdaParser();
if (c == null)
{
return null;
}
var val = double.Parse((string)TryGetValue(key, e));
if (key == nameof(EmployeeHealthEntity.BloodPressure2))
{
if (val > 140)
{
result = c.MappingConfig["偏高異常"];
}
else if (val < 90)
{
result = c.MappingConfig["偏低異常"];
}
else
{
result = c.MappingConfig["正常"];
}
}
else if (key == nameof(EmployeeHealthEntity.BloodPressure1))
{
if (val > 90)
{
result = c.MappingConfig["偏高異常"];
}
else if (val < 60)
{
result = c.MappingConfig["偏低異常"];
}
else
{
result = c.MappingConfig["正常"];
}
}
return result;
})));
return baseOne;
}
}
工具
- 此工具能將C#程式碼,轉換成使用語法工廠構造器(SyntaxFactory)生成等效語法樹程式碼
已知問題
作者資訊
作者:林小
郵箱:jevonsflash@qq.com
License
The MIT License (MIT)