通用Excel导出

导出Excel时,经常会遇到需要重复性的书写每个列的名称,以此造成代码编写的重复书写,例如:

为了避免这种编写,我们可以采取特性加反射的形式进行代码解耦。代码例子如下:

代码封装:

using Model.Attribute;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;

namespace Services
{
    public class OfficeService
    {
        /// <summary>
        /// 导出数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="list">数据列表</param>
        /// <returns></returns>
        public static MemoryStream ExportRecords<T>(List<T> list)
        {
            try
            {
                if (!list.Any())
                {
                    HttpContext.Current.Response.Write("没有数据需要导出");
                    return null;
                }
                var dt = ToExcelDataTable(list);//关键核心
                return DataTableToExcel(dt);//导出Excel的方法可以自己定义
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write("导出失败,失败原因:" + ex.Message);
            }
            return null;
        }

        /// <summary>
        /// 将泛型集合类转换成DataTable(只针对导出EXCEL)
        /// </summary>
        /// <typeparam name="T">集合项类型</typeparam>
        /// <param name="list">集合</param>
        /// <returns>数据集(表)</returns>
        public static DataTable ToExcelDataTable<T>(IList<T> list)
        {
            DataTable result = new DataTable();

            PropertyInfo[] propertys = typeof(T).GetProperties();
            foreach (PropertyInfo pi in propertys)
            {
                if (pi.IsDefined(typeof(ExportPropAttribute), true))
                {
                    result.Columns.Add(pi.Name.GetExtportName<T>(), pi.PropertyType == typeof(int) || pi.PropertyType == typeof(byte) ? typeof(String) : pi.PropertyType);
                }
            }
            if (list != null || list.Count > 0)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        if (pi.IsDefined(typeof(ExportPropAttribute), true))
                        {
                            object obj = pi.GetValue(list[i], null);
                            obj = pi.Name.GetEnumForDesc<T>(obj);
                            tempList.Add(obj);
                        }
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }

        /// <summary>  
        /// 导出Excel
        /// </summary>  
        /// <returns></returns>  
        public static MemoryStream DataTableToExcel(DataTable dt)
        {
            IWorkbook workbook = null;
            IRow row = null;
            ISheet sheet = null;
            ICell cell = null;
            MemoryStream ms = new MemoryStream();
            try
            {
                if (dt != null && dt.Columns.Count > 0)
                {
                    workbook = new HSSFWorkbook();
                    sheet = workbook.CreateSheet("Sheet0");//创建一个名称为Sheet0的表

                    int columnCount = dt.Columns.Count;//列数
                                                       //设置列头
                    row = sheet.CreateRow(0);//excel第一行设为列头
                    for (int c = 0; c < columnCount; c++)
                    {
                        cell = row.CreateCell(c);
                        cell.SetCellValue(dt.Columns[c].ColumnName);
                    }

                    if (dt != null && dt.Rows.Count > 0)
                    {
                        //设置每行每列的单元格,
                        int rowCount = dt.Rows.Count;//行数
                        for (int i = 0; i < rowCount; i++)
                        {
                            row = sheet.CreateRow(i + 1);
                            for (int j = 0; j < columnCount; j++)
                            {
                                cell = row.CreateCell(j);//excel第二行开始写入数据
                                cell.SetCellValue(dt.Rows[i][j].ToString());
                            }
                        }
                    }
                    workbook.Write(ms);//向打开的这个xls文件中写入数据
                    ms.Seek(0, SeekOrigin.Begin);
                }
                return ms;
            }
            catch (Exception ex)
            {
                if (ms != null)
                {
                    ms.Close();
                }
                return null;
            }
        }
    }
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    public class ExportPropAttribute : System.Attribute
    {
        /// <summary>
        /// //导出名称
        /// </summary>
        public string ExtportName = "";

        /// <summary>
        /// //枚举类型
        /// </summary>
        public Type EnumType = null;
    }

