C# net8使用NPOI导出多个sheet工作簿的execl文件

1、安装NPOI 2.7.2

2、工具类DataTableTool.cs,将list 转成DataTable

using System.Collections;
using System.Data;
using System.Reflection;

namespace Common.Helper
{
    public static class DataTableTool
    {
        /// <summary>    
        /// 转化一个DataTable    
        /// </summary>    
        /// <typeparam name="T"></typeparam>    
        /// <param name="list"></param>    
        /// <returns></returns>    
        public static DataTable ToDataTable<T>(this IEnumerable<T> list)
        {

            //创建属性的集合    
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //获得反射的入口    

            Type type = typeof(T);
            DataTable dt = new DataTable();
            //把所有的public属性加入到集合 并添加DataTable的列    
            Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
            foreach (var item in list)
            {
                //创建一个DataRow实例    
                DataRow row = dt.NewRow();
                //给row 赋值    
                pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
                //加入到DataTable    
                dt.Rows.Add(row);
            }
            return dt;
        }


        /// <summary>    
        /// DataTable 转换为List 集合    
        /// </summary>    
        /// <typeparam name="TResult">类型</typeparam>    
        /// <param name="dt">DataTable</param>    
        /// <returns></returns>    
        public static List<T> ToList<T>(this DataTable dt) where T : class, new()
        {
            //创建一个属性的列表    
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            //获取TResult的类型实例  反射的入口    

            Type t = typeof(T);

            //获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表     
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); });

            //创建返回的集合    

            List<T> oblist = new List<T>();

            foreach (DataRow row in dt.Rows)
            {
                //创建TResult的实例    
                T ob = new T();
                //找到对应的数据  并赋值    
                prlist.ForEach(p => { if (row[p.Name] != DBNull.Value) p.SetValue(ob, row[p.Name], null); });
                //放入到返回的集合中.    
                oblist.Add(ob);
            }
            return oblist;
        }




        /// <summary>    
        /// 将集合类转换成DataTable    
        /// </summary>    
        /// <param name="list">集合</param>    
        /// <returns></returns>    
        public static DataTable ToDataTableTow(IList list)
        {
            DataTable result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();

                foreach (PropertyInfo pi in propertys)
                {
                    Type colType = pi.PropertyType;
                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                    {
                        colType = colType.GetGenericArguments()[0];
                    }
                    result.Columns.Add(pi.Name, colType);
                }
                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }


        /// <summary>    
        /// 将泛型集合类转换成DataTable    
        /// </summary>    
        /// <typeparam name="T">集合项类型</typeparam>    
        /// <param name="list">集合</param>    
        /// <returns>数据集(表)</returns>    
        public static DataTable ToDataTable<T>(IList<T> list)
        {
            return ToDataTable<T>(list, null);

        }

        /// <summary>    
        /// 将泛型集合类转换成DataTable    
        /// </summary>    
        /// <typeparam name="T">集合项类型</typeparam>    
        /// <param name="list">集合</param>    
        /// <param name="propertyName">需要返回的列的列名</param>    
        /// <returns>数据集(表)</returns>    
        public static DataTable ToDataTable<T>(IList<T> list, params string[] propertyName)
        {
            List<string> propertyNameList = new List<string>();
            if (propertyName != null)
                propertyNameList.AddRange(propertyName);
            DataTable result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    if (propertyNameList.Count == 0)
                    {
                        result.Columns.Add(pi.Name, pi.PropertyType);
                    }
                    else
                    {
                        if (propertyNameList.Contains(pi.Name))
                            result.Columns.Add(pi.Name, pi.PropertyType);
                    }
                }

                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        if (propertyNameList.Count == 0)
                        {
                            object obj = pi.GetValue(list[i], null);
                            tempList.Add(obj);
                        }
                        else
                        {
                            if (propertyNameList.Contains(pi.Name))
                            {
                                object obj = pi.GetValue(list[i], null);
                                tempList.Add(obj);
                            }
                        }
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }
    }
}
View Code

 

3、execl生成类ExcelTool.cs

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Data;

