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. public IEnumerable<T> Read<T>(string? worksheetName, uint startFrom = 1, uint skip = 0) where T : class, new()
  33. {
  34. var worksheet = xlWorkbook.Worksheets.FirstOrDefault(x => x.Name.Equals(worksheetName, StringComparison.InvariantCultureIgnoreCase));
  35. if (worksheet == null) yield break;
  36. foreach (var value in Read<T>(worksheet, startFrom, skip))
  37. yield return value;
  38. }
  39. public IEnumerable<T> Read<T>(int worksheetIndex = 1, uint startFrom = 1, uint skip = 0) where T : class, new()
  40. {
  41. if (worksheetIndex > xlWorkbook.Worksheets.Count) yield break;
  42. var worksheet = xlWorkbook.Worksheets.FirstOrDefault(x => x.Position == worksheetIndex);
  43. if (worksheet == null) yield break;
  44. foreach (var value in Read<T>(worksheet, startFrom, skip))
  45. yield return value;
  46. }
  47. public IEnumerable<T> ReadAll<T>(uint startFrom = 1, uint skip = 0) where T : class, new()
  48. {
  49. foreach (var worksheet in xlWorkbook.Worksheets)
  50. {
  51. foreach (var item in Read<T>(worksheet, startFrom, skip))
  52. yield return item;
  53. }
  54. }
  55. private IEnumerable<T> Read<T>(IXLWorksheet? worksheet, uint startFrom, uint skip) where T : class, new()
  56. {
  57. if (worksheet == null) yield break;
  58. var firstRow = worksheet.Row((int)startFrom);
  59. if (firstRow.IsEmpty())
  60. firstRow = worksheet.RowsUsed().First(x => x.RowNumber() > startFrom && !x.IsEmpty());
  61. var mapping = Mapping.MapProperties<T>(firstRow.CellsUsed());
  62. if (mapping == null) yield break;
  63. var rowsToProcess = (ObeyFilter && worksheet.AutoFilter.IsEnabled) switch
  64. {
  65. true => worksheet.AutoFilter.VisibleRows
  66. .Where(x => x.RowNumber() > firstRow.RowNumber())
  67. .Select(x => x.WorksheetRow()),
  68. false => worksheet.RowsUsed().Where(x => x.RowNumber() > firstRow.RowNumber())
  69. };
  70. rowsToProcess = rowsToProcess
  71. .Skip((int)skip);
  72. foreach (var item in ProcessRows<T>(rowsToProcess, mapping))
  73. yield return item;
  74. }
  75. }