ExcelDynamicReader.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. var firstRow = worksheet.Row((int)startFrom);
  38. if (firstRow.IsEmpty())
  39. firstRow = worksheet.RowsUsed().First(x => x.RowNumber() > startFrom && !x.IsEmpty());
  40. var mapping = DynamicCell.MapHeader(firstRow.CellsUsed());
  41. if (mapping == null || mapping.Count == 0) yield break;
  42. var rowsToProcess = (ObeyFilter && worksheet.AutoFilter.IsEnabled) switch
  43. {
  44. true => worksheet.AutoFilter.VisibleRows
  45. .Where(x => x.RowNumber() > firstRow.RowNumber())
  46. .Select(x => x.WorksheetRow()),
  47. false => worksheet.RowsUsed().Where(x => x.RowNumber() > firstRow.RowNumber())
  48. };
  49. rowsToProcess = rowsToProcess
  50. .Skip((int)skip);
  51. foreach (var item in ProcessRows(rowsToProcess, mapping))
  52. yield return item;
  53. }
  54. }