namespace Common.Helper
{
    public static class ExcelTool
    {  /// <summary>
       /// 将excel中的数据导入到DataTable中
       /// </summary>
       /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>
       /// <param name="fileName">文件名称</param>
       /// <param name="sheetName">excel工作薄sheet的名称</param>
       /// <returns>返回的DataTable</returns>
        public static DataTable ExcelStreamToDataTable(bool isFirstRowColumn, string fileName, Stream fs, string sheetName = "")
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(fileName);
            }
            var data = new DataTable();
            IWorkbook workbook = null;
            try
            {
                if (fileName.IndexOf(".xlsx", StringComparison.Ordinal) > 0)
                {
                    workbook = new XSSFWorkbook(fs);
                }
                else if (fileName.IndexOf(".xls", StringComparison.Ordinal) > 0)
                {
                    workbook = new HSSFWorkbook(fs);
                }

                ISheet sheet = null;
                if (workbook != null)
                {
                    //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet
                    if (sheetName == "")
                    {
                        sheet = workbook.GetSheetAt(0);
                    }
                    else
                    {
                        sheet = workbook.GetSheet(sheetName) ?? workbook.GetSheetAt(0);
                    }

                }
                if (sheet == null) return data;
                var firstRow = sheet.GetRow(0);
                //一行最后一个cell的编号 即总的列数
                int cellCount = firstRow.LastCellNum;
                int startRow;
                if (isFirstRowColumn)
                {
                    for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
                    {
                        var cell = firstRow.GetCell(i);
                        var cellValue = cell.ToString();
                        if (cellValue == null) continue;
                        var column = new DataColumn(cellValue);
                        data.Columns.Add(column);
                    }
                    startRow = sheet.FirstRowNum + 1;
                }
                else
                {
                    startRow = sheet.FirstRowNum;
                }
                //最后一列的标号
                var rowCount = sheet.LastRowNum;
                for (var i = startRow; i <= rowCount; ++i)
                {
                    var row = sheet.GetRow(i);
                    //没有数据的行默认是null
                    if (row == null) continue;
                    var dataRow = data.NewRow();
                    for (int j = row.FirstCellNum; j < cellCount; ++j)
                    {
                        //同理,没有数据的单元格都默认是null
                        if (row.GetCell(j) != null)
                            dataRow[j] = row.GetCell(j).ToString();
                    }
                    data.Rows.Add(dataRow);
                }

                return data;
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 将excel中的数据导入到DataTable中
        /// </summary>
        /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>
        /// <param name="fileName">文件路径</param>
        /// <param name="sheetName">excel工作薄sheet的名称</param>
        /// <returns>返回的DataTable</returns>
        public static DataTable ExcelToDataTable(bool isFirstRowColumn, string fileName, string sheetName = "")
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(fileName);
            }
            var data = new DataTable();
            IWorkbook workbook = null;
            FileStream fs = null;
            try
            {
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                if (fileName.IndexOf(".xlsx", StringComparison.Ordinal) > 0)
                {
                    workbook = new XSSFWorkbook(fs);
                }
                else if (fileName.IndexOf(".xls", StringComparison.Ordinal) > 0)
                {
                    workbook = new HSSFWorkbook(fs);
                }

                ISheet sheet = null;
                if (workbook != null)
                {
                    //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet
                    if (sheetName == "")
                    {
                        sheet = workbook.GetSheetAt(0);
                    }
                    else
                    {
                        sheet = workbook.GetSheet(sheetName) ?? workbook.GetSheetAt(0);
                    }
                }
                if (sheet == null) return data;
                var firstRow = sheet.GetRow(0);
                //一行最后一个cell的编号 即总的列数
                int cellCount = firstRow.LastCellNum;
                int startRow;
                if (isFirstRowColumn)
                {
                    for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
                    {
                        var cell = firstRow.GetCell(i);
                        var cellValue = cell.StringCellValue;
                        if (cellValue == null) continue;
                        var column = new DataColumn(cellValue);
                        data.Columns.Add(column);
                    }
                    startRow = sheet.FirstRowNum + 1;
                }
                else
                {
                    startRow = sheet.FirstRowNum;
                }
                //最后一列的标号
                var rowCount = sheet.LastRowNum;
                for (var i = startRow; i <= rowCount; ++i)
                {
                    var row = sheet.GetRow(i);
                    //没有数据的行默认是null
                    if (row == null) continue;
                    var dataRow = data.NewRow();
                    for (int j = row.FirstCellNum; j < cellCount; ++j)
                    {
                        //同理,没有数据的单元格都默认是null
                        if (row.GetCell(j) != null)
                            dataRow[j] = row.GetCell(j).ToString();
                    }
                    data.Rows.Add(dataRow);
                }

                return data;
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }
        /// <summary>
        /// 将DataTable数据导入到excel中
        /// </summary>
        /// <param name="data">要导入的数据</param>
        /// <param name="isColumnWritten">DataTable的列名是否要导入</param>
        /// <param name="sheetName">要导入的excel的sheet的名称</param>
        /// <param name="fileName">文件夹路径</param>
        /// <returns>导入数据行数(包含列名那一行)</returns>
        public static int DataTableToExcel(DataTable[] dataArr, string[] sheetNameArr, bool isColumnWritten, string fileName)
        {
            if (dataArr == null)
            {
                throw new ArgumentNullException("data");
            }
            if (dataArr.Length != sheetNameArr.Length)
            {
                throw new ArgumentNullException("data长度与sheetName不一致");
            }
           
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(fileName);
            }
            IWorkbook workbook = null;
            if (fileName.IndexOf(".xlsx", StringComparison.Ordinal) > 0)
            {
                workbook = new XSSFWorkbook();
            }
            else if (fileName.IndexOf(".xls", StringComparison.Ordinal) > 0)
            {
                workbook = new HSSFWorkbook();
            }

