首页 > 编程语言 >C# net8使用NPOI导出多个sheet工作簿的execl文件

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

时间:2024-12-09 09:46:54浏览次数:5  
标签:execl sheet C# workbook var new DataTable Columns

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("异常");
            }
        }

 

标签:execl,sheet,C#,workbook,var,new,DataTable,Columns
From: https://www.cnblogs.com/handsomeziff/p/18594248

相关文章

  • 调代码爷爷大部分辈代码需要的东西VBC6.EXE 你还是个细胞,他诞生了
    '**********************************************************'*SubroutineName:InitFailSum'*Function:InitializesFailureSummaryVariables'*Inputs:none'*Outputs:none-initsglobals'*By:XXXXXXX'*Date:......
  • Atcoder Beginner Contest 380 (D~G)
    D.StrangeMirroring题意:给定一个只含有大小写字母的字符串$S$。现在对这个字符串操作无数次:对于$S$的每个字符,若是大写字母就改为对应的小写字母,否则改成对应的大写字母,形成一个新的字符串$T$。将$S$和$T$首尾连接,形成新的$S$。现在给定$Q$次......
  • 请使用canvas画一个椭圆
    <!DOCTYPEhtml><html><head><title>CanvasEllipse</title></head><body><canvasid="myCanvas"width="300"height="150"style="border:1pxsolid#d3d3d3;">Yourbrow......
  • 请举例说明width:fit-conten有什么使用场景
    width:fit-content在前端开发中非常有用,它允许元素根据其内容的宽度自适应大小,避免了硬编码宽度带来的问题。以下是一些使用场景:1.动态内容的容器:按钮:当按钮文本长度不固定时,width:fit-content可以确保按钮的宽度正好包裹住文本,并随着文本的变化而调整。例如,多语言......
  • 请使用canvas画一个渐变的长方形
    <!DOCTYPEhtml><html><head><title>渐变长方形</title></head><body><canvasid="myCanvas"width="300"height="150"style="border:1pxsolid#d3d3d3;">Yourbrowserdoes......
  • 当css中background或background-image的值为url()或url(#)时,会发生什么情况?为什么?如何
    当CSS中background或background-image的值为url()或url(#)时,会尝试加载指定的资源或引用。具体情况和解决方法如下:1.url(path/to/image.jpg)或url("path/to/image.jpg"):情况:浏览器会尝试加载指定路径的图片资源。如果路径正确且图片存在,则图片会作为背景显示。......
  • css穿透属性有哪些?
    CSS穿透属性主要用于处理样式优先级,特别是解决嵌套组件样式冲突的问题。常用的CSS穿透属性/方法有以下几种:::deep穿透(ShadowDOM穿透):主要用于穿透ShadowDOM的样式封装,访问和修改ShadowDOM内部元素的样式。使用方式:host::deep(selector){styles}注意:::deep......
  • 玩爆这些CSS中的负值技巧
    使用负值outline-offset实现加号假设我们有这样一个简单的结构:<div></div>div{width:200px;height:200px;outline:20pxsolid#000;outline-offset:10px;}div{width:200px;height:200px;outline:20pxsolid#000;outline-offse......
  • 当页面中使用application/xhtml+xml会出现什么问题吗?
    使用application/xhtml+xml作为MIME类型在前端开发中可能会出现一些问题,尽管在理想情况下它应该提供更严格的验证和结构。主要问题源于浏览器对XHTML的支持不一致以及与旧版浏览器和服务器的兼容性问题。以下是可能出现的一些问题:浏览器兼容性:并非所有浏览器都完全支......
  • C# 扩展方法
    文章目录一、引言二、扩展方法的基本概念1.定义扩展方法的语法2.扩展方法的调用方式三、示例演示1.为内置类型添加扩展方法2.为自定义类型添加扩展方法四、扩展方法的注意事项1.扩展方法的优先级2.扩展方法的可见性3.避免过度使用五、总结一、引言  在......