using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SysBaseLibs
{
    public class ExcelHelper
    {
        /// 
        /// 将数据导出至Excel文件
        /// 
        /// DataTable对象
        /// Excel文件路径
        public static bool OutputToExcel(DataTable Table, string ExcelFilePath)
        {
            if (File.Exists(ExcelFilePath))
            {
                throw new Exception("该文件已经存在!");
            }
            if ((Table.TableName.Trim().Length == 0) || (Table.TableName.ToLower() == "table"))
            {
                Table.TableName = "Sheet1";
            }
            //数据表的列数
            int ColCount = Table.Columns.Count;
            //用于记数,实例化参数时的序号
            int i = 0;
            //创建参数
            OleDbParameter[] para = new OleDbParameter[ColCount];
            //创建表结构的SQL语句
            string TableStructStr = @"Create Table " + Table.TableName + "(";
            //连接字符串
            string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0;";
            OleDbConnection objConn = new OleDbConnection(connString);
            //创建表结构
            OleDbCommand objCmd = new OleDbCommand();
            //数据类型集合
            ArrayList DataTypeList = new ArrayList();
            DataTypeList.Add("System.Decimal");
            DataTypeList.Add("System.Double");
            DataTypeList.Add("System.Int16");
            DataTypeList.Add("System.Int32");
            DataTypeList.Add("System.Int64");
            DataTypeList.Add("System.Single");
            //遍历数据表的所有列,用于创建表结构
            foreach (DataColumn col in Table.Columns)
            {
                //如果列属于数字列,则设置该列的数据类型为double
                if (DataTypeList.IndexOf(col.DataType.ToString()) >= 0)
                {
                    para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.Double);
                    objCmd.Parameters.Add(para[i]);
                    //如果是最后一列
                    if (i + 1 == ColCount)
                    {
                        TableStructStr += col.ColumnName + " double)";
                    }
                    else
                    {
                        TableStructStr += col.ColumnName + " double,";
                    }
                }
                else
                {
                    para[i] = new OleDbParameter("@" + col.ColumnName, OleDbType.VarChar);
                    objCmd.Parameters.Add(para[i]);
                    //如果是最后一列
                    if (i + 1 == ColCount)
                    {
                        TableStructStr += col.ColumnName + " varchar)";
                    }
                    else
                    {
                        TableStructStr += col.ColumnName + " varchar,";
                    }
                }
                i++;
            }
            //创建Excel文件及文件结构
            try
            {
                objCmd.Connection = objConn;
                objCmd.CommandText = TableStructStr;
                if (objConn.State == ConnectionState.Closed)
                {
                    objConn.Open();
                }
                objCmd.ExecuteNonQuery();
            }
            catch (Exception exp)
            {
                throw exp;
            }
            //插入记录的SQL语句
            string InsertSql_1 = "Insert into " + Table.TableName + " (";
            string InsertSql_2 = " Values (";
            string InsertSql = "";
            //遍历所有列,用于插入记录,在此创建插入记录的SQL语句
            for (int colID = 0; colID < ColCount; colID++)
            {
                if (colID + 1 == ColCount)  //最后一列
                {
                    InsertSql_1 += Table.Columns[colID].ColumnName + ")";
                    InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ")";
                }
                else
                {
                    InsertSql_1 += Table.Columns[colID].ColumnName + ",";
                    InsertSql_2 += "@" + Table.Columns[colID].ColumnName + ",";
                }
            }
            InsertSql = InsertSql_1 + InsertSql_2;
            //遍历数据表的所有数据行
            for (int rowID = 0; rowID < Table.Rows.Count; rowID++)
            {
                for (int colID = 0; colID < ColCount; colID++)
                {
                    if (para[colID].DbType == DbType.Double && Table.Rows[rowID][colID].ToString().Trim() == "")
                    {
                        para[colID].Value = 0;
                    }
                    else
                    {
                        para[colID].Value = Table.Rows[rowID][colID].ToString().Trim();
                    }
                }
                try
                {
                    objCmd.CommandText = InsertSql;
                    objCmd.ExecuteNonQuery();
                }
                catch (Exception exp)
                {
                    string str = exp.Message;
                }
            }
            try
            {
                if (objConn.State == ConnectionState.Open)
                {
                    objConn.Close();
                }
            }
            catch (Exception exp)
            {
                throw exp;
            }
            return true;
        }
        /// 
        /// 将数据导出至Excel文件
        /// 
        /// DataTable对象
        /// 要导出的数据列集合
        /// Excel文件路径
        public static bool OutputToExcel(DataTable Table, ArrayList Columns, string ExcelFilePath)
        {
            if (File.Exists(ExcelFilePath))
            {
                throw new Exception("该文件已经存在!");
            }
            //如果数据列数大于表的列数,取数据表的所有列
            if (Columns.Count > Table.Columns.Count)
            {
                for (int s = Table.Columns.Count + 1; s <= Columns.Count; s++)
                {
                    Columns.RemoveAt(s);   //移除数据表列数后的所有列
                }
            }
            //遍历所有的数据列,如果有数据列的数据类型不是 DataColumn,则将它移除
            DataColumn column = new DataColumn();
            for (int j = 0; j < Columns.Count; j++)
            {
                try
                {
                    column = (DataColumn)Columns[j];
                }
                catch (Exception)
                {
                    Columns.RemoveAt(j);
                }
            }
            if ((Table.TableName.Trim().Length == 0) || (Table.TableName.ToLower() == "table"))
            {
                Table.TableName = "Sheet1";
            }
            //数据表的列数
            int ColCount = Columns.Count;
            //创建参数
            OleDbParameter[] para = new OleDbParameter[ColCount];
            //创建表结构的SQL语句
            string TableStructStr = @"Create Table " + Table.TableName + "(";
            //连接字符串
            string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0;";
            OleDbConnection objConn = new OleDbConnection(connString);
            //创建表结构
            OleDbCommand objCmd = new OleDbCommand();
            //数据类型集合
            ArrayList DataTypeList = new ArrayList();
            DataTypeList.Add("System.Decimal");
            DataTypeList.Add("System.Double");
            DataTypeList.Add("System.Int16");
            DataTypeList.Add("System.Int32");
            DataTypeList.Add("System.Int64");
            DataTypeList.Add("System.Single");
            DataColumn col = new DataColumn();
            //遍历数据表的所有列,用于创建表结构
            for (int k = 0; k < ColCount; k++)
            {
                col = (DataColumn)Columns[k];
                //列的数据类型是数字型
                if (DataTypeList.IndexOf(col.DataType.ToString().Trim()) >= 0)
                {
                    para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.Double);
                    objCmd.Parameters.Add(para[k]);
                    //如果是最后一列
                    if (k + 1 == ColCount)
                    {
                        TableStructStr += col.Caption.Trim() + " Double)";
                    }
                    else
                    {
                        TableStructStr += col.Caption.Trim() + " Double,";
                    }
                }
                else
                {
                    para[k] = new OleDbParameter("@" + col.Caption.Trim(), OleDbType.VarChar);
                    objCmd.Parameters.Add(para[k]);
                    //如果是最后一列
                    if (k + 1 == ColCount)
                    {
                        TableStructStr += col.Caption.Trim() + " VarChar)";
                    }
                    else
                    {
                        TableStructStr += col.Caption.Trim() + " VarChar,";
                    }
                }
            }
            //创建Excel文件及文件结构
            try
            {
                objCmd.Connection = objConn;
                objCmd.CommandText = TableStructStr;
                if (objConn.State == ConnectionState.Closed)
                {
                    objConn.Open();
                }
                objCmd.ExecuteNonQuery();
            }
            catch (Exception exp)
            {
                throw exp;
            }
            //插入记录的SQL语句
            string InsertSql_1 = "Insert into " + Table.TableName + " (";
            string InsertSql_2 = " Values (";
            string InsertSql = "";
            //遍历所有列,用于插入记录,在此创建插入记录的SQL语句
            for (int colID = 0; colID < ColCount; colID++)
            {
                if (colID + 1 == ColCount)  //最后一列
                {
                    InsertSql_1 += Columns[colID].ToString().Trim() + ")";
                    InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ")";
                }
                else
                {
                    InsertSql_1 += Columns[colID].ToString().Trim() + ",";
                    InsertSql_2 += "@" + Columns[colID].ToString().Trim() + ",";
                }
            }
            InsertSql = InsertSql_1 + InsertSql_2;
            //遍历数据表的所有数据行
            DataColumn DataCol = new DataColumn();
            for (int rowID = 0; rowID < Table.Rows.Count; rowID++)
            {
                for (int colID = 0; colID < ColCount; colID++)
                {
                    //因为列不连续,所以在取得单元格时不能用行列编号,列需得用列的名称
                    DataCol = (DataColumn)Columns[colID];
                    if (para[colID].DbType == DbType.Double && Table.Rows[rowID][DataCol.Caption].ToString().Trim() == "")
                    {
                        para[colID].Value = 0;
                    }
                    else
                    {
                        para[colID].Value = Table.Rows[rowID][DataCol.Caption].ToString().Trim();
                    }
                }
                try
                {
                    objCmd.CommandText = InsertSql;
                    objCmd.ExecuteNonQuery();
                }
                catch (Exception exp)
                {
                    string str = exp.Message;
                }
            }
            try
            {
                if (objConn.State == ConnectionState.Open)
                {
                    objConn.Close();
                }
            }
            catch (Exception exp)
            {
                throw exp;
            }
            return true;
        }
        /// 
        /// 获取Excel文件数据表列表
        /// 
        public static ArrayList GetExcelTables(string ExcelFileName)
        {
            DataTable dt = new DataTable();
            ArrayList TablesList = new ArrayList();
            if (File.Exists(ExcelFileName))
            {
                using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName))
                {
                    try
                    {
                        conn.Open();
                        dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
                    }
                    catch (Exception exp)
                    {
                        throw exp;
                    }
                    //获取数据表个数
                    int tablecount = dt.Rows.Count;
                    for (int i = 0; i < tablecount; i++)
                    {
                        string tablename = dt.Rows[i][2].ToString().Trim().TrimEnd('$');
                        if (TablesList.IndexOf(tablename) < 0)
                        {
                            TablesList.Add(tablename);
                        }
                    }
                }
            }
            return TablesList;
        }
        /// 
        /// 将Excel文件导出至DataTable(第一行作为表头)
        /// 
        /// Excel文件路径
        /// 数据表名,如果数据表名错误,默认为第一个数据表名
        public static DataTable InputFromExcel(string ExcelFilePath, string TableName)
        {
            if (!File.Exists(ExcelFilePath))
            {
                throw new Exception("Excel文件不存在!");
            }
            //如果数据表名不存在,则数据表名为Excel文件的第一个数据表
            ArrayList TableList = new ArrayList();
            TableList = GetExcelTables(ExcelFilePath);
            if (TableName.IndexOf(TableName) < 0)
            {
                TableName = TableList[0].ToString().Trim();
            }
            DataTable table = new DataTable();
            OleDbConnection dbcon = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 8.0");
            OleDbCommand cmd = new OleDbCommand("select * from [" + TableName + "$]", dbcon);
            OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
            try
            {
                if (dbcon.State == ConnectionState.Closed)
                {
                    dbcon.Open();
                }
                adapter.Fill(table);
            }
            catch (Exception exp)
            {
                throw exp;
            }
            finally
            {
                if (dbcon.State == ConnectionState.Open)
                {
                    dbcon.Close();
                }
            }
            return table;
        }
        /// 
        /// 获取Excel文件指定数据表的数据列表
        /// 
        /// Excel文件名
        /// 数据表名
        public static ArrayList GetExcelTableColumns(string ExcelFileName, string TableName)
        {
            DataTable dt = new DataTable();
            ArrayList ColsList = new ArrayList();
            if (File.Exists(ExcelFileName))
            {
                using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + ExcelFileName))
                {
                    conn.Open();
                    dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, TableName, null });
                    //获取列个数
                    int colcount = dt.Rows.Count;
                    for (int i = 0; i < colcount; i++)
                    {
                        string colname = dt.Rows[i]["Column_Name"].ToString().Trim();
                        ColsList.Add(colname);
                    }
                }
            }
            return ColsList;
        }
        public static bool dataTableToCsv(DataTable table, string file)
        {
            bool lcRetval = false;
            if (File.Exists(file))
            {
                throw new Exception("该文件已经存在!");
            }
            try
            {
                string title = "";
                FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
                //FileStream fs1 = File.Open(file, FileMode.Open, FileAccess.Read);
                StreamWriter sw = new StreamWriter(new BufferedStream(fs), System.Text.Encoding.Default);
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    title += table.Columns[i].ColumnName + "\t"; //栏位:自动跳到下一单元格
                }
                title = title.Substring(0, title.Length - 1) + "\n";
                sw.Write(title);
                foreach (DataRow row in table.Rows)
                {
                    string line = "";
                    for (int i = 0; i < table.Columns.Count; i++)
                    {
                        line += row[i].ToString().Trim() + "\t"; //内容:自动跳到下一单元格
                    }
                    line = line.Substring(0, line.Length - 1) + "\n";
                    sw.Write(line);
                }
                sw.Close();
                fs.Close();
                lcRetval = true;
            }catch(Exception err)
            {
                ThreadLog.LogException(err);
            }
            return lcRetval;
        }
    }
    public static class ExcelHelper2
    {
        #region Excel导入
        /// 
        /// 从Excel取数据并记录到List集合里
        /// 
        /// 单元头的值和名称:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// 保存文件绝对路径
        /// 错误信息
        /// 数据行开始序列,默认为1(即第二列,从0开始)
        /// 转换后的List对象集合
        public static List ExcelToEntityList(this Dictionary cellHeader, string filePath, out string errMsg, int startIndex = 1) where T : new()
        {
            List enlist = new List();
            var errorMsg = new StringBuilder();
            try
            {
                if (Regex.IsMatch(filePath, ".xls$")) // 2003
                {
                    enlist = Excel2003ToEntityList(cellHeader, filePath, out errorMsg, startIndex);
                }
                else if (Regex.IsMatch(filePath, ".xlsx$")) // 2007
                {
                    enlist = Excel2007ToEntityList(cellHeader, filePath, out errorMsg, startIndex);
                }
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                //typeof(ExcelHelper).LogError(ex);
                return default(List);
            }
            errMsg = errorMsg.ToString();
            return enlist;
        }
        /// 
        /// 从Excel2003取数据并记录到List集合里
        /// 
        /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// 保存文件绝对路径
        /// 错误信息
        /// 
        /// 转换好的List对象集合
        private static List Excel2003ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new()
        {
            errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息
            List enlist = new List(); // 转换后的集合
            try
            {
                using (FileStream fs = File.OpenRead(filePath))
                {
                    HSSFWorkbook workbook = new HSSFWorkbook(fs);
                    HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++)
                    {
                        // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作
                        IRow row = sheet.GetRow(rowIndex);
                        if (row == null)
                        {
                            break;
                        }
                        // 2.每一个Excel row转换为一个实体对象
                        T en = new T();
                        ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg);
                        enlist.Add(en);
                    }
                }
                return enlist;
            }
            catch (Exception ex)
            {
                //typeof(ExcelHelper).LogError(ex);
                return default(List);
            }
        }
        /// 
        /// 从Excel2007取数据并记录到List集合里
        /// 
        /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// 保存文件绝对路径
        /// 错误信息
        /// 数据行开始序列,默认为1(即第二列,从0开始)
        /// 转换好的List对象集合
        private static List Excel2007ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1)
            where T : new()
        {
            errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息
            List enlist = new List(); // 转换后的集合
            try
            {
                using (FileStream fs = File.OpenRead(filePath))
                {
                    XSSFWorkbook workbook = new XSSFWorkbook(fs);
                    XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++)
                    {
                        // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作
                        IRow row = sheet.GetRow(rowIndex);
                        if (row == null)
                        {
                            break;
                        }
                        // 2.每一个Excel row转换为一个实体对象
                        T en = new T();
                        ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg);
                        enlist.Add(en);
                    }
                }
                return enlist;
            }
            catch (Exception ex)
            {
                //typeof(ExcelHelper).LogError(ex);
                return default(List);
            }
        }
        #endregion Excel导入
        #region Excel导出
        /// 
        /// 实体类集合导出到EXCEL2003
        /// 
        /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// 数据源
        /// 工作表名称
        /// 文件的下载地址
        /// 
        public static string EntityListToExcel2003(this Dictionary cellHeader, IList enList, string sheetName, string filePath)
        {
            var lcRetVal = "error@";
            try
            {
                string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称
                filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath);
                filePath = filePath.EndsWith("/") ? filePath : (filePath + "/");
                string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                // 2.解析单元格头部,设置单元头的中文名称
                HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿
                ISheet sheet = workbook.CreateSheet(sheetName); // 工作表
                IRow row = sheet.CreateRow(0);
                List keys = cellHeader.Keys.ToList();
                for (int i = 0; i < keys.Count; i++)
                {
                    row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值
                }
                // 3.List对象的值赋值到Excel的单元格里
                int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头)
                object propertyValue = null;
                foreach (var en in enList)
                {
                    IRow rowTmp = sheet.CreateRow(rowIndex);
                    for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值
                    {
                        string cellValue = "";
                        PropertyInfo propertyInfo = null; // 属性的信息
                        // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName
                        string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                        if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0)
                        {
                            // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理)
                            string subClassName = propertyArray[0]; // '.'前面的为子类的名称
                            string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称
                            PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型
                            if (subClassInfo != null)
                            {
                                // 3.1.2 获取子类的实例
                                var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null);
                                // 3.1.3 根据属性名称获取子类里的属性类型
                                propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName);
                                if (propertyInfo != null)
                                {
                                    propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值
                                }
                            }
                        }
                        else
                        {
                            // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性
                            propertyInfo = en.GetType().GetProperty(keys[i]);
                            if (propertyInfo != null)
                            {
                                propertyValue = propertyInfo.GetValue(en, null);
                            }
                        }
                        // 3.3 属性值经过转换赋值给单元格值
                        if (propertyValue != null)
                        {
                            if (propertyInfo?.PropertyType.Name == "int" || propertyInfo?.PropertyType.Name == "float" || propertyInfo?.PropertyType.Name == "double" || propertyInfo?.PropertyType.Name == "decimal")
                            {
                                var value = Convert.ToDouble(propertyValue);
                                rowTmp.CreateCell(i).SetCellValue(value);
                            }
                            else if (propertyInfo?.PropertyType.Name == "bool")
                            {
                                var value = Convert.ToBoolean(propertyValue);
                                rowTmp.CreateCell(i).SetCellValue(value);
                            }
                            else
                            {
                                cellValue = propertyValue.ToString();
                                // 3.3.1 对时间初始值赋值为空
                                if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59")
                                {
                                    cellValue = "";
                                }
                                // 3.4 填充到Excel的单元格里
                                rowTmp.CreateCell(i).SetCellValue(cellValue);
                            }
                        }
                        else
                        {
                            // 3.4 填充到Excel的单元格里
                            rowTmp.CreateCell(i).SetCellValue(cellValue);
                        }
                    }
                    rowIndex++;
                }
                // 4.生成文件
                FileStream file = new FileStream($"{path}{fileName}", FileMode.Create);
                workbook.Write(file);
                file.Close();
                lcRetVal = $"{filePath}{fileName}";
            }
            catch (Exception ex)
            {
                lcRetVal += ex.Message;
                //typeof(ExcelHelper).LogError(ex);
            }
            return lcRetVal;
        }
        public static string EntityListToExcel2003(this HSSFWorkbook workbook,
            string sheetName, string filePath)
        {
            var lcRetVal = "error@";
            try
            {
                string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称
                filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath);
                filePath = filePath.EndsWith("/") ? filePath : (filePath + "/");
                string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                FileStream file = new FileStream($"{path}{fileName}", FileMode.Create);
                workbook.Write(file);
                file.Close();
                lcRetVal = $"{filePath}{fileName}";
            }
            catch (Exception ex)
            {
                lcRetVal += ex.Message;
                //typeof(ExcelHelper).LogError(ex);
            }
            return lcRetVal;
        }
        public static HSSFWorkbook EntityListToExcel2003Book(this Dictionary cellHeader, IList enList,
            string sheetName)
        {
            HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿
            ISheet sheet = workbook.CreateSheet(sheetName); // 工作表
            IRow row = sheet.CreateRow(0);
            List keys = cellHeader.Keys.ToList();
            for (int i = 0; i < keys.Count; i++)
            {
                row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值
            }
            // 3.List对象的值赋值到Excel的单元格里
            int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头)
            foreach (var en in enList)
            {
                IRow rowTmp = sheet.CreateRow(rowIndex);
                for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值
                {
                    string cellValue = ""; // 单元格的值
                    object propertyValue = null; // 属性的值
                    PropertyInfo propertyInfo; // 属性的信息
                    // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName
                    if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0)
                    {
                        // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理)
                        string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                        string subClassName = propertyArray[0]; // '.'前面的为子类的名称
                        string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称
                        PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型
                        if (subClassInfo != null)
                        {
                            // 3.1.2 获取子类的实例
                            var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null);
                            // 3.1.3 根据属性名称获取子类里的属性类型
                            propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName);
                            if (propertyInfo != null)
                            {
                                propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值
                            }
                        }
                    }
                    else
                    {
                        // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性
                        propertyInfo = en.GetType().GetProperty(keys[i]);
                        if (propertyInfo != null)
                        {
                            propertyValue = propertyInfo.GetValue(en, null);
                        }
                    }
                    // 3.3 属性值经过转换赋值给单元格值
                    if (propertyValue != null)
                    {
                        cellValue = propertyValue.ToString();
                        // 3.3.1 对时间初始值赋值为空
                        if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59")
                        {
                            cellValue = "";
                        }
                    }
                    // 3.4 填充到Excel的单元格里
                    rowTmp.CreateCell(i).SetCellValue(cellValue);
                }
                rowIndex++;
            }
            return workbook;
        }
        /// 
        /// 实体类集合导出到EXCEL2007
        /// 
        /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// 数据源
        /// 工作表名称
        /// 文件的下载地址
        /// 
        public static string EntityListToExcel2007(this Dictionary cellHeader, IList enList, string sheetName, string filePath)
        {
            var lcRetVal = "error@";
            try
            {
                string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xlsx"; // 文件名称
                filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath);
                filePath = filePath.EndsWith("/") ? filePath : (filePath + "/");
                string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                // 2.解析单元格头部,设置单元头的中文名称
                XSSFWorkbook workbook = new XSSFWorkbook(); // 工作簿
                ISheet sheet = workbook.CreateSheet(sheetName); // 工作表
                IRow row = sheet.CreateRow(0);
                List keys = cellHeader.Keys.ToList();
                for (int i = 0; i < keys.Count; i++)
                {
                    row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值
                }
                // 3.List对象的值赋值到Excel的单元格里
                int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头)
                foreach (var en in enList)
                {
                    IRow rowTmp = sheet.CreateRow(rowIndex);
                    for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值
                    {
                        string cellValue = ""; // 单元格的值
                        object propertyValue = null; // 属性的值
                        PropertyInfo propertyInfo = null; // 属性的信息
                        // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName
                        if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0)
                        {
                            // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理)
                            string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                            string subClassName = propertyArray[0]; // '.'前面的为子类的名称
                            var subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称
                            PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型
                            if (subClassInfo != null)
                            {
                                // 3.1.2 获取子类的实例
                                var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null);
                                // 3.1.3 根据属性名称获取子类里的属性类型
                                propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName);
                                if (propertyInfo != null)
                                {
                                    propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值
                                }
                            }
                        }
                        else
                        {
                            // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性
                            propertyInfo = en.GetType().GetProperty(keys[i]);
                            if (propertyInfo != null)
                            {
                                propertyValue = propertyInfo.GetValue(en, null);
                            }
                        }
                        // 3.3 属性值经过转换赋值给单元格值
                        if (propertyValue != null)
                        {
                            if (propertyInfo.PropertyType.Name.ToLower() == "int" || propertyInfo.PropertyType.Name.ToLower() == "int16" || propertyInfo.PropertyType.Name.ToLower() == "int32" || propertyInfo.PropertyType.Name.ToLower() == "int64" || propertyInfo.PropertyType.Name.ToLower() == "double" || propertyInfo.PropertyType.Name.ToLower() == "decimal")
                            {
                                var value = Convert.ToDouble(propertyValue);
                                rowTmp.CreateCell(i).SetCellValue(value);
                            }
                            else if (propertyInfo.PropertyType.Name.ToLower() == "bool")
                            {
                                var value = Convert.ToBoolean(propertyValue);
                                rowTmp.CreateCell(i).SetCellValue(value);
                            }
                            else if (propertyInfo.PropertyType.Name.ToLower() == "nullable`1")
                            {
                                if (propertyInfo.PropertyType.FullName == null)
                                {
                                }
                                else if (propertyInfo.PropertyType.FullName.ToLower().Contains("datetime"))
                                {
                                    cellValue = propertyValue.ToString();
                                    // 3.3.1 对时间初始值赋值为空
                                    if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59")
                                    {
                                        cellValue = "";
                                    }
                                    rowTmp.CreateCell(i).SetCellValue(cellValue);
                                }
                                else if (propertyInfo.PropertyType.FullName.ToLower().Contains("int"))
                                {
                                    var value = (int)Convert.ChangeType(propertyValue, typeof(int));
                                    rowTmp.CreateCell(i).SetCellValue(value);
                                }
                                else if (propertyInfo.PropertyType.FullName.ToLower().Contains("float") || propertyInfo.PropertyType.FullName.ToLower().Contains("double") || propertyInfo.PropertyType.FullName.ToLower().Contains("decimal") || propertyInfo.PropertyType.FullName.ToLower().Contains("single"))
                                {
                                    var value = (float)Convert.ChangeType(propertyValue, typeof(float));
                                    rowTmp.CreateCell(i).SetCellValue(value);
                                }
                                else if (propertyInfo.PropertyType.FullName.ToLower().Contains("bool"))
                                {
                                    var value = (bool)Convert.ChangeType(propertyValue, typeof(bool));
                                    rowTmp.CreateCell(i).SetCellValue(value);
                                }
                            }
                            else
                            {
                                cellValue = propertyValue.ToString();
                                // 3.3.1 对时间初始值赋值为空
                                if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59")
                                {
                                    cellValue = "";
                                }
                                // 3.4 填充到Excel的单元格里
                                rowTmp.CreateCell(i).SetCellValue(cellValue);
                            }
                        }
                        else
                        {
                            // 3.4 填充到Excel的单元格里
                            rowTmp.CreateCell(i).SetCellValue(cellValue);
                        }
                    }
                    rowIndex++;
                }
                // 4.生成文件
                FileStream file = new FileStream($"{path}{fileName}", FileMode.Create);
                workbook.Write(file);
                file.Close();
                lcRetVal = $"{filePath}{fileName}";
            }
            catch (Exception ex)
            {
                lcRetVal += ex.Message;
                //typeof(ExcelHelper).LogError(ex);
            }
            return lcRetVal;
        }
        #endregion Excel导出
        #region Common
        /// 
        /// Excel row转换为实体对象
        /// 
        /// 
        /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } };
        /// Excel row
        /// row index
        /// 实体
        /// 错误信息
        private static void ExcelRowToEntity(Dictionary cellHeader, IRow row, int rowIndex, T en, ref StringBuilder errorMsg)
        {
            List keys = cellHeader.Keys.ToList(); // 要赋值的实体对象属性名称
            string errStr = ""; // 当前行转换时,是否有错误信息,格式为:第1行数据转换异常:XXX列;
            for (int i = 0; i < keys.Count; i++)
            {
                // 1.若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.TrueName
                if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0)
                {
                    // 1)解析子类属性
                    string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                    string subClassName = propertyArray[0]; // '.'前面的为子类的名称
                    string classPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称
                    PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型
                    if (subClassInfo != null)
                    {
                        // 2)获取子类的实例
                        var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null);
                        // 3)根据属性名称获取子类里的属性信息
                        PropertyInfo propertyInfo = subClassInfo.PropertyType.GetProperty(classPropertyName);
                        if (propertyInfo != null)
                        {
                            try
                            {
                                // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息
                                propertyInfo.SetValue(subClassEn, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null);
                            }
                            catch (Exception e)
                            {
                                //typeof(ExcelHelper).LogError(e);
                                if (errStr.Length == 0)
                                {
                                    errStr = "第" + rowIndex + "行数据转换异常:";
                                }
                                errStr += cellHeader[keys[i]] + "列;";
                            }
                        }
                    }
                }
                else
                {
                    // 2.给指定的属性赋值
                    PropertyInfo propertyInfo = en.GetType().GetProperty(keys[i]);
                    if (propertyInfo != null)
                    {
                        try
                        {
                          
                            // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息
                            propertyInfo.SetValue(en, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null);
                        }
                        catch (Exception e)
                        {
                            //typeof(ExcelHelper).LogError(e);
                            if (errStr.Length == 0)
                            {
                                errStr = "第" + rowIndex + "行数据转换异常:";
                            }
                            errStr += cellHeader[keys[i]] + "列;";
                        }
                    }
                }
            }
            // 若有错误信息,就添加到错误信息里
            if (errStr.Length > 0)
            {
                errorMsg.AppendLine(errStr);
            }
        }
        /// 
        /// Excel Cell转换为实体的属性值
        /// 
        /// 目标对象类型
        /// 对象属性的值
        private static object GetExcelCellToProperty(Type distanceType, ICell sourceCell)
        {
            object rs = distanceType.IsValueType ? Activator.CreateInstance(distanceType) : null;
            // 1.判断传递的单元格是否为空
            if (sourceCell == null || string.IsNullOrEmpty(sourceCell.ToString()))
            {
                return rs;
            }
            // 2.Excel文本和数字单元格转换,在Excel里文本和数字是不能进行转换,所以这里预先存值
            object sourceValue = null;
            switch (sourceCell.CellType)
            {
                case CellType.Blank:
                    break;
                case CellType.Boolean:
                    sourceValue = sourceCell.BooleanCellValue;
                    break;
                case CellType.Error:
                    break;
                case CellType.Formula:
                    break;
                case CellType.Numeric:
                    sourceValue = sourceCell.NumericCellValue;
                    break;
                case CellType.String:
                    sourceValue = sourceCell.StringCellValue;
                    break;
                case CellType.Unknown:
                    break;
                default:
                    sourceValue = sourceCell.StringCellValue;
                    break;
            }
            string valueDataType = distanceType.Name;
            // 在这里进行特定类型的处理
            switch (valueDataType.ToLower()) // 以防出错,全部小写
            {
                case "string":
                    rs = sourceValue?.ToString();
                    break;
                case "int":
                case "int32":
                    rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "int16":
                    rs = (short)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "int64":
                    rs = (long)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "float":
                case "single":
                    rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "double":
                    rs = (double)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "decimal":
                    rs = (decimal)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "datetime":
                    rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "guid":
                    rs = (Guid)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType);
                    break;
                case "nullable`1":
                    if (distanceType.FullName == null)
                    {
                        rs = "";
                    }
                    else if (distanceType.FullName.ToLower().Contains("datetime"))
                    {
                        rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(DateTime));
                    }
                    else if ((bool)distanceType.FullName?.ToLower().Contains("int"))
                    {
                        rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(int));
                    }
                    else if ((bool)distanceType.FullName?.ToLower().Contains("float") || (bool)distanceType.FullName?.ToLower().Contains("double") || (bool)distanceType.FullName?.ToLower().Contains("decimal") || (bool)distanceType.FullName?.ToLower().Contains("single"))
                    {
                        rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(float));
                    }
                    else if ((bool)distanceType.FullName?.ToLower().Contains("bool"))
                    {
                        rs = (bool)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(bool));
                    }
                    break;
            }
            return rs;
        }
        #endregion
        public static HSSFWorkbook CreateWorkBook03(string filePath = null)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return new HSSFWorkbook();
            }
            FileStream file = new FileStream(filePath, FileMode.Open);
            return new HSSFWorkbook(file);
        }
        public static XSSFWorkbook CreateWorkBook07(string filePath = null)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return new XSSFWorkbook();
            }
            return new XSSFWorkbook(filePath);
        }
        /// 
        /// 创建Sheet
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static ISheet GenerateSheet(this string sheetName, int defaultWidth = 20, int defaultHeight = 20, bool is07 = true, IWorkbook workbook = null)
        {
            workbook = is07 ? workbook ?? CreateWorkBook07() : workbook ?? CreateWorkBook03();
            var sheet = workbook.CreateSheet(sheetName);
            sheet.DefaultColumnWidth = defaultWidth;
            sheet.DefaultRowHeight = (short)(defaultHeight * 20);
            return sheet;
        }
        /// 
        /// 创建行
        /// 
        /// 表
        /// 第几行(从1开始计数)
        /// 
        public static IRow GenerateRow(this ISheet sheet, int rowIndex)
        {
            rowIndex = rowIndex <= 0 ? 1 : rowIndex;
            var row = sheet.GetRow(rowIndex - 1) ?? sheet.CreateRow(rowIndex - 1);
            return row;
        }
        /// 
        /// 创建单元格
        /// 
        /// 表
        /// 第几行(从1开始计数)
        /// 第几列(从1开始计数)
        /// 值
        /// 单元格类型
        /// 
        public static ICell GenerateCell(this ISheet sheet, int rowIndex, int columnIndex, string val = null, CellType cellType = CellType.String)
        {
            var row = sheet.GenerateRow(rowIndex);
            var cell = GenerateCell(row, columnIndex, val, cellType);
            return cell;
        }
        /// 
        /// 创建单元格
        /// 
        /// 行
        /// 第几列(从1开始计数)
        /// 值
        /// 单元格类型
        /// 
        public static ICell GenerateCell(this IRow row, int columnIndex, string val = null, CellType cellType = CellType.String)
        {
            columnIndex = columnIndex <= 0 ? 1 : columnIndex;
            var cell = row.GetCell(columnIndex - 1) ?? row.CreateCell(columnIndex - 1);
            if (!string.IsNullOrEmpty(val))
            {
                cell.SetCellValue(val);
                cell.SetCellType(cellType);
            }
            return cell;
        }
        /// 
        /// 设置列宽度
        /// 
        /// 表
        /// 第几列(从1开始计数)
        /// 宽度
        /// 
        public static ISheet SetCellWidth(this ISheet sheet, int columnIndex, int width)
        {
            sheet.SetColumnWidth(columnIndex - 1, width * 256);
            return sheet;
        }
        /// 
        /// 设置列宽度
        /// 
        /// 行
        /// 第几列(从1开始计数)
        /// 宽度
        /// 
        public static IRow SetCellWidth(this IRow row, int columnIndex, int width)
        {
            row.Sheet.SetColumnWidth(columnIndex - 1, width * 256);
            return row;
        }
        /// 
        /// 设置列宽度
        /// 
        /// 单元格
        /// 第几列(从1开始计数)
        /// 宽度
        /// 
        public static ICell SetCellWidth(this ICell cell, int columnIndex, int width)
        {
            cell.Sheet.SetColumnWidth(columnIndex - 1, width * 256);
            return cell;
        }
        /// 
        /// 设置行高度
        /// 
        /// 表
        /// 第几行(从1开始计数)
        /// 宽度
        /// 
        public static ISheet SetRowHeight(this ISheet sheet, int rowIndex, int height)
        {
            sheet.GetRow(rowIndex - 1).SetRowHeight(height);
            return sheet;
        }
        /// 
        /// 设置行高度
        /// 
        /// 行
        /// 宽度
        /// 
        public static IRow SetRowHeight(this IRow row, int height)
        {
            row.Height = (short)(height * 20);
            return row;
        }
        /// 
        /// 设置行高度
        /// 
        /// 单元格
        /// 宽度
        /// 
        public static ICell SetRowHeight(this ICell cell, int height)
        {
            cell.Row.SetRowHeight(height);
            return cell;
        }
        /// 
        /// 设置单元格的值
        /// 
        /// 
        /// 
        /// 
        public static ICell SetValue(this ICell cell, string obj)
        {
            return SetValue(cell, obj);
        }
        /// 
        /// 设置单元格的值
        /// 
        /// 值类型(sting,bool,double,DateTime)
        /// 
        /// 
        /// 
        public static ICell SetValue(this ICell cell, object obj)
        {
            Type type = typeof(T);
            bool bValue;
            double iValue;
            DateTime dValue;
            if (type == typeof(string))
            {
                cell.SetCellValue(obj.ToString());
            }
            else if (type == typeof(bool) && bool.TryParse(obj.ToString(), out bValue))
            {
                cell.SetCellValue(bValue);
            }
            else if ((type == typeof(int) || type == typeof(double) || type == typeof(decimal)) && double.TryParse(obj.ToString(), out iValue))
            {
                cell.SetCellValue(iValue);
            }
            else if (type == typeof(DateTime) && DateTime.TryParse(obj.ToString(), out dValue))
            {
                cell.SetCellValue(dValue);
            }
            return cell;
        }
        #region DATA-FORMAT
        public static ICellStyle SetCellDateTime(this ICell cell, DateTime value, string formatStr = "yyyy-MM-dd HH:mm:ss")
        {
            cell.SetCellValue(value);
            cell.SetDataFormat(formatStr);
            return cell.CellStyle;
        }
        public static ICellStyle SetCellString(this ICell cell, double value, string formatStr = "@")
        {
            cell.SetCellValue(value);
            cell.SetDataFormat(formatStr);
            return cell.CellStyle;
        }
        public static ICellStyle SetCellDouble(this ICell cell, double value, string formatStr = "0.00")
        {
            cell.SetCellValue(value);
            cell.SetDataFormat(formatStr);
            return cell.CellStyle;
        }
        public static ICellStyle SetCellCurrency(this ICell cell, double value, string formatStr = "¥#,###.##")
        {
            cell.SetCellValue(value);
            cell.SetDataFormat(formatStr);
            return cell.CellStyle;
        }
        public static ICellStyle SetCellPercent(this ICell cell, double value, string formatStr = "0.00%")
        {
            cell.SetCellValue(value);
            cell.SetDataFormat(formatStr);
            return cell.CellStyle;
        }
        public static void SetDataFormat(this ICell cell, string formatStr = "¥#,##0.00")
        {
            var cellStyle = cell.CellStyle ?? GetCellStyle(cell);
            var format = cell.Sheet.Workbook.CreateDataFormat();
            cellStyle.DataFormat = format.GetFormat(formatStr);
            cell.SetCellStyle(cellStyle);
        }
        #endregion
        #region 合并单元格
        /// 
        /// 合并单元格
        /// 
        /// 
        /// 开始行数(从1开始计数)
        /// 结束行数(从1开始计数)
        /// 开始列数(从1开始计数)
        /// 结束列数(从1开始计数)
        /// 
        public static ISheet MergedRegion(this ISheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn)
        {
            var region = GetCellRegion(firstRow, lastRow, firstColumn, lastColumn);
            sheet.MergedRegion(region);
            return sheet;
        }
        public static ISheet MergedRegion(this ISheet sheet, CellRangeAddress region)
        {
            sheet.AddMergedRegion(region);
            //SetRegionBorder(sheet, region, borderTypeStr, borderColorStr);
            return sheet;
        }
        public static CellRangeAddress GetCellRegion(this int firstRow, int lastRow, int firstColumn, int lastColumn)
        {
            firstRow = firstRow <= 0 ? 1 : firstRow;
            firstColumn = firstColumn <= 0 ? 1 : firstColumn;
            lastRow = lastRow <= 0 ? 1 : lastRow;
            lastColumn = lastColumn <= 0 ? 1 : lastColumn;
            return new CellRangeAddress(firstRow - 1, lastRow - 1, firstColumn - 1, lastColumn - 1);
        }
        #endregion
        public static ICellStyle GetCellStyle(this ICell cell)
        {
            return cell.CellStyle ?? cell.Sheet.Workbook.CreateCellStyle();
        }
        public static void SetCellStyle(this ICell cell, ICellStyle cellStyle)
        {
            cell.CellStyle = cellStyle;
        }
        /// 
        /// 保存工作簿
        /// 
        /// 
        /// 
        /// 
        /// 
        public static string SaveWorkBook(this ISheet sheet, string filePath, string fileName)
        {
            try
            {
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }
                filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\";
                FileStream file = new FileStream(filePath + fileName, FileMode.Create);
                sheet.Workbook.Write(file);
                file.Close();
                return "";
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }
        /// 
        /// 保存工作簿
        /// 
        /// 
        /// 
        /// 
        /// 
        public static string SaveWorkBook(this IWorkbook workbook, string filePath, string fileName)
        {
            try
            {
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }
                filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\";
                var path = filePath + fileName;
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                FileStream file = new FileStream(path, FileMode.Create);
                workbook.Write(file);
                file.Close();
                return "";
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }
    }
}