ExcelReader.cs 3.2 KB

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