|
@@ -0,0 +1,85 @@
|
|
|
|
+using ClosedXML.Excel;
|
|
|
|
+
|
|
|
|
+namespace ExcelORM;
|
|
|
|
+
|
|
|
|
+public class ExcelReader
|
|
|
|
+{
|
|
|
|
+ private readonly IXLWorkbook xlWorkbook;
|
|
|
|
+ public uint SkipFirstNRows { get; set; } = 1;
|
|
|
|
+ public bool SkipHidden { get; set; }
|
|
|
|
+ public bool ObeyFilter { get; set; }
|
|
|
|
+
|
|
|
|
+ public ExcelReader(string? path)
|
|
|
|
+ {
|
|
|
|
+ xlWorkbook = new XLWorkbook(path);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private IEnumerable<T> ProcessRows<T>(IEnumerable<IXLRow> rows, List<Mapping> mapping) where T : class, new()
|
|
|
|
+ {
|
|
|
|
+ foreach (var row in rows)
|
|
|
|
+ {
|
|
|
|
+ if (SkipHidden && row.IsHidden) continue;
|
|
|
|
+ if (row.RowNumber() <= SkipFirstNRows) continue;
|
|
|
|
+
|
|
|
|
+ var current = new T();
|
|
|
|
+ foreach (var item in mapping)
|
|
|
|
+ {
|
|
|
|
+ if (item.Position == null || item.PropertyName == null) continue;
|
|
|
|
+
|
|
|
|
+ var cell = row.Cell(item.Position.Value);
|
|
|
|
+ if (cell == null || cell.Value.IsBlank) continue;
|
|
|
|
+
|
|
|
|
+ var property = current.GetType().GetProperty(item.PropertyName);
|
|
|
|
+ if (property == null) continue;
|
|
|
|
+
|
|
|
|
+ switch (property.PropertyType)
|
|
|
|
+ {
|
|
|
|
+ case Type _ when property.PropertyType == typeof(string):
|
|
|
|
+ property.SetValue(current, cell.Value.ToString());
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ yield return current;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public IEnumerable<T> Read<T>() where T : class, new()
|
|
|
|
+ {
|
|
|
|
+ foreach (var worksheet in xlWorkbook.Worksheets)
|
|
|
|
+ {
|
|
|
|
+ foreach (var value in Read<T>(worksheet))
|
|
|
|
+ yield return value;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public IEnumerable<T> Read<T>(string? worksheetName) where T : class, new()
|
|
|
|
+ {
|
|
|
|
+ var worksheet = xlWorkbook.Worksheets.FirstOrDefault(x => x.Name.Equals(worksheetName, StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
+ if (worksheet == null) yield break;
|
|
|
|
+
|
|
|
|
+ foreach (var value in Read<T>(worksheet))
|
|
|
|
+ yield return value;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public IEnumerable<T> Read<T>(IXLWorksheet? worksheet) where T : class, new()
|
|
|
|
+ {
|
|
|
|
+ if (worksheet == null) yield break;
|
|
|
|
+
|
|
|
|
+ var mapping = Mapping.MapProperties<T>(worksheet.FirstRowUsed().CellsUsed());
|
|
|
|
+ if (mapping == null) yield break;
|
|
|
|
+
|
|
|
|
+ if (ObeyFilter && worksheet.AutoFilter.IsEnabled)
|
|
|
|
+ {
|
|
|
|
+ foreach (var item in ProcessRows<T>(worksheet.AutoFilter.VisibleRows.Select(x => x.WorksheetRow()), mapping))
|
|
|
|
+ yield return item;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ foreach (var item in ProcessRows<T>(worksheet.RowsUsed(), mapping))
|
|
|
|
+ yield return item;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|