-
Notifications
You must be signed in to change notification settings - Fork 1
開始使用 Excely
本套件尚未發布,暫時無法透過 Nuget 安裝。 請下載此專案並以專案參考形式或編譯為 .dll 檔以使用本套件。
以下以 EPPlus.LGPL 依賴版本,進行 Excel 匯入、匯出的示範。
您所要做的第一件事是建立一個 Exporter,為此您需要引用 Excely.Workflows
命名空間。
Exporter 是我們為您包裝過後的類別,用以簡化匯出過程中的繁雜流程。
現在您可以透過 ExcelyExporter
快速建立一個 Exporter,比如以下所示:
var exporter = ExcelyExporter.FromClassList<Student>();
FromClassList<Student>()
代表我們要建立一個接收物件列表(準確來說是 IEnumerable)參數的匯出工具。
這個函式有許多參數,我們稍後再細看。現在,讓我們試著匯出一個基本的列表:
var students = new List<Student>()
{
new Student(0, "Test1", DateTime.Now),
new Student(1, "Test2", DateTime.Now),
};
var exporter = ExcelyExporter.FromClassList<Student>();
using var excel = exporter.ToExcel(students);
這樣就完成了一份 Excel 的匯出。
現在我們回頭看看 FromClassList
的參數:
-
propertyShowPolicy
- 決定 Property 是否要成為匯出的欄位 -
propertyNamePolicy
- 決定 Property 代表的欄位名稱(表頭顯示文字) -
propertyOrderPolicy
- 決定 property 排列的順序 -
customValuePolicy
- 決定欄位寫入的值 -
shaders
- 匯出後用於調整結果的執行單元
Policy 結尾的參數是以 Function 的方式傳入,用以決定匯出邏輯。他們都可以是 null,代表以預設行為匯出, 但接下來讓我們動點手腳...
假設我們想讓表頭改為中文,Student.Id 隱藏不匯出,名字排在生日的後面,日期改採 yyyy/MM/dd
格式,則可以這樣做:
var exporter = ExcelyExporter.FromClassList<Student>(
propertyShowPolicy: p => p.Name != nameof(Student.Id),
propertyNamePolicy: p => p.Name switch
{
nameof(Student.Name) => "名字",
nameof(Student.Birthday) => "生日",
_ => string.Empty
},
customValuePolicy: (student, p) => p.Name switch
{
nameof(Student.Birthday) => student.Birthday.ToString("yyyy/MM/dd"),
_ => p.GetValue(student)
});
這會需要您有些許映射與委派的基礎概念,搭配上 Lambda
與 switch 運算式
,可以非常容易的修改匯出邏輯。
至於 shaders
參數則可以傳入用於調整匯出結果的執行單元,比如可以為表頭加上篩選的 SchemaFilterShader
、自適應儲存格大小的 CellFittingShader
等等。
使用方式如下:
var exporter = ExcelyExporter.FromClassList<Student>(
shaders: new IShader[] {
new CellFittingShader(),
new SchemaFilterShader(3)
});
更多關於 Shader 的資訊,請參考這裡(尚未撰寫)。
匯入與匯出類似,也需要建立 Importer,讓我們同樣引用 Excely.Workflows
命名空間。
建立 Importer 較為特別,需要分為兩段進行建立,第一次指定匯入來源,第二次指定目標結構。
var importer = new XlsxImporterBuilder().BuildForClassList<Student>();
透過建立 XlsxImporterBuilder
,我們指定匯入來源為 Xlsx 檔案,接著呼叫 BuildForClassList<Student>
來指名我們想將資料匯入至 IEnumerable<Student>
。
接著,我們將第一次匯出的 Excel 中的第一個工作表取出,用於當作匯入來源:
// 匯出為 Excel
var exporter = ExcelyExporter.FromClassList<Student>();
using var excel = exporter.ToExcel(students);
// 匯入為 List<Student>
var importer = new XlsxImporterBuilder().BuildForClassList<Student>();
var importResult = importer.Import(excel.Workbook.Worksheets.First());
這樣就完成了 Excel 的匯入。
我們同樣可以發現 BuildForClassList 中有許多參數可供選擇:
-
hasSchema
- 指示匯入的資料是否含有表頭。若有,則使用propertyNamePolicy
,否則使用propertyIndexPolicy
-
stopWhenError
- 指示當匯入發生錯誤(通常是型別不符)時是否中斷匯入過程 -
propertyNamePolicy
- 同匯出時,定義 Property 作為標頭的名稱。(這裡沒有反過來以表頭名稱獲得 Property 的原因是希望匯入、匯出能夠共用邏輯) -
propertyIndexPolicy
- 當資料沒有表頭時,以欄位順序解析對應的 Property -
customValuePolicy
- 決定如何將資料的值寫入至物件中 -
errorHandlingPolicy
- 決定當錯誤發生時的處理方式,以及是否忽略此錯誤
參數使用方式與匯出時類似,特別要注意的是 propertyNamePolicy
與 propertyIndexPolicy
不會同時被執行,而是根據 hasSchema
來決定呼叫哪一個邏輯。
接著來說說最複雜的 errorHandlingPolicy
參數,他需要傳遞5個引數,分別是
(錯誤儲存格座標
, 正在寫入的物件
, 正在解析的 Property
, 儲存格中的值
, 發生的錯誤
)
需要特別注意的是 正在寫入的物件
,由於解析正進行到一半,因次物件中的資料絕對不是完整的,
比如解析到第2個欄位時出錯,則第一個欄位對應的Property會有值,其餘欄位則為預設值。
最後,errorHandlingPolicy
需要回傳一個 bool,指名這次錯誤是否有被成功善後,
若回傳 true,則繼續進行下一個欄位的解析,
否則根據 stopWhenError
,若為 true,則中斷匯入;若為 false,則忽略這一 Row 資料,開始解析下一 Row。
以下是一個將錯誤紀錄下來,跳過該列,並繼續匯入其他資料的範例:
var cellErrors = new Dictionary<CellLocation, string>();
var importer = new XlsxImporterBuilder().BuildForClassList<Student>(
stopWhenError: false,
errorHandlingPolicy: (cell, student, prop, value, ex) =>
{
cellErrors.Add(cell, ex.ToString());
return false;
});
var importResult = importer.Import(excel.Workbook.Worksheets.First());