            FileStream fs = null;
            try
            {
                fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                ISheet[] sheetArr = new ISheet[sheetNameArr.Length];
                for(int n= 0; n < sheetArr.Length; n++)
                {
                        sheetArr[n] = workbook.CreateSheet(sheetNameArr[n]);
                }
                
                var cellStyle = workbook.CreateCellStyle();
                cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@");

                //  var cellStyle1 = workbook.CreateCellStyle();
                // cellStyle1.DataFormat = HSSFDataFormat.GetBuiltinFormat("yyyy年m月d日");
                var cellStyle1 = workbook.CreateCellStyle();
                var format = workbook.CreateDataFormat();
                cellStyle1.DataFormat = (format.GetFormat("yyyy-mm-dd"));
                //   cell.setCellStyle(cellStyle);


                int j;
                int count = 0 ;
                //写入DataTable的列名,写入单元格中
                for(int m = 0; m < sheetArr.Length; m++)
                {
                    var sheet = sheetArr[m];
                    DataTable data = dataArr[m];
                    if (isColumnWritten)
                    {
                        var row = sheet.CreateRow(0);
                        for (j = 0; j < data.Columns.Count; ++j)
                        {
                            row.CreateCell(j).SetCellValue(data.Columns[j].ColumnName);

                            Type types = data.Columns[j].DataType;
                            if (types.Name == "DateTime")
                            {
                                sheet.SetDefaultColumnStyle(j, cellStyle1);
                            }
                            else
                            {
                                sheet.SetDefaultColumnStyle(j, cellStyle);
                            }
                        }
                        count = 1;
                    }
                    else
                    {
                        count = 0;
                    }
                    //遍历循环datatable具体数据项
                    int i;
                    for (i = 0; i < data.Rows.Count; ++i)
                    {
                        var row = sheet.CreateRow(count);
                        for (j = 0; j < data.Columns.Count; ++j)
                        {
                            row.CreateCell(j).SetCellValue(data.Rows[i][j].ToString());
                        }
                        ++count;
                    }
                }
                
                //将文件流写入到excel
                workbook.Write(fs);
                return count;
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }
    }
}
View Code

 

