基于DotNetCoreNPOI封装特性通用导出excel
基于DotNetCoreNPOI封装特性通用导出excel
目前根据项目中的要求,支持列名定义,列索引排序,行合并单元格,EXCEL单元格的格式也是随着数据的类型做对应的调整。
效果图:

调用方式
可以看到时非常容易的能够导出数据
            // 你的需要导出的数据集合,这里的DownloadResponse就是你自己的数据集合
            List<DownloadResponse> dataList = GetDownloadList(data);
            var workbook = new XSSFWorkbook();
            #region 表格自定义样式
            var cellStyle = workbook.CreateCellStyle();
            cellStyle.VerticalAlignment = VerticalAlignment.Center;
            cellStyle.Alignment = HorizontalAlignment.Center;
            var sheet = workbook.CreateSheet("Sheet1");
            #endregion
            #region 赋值
            sheet.SetValue(PropertyHelper.GetPropertyGetters(dataList), workbook);
            #endregion
#if DEBUG
            string path = Path.Combine(@"D:\", $"{Guid.NewGuid()}.xlsx");
            // 输出 Exce 文件
            using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                workbook.Write(fs);
            }
#endif
 public class DownloadResponse
    {
        /// <summary>
        /// 第一个参数:列名
        /// 第二个参数:索引(顺序)
        /// 第三个参数:是否合并单元格
        /// 后期可以添加一些样式,比如宽度,颜色等,暂时先这样吧
        /// </summary>
        [Excel("Customs Area", 0, true)]
        public string? CustomsArea { get; set; }
        [Excel("Vender", 1, true)]
        public string? VendorCode { get; set; }
    }
