基于DotNetCoreNPOI封装特性通用导出excel

基于DotNetCoreNPOI封装特性通用导出excel

目前根据项目中的要求,支持列名定义,列索引排序,行合并单元格,EXCEL单元格的格式也是随着数据的类型做对应的调整。

效果图:

基于DotNetCoreNPOI封装特性通用导出excel插图

调用方式

可以看到时非常容易的能够导出数据,实际调用可能就三四句话

            // 你的需要导出的数据集合,这里的DownloadResponse就是你自己的数据集合
            List dataList = GetDownloadList(data);

            // 导出逻辑
            var workbook = new XSSFWorkbook();
            var sheet = workbook.CreateSheet("Sheet1");
            sheet.SetValue(PropertyHelper.GetPropertyGetters(dataList), workbook);

            string path = Path.Combine(@"D:", $"{Guid.NewGuid()}.xlsx");
            // 输出 Exce 文件
            using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                workbook.Write(fs);
            }
 public class DownloadResponse
    {
        /// 
        /// 第一个参数:列名
        /// 第二个参数:索引(顺序)
        /// 第三个参数:是否合并单元格
        /// 后期可以添加一些样式,比如宽度,颜色等,暂时先这样吧
        /// 
        [Excel("Customs Area", 0, true)]
        public string? CustomsArea { get; set; }
        [Excel("Vender", 1, true)]
        public string? VendorCode { get; set; }
    }

实现代码

   public static class PropertyHelper
    {
        /// 
        /// 获取RemarkAttribute的值,并按index正序排序。
        /// 
        /// 
        /// 
        /// 
        public static Dictionary> GetPropertyGetters(List dataList)
        {
            var propertyGetters = GetExcelPropertyGetters();

            var values = new Dictionary>();

            int rowIndex = 0;
            foreach (var response in dataList)
            {
                foreach (var getter in propertyGetters)
                {
                    string propertyName = getter.Key;
                    var attr = getter.Value.Attribute;

                    if (attr != null)
                    {
                        var value = getter.Value.Getter(response) as PropertyGetterInfo;
                        if (!values.TryGetValue(rowIndex, out var list))
                        {
                            list = new List();
                        }
                        list.Add(value);
                        values[rowIndex] = list;
                    }
                }
                rowIndex++;
            }
            return values;
        }

        /// 
        /// 获取ExcelAttribute的值。
        /// 
        /// 
        /// 
        public static Dictionary> GetExcelPropertyGetters()
        {
            var result = new Dictionary>();
            var properties = (from property in typeof(T).GetProperties()
                                  //where Attribute.IsDefined(property, typeof(RemarkAttribute))
                              orderby ((ExcelAttribute)property
                                        .GetCustomAttributes(typeof(ExcelAttribute), false)
                                        .Single()).Index
                              select property).ToArray();
            foreach (var prop in properties)
            {
                var attr = prop.GetCustomAttribute();
                if (attr != null)
                {
                    var getter = CreateGetter(prop);
                    result[prop.Name] = new PropertyGetterInfo
                    {
                        Attribute = attr,
                        Getter = getter
                    };
                }
            }
            return result;
        }
        private static Func CreateGetter(PropertyInfo prop)
        {
            var instance = Expression.Parameter(typeof(T), "instance");
            var propertyAccess = Expression.Property(instance, prop);
            var castToObject = Expression.Convert(propertyAccess, typeof(object));
            var lambdaBody = Expression.MemberInit(
                Expression.New(typeof(PropertyGetterInfo)),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.Description)),
                    Expression.Constant(prop.GetCustomAttribute()?.Description ?? string.Empty)
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.Index)),
                    Expression.Constant(prop.GetCustomAttribute()?.Index ?? 0)
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.IsMerge)),
                    Expression.Constant(prop.GetCustomAttribute()?.IsMerge ?? false)
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.Value)),
                    Expression.TypeAs(castToObject, typeof(object))
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.ValueType)),
                    Expression.Constant(prop.PropertyType.FullName)
                )
            );
            var lambda = Expression.Lambda>(lambdaBody, instance);
            return lambda.Compile();
        }
    }

    public class PropertyGetterInfo
    {
        public string Description { get; set; }
        public int Index { get; set; }
        public bool IsMerge { get; set; }
        public object? Value { get; set; }
        public string ValueType { get; set; }
    }
    public class PropertyGetterInfo
    {
        public ExcelAttribute? Attribute { get; set; }
        public Func Getter { get; set; }
    }

     public class ExcelAttribute : Attribute
    {
        /// 
        /// 列描述
        /// 
        private string _description;
        /// 
        /// 列索引
        /// 
        private int _index;
        /// 
        /// 是否合并
        /// 
        private bool _isMerge;
        public ExcelAttribute(string desc)
        {
            _description = desc;
        }
        public ExcelAttribute(string desc, int index)
        {
            _description = desc;
            _index = index;
        }
        public ExcelAttribute(string desc, int index, bool isMerge)
        {
            _description = desc;
            _index = index;
            _isMerge = isMerge;
        }
        public string Description
        {
            get
            {
                return _description;
            }
        }
        public int Index
        {
            get
            {
                return _index;
            }
        }
        public bool IsMerge
        {
            get
            {
                return _isMerge;
            }
        }
    }

  public static class ExcelHelper
    {
        static readonly string? _intType = typeof(int).FullName;
        static readonly string? _intNullType = typeof(int?).FullName;
        static readonly string? _longType = typeof(long).FullName;
        static readonly string? _longNullType = typeof(long?).FullName;
        static readonly string? _doubleType = typeof(double).FullName;
        static readonly string? _doubleNullType = typeof(double?).FullName;
        static readonly string? _decimalType = typeof(decimal).FullName;
        static readonly string? _decimalNullType = typeof(decimal?).FullName;
        static readonly string? _stringType = typeof(string).FullName;
        static readonly string? _dateTimeType = typeof(DateTime).FullName;
        static readonly string? _dateTimeNullType = typeof(DateTime?).FullName;
        static readonly string? _boolType = typeof(bool).FullName;
        static readonly string? _boolNullType = typeof(bool?).FullName;
        static readonly string? _guidType = typeof(Guid).FullName;
        static readonly string? _guidNullType = typeof(Guid?).FullName;

        public static void SetValue(this ISheet sheet, Dictionary> propertyGetters, XSSFWorkbook workbook)
        {
            bool isHead = true;
            int sheetRowIndex = 0;
            for (int i = 0; i = propertyGetters.Count)
                        {
                            continue;
                        }
                        var nextValue = propertyGetters[nextIndex];
                        var e = nextValue.FirstOrDefault(x => x.Description == thisValue.Description && (x.Value?.Equals(thisValue.Value) ?? false));
                        if (e != null)
                        {
                            // 合并当前行和下一行
                            var range = new CellRangeAddress(sheetRowIndex, sheetRowIndex + 1, e.Index, e.Index);
                            sheet.AddMergedRegion(range);
                        }
                    }
                }
            }
        }

    }

文章来源于互联网:基于DotNetCoreNPOI封装特性通用导出excel

THE END
分享
二维码