4、使用

        [HttpGet]
        public async Task<MessageModel<string>> ExportExcel(string key = "",  int orderBy = 0)
        {
            try
            {
                string fileName = $"{DateTime.Now.ToString("yyyyMMdd_HHmss")}_{_user.ShopID}" + ".xlsx";
                string folder = $"execl\\shopbak";
                string urlFolder = $"execl/shopbak";
                string folderpath = Path.Combine($"{_env.WebRootPath}\\{folder}\\");
                string path = folderpath + fileName;

                if (!Directory.Exists(folderpath))
                {
                    Directory.CreateDirectory(folderpath);
                }
                //删除旧文件
                foreach (string file in Directory.GetFiles(folderpath))
                {
                    try
                    {
                        FileInfo fileInfo = new FileInfo(file);
                        DateTime localCreationTime = fileInfo.CreationTime; // 获取文件的本地创建时间
                        Console.WriteLine("文件创建时间(本地): " + localCreationTime.ToString());
                        //创建时间与当前时间比较,相差30秒以上则删除
                        if (DateTime.Now.Subtract(localCreationTime).TotalSeconds > 60)
                        {
                            System.IO.File.Delete(file);
                        }
                    }
                    catch(Exception ex)
                    {
                        _logger.LogError("删除文件失败" + ex);
                    }
                }
                DataTable[] dtArr = new DataTable[2];
                string[] sheetNameArr = { "全部会员", "次卡会员"};

                #region 全部会员
                var result = await Get(page: 1, intPageSize: 5000, key: key, memberType: 0, orderBy: orderBy);  //获取数据
                if (!result.success)
                {
                    return Failed("查询数据失败");
                }
                var list = result.response.data.Select(s => new {
                    s.Name,
                    s.Phone,
                    s.Points,
                    s.Birthday,
                    s.Sex,
                    s.CardNO,
                    s.Detail,
                    s.StoreCardName,
                    s.StoreCardBalance,
                    s.CreateTime
                });
                DataTable dt = DataTableTool.ToDataTableTow(list.ToList());
                dt.Columns["Name"].ColumnName = "名字";
                dt.Columns["Phone"].ColumnName = "手机";
                dt.Columns["Points"].ColumnName = "积分";
                dt.Columns["Birthday"].ColumnName = "生日";
                dt.Columns["Sex"].ColumnName = "性别";
                dt.Columns["CardNO"].ColumnName = "会员卡号";
                dt.Columns["Detail"].ColumnName = "详情";
                dt.Columns["StoreCardName"].ColumnName = "储值卡";
                dt.Columns["StoreCardBalance"].ColumnName = "储值卡余额";
                dt.Columns["CreateTime"].ColumnName = "添加时间";

                dtArr[0] = dt;
                #endregion

                #region 次卡
                var timesResult = await Get(page: 1, intPageSize: 5000, key: key, memberType: 1, orderBy: orderBy);
                if (!timesResult.success)
                {
                    return Failed("查询数据失败");
                }
                var timesList = timesResult.response.data.Select(s => new {
                    s.Name,
                    s.Phone,
                    s.Points,
                    s.Birthday,
                    s.Sex,
                    s.CardNO,
                    s.Detail,
                    s.TimesCardName,
                    s.TimesBusinessName,
                    s.TimesCardRemainCount,
                    s.CreateTime
                });
                DataTable timesDT = DataTableTool.ToDataTableTow(timesList.ToList());
                timesDT.Columns["Name"].ColumnName = "名字";
                timesDT.Columns["Phone"].ColumnName = "手机";
                timesDT.Columns["Points"].ColumnName = "积分";
                timesDT.Columns["Birthday"].ColumnName = "生日";
                timesDT.Columns["Sex"].ColumnName = "性别";
                timesDT.Columns["CardNO"].ColumnName = "会员卡号";
                timesDT.Columns["Detail"].ColumnName = "详情";
                timesDT.Columns["TimesCardName"].ColumnName = "次卡";
                timesDT.Columns["TimesBusinessName"].ColumnName = "次卡项目";
                timesDT.Columns["TimesCardRemainCount"].ColumnName = "剩余次数";
                timesDT.Columns["CreateTime"].ColumnName = "添加时间";

                dtArr[1] = timesDT;

                #endregion


                int count = ExcelTool.DataTableToExcel(dtArr, sheetNameArr, true, path);

                if (System.IO.File.Exists(path))
                {
                    var imgUrl = $"{Request.Scheme}://{Request.Host}/{urlFolder}/{fileName}";
                    return Success(imgUrl, "成功");
                }
                return Failed("导出失败");
            }
            catch(Exception ex)
            {
                _logger.LogError("导出execl异常" + ex);
                return Failed("异常");
            }
        }

 

posted @ 2024-12-09 09:32  ziff123  阅读(14)  评论(0编辑  收藏  举报