using System.Globalization; using System.Linq; using OfficeOpenXml; using Szmedi.Toolkit.Assists; namespace Szmedi.RvKits.Assists { public static class ExcelReaderExtensions { public static IEnumerable Read(this ExcelWorksheet sheet, int headerIndex = 1, Type type = null) where T : new() { var results = new List(); if (sheet == null) { return results; } var mapClass = type ?? AppDomain.CurrentDomain .GetAssemblies() .Where(a => a.FullName.StartsWith("Namespace")) .SelectMany(i => i.GetTypes().Where(i => i.IsClass && typeof(BaseTypeConfiguration).IsAssignableFrom(i))) .FirstOrDefault(); var instance = (BaseTypeConfiguration)Activator.CreateInstance(mapClass); var mappings = instance.GetMappings(); var rows = sheet.Dimension.Rows; var cols = new List<(int index, string name, PropertyConfiguration propertyConfiguration)>(); for (var i = 1; i < sheet.Dimension.Columns; i++) { var col = mappings.FirstOrDefault(a => !string.IsNullOrEmpty(a.Name) && a.Name == (string)sheet.Cells[headerIndex, i].Value); if (col != null) { cols.Add((index: i, name: col.Name, propertyConfiguration: col)); } } if (cols.Any()) { mappings.Where(x => x.DefaultValue != null) .ToList() .ForEach(map => { cols.Add((index: cols.Max(x => x.index) + 1, name: map.Name, propertyConfiguration: map)); }); } for (var i = ++headerIndex; i <= rows; i++) { var t = new T(); for (var j = 0; j < cols.Count; j++) { var property = cols[j]; var propertyInfo = t.GetType().GetProperty(property.propertyConfiguration.Member.Name); if (property.propertyConfiguration.DefaultValue != null) { propertyInfo.SetValue(t, property.propertyConfiguration.DefaultValue); } else { var value = Cast(sheet.Cells[i, property.index].Value, propertyInfo.PropertyType, property.propertyConfiguration); if (propertyInfo.PropertyType.IsEnum && value != null) { propertyInfo.SetValue(t, Enum.Parse(propertyInfo.PropertyType, value.ToString())); } else { propertyInfo.SetValue(t, value); } } } results.Add(t); } return results; } private static object Cast(object value, Type propertyType, PropertyConfiguration propertyConfiguration) { if (value == null) { return null; } if (propertyType == typeof(byte) || propertyType == typeof(byte?)) { byte.TryParse(propertyConfiguration.StringFormatFunc == null ? value.ToString() : propertyConfiguration.StringFormatFunc(value.ToString()), out var result); return result; } else if (propertyType == typeof(int)) { int.TryParse(propertyConfiguration.StringFormatFunc == null ? value.ToString() : propertyConfiguration.StringFormatFunc(value.ToString()), out var result); return result; } else if (propertyType == typeof(short)) { short.TryParse(propertyConfiguration.StringFormatFunc == null ? value.ToString() : propertyConfiguration.StringFormatFunc(value.ToString()), out var result); return result; } else { return propertyType == typeof(DateTime) || propertyType == typeof(DateTime?) ? propertyConfiguration.DateFormatFunc != null ? propertyConfiguration.DateFormatFunc(value.ToString()) : value : propertyType == typeof(double) || propertyType == typeof(double?) || propertyType == typeof(decimal) || propertyType == typeof(decimal?) ? propertyConfiguration.DecimalFormatFunc != null ? propertyConfiguration.DecimalFormatFunc(value.ToString()) : (object)value.ToString().ToDecimal() : propertyConfiguration.StringFormatFunc != null ? propertyConfiguration.StringFormatFunc(value.ToString()) : (object)value.ToString().Trim(); } } private static decimal ToDecimal(this string value, CultureInfo cultureInfo = null) { decimal.TryParse(value, NumberStyles.Any, cultureInfo ?? CultureInfo.InvariantCulture, out var decimalValue); return decimalValue; } } }