 public static class AttributeExt
    {
        /// <summary>
        /// 获取导出字段的名称
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propName"></param>
        /// <returns></returns>
        public static string GetExtportName<T>(this string propName)
        {
            Type t = typeof(T);
            var item = t.GetProperty(propName);
            if (item != null && item.IsDefined(typeof(ExportPropAttribute), true))
            {
                var attribute = item.GetCustomAttributes(typeof(ExportPropAttribute), true)[0];
                return ((ExportPropAttribute)attribute).ExtportName;
            }
            return propName;
        }

        /// <summary>
        /// 获取扩展的枚举值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static object GetEnumForDesc<T>(this string propName, object value)
        {
            Type t = typeof(T);
            var item = t.GetProperty(propName);
            if (item != null && item.IsDefined(typeof(ExportPropAttribute), true))
            {
                var attribute = item.GetCustomAttributes(typeof(ExportPropAttribute), true)[0];
                var objEnmu = ((ExportPropAttribute)attribute).EnumType;
                if (objEnmu != null && value != null)
                {
                    return EnumHelper.GetEnumDesc(objEnmu, Convert.ToByte(value));
                }
            }
            return value;
        }

    }

枚举相关代码:

 /// <summary>
    /// 学生类型
    /// </summary>
    public enum StudentTypeEnum
    {
        /// <summary>
        /// 小学生
        /// </summary>
        [Description("小学生")]
        Small = 1,
        /// <summary>
        /// 中学生
        /// </summary>
        [Description("中学生")]
        Middle = 2,
        /// <summary>
        /// 大学生
        /// </summary>
        [Description("大学生")]
        Big = 3,
    }  

public static class EnumHelper
    {
        #region 获取枚举的描述信息

        /// <summary>
        ///     获取枚举的描述信息
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static String GetEnumDesc(this Enum e)
        {
            try
            {
                FieldInfo enumInfo = e.GetType().GetField(e.ToString());
                var enumAttributes
                    = (DescriptionAttribute[])enumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
                return enumAttributes.Length > 0 ? enumAttributes[0].Description : e.ToString();
            }
            catch
            {
                return string.Empty;
            }

        }

        /// <summary>
        /// 获取枚举的描述信息,根据传入的枚举值
        /// </summary>
        /// <param name="enumType"></param>
        /// <param name="enumValue"></param>
        /// <returns></returns>
        public static String GetEnumDesc(Type enumType, byte enumValue)
        {
            string result = "";
            foreach (var e in Enum.GetValues(enumType).Cast<Enum>().Where(e => Convert.ToInt32(e) == enumValue))
            {
                result = GetEnumDesc(e);
                break;
            }

            return result;
        }

        #endregion
    }

调用端代码:

  public class OfficeController : Controller
    {
        // GET: ExcelDemo
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 导出Excel
        /// </summary>
        /// <returns></returns>
        public FileResult ExportRecordExcel()
        {
            var list = new List<StudentEntity>
            {
               new StudentEntity{ Age=10, StuId=1, StuName="张三", StuType = (int)StudentTypeEnum.Middle },
               new StudentEntity{ Age=10, StuId=2, StuName="李四", StuType = (int)StudentTypeEnum.Middle },
               new StudentEntity{ Age=12, StuId=3, StuName="王五", StuType = (int)StudentTypeEnum.Big },
               new StudentEntity{ Age=8, StuId=4, StuName="赵六" , StuType = (int)StudentTypeEnum.Small}
            };
            return File(OfficeService.ExportRecords(list), "application/vnd.ms-excel", $"导出记录{DateTime.Now.ToLongTimeString()}.xls");
        }
    }

Index.cshtml:

@{
    ViewBag.Title = "导出Excel测试";
}

<script type="text/javascript">

    //导出
    function btn_export() {
        window.open("ExportRecordExcel");
    }

</script>

<h2>导出Excel测试</h2>
<br />
<input id="btnExport" type="button" value="导出Excel" onclick="btn_export()" />

效果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值