ExcelDynamicReader.cs 2.9 KB

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