From 811890cbfc662c8126b3325dd100ef6ff3ce3a8a Mon Sep 17 00:00:00 2001
From: Max Zheng <34936931+maxzh1999tw@users.noreply.github.com>
Date: Sun, 10 Dec 2023 10:55:01 +0800
Subject: [PATCH] =?UTF-8?q?ClosedXML=20=E4=BE=9D=E8=B3=B4=E7=89=88?=
=?UTF-8?q?=E6=9C=AC=E8=A3=9C=E4=B8=8A=20TableThemeShader=EF=BC=8C?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=8C=AF=E8=AA=A4=E8=99=95=E7=90=86=E7=AF=84?=
=?UTF-8?q?=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Excely.ClosedXML/Shaders/ErrorMarkShader.cs | 1 -
Excely.ClosedXML/Shaders/TableThemeShader.cs | 100 ++++++++++++++++++
.../Exemples/SimpleClassListToXlsxExemple.cs | 2 +-
.../XlsxImportErrorHandlingExemple.cs | 99 +++++++++++++++++
Excely.Example.Console/Program.cs | 2 +-
5 files changed, 201 insertions(+), 3 deletions(-)
create mode 100644 Excely.ClosedXML/Shaders/TableThemeShader.cs
create mode 100644 Excely.Example.Console/Exemples/XlsxImportErrorHandlingExemple.cs
diff --git a/Excely.ClosedXML/Shaders/ErrorMarkShader.cs b/Excely.ClosedXML/Shaders/ErrorMarkShader.cs
index 044c46b..1832d31 100644
--- a/Excely.ClosedXML/Shaders/ErrorMarkShader.cs
+++ b/Excely.ClosedXML/Shaders/ErrorMarkShader.cs
@@ -18,7 +18,6 @@ public class ErrorMarkShader : XlsxShaderBase
public XLColor TextColor { get; set; } = XLColor.Red;
/// 匯入錯誤資料
- /// Comment 作者(不得為空)
public ErrorMarkShader(Dictionary errorCells)
{
CellErrors = errorCells;
diff --git a/Excely.ClosedXML/Shaders/TableThemeShader.cs b/Excely.ClosedXML/Shaders/TableThemeShader.cs
new file mode 100644
index 0000000..4edcec9
--- /dev/null
+++ b/Excely.ClosedXML/Shaders/TableThemeShader.cs
@@ -0,0 +1,100 @@
+using ClosedXML.Excel;
+using System.Drawing;
+
+namespace Excely.ClosedXML.Shaders
+{
+ ///
+ /// 將一段範圍內的儲存格視為表格,並為其套上表格造型。
+ ///
+ public class TableThemeShader : XlsxShaderBase
+ {
+ ///
+ /// 表格左上角的儲存格座標。
+ ///
+ public CellLocation StartCell { get; set; } = new(0, 0);
+
+ ///
+ /// 表頭高度。
+ ///
+ public int SchemaHeight { get; set; } = 1;
+
+ ///
+ /// 表格寬度。
+ ///
+ public int TableWidth { get; set; }
+
+ ///
+ /// 表格高度。
+ ///
+ public int TableHeight { get; set; }
+
+ ///
+ /// 表格主題。
+ ///
+ public TableTheme Theme { get; set; } = TableTheme.Default;
+
+ public TableThemeShader() { }
+
+ /// 表格寬度(0為自適應)
+ /// 表格高度(0為自適應)
+ public TableThemeShader(int tableWidth, int tableHeight)
+ {
+ TableWidth = tableWidth;
+ TableHeight = tableHeight;
+ }
+
+ protected override void ExcuteOnWorksheet(IXLWorksheet worksheet)
+ {
+ var tableWidth = TableWidth;
+ if(TableWidth == 0)
+ {
+ tableWidth = worksheet.LastColumnUsed().ColumnNumber();
+ }
+
+ var tableHeight = TableHeight;
+ if (TableHeight == 0)
+ {
+ tableHeight = worksheet.LastRowUsed().RowNumber();
+ }
+
+ // 設定標題的背景色和文字色
+ var header = worksheet.Range(StartCell.Row + 1, StartCell.Column + 1, StartCell.Row + SchemaHeight, StartCell.Column + tableWidth);
+ header.Style.Fill.BackgroundColor = XLColor.FromColor(Theme.HeaderBackgroundColor);
+ header.Style.Font.FontColor = XLColor.FromColor(Theme.HeaderTextColor);
+ header.Style.Font.Bold = true;
+
+ // 給整個表格設定邊框色
+ var table = worksheet.Range(StartCell.Row + 1, StartCell.Column + 1, StartCell.Row + tableHeight, StartCell.Column + tableWidth);
+ table.Style.Border.OutsideBorder = table.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
+ table.Style.Border.OutsideBorderColor = table.Style.Border.InsideBorderColor = XLColor.FromColor(Theme.BorderColor);
+ }
+ }
+
+ ///
+ /// 用於表達表格主題的結構。
+ ///
+ public struct TableTheme
+ {
+ ///
+ /// 表頭背景色。
+ ///
+ public Color HeaderBackgroundColor { get; set; }
+
+ ///
+ /// 表頭文字顏色。
+ ///
+ public Color HeaderTextColor { get; set; }
+
+ ///
+ /// 邊框顏色。
+ ///
+ public Color BorderColor { get; set; }
+
+ public static TableTheme Default => new()
+ {
+ HeaderBackgroundColor = Color.FromArgb(68, 114, 196),
+ HeaderTextColor = Color.White,
+ BorderColor = Color.FromArgb(68, 114, 196),
+ };
+ }
+}
\ No newline at end of file
diff --git a/Excely.Example.Console/Exemples/SimpleClassListToXlsxExemple.cs b/Excely.Example.Console/Exemples/SimpleClassListToXlsxExemple.cs
index 7a4639f..2252224 100644
--- a/Excely.Example.Console/Exemples/SimpleClassListToXlsxExemple.cs
+++ b/Excely.Example.Console/Exemples/SimpleClassListToXlsxExemple.cs
@@ -47,7 +47,7 @@ public static void Demo()
PropertyValueSettingPolicy = (p, value) => p.Name switch
{
nameof(SimpleClass.DateTimeField) => value != null ? DateTime.Parse(value.ToString()) : null,
- nameof(SimpleClass.BoolField) => value != null ? value == "是" : null,
+ nameof(SimpleClass.BoolField) => value != null ? value?.ToString() == "是" : null,
_ => value
},
};
diff --git a/Excely.Example.Console/Exemples/XlsxImportErrorHandlingExemple.cs b/Excely.Example.Console/Exemples/XlsxImportErrorHandlingExemple.cs
new file mode 100644
index 0000000..b0564d4
--- /dev/null
+++ b/Excely.Example.Console/Exemples/XlsxImportErrorHandlingExemple.cs
@@ -0,0 +1,99 @@
+using ClosedXML.Excel;
+using Excely.ClosedXML.Shaders;
+using Excely.ClosedXML.Workflows;
+using Excely.Example.Console.Models;
+using Excely.Example.Console.Utilities;
+using Excely.Shaders;
+using Excely.TableConverters;
+using Excely.TableFactories;
+using Excely.Workflows;
+
+namespace Excely.Example.Console.Exemples
+{
+ internal class XlsxImportErrorHandlingExemple
+ {
+ private static IEnumerable GetList()
+ {
+ return new List()
+ {
+ new SimpleClass()
+ {
+ Id = 1,
+ StringField = "比較長的文字欄位111111111111111111",
+ DateTimeField = DateTime.Now,
+ BoolField = true,
+ },
+ new SimpleClass()
+ {
+ Id = 2,
+ StringField = "比較長的文字欄位222222222222222222",
+ DateTimeField = DateTime.Now,
+ BoolField = false,
+ },
+ };
+ }
+
+ private static XLWorkbook GetExampleWorkbook()
+ {
+ var list = GetList();
+ var exportOption = new ClassListTableFactoryOptions
+ {
+ PropertyNamePolicy = p => p.GetDisplayName(),
+ CustomValuePolicy = (p, obj) => p.Name switch
+ {
+ // 故意設定錯誤的日期格式
+ nameof(SimpleClass.DateTimeField) => obj.DateTimeField?.ToString("yyyy/yyyy/dd"),
+ nameof(SimpleClass.BoolField) => obj.BoolField == null ? null : (obj.BoolField.Value ? "是" : "否"),
+ _ => p.GetValue(obj)
+ },
+ };
+
+ var shaders = new IShader[]
+ {
+ new SchemaFilterShader(),
+ new CellFittingShader(),
+ };
+
+ var exporter = ExcelyExporter.FromClassList(exportOption, shaders);
+ return exporter.ToExcel(list);
+ }
+
+ public static void Demo()
+ {
+ using var excel = GetExampleWorkbook();
+ var worksheet = excel.Worksheets.First();
+ var importer = new XlsxImporter();
+ var errorDict = new Dictionary();
+
+ var importOption = new ClassListTableConverterOptions
+ {
+ PropertyNamePolicy = p => p.GetDisplayName(),
+ PropertyValueSettingPolicy = (p, value) => p.Name switch
+ {
+ nameof(SimpleClass.BoolField) => value != null ? value?.ToString() == "是" : null,
+ _ => value
+ },
+ ErrorHandlingPolicy = (cellLocation, obj, p, value, ex) =>
+ {
+ switch (p.Name)
+ {
+ case nameof(SimpleClass.DateTimeField):
+ errorDict.Add(cellLocation, "錯誤的日期格式");
+ break;
+ default:
+ errorDict.Add(cellLocation, ex.Message);
+ break;
+ };
+ return true;
+ }
+ };
+
+ var importedList = importer.ToClassList(worksheet, importOption);
+ new ErrorMarkShader(errorDict).Excute(worksheet);
+ new CellFittingShader().Excute(worksheet);
+ new SchemaFilterShader().Excute(worksheet);
+ new TableThemeShader().Excute(worksheet);
+ excel.SaveAs("XlsxImportErrorHandlingExemple.xlsx");
+ }
+ }
+}
diff --git a/Excely.Example.Console/Program.cs b/Excely.Example.Console/Program.cs
index 21fab20..120f034 100644
--- a/Excely.Example.Console/Program.cs
+++ b/Excely.Example.Console/Program.cs
@@ -1,3 +1,3 @@
using Excely.Example.Console.Exemples;
-SimpleClassListToXlsxExemple.Demo();
\ No newline at end of file
+XlsxImportErrorHandlingExemple.Demo();
\ No newline at end of file