ExcelReader.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using ClosedXML.Excel;
  2. namespace ExcelORM;
  3. public class ExcelReader
  4. {
  5. private readonly IXLWorkbook xlWorkbook;
  6. public bool SkipHidden { get; set; }
  7. public bool ObeyFilter { get; set; }
  8. public ExcelReader(string? path)
  9. {
  10. xlWorkbook = new XLWorkbook(path);
  11. }
  12. private IEnumerable<T> ProcessRows<T>(IEnumerable<IXLRow> rows, List<Mapping> mapping) where T : class, new()
  13. {
  14. var type = typeof(T);
  15. foreach (var row in rows)
  16. {
  17. if (SkipHidden && row.IsHidden) continue;
  18. var current = new T();
  19. foreach (var item in mapping)
  20. {
  21. if (item.Position == null || item.PropertyName == null) continue;
  22. var cell = row.Cell(item.Position.Value);
  23. if (cell == null || cell.Value.IsBlank) continue;
  24. var property = type.GetProperty(item.PropertyName);
  25. if (property == null) continue;
  26. current.SetPropertyValue(property, cell.Value);
  27. }
  28. yield return current;
  29. }
  30. }
  31. public IEnumerable<T> Read<T>(uint startFrom = 1, uint skip = 0) where T : class, new()
  32. {
  33. return xlWorkbook.Worksheets.SelectMany(worksheet => Read<T>(worksheet, startFrom, skip));
  34. }
  35. public IEnumerable<T> Read<T>(string? worksheetName, uint startFrom = 1, uint skip = 0) where T : class, new()
  36. {
  37. var worksheet = xlWorkbook.Worksheets.FirstOrDefault(x => x.Name.Equals(worksheetName, StringComparison.InvariantCultureIgnoreCase));
  38. if (worksheet == null) yield break;
  39. foreach (var value in Read<T>(worksheet, startFrom, skip))
  40. yield return value;
  41. }
  42. private IEnumerable<T> Read<T>(IXLWorksheet? worksheet, uint startFrom, uint skip) where T : class, new()
  43. {
  44. if (worksheet == null) yield break;
  45. var firstRow = worksheet.Row((int)startFrom);
  46. if (firstRow.IsEmpty())
  47. firstRow = worksheet.RowsUsed().First(x => x.RowNumber() > startFrom && !x.IsEmpty());
  48. var mapping = Mapping.MapProperties<T>(firstRow.CellsUsed());
  49. if (mapping == null) yield break;
  50. var rowsToProcess = (ObeyFilter && worksheet.AutoFilter.IsEnabled) switch
  51. {
  52. true => worksheet.AutoFilter.VisibleRows
  53. .Where(x => x.RowNumber() > firstRow.RowNumber())
  54. .Select(x => x.WorksheetRow()),
  55. false => worksheet.RowsUsed().Where(x => x.RowNumber() > firstRow.RowNumber())
  56. };
  57. rowsToProcess = rowsToProcess
  58. .Skip((int)skip);
  59. foreach (var item in ProcessRows<T>(rowsToProcess, mapping))
  60. yield return item;
  61. }
  62. }