实现代码
   public static class PropertyHelper
    {
        /// <summary>
        /// 获取RemarkAttribute的值,并按index正序排序。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataList"></param>
        /// <returns></returns>
        public static Dictionary<int, List<PropertyGetterInfo>> GetPropertyGetters<T>(List<T> dataList)
        {
            var propertyGetters = GetExcelPropertyGetters<T>();
            var values = new Dictionary<int, List<PropertyGetterInfo>>();
            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<PropertyGetterInfo>();
                        }
                        list.Add(value);
                        values[rowIndex] = list;
                    }
                }
                rowIndex++;
            }
            return values;
        }
        /// <summary>
        /// 获取ExcelAttribute的值。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Dictionary<string, PropertyGetterInfo<T>> GetExcelPropertyGetters<T>()
        {
            var result = new Dictionary<string, PropertyGetterInfo<T>>();
            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<ExcelAttribute>();
                if (attr != null)
                {
                    var getter = CreateGetter<T>(prop);
                    result[prop.Name] = new PropertyGetterInfo<T>
                    {
                        Attribute = attr,
                        Getter = getter
                    };
                }
            }
            return result;
        }
        private static Func<T, PropertyGetterInfo> CreateGetter<T>(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<ExcelAttribute>()?.Description ?? string.Empty)
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.Index)),
                    Expression.Constant(prop.GetCustomAttribute<ExcelAttribute>()?.Index ?? 0)
                ),
                Expression.Bind(
                    typeof(PropertyGetterInfo).GetProperty(nameof(PropertyGetterInfo.IsMerge)),
                    Expression.Constant(prop.GetCustomAttribute<ExcelAttribute>()?.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<Func<T, PropertyGetterInfo>>(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<T>
    {
        public ExcelAttribute? Attribute { get; set; }
        public Func<T, object?> Getter { get; set; }
    }
     public class ExcelAttribute : Attribute
    {
        /// <summary>
        /// 列描述
        /// </summary>
        private string _description;
        /// <summary>
        /// 列索引
        /// </summary>
        private int _index;
        /// <summary>
        /// 是否合并
        /// </summary>
        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<int, List<PropertyGetterInfo>> propertyGetters, XSSFWorkbook workbook)
        {
            bool isHead = true;
            int sheetRowIndex = 0;
            for (int i = 0; i < propertyGetters.Count; i++)
            {
                var item = propertyGetters[i];
                // 创建表头
                if (isHead)
                {
                    var headerRow = sheet.CreateRow(sheetRowIndex);
                    for (int j = 0; j < item.Count; j++)
                    {
                        headerRow.CreateCell(j).SetCellValue(item[j].Description);
                    }
                    isHead = false;
                    i--;
                    continue;
                }
                // 创建行
                sheetRowIndex++;
                var row = sheet.CreateRow(sheetRowIndex);
                for (int k = 0; k < item.Count; k++)
                {
                    var thisValue = item[k];
                    var cell = row.CreateCell(thisValue.Index);
                    if (thisValue.Value == null)
                    {
                        cell.SetCellType(CellType.String);
                        cell.SetCellValue(string.Empty);
                    }
                    if (thisValue.Value != null && thisValue.ValueType == _stringType)
                    {
                        cell.SetCellType(CellType.String);
                        cell.SetCellValue(thisValue.Value?.ToString());
                    }
                    // 数值类型
                    else if (thisValue.Value != null && (thisValue.ValueType == _intNullType
                       || thisValue.ValueType == _intType
                       || thisValue.ValueType == _decimalNullType
                       || thisValue.ValueType == _decimalType
                       || thisValue.ValueType == _longNullType
                       || thisValue.ValueType == _longType
                       || thisValue.ValueType == _doubleType
                       || thisValue.ValueType == _doubleNullType
                       ))
                    {
                        cell.SetCellType(CellType.Numeric);
                        double.TryParse(thisValue.Value?.ToString(), out double value);
                        cell.SetCellValue(value);
                    }
                    // 时间类型
                    else if (thisValue.Value != null && (thisValue.ValueType == _dateTimeNullType
                        || thisValue.ValueType == _dateTimeType))
                    {
                        DateTime.TryParse(thisValue.Value?.ToString(), out var value);
                        // 时间类型比较特殊,需要设置特定的单元格样式
                        var style = workbook.CreateCellStyle();
                        cell.SetCellValue(value.ToOADate());
                        style = workbook.CreateCellStyle();
                        style.DataFormat = HSSFDataFormat.GetBuiltinFormat("m/d/yy");
                        cell.CellStyle = style;
                    }
                    // bool类型
                    else if (thisValue.Value != null && (thisValue.ValueType == _boolNullType
                        || thisValue.ValueType == _boolType))
                    {
                        cell.SetCellType(CellType.Boolean);
                        bool.TryParse(thisValue.Value?.ToString(), out bool value);
                        cell.SetCellValue(value);
                    }
                    // 合并单元格
                    if (thisValue.IsMerge && thisValue.Value != null)
                    {
                        int nextIndex = i + 1;
                        if (nextIndex >= 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的更多相关文章
- (gridcontrol等)通用导出excel z
		
关于DevExpress Winform 的所有可打印控件的导出excel 的通用方法,并且解决DevExpress控件自带的方法存在的缺陷问题 1.解决GridControl自带方法不能导出图片: ...
 - Java基于注解和反射导入导出Excel
		
代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...
 - 基于 POI 封装 ExcelUtil 精简的 Excel 导入导出
		
注 本文是使用 org.apache.poi 进行一次简单的封装,适用于大部分 excel 导入导出功能.过程中可能会用到反射,如若有对于性能有极致强迫症的同学,看看就好. 序 由于 poi 本身只是 ...
 - POI通用导出Excel数据(包括样式设计)
		
前言 前一段时间我写过通用的导入Excel,前几天也写了导出pdf格式的,还有我之前搞得导出Word,我在之前的博客也都介绍了导出和导入是一个道理,无非是一个获取一个是赋值.昨天有一位同仁看了我的Ex ...
 - 通用导出excel
		
循环导出所有行和列 def export_excel(table_name): host,user,passwd,db='192.168.0.12','root','myjcyf','us_sys' ...
 - 基于Vue + axios + WebApi + NPOI导出Excel文件
		
一.前言 项目中前端采用的Element UI 框架, 远程数据请求,使用的是axios,后端接口框架采用的asp.net webapi,数据导出成Excel采用NPOI组件.其业务场景,主要是列表页 ...
 - 通过注解实现通用导出Excel
		
Javaweb开发中数据的导入导出很常见,每次我们都需要写很多代码,所以我就在想能不能写一些通用的方法,之前已经在网上 整理过一些通用的方法,最近在网上看到一位牛人封装的更加简介,自己拿过来整理了一下 ...
 - 【ITOO 1】将List数据导出Excel表
		
需求描述:在课表导入的时候,首先给用户提供模板(excel),然后将用户填写好的数据读取到list集合中.再进行判空处赋值处理,以及去重处理.这篇博客,主要介绍读取excel表和导出excel表的方法 ...
 - JAVA实现导出excel功能,封装通用导出工具类
		
引入maven <!--excel导出--> <dependency> <groupId>net.sourceforge.jexcelapi</groupId ...
 - C#中缓存的使用  ajax请求基于restFul的WebApi(post、get、delete、put)  让 .NET 更方便的导入导出 Excel  .net core api +swagger(一个简单的入门demo 使用codefirst+mysql)  C# 位运算详解  c# 交错数组  c# 数组协变  C# 添加Excel表单控件(Form Controls)  C#串口通信程序
		
C#中缓存的使用 缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可: <%@ Outp ...
 
随机推荐
- Mongodb可参考的查询
			
条件AND 1 db.csr_log_info.find({$and:[{enterTime :{$regex:/2021-08-31 18:01/}},{enterTime :{$ne:" ...
 - LoadRunner压力测试(web)
			
1.打开Virtual User Generator->新建脚本->选择创建新脚本类型,web-HTTP,HTML->创建 2.录制脚本 3.停止脚本录制 4.创建controlle ...
 - MySql5.7基础配置
			
MySql5.7基础配置 [client] #设置mysql客户端的字符集 default-character-set=utf8 [mysqld] #设置mysql端口为3306 port = 330 ...
 - .net 生成Excel并保存
			
void SaveQuestionToExcel(List<Question> datas, string path) { using (Workbook workbook = new H ...
 - Windows软件堆栈溢出(stack overflow)的一些解决方法
			
欢迎访问我的个人博客:xie-kang.com 原文地址 Windows平台下,有三种方法调整堆栈大小(适用于MSVC编译器): 1)添加编译参数:/F size #其中size的单位是byte可设 ...
 - 使用redis分布式锁重复执行采坑
			
事件:生产环境部署两台,每天凌晨1点,定时任务同步更新(先删除,后全部插入)账号表,使用了redis分布式锁,发现定时任务还是执行了两次,导致数据重复,影响对应业务. 原因分析:定时任务执行的逻辑是调 ...
 - Nginx TP框架伪静态配置
			
location / { if (!-e $request_filename){ rewrite ^(.*)$ /index.php?s=$1 last; break; } }
 - Oracle-安装问题:Win10系统离线安装framework3.5报0x8024402c的问题
			
Oracle-安装问题:Win10系统离线安装framework3.5报0x8024402c的问题 像神州信用政府版本相关的系统都不允许联网,也就需要离线安装下,Net3.5之类的文件 具体步骤可以参 ...
 - .bat 脚本替换文件内容
			
rem 定义变量延迟环境,关闭回显 @echo off&setlocal enabledelayedexpansion rem 读取a.txt所有内容 for /f "eol=* t ...
 - OSPF之路由撤销1