• NPOI导入,导出


    概述

    NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。NPOI 可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写,包含了大部分EXCEL的特性(单元格样式、数据格式、公式等等)。(复制百度百科)

    表格导入导出的操作经常会碰到,最近抽空专门封装了一下。

    遵循的原则:

    1. 一行数据对应一个数据实体,需提供它们二者间的映射关系。

    2. 支持合并单元格的导入导出(导出数据只支持竖向合并,导入数据遇到横向合并的单元格会抛出异常),图片未支持

    导出的复杂在于样式的控制,当解决这一问题后后续操作就很简单了,而样式解析相关的代码行数也真的是不少,因为对API的不熟悉,连写带测折腾了不少时间。

    导入因为行为的多变性,要求程序员调用时将具体的读写逻辑以策略的形式传入。所以代码量相对来说要少得多。其实也是避开了一些难题,比如公式符号,数字的上标,下标的解析(尚不知道怎么解决)。

    导出效果

    表格导入

    单元格数据的解析

    1. 先依据单元格类的数据类型cell.CellType(枚举类型),读取其内部保存的数据,如果类型是公式的,则依据cell.CachedFormulaResultType再进行一次判别。

    2. 从单元格读到数据后还再进一步完成一次类型的转换,将它转换为我们需要的类型。

    /// <summary>
    /// 扩展
    /// </summary>
    public static class IRowExtension
    {
        /// <summary>
        /// 读取表格中某单元格的值,如果单元格是合并单元格,则竖向合并的正常返回,横向合并的抛出异常
        /// </summary>
        /// <typeparam name="A">要读取的数据类型</typeparam>
        /// <param name="row">Excel中的某行数据</param>
        /// <param name="index">行内的列下标</param>
        /// <returns></returns>
        public static A GetValue<A>(this IRow row, int index)
        {
            try
            {
                //获取单元格
                ICell cell = row.GetCell(index);
    
                //判别是否合并单元格
                if (cell.IsMergedCell)
                {
                    ISheet sheet = cell.Sheet;
                    for (int i = 0, length = sheet.NumMergedRegions; i < length; i++)
                    {
                        var cellRange = sheet.GetMergedRegion(i);
                        if (cell.ColumnIndex >= cellRange.FirstColumn
                            && cell.ColumnIndex <= cellRange.LastColumn
                            && cell.RowIndex >= cellRange.FirstRow
                            && cell.RowIndex <= cellRange.LastRow)
                        {
                            if (cellRange.FirstColumn != cellRange.LastColumn)
                            {
                                throw new Exception("不能有横向合并的单元格");
                            }
    
                            cell = sheet.GetRow(cellRange.FirstRow).GetCell(cellRange.FirstColumn);
                        }
                    }
                }
                return GetValue<A>(cell);
            }
            catch (Exception ex)
            {
                //读取单元格信息时出错
                throw new Exception("出错位置的列下标:" + index + ",报错信息:" + ex.Message);
            }
        }
    
        /// <summary>
        /// 读取表格中某单元格的值,如果单元格是合并单元格,则竖向合并的正常返回,横向合并的抛出异常
        /// </summary>
        /// <typeparam name="A">要读取的数据类型</typeparam>
        /// <param name="cell">Excel中的某单元格</param>
        /// <returns></returns>
        private static A GetValue<A>(ICell cell)
        {
            //依据单元格数据类型读取数据,并强转为目标类型
            switch (cell.CellType)
            {
                case CellType.Boolean:
                    return cell.BooleanCellValue.ChangeType<A>();
                case CellType.Error:
                    return ErrorEval.GetText(cell.ErrorCellValue).ChangeType<A>();
                case CellType.Numeric:
                    if (DateUtil.IsCellDateFormatted(cell))
                    {
                        return cell.DateCellValue.ChangeType<A>();
                    }
                    else
                    {
                        return cell.NumericCellValue.ChangeType<A>();
                    }
                case CellType.String:
                    string strValue = cell.StringCellValue;
                    if (string.IsNullOrEmpty(strValue))
                    {
                        return default(A);
                    }
                    else
                    {
                        return strValue.ChangeType<A>();
                    }
                case CellType.Formula://公式
                    switch (cell.CachedFormulaResultType)
                    {
                        case CellType.Boolean:
                            return cell.BooleanCellValue.ChangeType<A>();
                        case CellType.Error:
                            return ErrorEval.GetText(cell.ErrorCellValue).ChangeType<A>();
                        case CellType.Numeric:
                            if (DateUtil.IsCellDateFormatted(cell))
                            {
                                return cell.DateCellValue.ChangeType<A>();
                            }
                            else
                            {
                                return cell.NumericCellValue.ChangeType<A>();
                            }
                        case CellType.String:
                            string str = cell.StringCellValue;
                            if (string.IsNullOrEmpty(str))
                            {
                                return default(A);
                            }
                            else
                            {
                                return str.ChangeType<A>();
                            }
                        case CellType.Unknown:
                        case CellType.Blank:
                        default:
                            return default(A);
                    }
                case CellType.Unknown:
                case CellType.Blank:
                default:
                    return default(A);
            }
        }
    }
    

    类型转换

    /// <summary>
    /// 调用Convert.ChangeType
    /// </summary>
    /// <typeparam name="T">要返回的类型</typeparam>
    /// <param name="token">待转换的值</param>
    /// <returns>转换后的值</returns>
    public static T ChangeType<T>(this object token)
    {
        object result = ChangeType(token, typeof(T));
        if (result == null)
        {
            return default(T);
        }
        return (T)result;
    }
    
    /// <summary>
    /// 把对象类型转换为指定类型
    /// </summary>
    /// <param name="value">要转换的值</param>
    /// <param name="targetType">目标类型</param>
    /// <returns> 转化后的指定类型的对象</returns>
    public static object ChangeType(this object value, Type targetType)
    {
        if (value == null)
        {
            return null;
        }
        if (targetType.IsNullableType())
        {
            targetType = targetType.GetUnderlyingType();
        }
        if (targetType.IsEnum)
        {
            return Enum.Parse(targetType, value.ToString());
        }
        if (targetType == typeof(Guid))
        {
            return Guid.Parse(value.ToString());
        }
        return Convert.ChangeType(value, targetType);
    }
    

    导出代码的主体部分

    策略接口

    /// <summary>
    /// 提供每行数据的操作策略(不同的实现方式,达成不同的导入目标,存储目标不必一定是数据库)
    /// 通过GetValue读取某单元格数据
    /// </summary>
    public interface ExcelImportHelper
    {
         /// <summary>
         /// 判断本行数据是否数据库中已存在(有则会进行修改,没有则会新建)
         /// </summary>
         /// <param name="row">Excel中的某行数据</param>
         /// <returns>不存在则返回null,存在则返回该项数据</returns>
         T IsExist(IRow row);
    
        /// <summary>
        /// 新数据添加到数据库
        /// </summary>
        /// <param name="model">已完成映射的实体类实例</param>
        void Add(T model);
    
        /// <summary>
        /// 更新数据库中的已有数据
        /// </summary>
        /// <param name="model">已完成映射的实体类实例</param>
        void Update(T model);
    
        /// <summary>
        /// 提供从表格行数据映射到实体类的方法(解析失败的时候直接要抛出异常)
        /// </summary>
        /// <param name="row">Excel中的某行数据</param>
        /// <param name="model">新建的或刚从数据库中读取到的实体类实例</param>
        /// <returns>映射失败或数据为空时返回false,则不会录入数据库</returns>
        bool Map(IRow row, T model);
    }
    

    其他部分代码

    /// <summary>
    /// 表格导入数据库
    /// 也可以是导入DataTable等形式,只要提供不同的策略
    /// </summary>
    /// <typeparam name="T">Model的类型</typeparam>
    public class ExcelImport<T> where T : new()
    {
        private ExcelImportHelper helper;
    
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="helper">操作策略</param>
        public ExcelImport(ExcelImportHelper helper)
        {
            this.helper = helper;
        }
    
        /// <summary>
        /// 处理结果
        /// </summary>
        public struct Result
        {
            private int num;           //导入行数
            private int num_add;       //新增行数
            private int num_edit;      //修改行数
    
            /// <summary>
            /// 导入行数
            /// </summary>
            public int Num
            {
                get
                {
                    return num;
                }
    
                set
                {
                    num = value;
                }
            }
    
            /// <summary>
            /// 新增行数
            /// </summary>
            public int Num_add
            {
                get
                {
                    return num_add;
                }
    
                set
                {
                    num_add = value;
                }
            }
    
            /// <summary>
            /// 修改行数
            /// </summary>
            public int Num_edit
            {
                get
                {
                    return num_edit;
                }
    
                set
                {
                    num_edit = value;
                }
            }
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="num">导入行数</param>
            /// <param name="num_add">新增行数</param>
            /// <param name="num_edit">修改行数</param>
            internal Result(int num, int num_add, int num_edit)
            {
                this.num = num;
                this.num_add = num_add;
                this.num_edit = num_edit;
            }
        }
    
        #region 导入操作
    
        /// <summary>
        /// 表格导入到数据库
        /// </summary>
        /// <param name="name">上传控件的name</param>
        /// <param name="maxLength">最大上传的文件大小(MB)</param>
        /// <param name="headerRowsNum">表格头部所占的高度</param>
        /// <returns>表中的数据(只读取表中第一个Sheet)</returns>
        public Result Inport(string name, int maxLength, int headerRowsNum)
        {
            Stream stream = null;
            try
            {
                HttpContext context = HttpContext.Current;
                HttpRequest request = context.Request;
    
                //验证文件格式大小,返回文件流
                stream = GetInputStream(request, name, maxLength);
    
                //逐行读取文件内容并执行导入
                return Operation(stream, headerRowsNum);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                }
            }
        }
    
        private Result Operation(Stream stream,int headerRowsNum)
        {
            //操作结果
            Result result = new Result(0, 0, 0);
    
            //读取表格内容
            try
            {
                using (stream)
                {
                    //自动识别.xlsx(XSSFWorkbook),.xls(HSSFWorkbook)
                    IWorkbook workbook = WorkbookFactory.Create(stream);
    
                    if (workbook.NumberOfSheets == 0)
                        throw new Exception("报错信息:文件无数据");
                    //取第一张表
                    ISheet sheet = workbook.GetSheetAt(0);
                    if (sheet.PhysicalNumberOfRows == 0)
                        throw new Exception("报错信息:文件无数据");
    
                    //数据行数
                    int rowCount = sheet.LastRowNum;
    
                    //读取表中所有数据
                    for (int i = sheet.FirstRowNum + headerRowsNum; i <= rowCount; i++)
                    {
                        IRow row = sheet.GetRow(i);
                        if (row != null)
                        {
                            result.Num++;
                            T model = helper.IsExist(row);
                            if (model == null)
                            {
                                result.Num_add++;
                                //新建
                                model = new T();
                                bool ok = helper.Map(row, model);
                                if (ok)
                                {
                                    helper.Add(model);
                                }
                            }
                            else
                            {
                                result.Num_edit++;
                                //修改
                                bool ok = helper.Map(row, model);
                                if (ok)
                                {
                                    helper.Update(model);
                                }
                            }
                        }
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                //在异常信息中添加出错位置
                throw new Exception("当前读取到第"+ result.Num + "行数据,已添加"+ result .Num_add+ "条,已更新" 
                    + result.Num_edit + "条," + ex.Message);
            }
        }
        #endregion
    }
    

    调用

    //策略
    private class helper : ExcelImport<B_NEWS>.ExcelImportHelper
    {
        public void Add(B_NEWS model)
        {
            bll.Add(model);
        }
    
        public B_NEWS IsExist(IRow row)
        {
            return null;
        }
    
        public bool Map(IRow row, B_NEWS model)
        {
            model.id = row.GetValue<int>(0);
            model.c_info_title = row.GetValue<string>(1);
            model.c_info_content = row.GetValue<string>(2);
            model.d_list_date = row.GetValue<DateTime>(3);
            model.d_add_date = row.GetValue<DateTime>(4);
            model.n_is_active = (row.GetValue<bool>(5) ? 1 : 0);
            model.int1 = row.GetValue<int>(6);
            return true;
        }
    
        public void Update(B_NEWS model)
        {
            bll.Update(model);
        }
    }
    
    protected void daoru(object sender, EventArgs e)
    {
        new ExcelImport<B_NEWS>(new helper()).Inport("excel", 10, 2);
    }
    

    表格导出

    调用者直接接触的操作类

    public class ExcelExport<T>
    {
        /// <summary>
        /// 每列数据的解析方法
        /// </summary>
        private List<Func<T, object>> func = new List<Func<T, object>>();
    
        private IExcelBuilder builder = new ExcelBuilder();
    
        private string headJson;
    
        /// <summary>
        /// 更换表格建造器
        /// </summary>
        /// <param name="builder">自定义的建造器</param>
        /// <returns></returns>
        public ExcelExport<T> ChangeBuilder(IExcelBuilder builder)
        {
            this.builder = builder;
            return this;
        }
        
        /// <summary>
        /// 定义列 
        /// </summary>
        /// <param name="convert">委托</param>
        /// <returns></returns>
        public ExcelExport<T> Column(Func<T, object> convert)
        {
            func.Add(convert);
            return this;
        }
    
        /// <summary>
        /// 设置Excel属性
        /// </summary>
        /// <param name="ext"></param>
        /// <returns></returns>
        public ExcelExport<T> SetExcelProperty(ExcelProperty ext)
        {
            builder.SetWorkbook(ext);
            return this;
        }
    
        /// <summary>
        /// 设置表头
        /// </summary>
        /// <param name="headJson">json形式的表头配置,可以配置多行表头</param>
        /// <returns></returns>
        public ExcelExport<T> SetExcelHeadJson(string headJson)
        {
            this.headJson = headJson;
            return this;
        }
    
        /// <summary>
        /// 设置表头
        /// </summary>
        /// <param name="path">绝对路径,内里保存json形式的表头配置</param>
        /// <returns></returns>
        public ExcelExport<T> SetExcelHeadFromFile(string path)
        {
            //读取配置信息
            this.headJson = File.ReadAllText(path);
            return this;
        }
    
        /// <summary>
        /// 设置表头
        /// </summary>
        /// <param name="headStr">“序号|订单号|订单状态|客户收货情况反馈|商品评价”的形式,仅支持单行表头</param>
        /// <returns></returns>
        public ExcelExport<T> SetExcelHeadStr(string headStr)
        {
            string[] head = headStr.Split('|');
            string headJson = "{"root":{"head":[";
            for (int i = 0, length = head.Length; i < length; i++)
            {
                if (i > 0)
                {
                    headJson += ",";
                }
                headJson += "{";
                headJson += ""text":"" + head [i]+ "",";
                headJson += ""cell_region":"0,0," + i + "," + i + """;
                headJson += "}";
            }
            headJson += "]";
            headJson += "}";
            headJson += "}";
    
            this.headJson = headJson;
            return this;
        }
    
        /// <summary>
        /// 导出WEB
        /// </summary>
        /// <param name="list">数据源(分组后的)</param>
        /// <param name="fileName">将要下载显示的名字</param>
        public void ExportToWeb(List<T> list, string fileName)
        {
            byte[] buffers = ForExport(list, fileName);
            ExportToWebExcel(buffers, fileName);
        }
    
        /// <summary>
        /// 导出到本地存储
        /// </summary>
        /// <param name="list">数据源(分组后的)</param>
        /// <param name="fileName">文件名称,请自己包含路径,例如C:\test.xls</param>
        public void ExportToLocal(List<T> list, string fileName)
        {
            byte[] buffers = ForExport(list, fileName);
            ExportToLocalExcel(buffers, fileName);
        }
    
        #region private
        private byte[] ForExport(List<T> list, string fileName)
        {
            Check(list);
            
            //构建表格
            IWorkbook workbook = builder.BuildExcel<T>(list, headJson, func.ToArray());
            return SaveToByteArray(workbook);
        }
    
        private void Check(List<T> list)
        {
            //表头不算必填项
            //数据却不能为空
            if (list.Count == 0)
            {
                throw new Exception("数据源不能为空");
            }
        }
    
        /// <summary>
        /// 将WorkBook对象转换成内存流
        /// </summary>
        /// <param name="wookbook"></param>
        /// <returns></returns>
        private byte[] SaveToByteArray(IWorkbook wookbook)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                wookbook.Write(ms);
                ms.Flush();
                ms.Position = 0;
                return ms.GetBuffer();
            }
        }
    
        /// <summary>
        ///  本地存储到excel
        /// </summary>
        /// <param name="buffers">文件二进制流</param>
        /// <param name="fileName">文件目录例如C:\test.xls</param>
        private void ExportToLocalExcel(byte[] buffers, string fileName)
        {
            using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buffers, 0, buffers.Length);
                fs.Flush();
            }
        }
    
        /// <summary>
        /// web导出excel
        /// </summary>
        /// <param name="buffers">文件二进制流</param>
        /// <param name="fileName">文件名称</param>
        private void ExportToWebExcel(byte[] buffers, string fileName)
        {
            HttpResponse Response = HttpContext.Current.Response;
    
            Response.BufferOutput = false;
            Response.ContentEncoding = Encoding.UTF8;
            Response.Charset = "utf-8";
    
            Response.ContentType = "application/octet-stream";
            Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
            Response.AddHeader("Content-Length", buffers.Length.ToString());
    
            Response.Clear();
            Response.BinaryWrite(buffers);
            Response.End();
        }
        #endregion
    }
    

      

    表格样式配置

    /**为方便样式书写,属性统一用小写*/
    
    /// <summary>
    /// 根节点, 定义Json表头的格式
    /// </summary>
    public class JsonSetting
    {
        /// <summary>
        /// Root类
        /// </summary>
        public HeadInfo root { get; set; }
    }
    
    #region HeadInfo
    
    /// <summary>
    /// 报表表格头部信息
    /// </summary>
    public class HeadInfo
    {
        /// <summary>
        /// 表头的样式
        /// </summary>
        public IList<Attribute4Head> head { get; set; }
        /// <summary>
        /// 每列单元格的样式
        /// </summary>
        public IList<Attribute4Cell> cell { get; set; }
    
        /// <summary>
        /// 表名,默认sheet
        /// </summary>
        public string sheet_name { get; set; }
    
        /// <summary>
        /// 默认单元格宽度(所有列),不设置则自适应宽度
        /// </summary>
        public int? default_width { get; set; }
    
        /// <summary>
        /// 默认行高度,不设置则使用表格的默认单元格高度
        /// </summary>
        public int? default_height { get; set; }
    
        /// <summary>
        /// 表格边框颜色 例如#000000
        /// </summary>
        public string border_color { get; set; }
    
        /// <summary>
        /// 边框风格,none,thin,dashed,dotted,double 默认 thin
        /// </summary>
        public string border_style { get; set; }
    
        /// <summary>
        /// 分组所在的列(索引从0开始:0,1)
        /// </summary>
        public string group_column { get; set; }
    }
    #endregion
    
    /// <summary>
    /// 关于表头单元格设置属性
    /// </summary>
    public class Attribute4Head : CellAttribute
    {
        /// <summary>
        /// 单元格合并位置,(fromRow,toRow,fromColumn,toColumn)
        /// </summary>
        public string cell_region { get; set; }
        /// <summary>
        /// 显示的文字
        /// </summary>
        public string text { get; set; }
    }
    
    /// <summary>
    /// 关于内容单元格设置属性
    /// </summary>
    public class Attribute4Cell : CellAttribute
    {
        /// <summary>
        /// 数据格式(仅支持Excel的内嵌格式)
        /// </summary>
        public string data_format { get; set; }
    
        /// <summary>
        /// 宽度(内容单元格宽度覆盖默认宽度)
        /// </summary>
        public int? width { get; set; }
    }
    
    #region 公共属性
    /// <summary>
    /// 公共属性
    /// </summary>
    public abstract class CellAttribute
    {
        /// <summary>
        /// 高度(限定行高,一行中只要一个单元格给定高度就可以了,多个单元格都有配置高度时,取最后一次赋值)
        /// </summary>
        public int? height { get; set; }
        /// <summary>
        /// 水平对齐方式 center,left,right
        /// </summary>
        public string align { get; set; }
        /// <summary>
        /// 垂直对齐方式center,top,bottom
        /// </summary>
        public string vertical_align { get; set; }
        /// <summary>
        /// 背景颜色.例如#000000
        /// </summary>
        public string background_color { get; set; }
        /// <summary>
        /// 前景颜色.例如#000000(单元格的背景色有bgcolor和forecolor两个背景色,一般使用forecolor)
        /// </summary>
        public string foreground_color { get; set; }
        /// <summary>
        /// 背景填充方式
        /// </summary>
        public string fill_pattern { get; set; }
        /// <summary>
        /// 字体大小
        /// </summary>
        public short? font_size { get; set; }
        /// <summary>
        /// 字体颜色
        /// </summary>
        public string font_color { get; set; }
        /// <summary>
        /// 字体名称,默认微软雅黑
        /// </summary>
        public string font_name { get; set; }
        /// <summary>
        ///是否是斜体
        /// </summary>
        public bool? italic { get; set; }
        /// <summary>
        /// 是否有中间线
        /// </summary>
        public bool? strike_out { get; set; }
        /// <summary>
        /// 是否设置下划线
        /// </summary>
        public bool? underline { get; set; }
        /// <summary>
        /// 表头文字是否加粗
        /// </summary>
        public bool? font_weight { get; set; }
    }
    

    样式解析

    /// <summary>
    /// 由字符样式读取相应的枚举值
    /// </summary>
    /// <typeparam name="T">枚举类型</typeparam>
    /// <param name="str">字符串</param>
    /// <param name="defaultValue">默认值</param>
    /// <returns></returns>
    private T ToEnumValue<T>(string str,T defaultValue)
    {
        if (string.IsNullOrEmpty(str))
        {
            return defaultValue;
        }
    
        //不区分大小写
        str = str.Trim().ToLower();
        if (str == "0")
        {
            //输入的是数值
            return (T)Enum.Parse(typeof(T),"0");
        }
        else
        {
            var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
            int val = str.ToInt();
            if (val != 0 && val < fields.Length)
            {
                //输入的是数值
                return (T)Enum.Parse(typeof(T), str);
            }
            else
            {
                //输入的是枚举名
                foreach (var fi in fields)
                {
                    var value = fi.GetValue(null);
                    if(value.ToString().ToLower() == str)
                    {
                        return (T)value;
                    }
                }
                return defaultValue;
            }
        }
    }
    
    /// <summary>
    /// 根据十六进制颜色获得颜色索引
    /// </summary>
    /// <param name="workbook"></param>
    /// <param name="color"></param>
    /// <returns></returns>
    private short GetColorIndex(string color, HSSFWorkbook workbook)
    {
        Color colour = ColorTranslator.FromHtml(color);
    
        if (this.XlPalette == null)
        {
            this.XlPalette = workbook.GetCustomPalette();
        }
    
        short s = 0;
        HSSFColor XlColour = XlPalette.FindColor(colour.R, colour.G, colour.B);
        if (XlColour == null)
        {
            XlColour = XlPalette.FindSimilarColor(colour.R, colour.G, colour.B);
            s = XlColour.Indexed;
        }
        else
        {
            s = XlColour.Indexed;
        }
        return s;
    }
    

     涉及到的枚举类型

    涉及到的枚举类型
    
     public enum FillPattern : short
    {
        NoFill = 0,
        SolidForeground = 1,
        FineDots = 2,
        AltBars = 3,
        SparseDots = 4,
        ThickHorizontalBands = 5,
        ThickVerticalBands = 6,
        ThickBackwardDiagonals = 7,
        ThickForwardDiagonals = 8,
        BigSpots = 9,
        Bricks = 10,
        ThinHorizontalBands = 11,
        ThinVerticalBands = 12,
        ThinBackwardDiagonals = 13,
        ThinForwardDiagonals = 14,
        Squares = 15,
        Diamonds = 16,
        LessDots = 17,
        LeastDots = 18
    }
    
    public enum HorizontalAlignment
    {
        General = 0,
        Left = 1,
        Center = 2,
        Right = 3,
        Fill = 4,
        Justify = 5,
        CenterSelection = 6,
        Distributed = 7
    }
    
    public enum VerticalAlignment
    {
        None = -1,
        Top = 0,
        Center = 1,
        Bottom = 2,
        Justify = 3,
        Distributed = 4
    }
    
    public enum BorderStyle : short
    {
        None = 0,
        Thin = 1,
        Medium = 2,
        Dashed = 3,
        Dotted = 4,
        Thick = 5,
        Double = 6,
        Hair = 7,
        MediumDashed = 8,
        DashDot = 9,
        MediumDashDot = 10,
        DashDotDot = 11,
        MediumDashDotDot = 12,
        SlantedDashDot = 13
    }
    

      

    表格建造器

        /// <summary>
        /// 表格建造器
        /// </summary>
        public interface IExcelBuilder
        {
            /// <summary>
            /// 更换样式解析器
            /// </summary>
            IExcelHelper Helper { set; }
    
            /// <summary>
            /// 构建表格
            /// </summary>
            /// <typeparam name="T">泛型实体</typeparam>
            /// <param name="list">要转换的列表</param>
            /// <param name="headJson">json形式的表头配置</param>
            /// <param name="fieldFuncs">字段委托</param>
            /// <returns></returns>
            HSSFWorkbook BuildExcel<T>(List<T> list, string headJson, Func<T, object>[] fieldFuncs);
    
            /// <summary>
            /// 设置excel文件基本属性
            /// </summary>
            /// <param name="ep"></param>
            void SetWorkbook(ExcelProperty ep);
        }
    

      

        /// <summary>
        /// 构建表格
        /// </summary>
        public class ExcelBuilder : IExcelBuilder
        {
            #region 字段及属性
            private const int RowPerSheet = 65530;                             //每张sheet最多数据行数
            private const int MaxColumnWidth = 50;                             //自适应列宽时的上限
            private string SheetName                                           //表名
            {
                get
                {
                    return Helper.SheetName;
                }
            }
            private int HeadRow                                                //表头占据的行数
            {
                get
                {
                    return Helper.HeadRow;
                }
            }
    
            /// <summary>
            /// 样式解析器
            /// </summary>
            public IExcelHelper Helper
            {
                set
                {
                    this.helper = value;
                }
                private get
                {
                    return helper;
                }
            }
    
            private HSSFWorkbook Workbook = new HSSFWorkbook();                //要导出的excel
            private IExcelHelper helper = new ExcelHelper();                   //用于解析属性
            private List<GroupClass> GroupColumn = new List<GroupClass>();     //分组的列的配置信息
            private List<CellRangeAddress> CellRange = new List<CellRangeAddress>(); //要合并的单元格
            private ISheet sheet = null;                                       //要导出的excel对象中的一个表
            #endregion
    
            #region IExcelBuilder
    
            /// <summary>
            /// 构建表格
            /// </summary>
            /// <typeparam name="T">泛型实体</typeparam>
            /// <param name="list">要转换的列表</param>
            /// <param name="headJson">json形式的表头配置</param>
            /// <param name="fieldFuncs">字段委托</param>
            /// <returns></returns>
            public HSSFWorkbook BuildExcel<T>(List<T> list, string headJson, Func<T, object>[] fieldFuncs)
            {
                //获取第一行数据
                List<object> dataRow = GetRowData(list[0], fieldFuncs);
    
                //解析第一行的数据,初步定下每列的默认样式
                Helper.GetStyle(headJson,dataRow, fieldFuncs, Workbook, GroupColumn);
    
                //写入数据
                Process(list, fieldFuncs);
    
                return Workbook;
            }
    
            /// <summary>
            /// 设置excel文件基本属性
            /// </summary>
            /// <param name="ep"></param>
            public void SetWorkbook(ExcelProperty ep)
            {
                DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
                dsi.Company = ep.Company;
                dsi.Manager = ep.Manager;
                dsi.Category = ep.Catagory;
                Workbook.DocumentSummaryInformation = dsi;
                SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
                si.Author = ep.Author;                    //填加xls文件作者信息
                si.ApplicationName = ep.ApplicationName;  //填加xls文件创建程序信息
                si.LastAuthor = ep.LastAuthor;            //填加xls文件最后保存者信息
                si.Comments = ep.Comments;                //填加xls文件作者信息
                si.Title = ep.Title;                      //填加xls文件标题信息
                si.Subject = ep.Subject;                  //填加文件主题信息
                si.Keywords = ep.KeyWord;
                si.CreateDateTime = DateTime.Now;
                si.Comments = ep.Comments;
                Workbook.SummaryInformation = si;
            }
            #endregion
    
            #region 完成从数据到excel的转化
            /// <summary>
            /// 整合数据
            /// </summary>
            /// <typeparam name="T">泛型实体</typeparam>
            /// <param name="list">要转换的列表</param>
            /// <param name="fieldFuncs">字段委托</param>
            private void Process<T>(List<T> list, Func<T, object>[] fieldFuncs)
            {
                //内容行
                int rowNum = -1;
                foreach (T item in list)
                {
                    rowNum++;
    
                    if ((rowNum % RowPerSheet) == 0)
                    {
                        //新建sheet
                        NewSheet(rowNum);
                    }
    
                    //创建新行,获取数据
                    int rowIndex = rowNum % RowPerSheet + HeadRow;
                    IRow row = sheet.CreateRow(rowIndex);
                    if (Helper.CellHeight.HasValue)
                    {
                        //行高
                        row.HeightInPoints = Helper.CellHeight.Value;
                    }
                    List<object> dataRow = GetRowData(item, fieldFuncs);
    
                    //写入
                    int maxIndex = dataRow.Count;
                    
                    for (int colIndex = 0; colIndex < maxIndex; colIndex++)
                    {
                        //bool,时间,字符串,数字
                        var val = dataRow[colIndex];
                        GroupClass groupClass = CheckGroup(colIndex);
                        if (groupClass == null)
                        {
                            ICell cell = row.CreateCell(colIndex);
                            WriteCell(row, cell, colIndex, val, fieldFuncs);
                        }
                        else
                        {
                            //分组
                            MergedRegionInColumn(groupClass, val, fieldFuncs, row, rowIndex, colIndex);
                        }
                    }
                }
    
                //单元格合并
                foreach (var cellRange in CellRange)
                {
                    sheet.AddMergedRegion(cellRange);
                    //设置边框
                    ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(cellRange, Helper.WholeBorderStyle, Helper.WholeBorderColor);
                }
            }
    
            private void NewSheet(int rowNum)
            {
                int sheetIndex = (rowNum / RowPerSheet) + 1;
                sheet = Workbook.CreateSheet(SheetName + sheetIndex);
                //表头
                Helper.SetHeadAndDefaultStyle(Workbook, sheet);
                //新表新列
                for (int i = 0, length = GroupColumn.Count; i < length; i++)
                {
                    GroupColumn[i].Value = null;
                    GroupColumn[i].Count = 0;
                    GroupColumn[i].cellRange = null;
                }
            }
    
            private void MergedRegionInColumn<T>(GroupClass groupClass,object val, Func<T, object>[] fieldFuncs, IRow row, int rowIndex, int colIndex)
            {
                object LastRowValue = groupClass.Value;
                //比对上一行的数据
                if (LastRowValue != null && LastRowValue.Equals(val))
                {
                    //相等则合并单元格,行数累计
    
                    //同一个单元格参与多次单元格合并,最终表格样式会出问题,需要先将旧的合并记录清掉
                    CellRangeAddress lastCellRange = groupClass.cellRange;
                    if (lastCellRange != null)
                    {
                        CellRange.Remove(lastCellRange);
                    }
    
                    //新的合并配置
                    groupClass.Count++;
                    CellRangeAddress cellRange = new CellRangeAddress(rowIndex - groupClass.Count, rowIndex, colIndex, colIndex);
                    CellRange.Add(cellRange);
                    groupClass.cellRange = cellRange;
                }
                else
                {
                    //不等则更新后续分组的信息
                    for (int i = groupClass.Index, length = GroupColumn.Count; i < length; i++)
                    {
                        GroupColumn[i].Value = null;
                        GroupColumn[i].Count = 0;
                        groupClass.cellRange = null;
                    }
                    groupClass.Value = val;
                    //创建新单元格,普通写入操作
                    ICell cell = row.CreateCell(colIndex);
                    WriteCell(row, cell, colIndex, val, fieldFuncs);
                }
            }
            private void WriteCell<T>(IRow row, ICell cell,int colIndex,object val,Func<T, object>[] fieldFuncs)
            {
                ColumnInfo cellInfo = Helper.GetColumnInfo(colIndex);
                if (cellInfo == null)
                {
                    cellInfo = Helper.AddColumn<T>(val, fieldFuncs, Workbook, sheet);
                }
    
                SetValue(cell, val);
                cell.CellStyle = cellInfo.Style;
    
                //调整列宽度
                if (cellInfo.Width == ColumnInfo.Auto)
                {
                    int len = Encoding.GetEncoding(936).GetByteCount(val + "") + 8;
                    if (len > MaxColumnWidth)
                    {
                        len = MaxColumnWidth;
                    }
                    len = len * 256;
                    if (sheet.GetColumnWidth(colIndex) < len)
                    {
                        sheet.SetColumnWidth(colIndex, len);
                    }
                }
            }
    
            #region 取值与填值
    
            /// <summary>
            /// 设置单元格的值
            /// </summary>
            /// <param name="cell"></param>
            /// <param name="val"></param>
            private void SetValue(ICell cell, object val)
            {
                if (val is bool)
                {
                    var data = val.ChangeType<bool>();
                    cell.SetCellValue(data);
                }
                else if (val is DateTime)
                {
                    var data = val.ChangeType<DateTime>();
                    cell.SetCellValue(data);
                }
                else if (val is double ||
                 val is float ||
                 val is long ||
                 val is int ||
                 val is short ||
                 val is byte ||
                 val is decimal)
                {
                    var data = val.ChangeType<double>();
                    cell.SetCellValue(data);
                }
                else
                {
                    var data = val.ToString();
                    cell.SetCellValue(data);
                }
            }
    
            /// <summary>
            /// 解析数据
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="item"></param>
            /// <param name="fieldFuncs"></param>
            /// <returns></returns>
            private List<object> GetRowData<T>(T item, Func<T, object>[] fieldFuncs)
            {
                List<object> dataRow = new List<object>();
                if (fieldFuncs.Length > 0)
                {
                    for (int i = 0; i < fieldFuncs.Length; i++)
                    {
                        dataRow.Add(fieldFuncs[i](item));
                    }
                }
                else
                {
                    if (item is DataRow)
                    {
                        var row = item as DataRow;
                        foreach (DataColumn column in row.Table.Columns)
                        {
                            dataRow.Add(row[column]);
                        }
                    }
                    else if (item is IEnumerable<T>)
                    {
                        foreach (var val in item as IEnumerable<T>)
                        {
                            dataRow.Add(val);
                        }
                    }
                    else
                    {
                        throw new Exception("请添加从数据实例映射到表格行的方法");
                    }
                }
                return dataRow;
            }
    
            #endregion
    
            /// <summary>
            /// 判断当前操作的列是不是要分组
            /// </summary>
            /// <param name="colIndex">列下表</param>
            /// <returns></returns>
            private GroupClass CheckGroup(int colIndex)
            {
                foreach (var item in GroupColumn)
                {
                    if(item.Column == colIndex)
                    {
                        return item;
                    }
                }
                return null;
            }
            #endregion      
        }
    

    表格样式解析器

     /// <summary>
        /// 表格样式解析器
        /// </summary>
        public interface IExcelHelper
        {
            /// <summary>
            /// 内容行的定高
            /// </summary>
            int? CellHeight { get; }
    
            /// <summary>
            /// 表头占据的行数
            /// </summary>
            int HeadRow { get; }
    
            /// <summary>
            /// 表名
            /// </summary>
            string SheetName { get; }
    
            /// <summary>
            /// 整个表格border样式
            /// </summary>
            short WholeBorderColor { get; }
    
            /// <summary>
            /// 整个表格border颜色
            /// </summary>
            BorderStyle WholeBorderStyle { get; }
    
            /// <summary>
            /// 比第一行数据多出的列
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="val"></param>
            /// <param name="fieldFuncs"></param>
            /// <param name="workbook"></param>
            /// <param name="sheet"></param>
            ColumnInfo AddColumn<T>(object val, Func<T, object>[] fieldFuncs, HSSFWorkbook workbook, ISheet sheet);
    
            /// <summary>
            /// 读取列配置
            /// </summary>
            /// <param name="index">列下标</param>
            /// <returns></returns>
            ColumnInfo GetColumnInfo(int index);
    
            /// <summary>
            /// 计算每一列的默认单元格样式
            /// </summary>
            void GetStyle<T>(string headJson, List<object> dataRow, Func<T, object>[] fieldFuncs, HSSFWorkbook workbook, List<GroupClass> groupList);
    
            /// <summary>
            /// 为新sheet设置表头和默认样式
            /// </summary>
            /// <param name="workbook"></param>
            /// <param name="sheet"></param>
            void SetHeadAndDefaultStyle(HSSFWorkbook workbook, ISheet sheet);
        }
    
        /// <summary>
        /// 解析表格样式
        /// </summary>
        public class ExcelHelper : IExcelHelper
        {
            #region 字段及属性
            private IList<Attribute4Head> CellStyle4Head = null;               //头部的配置信息
            private IList<Attribute4Cell> CellStyle4Cell = null;               //列配置信息
            private IList<ColumnInfo> columnInfo = new List<ColumnInfo>();     //记录解析后得到的每列的宽度及样式
            private string sheetName;                                          //表名
            private int headRow = 1;                                           //表头占据的行数
            private int  CellDefaultWidth;                                     //单元格宽度(默认值为ColumnInfo.Auto)
            private int? RowDefaultHeight;                                     //默认单元格高度(内容多了会自动撑高)
            private int? cellHeight;                                           //内容行的定高
            private BorderStyle wholeBorderStyle;                              //整个表格border样式,默认solid(thin)
            private short wholeBorderColor;                                    //整个表格border颜色
            private HSSFPalette XlPalette = null;                              //用于自定义颜色的对象(GetSetting中创建)
    
            /// <summary>
            /// 表名
            /// </summary>
            public string SheetName
            {
                get
                {
                    return sheetName;
                }
            }
    
            /// <summary>
            /// 表头占据的行数
            /// </summary>
            public int HeadRow
            {
                get
                {
                    return headRow;
                }
            }
    
            /// <summary>
            /// 内容行的定高
            /// </summary>
            public int? CellHeight
            {
                get
                {
                    return cellHeight;
                }
            }
    
            /// <summary>
            /// 整个表格border样式
            /// </summary>
            public BorderStyle WholeBorderStyle
            {
                get
                {
                    return wholeBorderStyle;
                }
            }
    
            /// <summary>
            /// 整个表格border颜色
            /// </summary>
            public short WholeBorderColor
            {
                get
                {
                    return wholeBorderColor;
                }
            }
            #endregion
    
            #region 列配置操作
    
            /// <summary>
            /// 比第一行数据多出的列
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="val"></param>
            /// <param name="fieldFuncs"></param>
            /// <param name="workbook"></param>
            /// <param name="sheet"></param>
            public ColumnInfo AddColumn<T>(object val, Func<T, object>[] fieldFuncs, HSSFWorkbook workbook, ISheet sheet)
            {
                ColumnInfo info = GetDefaultCellStyle(val, fieldFuncs, workbook);
                columnInfo.Add(info);
                int index = columnInfo.Count - 1;
                UpdateColumn(index, workbook);
                //设置列宽
                if (info.Width != ColumnInfo.Auto)
                {
                    sheet.SetColumnWidth(index, info.Width * 256);
                }
                return info;
            }
    
            /// <summary>
            /// 依据配置更新列配置
            /// </summary>
            /// <param name="index">列下标</param>
            /// <param name="workbook"></param>
            private void UpdateColumn(int index,HSSFWorkbook workbook)
            {
                ColumnInfo columnInfo = GetColumnInfo(index);
                if (columnInfo != null)
                {
                    //列宽先赋值一个默认宽度
                    columnInfo.Width = this.CellDefaultWidth;
                    ICellStyle cellStyle = columnInfo.Style;
                    //设置单元格边框
                    cellStyle.BorderRight
                        = cellStyle.BorderLeft
                        = cellStyle.BorderBottom
                        = cellStyle.BorderTop
                        = WholeBorderStyle;
                    cellStyle.BottomBorderColor
                           = cellStyle.RightBorderColor
                           = cellStyle.LeftBorderColor
                           = cellStyle.TopBorderColor
                           = WholeBorderColor;
                    //更新样式
                    Attribute4Cell style = null;
                    if (CellStyle4Cell != null && CellStyle4Cell.Count > index)
                    {
                        style = CellStyle4Cell[index];
                    }
                    if (style != null)
                    {
                        //数据格式
                        if (!string.IsNullOrEmpty(style.data_format))
                        {
                            cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat(style.data_format);
                        }
                        //列宽
                        if (style.width.HasValue)
                        {
                            columnInfo.Width = style.width.Value;
                        }
                        //高度
                        if (style.height.HasValue)
                        {
                            this.cellHeight = style.height.Value;
                        }
    
                        //其他属性
                        AdaperCellStyle(cellStyle, style, workbook);
                    }
                }
            }
    
            /// <summary>
            /// 读取列配置
            /// </summary>
            /// <param name="index">列下标</param>
            /// <returns></returns>
            public ColumnInfo GetColumnInfo(int index)
            {
                if (columnInfo.Count > index)
                {
                    return columnInfo[index];
                }
                return null;
            }
            #endregion
    
            #region 解析样式
    
            /// <summary>
            /// 计算每一列的默认单元格样式
            /// </summary>
            public void GetStyle<T>(string headJson, List<object> dataRow, Func<T, object>[] fieldFuncs, HSSFWorkbook workbook, List<GroupClass> groupList)
            {
                // 读取第一行数据,为每列解析默认样式,依序加入cellStyle4Cell
                GetDefaultCellStyle(dataRow, fieldFuncs, workbook);
    
                //解析headJson
                GetSetting(headJson, workbook, groupList);
            }
    
            /// <summary>
            /// 依据一行示例数据为每列解析默认样式,依序加入cellStyle4Cell
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="dataRow"></param>
            /// <param name="fieldFuncs"></param>
            /// <param name="workbook"></param>
            private void GetDefaultCellStyle<T>(List<object> dataRow, Func<T, object>[] fieldFuncs, IWorkbook workbook)
            {
                for (int colIndex = 0; colIndex < dataRow.Count; colIndex++)
                {
                    var val = dataRow[colIndex];
                    ColumnInfo info = GetDefaultCellStyle(val, fieldFuncs, workbook);
                    columnInfo.Add(info);
                }
            }
            /// <summary>
            /// //依据每个单元格对应的数据的数据类型计算出每列的默认样式,列的宽度设为自动
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="val"></param>
            /// <param name="fieldFuncs"></param>
            /// <param name="workbook"></param>
            /// <returns></returns>
            private ColumnInfo GetDefaultCellStyle<T>(object val, Func<T, object>[] fieldFuncs, IWorkbook workbook)
            {
                ICellStyle cellStyle;
                if (val is bool)
                {
                    cellStyle = GetCellStyle(workbook, "默认");
                }
                else if (val is DateTime)
                {
                    var data = val.ChangeType<DateTime>();
                    if (data.Hour == 0 && data.Minute == 0 && data.Second == 0)
                    {
                        cellStyle = GetCellStyle(workbook, "时间");
                    }
                    else
                    {
                        cellStyle = GetCellStyle(workbook, "时间2");
                    }
                }
                else if (val is double ||
                 val is float ||
                 val is long ||
                 val is int ||
                 val is short ||
                 val is byte ||
                 val is decimal)
                {
                    var data = val.ChangeType<double>();
                    if ((val + "").IndexOf(".") > 0)
                    {
                        cellStyle = GetCellStyle(workbook, "数字");
                    }
                    else
                    {
                        cellStyle = GetCellStyle(workbook, "数字2");
                    }
                }
                else
                {
                    cellStyle = GetCellStyle(workbook, "默认");
                }
    
                return new ColumnInfo() { Style = cellStyle, Width = ColumnInfo.Auto };
            }
    
            /// <summary>
            /// 解析json配置
            /// </summary>
            /// <param name="headJson">json字符串</param>
            /// <param name="workbook"></param>
            /// <param name="groupList"></param>
            private void GetSetting(string headJson, HSSFWorkbook workbook, List<GroupClass> groupList)
            {
                JsonSetting T = headJson.ToObject<JsonSetting>();
                //DebugUtils.Log(new MT.Business.Json().Convert2Json(T));
                //==========
    
                //分组的列信息
                GetGroupCellSetting(T.root.group_column, groupList);
    
                //表名
                this.sheetName = T.root.sheet_name;
                if (string.IsNullOrEmpty(this.sheetName))
                {
                    this.sheetName = "sheet";
                }
    
                //默认单元格高度
                this.RowDefaultHeight = T.root.default_height;
                //边框样式
                this.wholeBorderStyle = ToEnumValue<BorderStyle>(T.root.border_style, BorderStyle.Thin);
                //边框颜色
                this.wholeBorderColor = GetColorIndex(T.root.border_color, workbook);
    
                //表头样式
                CellStyle4Head = T.root.head;
                //单元格样式
                CellStyle4Cell = T.root.cell;
                //默认单元格宽度
                this.CellDefaultWidth = (T.root.default_width.HasValue ? T.root.default_width.Value : ColumnInfo.Auto);
    
                //修正每列的配置信息
                for (int i = 0, length = this.columnInfo.Count; i < length; i++)
                {
                    UpdateColumn(i, workbook);
                }
            }
    
            /// <summary>
            /// 初始化分组统计
            /// </summary>
            private void GetGroupCellSetting(string groupColumn, List<GroupClass> list)
            {
                int[] group = (string.IsNullOrEmpty(groupColumn) ? null : ToIntArray(groupColumn.Split(',')));
                if (group != null)
                {
                    //依列下标排序
                    group = group.OrderBy(x => x).ToArray();
                    for (int i = 0, length = group.Length; i < length; i++)
                    {
                        list.Add(new GroupClass { Column = group[i], Count = 0, Index = i });
                    }
                }
            }
    
            #endregion
    
            #region 为新sheet设置表头和默认样式等
    
            /// <summary>
            /// 设置表头和默认样式
            /// </summary>
            /// <param name="workbook"></param>
            /// <param name="sheet"></param>
            public void SetHeadAndDefaultStyle(HSSFWorkbook workbook, ISheet sheet)
            {
                sheet.DisplayGridlines = true;
                if(this.CellDefaultWidth != ColumnInfo.Auto)
                {
                    //默认单元格宽度
                    sheet.DefaultColumnWidth = this.CellDefaultWidth;
                }
                if (this.RowDefaultHeight.HasValue)
                {
                    //设置表格默认行高
                    sheet.DefaultRowHeight = (short)(this.RowDefaultHeight.Value * 20);
                }
    
                //给定的列宽
                for (int i = 0, length = this.columnInfo.Count; i < length; i++)
                {
                    var info = this.columnInfo[i];
                    if (info.Width != ColumnInfo.Auto)
                    {
                        sheet.SetColumnWidth(i, info.Width * 256);
                    }
                }
                //写入表头
                SetHead(workbook,sheet);
            }
    
            /// <summary>
            /// 设置表头
            /// </summary>
            /// <param name="workbook"></param>
            /// <param name="sheet"></param>
            private void SetHead(HSSFWorkbook workbook, ISheet sheet)
            {
                List<IRow> rowList = new List<IRow>();
                //创建行
                for (int i = 0; i < HeadRow; i++)
                {
                    IRow temp = sheet.CreateRow(i);
                    rowList.Add(temp);
                }
    
                for (int i = 0; i < CellStyle4Head.Count; i++)
                {
                    Attribute4Head attribute4Head = CellStyle4Head[i];
                    int[] c = ToIntArray(attribute4Head.cell_region.Split(','));
                    
                    //计算title要插入的位置的索引
                    int txtIndex = -1;
                    int txtRow = -1;
                    if ((c[0] <= c[1] && c[2] <= c[3]))
                    {
                        #region 写入表头
                        //表头所占的列数
                        int _headRow = c[1] + 1;
                        if (headRow<= _headRow)
                        {
                            //创建行
                            for (int j = headRow; j < _headRow; j++)
                            {
                                IRow temp = sheet.CreateRow(j);
                                rowList.Add(temp);
                            }
                            headRow = _headRow;
                        }
    
                        //@ 合并单元格
                        if (c[0] < c[1] || c[2] < c[3])
                        {
                            //例如1,1,2,2 第二行中的第3列,例如1,1,2,7 第二行中的(第3列到8列),合并列
                            CellRangeAddress cellRange = new CellRangeAddress(c[0], c[1], c[2], c[3]);
                            sheet.AddMergedRegion(cellRange);
                            //设置边框
                            ((HSSFSheet)sheet).SetEnclosedBorderOfRegion(cellRange, WholeBorderStyle, WholeBorderColor);
                        }
    
                        //@ 填充内容
                        txtIndex = c[2];
                        txtRow = c[0];
                        ICell cell1 = rowList[txtRow].CreateCell(txtIndex);
    
                        cell1.SetCellValue(attribute4Head.text);
                        cell1.CellStyle = GetHeadCellStyle(workbook, attribute4Head);
    
                        //高度
                        if (attribute4Head.height.HasValue)
                        {
                            rowList[txtRow].HeightInPoints = attribute4Head.height.Value;
                        }
                        #endregion
                    }
                }
                
            }
    
            private ICellStyle GetHeadCellStyle(HSSFWorkbook workbook,Attribute4Head cellStyle)
            {
                ICellStyle headStyle = workbook.CreateCellStyle();
                //设置单元格边框
                headStyle.BorderRight
                    = headStyle.BorderLeft
                    = headStyle.BorderBottom
                    = headStyle.BorderTop
                    = WholeBorderStyle;
                headStyle.BottomBorderColor
                       = headStyle.RightBorderColor
                       = headStyle.LeftBorderColor
                       = headStyle.TopBorderColor
                       = WholeBorderColor;
                //默认样式
                //水平对齐
                headStyle.Alignment = HorizontalAlignment.Center;
    
                //垂直对齐
                headStyle.VerticalAlignment = VerticalAlignment.Center;
    
                IFont font = workbook.CreateFont();
                //字体大小
                font.FontHeightInPoints = 12;
                //字体颜色
                font.Color = 8; //默认黑色
                //字体名称
                font.FontName = "微软雅黑";
                //加粗
                font.Boldweight = (short)FontBoldWeight.Bold;
                headStyle.SetFont(font);
    
                AdaperCellStyle(headStyle, cellStyle, workbook);
                return headStyle;
            }
    
            #endregion
    
            #region 字符串To 样式
    
            /// <summary>
            /// 由字符样式读取响应的枚举值
            /// </summary>
            /// <typeparam name="T">枚举类型</typeparam>
            /// <param name="str">字符串</param>
            /// <param name="defaultValue">默认值</param>
            /// <returns></returns>
            private T ToEnumValue<T>(string str,T defaultValue)
            {
                if (string.IsNullOrEmpty(str))
                {
                    return defaultValue;
                }
    
                //不区分大小写
                str = str.Trim().ToLower();
                if (str == "0")
                {
                    //输入的是数值
                    return (T)Enum.Parse(typeof(T),"0");
                }
                else
                {
                    var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
                    int val = str.ToInt();
                    if (val != 0 && val < fields.Length)
                    {
                        //输入的是数值
                        return (T)Enum.Parse(typeof(T), str);
                    }
                    else
                    {
                        //输入的是枚举名
                        foreach (var fi in fields)
                        {
                            var value = fi.GetValue(null);
                            if(value.ToString().ToLower() == str)
                            {
                                return (T)value;
                            }
                        }
                        return defaultValue;
                    }
                }
            }
    
            /// <summary>
            /// 根据十六进制颜色获得颜色索引
            /// </summary>
            /// <param name="workbook"></param>
            /// <param name="color"></param>
            /// <returns></returns>
            private short GetColorIndex(string color, HSSFWorkbook workbook)
            {
                Color colour = ColorTranslator.FromHtml(color);
    
                if (this.XlPalette == null)
                {
                    this.XlPalette = workbook.GetCustomPalette();
                }
    
                short s = 0;
                HSSFColor XlColour = XlPalette.FindColor(colour.R, colour.G, colour.B);
                if (XlColour == null)
                {
                    XlColour = XlPalette.FindSimilarColor(colour.R, colour.G, colour.B);
                    s = XlColour.Indexed;
                }
                else
                {
                    s = XlColour.Indexed;
                }
                return s;
            }
            #endregion
    
            #region utils
    
            /// <summary>
            /// 依据用户json配置调整样式(公共部分)
            /// </summary>
            /// <param name="defaultCellStyle">默认样式</param>
            /// <param name="cellStyle">json传入的配置信息</param>
            /// <param name="workbook"></param>
            private void AdaperCellStyle(ICellStyle defaultCellStyle, CellAttribute cellStyle, HSSFWorkbook workbook)
            {
                //水平对齐
                if (!string.IsNullOrEmpty(cellStyle.align))
                {
                    defaultCellStyle.Alignment = ToEnumValue<HorizontalAlignment>(cellStyle.align, HorizontalAlignment.Center);
                }
    
                //垂直对齐
                if (!string.IsNullOrEmpty(cellStyle.vertical_align))
                {
                    defaultCellStyle.VerticalAlignment = ToEnumValue<VerticalAlignment>(cellStyle.vertical_align, VerticalAlignment.Center);
                }
    
                //背景颜色
                if (!string.IsNullOrEmpty(cellStyle.background_color) || !string.IsNullOrEmpty(cellStyle.foreground_color))
                {
                    //重复设置背景色,有时候颜色会叠加,这里并不是简单的更换新值……
                    //defaultCellStyle.FillForegroundColor = HSSFColor.White.Index;
                    //defaultCellStyle.FillBackgroundColor = HSSFColor.Maroon.Index;
                    defaultCellStyle.FillPattern = ToEnumValue<FillPattern>(cellStyle.fill_pattern, FillPattern.SolidForeground);
                    if (!string.IsNullOrEmpty(cellStyle.background_color))
                    {
                        //背景色
                        defaultCellStyle.FillBackgroundColor = GetColorIndex(cellStyle.background_color, workbook);
    
                    }
                    if (!string.IsNullOrEmpty(cellStyle.foreground_color))
                    {
                        //前景色
                        defaultCellStyle.FillForegroundColor = GetColorIndex(cellStyle.foreground_color, workbook);
                    }
                }
    
                IFont font = defaultCellStyle.GetFont(workbook);
                //字体大小
                if (cellStyle.font_size.HasValue)
                {
                    font.FontHeightInPoints = cellStyle.font_size.Value; //设置字体大小
                }
                //字体颜色
                if (!string.IsNullOrEmpty(cellStyle.font_color))
                {
                    font.Color = GetColorIndex(cellStyle.font_color, workbook);
                }
                //字体名称
                if (!string.IsNullOrEmpty(cellStyle.font_name))
                {
                    font.FontName = cellStyle.font_name;
                }
                //是否是斜体
                if (cellStyle.italic.HasValue)
                {
                    font.IsItalic = cellStyle.italic.Value ? true : false;
                }
                //是否有中间线
                if (cellStyle.strike_out.HasValue)
                {
                    font.IsStrikeout = cellStyle.strike_out.Value ? true : false;
                }
                //是否设置下划线
                if (cellStyle.underline.HasValue)
                {
                    font.Underline = cellStyle.underline.Value ? FontUnderlineType.Single : FontUnderlineType.None;
                }
                //是否加粗
                if (cellStyle.font_weight.HasValue)
                {
                    font.Boldweight = cellStyle.font_weight.Value ? (short)FontBoldWeight.Bold : (short)FontBoldWeight.None;
                }
            }
    
            /// <summary>
            /// 获取默认样式
            /// </summary>
            /// <param name="wb">IWorkbook</param>
            /// <param name="str">标识</param>
            /// <returns></returns>
            private ICellStyle GetCellStyle(IWorkbook wb, string str)
            {
                ICellStyle cellStyle = wb.CreateCellStyle();
                IFont font = wb.CreateFont();
    
                //字体
                font.FontName = "微软雅黑";
    
                //居中对齐        
                cellStyle.Alignment = HorizontalAlignment.Center;
                //垂直对齐
                cellStyle.VerticalAlignment = VerticalAlignment.Center;
    
                //自动换行
                cellStyle.WrapText = true;
    
                //缩进
                cellStyle.Indention = 0;
                IDataFormat datastyle = wb.CreateDataFormat();
                switch (str)
                {
                    /*
                      HSSFDataFormat.GetBuiltinFormat("0.00") 与 datastyle.GetFormat("yyyy/mm/dd"):
                      前者调用的是Excel的内嵌格式
                    */
                    case "时间":
                        cellStyle.DataFormat = datastyle.GetFormat("yyyy/mm/dd");
                        cellStyle.SetFont(font);
                        break;
                    case "时间2":
                        cellStyle.DataFormat = datastyle.GetFormat("yyyy/mm/dd HH:mm");
                        cellStyle.SetFont(font);
                        break;
                    case "数字":
                        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");
                        cellStyle.SetFont(font);
                        break;
                    case "数字2":
                        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0");
                        cellStyle.SetFont(font);
                        break;
                    case "钱":
                        cellStyle.DataFormat = datastyle.GetFormat("¥#,##0");
                        cellStyle.SetFont(font);
                        break;
                    case "url":
                        font.Underline = FontUnderlineType.Single;
                        font.Color = HSSFColor.OliveGreen.Blue.Index;
                        font.IsItalic = true;
                        cellStyle.SetFont(font);
                        cellStyle.Alignment = HorizontalAlignment.Center;
                        break;
                    case "百分比":
                        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00%");
                        cellStyle.SetFont(font);
                        break;
                    case "中文大写":
                        cellStyle.DataFormat = datastyle.GetFormat("[DbNum2][$-804]0");
                        cellStyle.Alignment = HorizontalAlignment.Center;
                        cellStyle.SetFont(font);
                        break;
                    case "科学计数法":
                        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00E+00");
                        cellStyle.SetFont(font);
                        break;
                    case "默认":
                        cellStyle.SetFont(font);
                        cellStyle.Alignment = HorizontalAlignment.Center;
                        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@");//全部做字符串处理
                        break;
                }
                return cellStyle;
            }
    
            /// <summary>
            /// 字符串数组to整型数组
            /// </summary>
            /// <param name="region">字符串数组</param>
            /// <returns></returns>
            private int[] ToIntArray(string[] region)
            {
                ArrayList aList = new ArrayList();
                foreach (string i in region)
                {
                    aList.Add(Convert.ToInt32(i));
                }
                return (int[])aList.ToArray(typeof(int));
            }
            #endregion
        }
    

    调用

        public class ExamEntity
        {
            public int Id { get; set; }
            /// <summary>
            /// 学生姓名
            /// </summary>
            public string Name { get; set; }
            public bool Sex { get; set; }
            /// <summary>
            /// 考试时间,每次考试时间
            /// </summary>
            public DateTime ExamTime { get; set; }
            /*各科成绩,语数英 物化生*/
            public int Chinese { get; set; }
            public int English { get; set; }
            public int Math { get; set; }
            public int Physics { get; set; }
            public int Chemistry { get; set; }
            public int Biology { get; set; }
            /// <summary>
            /// 总分
            /// </summary>
            public int SumCount { get; set; }
    
        }
        public List<ExamEntity> exam = new List<ExamEntity> {
              new ExamEntity{Id=1,Name="张三",ExamTime=Convert.ToDateTime("2013-03-01 08:30:00"),Chinese=122,English=111,Math=90,Physics=50,Chemistry=80,Biology=40,SumCount=493},
              new ExamEntity{Id=1,Name="张三",ExamTime=Convert.ToDateTime("2013-04-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529},
              new ExamEntity{Id=1,Name="张三",ExamTime=Convert.ToDateTime("2013-05-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529},
               new ExamEntity{Id=2,Name="李四",ExamTime=Convert.ToDateTime("2013-03-01 08:30:00"),Chinese=122,English=111,Math=90,Physics=50,Chemistry=80,Biology=40,SumCount=493},
              new ExamEntity{Id=2,Name="李四",ExamTime=Convert.ToDateTime("2013-04-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529},
              new ExamEntity{Id=2,Name="李四",ExamTime=Convert.ToDateTime("2013-05-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529},
              new ExamEntity{Id=3,Name="王五",ExamTime=Convert.ToDateTime("2013-03-01 08:30:00"),Chinese=122,English=111,Math=90,Physics=50,Chemistry=80,Biology=40,SumCount=493},
              new ExamEntity{Id=3,Name="王五",ExamTime=Convert.ToDateTime("2013-04-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529},
              new ExamEntity{Id=4,Name="陈流",ExamTime=Convert.ToDateTime("2013-05-01 08:30:00"),Chinese=109,English=100,Math=100,Physics=90,Chemistry=70,Biology=60,SumCount=529}
            };
        protected void daochu(object sender, EventArgs e)
        {
            string json = @"{ 'root':{'sheet_name':'学生成绩','default_width':12,'group_column': '0,1,2,3','head':[ {
                                                                           'text':'编号',
                                                                           'height':54,
                                                                          'cell_region':'0,2,0,0'
                                                                       },
                                                                      {
                                                                          'text':'学生姓名',
                                                                          'cell_region':'0,2,1,1'
                                                                     },
                                                                        {
                                                                          'text':'性别',
                                                                          'cell_region':'0,2,2,2'
                                                                     }, {
                                                                          'text':'考试时间',
                                                                          'cell_region':'0,2,3,3'
                                                                     }, {
                                                                          'text':'主科目',
     'height':18,
                                                                          'cell_region':'0,0,4,6'
                                                                     }, {
                                                                          'text':'副科目',
                                                                          'cell_region':'0,1,7,9'
                                                                     }, 
                                                                         {
                                                                          'text':'必修课',
                                                                        'height':18,
                                                                          'cell_region':'1,1,4,5'
                                                                     }, {
                                                                          'text':'选修课',
                                                                          'cell_region':'1,1,6,6'
                                                                     }, 
                                                                    {
                                                                          'text':'语文',
                                                                          'height':18,  
                                                                          'cell_region':'2,2,4,4'
                                                                     }, {
                                                                          'text':'数学',
                                                                          'cell_region':'2,2,5,5'
                                                                     }, {
                                                                          'text':'英语',
                                                                          'cell_region':'2,2,6,6'
                                                                     }, {
                                                                          'text':'物理',
                                                                          'cell_region':'2,2,7,7'
                                                                     }, {
                                                                          'text':'化学',
                                                                          'cell_region':'2,2,8,8'
                                                                     }, {
                                                                          'text':'生物',
                                                                          'cell_region':'2,2,9,9'
                                                                     }, {
                                                                          'text':'总分',
                                                                          'cell_region':'0,2,10,10'
                                                                     }
                                                                        ],
                                                                   'cell':[{},{},{},{'width':30}]
                                                                    }
                                                                   }";
            //处理数据源,对要分组的几列进行排序(order by Name,ExamTime)
            List<ExamEntity> exams = exam.OrderByDescending(x => x.Name).ThenByDescending(x => x.ExamTime).ToList<ExamEntity>();
    
            new ExcelExport<ExamEntity>()
                        //.SetExcelHeadStr(headStr)
                        .SetExcelHeadJson(json)
                        .Column(a => a.Id)
                        .Column(a => a.Name)
                        .Column(a => a.Sex ? "男" : "女")
                        .Column(a => a.ExamTime)
                        .Column(a => a.Chinese)
                        .Column(a => a.Math)
                        .Column(a => a.English)
                        .Column(a => a.Physics)
                        .Column(a => a.Chemistry)
                        .Column(a => a.Biology)
                        .Column(a => a.SumCount)
                        .ExportToWeb(exams, "daochu.xls");
        }
    
  • 相关阅读:
    java陷阱一箩筐面试
    应用MVC设计模式解决J2ME应用程序导航问题 mingjava
    我怎么了
    运营商掘宝手机游戏 无限“钱途”引人竞折腰
    网络工程师考试大纲
    java 正则
    java集合使用——LinkedList
    java集合使用——HashMap
    java集合使用——HashSet
    JAVA集合使用——基本概念
  • 原文地址:https://www.cnblogs.com/wj033/p/5544481.html
Copyright © 2020-2023  润新知