C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)

原文:C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)

项目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2

本篇文章是对WebAPI项目使用NPOI操作Excel时的帮助类:ExcelHelper的改进优化做下记录:

备注:下面的帮助类代码使用的文件格式为:xlsx文件,xlsx相对xls的优缺点代码里有注释,推荐使用xlsx文件保存数据!

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace PaymentAccountAPI.Helper
{
    /// <summary>
    /// EXCEL帮助类
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <typeparam name="TCollection">泛型类集合</typeparam>
    public class ExcelHelp
    {
        private ILogger Logger = null;

        public ExcelHelp(ILogger<ExcelHelp> logger)
        {
            this.Logger = logger;
        }

        /// <summary>
        /// 将数据导出EXCEL
        /// </summary>
        /// <param name="tList">要导出的数据集</param>
        /// <param name="fieldNameAndShowNameDic">键值对集合(键:字段名,值:显示名称)</param>
        /// <param name="fileDirectoryPath">文件路径</param>
        /// <param name="excelName">文件名(必须是英文或数字)</param>
        /// <returns></returns>
        public IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, Dictionary<string, string> fieldNameAndShowNameDic, IWorkbook workbook = null, string sheetName = "sheet1") where T : new()
        {
            //xls文件格式属于老版本文件,一个sheet最多保存65536行;而xlsx属于新版文件类型;
            //Excel 07 - 2003一个工作表最多可有65536行,行用数字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一个工作簿中最多含有255个工作表,默认情况下是三个工作表;
            //Excel 2007及以后版本,一个工作表最多可有1048576行,16384列;
            if (workbook == null)
            {
                workbook = new XSSFWorkbook();
                //workbook = new HSSFWorkbook();
            }
            ISheet worksheet = workbook.CreateSheet(sheetName);

            List<string> columnNameList = fieldNameAndShowNameDic.Values.ToList();
            //设置首列显示
            IRow row1 = worksheet.CreateRow(0);

            ICell cell = null;
            ICellStyle cellHeadStyle = workbook.CreateCellStyle();
            //设置首行字体加粗
            IFont font = workbook.CreateFont();
            font.Boldweight = short.MaxValue;
            cellHeadStyle.SetFont(font);
            int cloumnCount = columnNameList.Count;
            for (var i = 0; i < cloumnCount; i++)
            {
                cell = row1.CreateCell(i);
                cell.SetCellValue(columnNameList[i]);
                cell.CellStyle = cellHeadStyle;
            }

            //根据反射创建其他行数据
            var raws = tList.Count;
            Dictionary<string, PropertyInfo> titlePropertyDic = this.GetIndexPropertyDic<T>(fieldNameAndShowNameDic);

            PropertyInfo propertyInfo = null;
            T t = default(T);
            for (int i = 0; i < raws; i++)
            {
                if (i % 10000 == 0)
                {
                    this.Logger.LogInformation($"Excel已创建{i + 1}条数据");
                }
                row1 = worksheet.CreateRow(i + 1);
                t = tList[i];

                int cellIndex = 0;
                foreach (var titlePropertyItem in titlePropertyDic)
                {
                    propertyInfo = titlePropertyItem.Value;
                    cell = row1.CreateCell(cellIndex);

                    if (propertyInfo.PropertyType == typeof(int)
                        || propertyInfo.PropertyType == typeof(decimal)
                        || propertyInfo.PropertyType == typeof(double))
                    {
                        cell.SetCellValue(Convert.ToDouble(propertyInfo.GetValue(t) ?? 0));
                    }
                    else if (propertyInfo.PropertyType == typeof(DateTime))
                    {
                        cell.SetCellValue(Convert.ToDateTime(propertyInfo.GetValue(t)?.ToString()).ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else if (propertyInfo.PropertyType == typeof(bool))
                    {
                        cell.SetCellValue(Convert.ToBoolean(propertyInfo.GetValue(t).ToString()));
                    }
                    else
                    {
                        cell.SetCellValue(propertyInfo.GetValue(t)?.ToString() ?? "");
                    }
                    cellIndex++;
                }

                //重要:设置行宽度自适应(大批量添加数据时,该行代码需要注释,否则会极大减缓Excel添加行的速度!)
                //worksheet.AutoSizeColumn(i, true);
            }

            return workbook;
        }

        /// <summary>
        /// 保存Workbook数据为文件
        /// </summary>
        /// <param name="workbook"></param>
        /// <param name="fileDirectoryPath"></param>
        /// <param name="fileName"></param>
        public void SaveWorkbookToFile(IWorkbook workbook, string fileDirectoryPath, string fileName)
        {
            //xls文件格式属于老版本文件,一个sheet最多保存65536行;而xlsx属于新版文件类型;
            //Excel 07 - 2003一个工作表最多可有65536行,行用数字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一个工作簿中最多含有255个工作表,默认情况下是三个工作表;
            //Excel 2007及以后版本,一个工作表最多可有1048576行,16384列;

            MemoryStream ms = new MemoryStream();
            //这句代码非常重要,如果不加,会报:打开的EXCEL格式与扩展名指定的格式不一致
            ms.Seek(0, SeekOrigin.Begin);
            workbook.Write(ms);
            byte[] myByteArray = ms.GetBuffer();

            fileDirectoryPath = fileDirectoryPath.TrimEnd(‘\\‘) + "\\";
            if (!Directory.Exists(fileDirectoryPath))
            {
                Directory.CreateDirectory(fileDirectoryPath);
            }

            string filePath = fileDirectoryPath + fileName;
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            File.WriteAllBytes(filePath, myByteArray);
        }

        /// <summary>
        /// 保存Workbook数据为下载文件
        /// </summary>
        public FileContentResult SaveWorkbookToDownloadFile(IWorkbook workbook)
        {
            MemoryStream ms = new MemoryStream();
            //这句代码非常重要,如果不加,会报:打开的EXCEL格式与扩展名指定的格式不一致
            ms.Seek(0, SeekOrigin.Begin);
            workbook.Write(ms);
            byte[] myByteArray = ms.GetBuffer();

            //对于.xls文件
            //application/vnd.ms-excel
            //用于.xlsx文件。
            //application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            mediaType.Encoding = System.Text.Encoding.UTF8;

            return new FileContentResult(myByteArray, mediaType.ToString());
        }

        /// <summary>
        /// 读取Excel数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fieldNameAndShowNameDic"></param>
        /// <returns></returns>
        public List<T> ReadDataList<T>(string filePath, Dictionary<string, string> fieldNameAndShowNameDic) where T : new()
        {
            List<T> tList = null;
            T t = default(T);

            //标题属性字典列表
            Dictionary<string, PropertyInfo> titlePropertyDic = this.GetIndexPropertyDic<T>(fieldNameAndShowNameDic);
            //标题下标列表
            Dictionary<string, int> titleIndexDic = new Dictionary<string, int>(0);

            PropertyInfo propertyInfo = null;

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                IWorkbook xssfWorkbook = new XSSFWorkbook(fileStream);
                var sheet = xssfWorkbook.GetSheetAt(0);

                var rows = sheet.GetRowEnumerator();
                tList = new List<T>(sheet.LastRowNum + 1);
                //第一行数据为标题,
                if (rows.MoveNext())
                {
                    IRow row = (XSSFRow)rows.Current;
                    ICell cell = null;
                    string cellValue = null;
                    for (int i = 0; i < row.Cells.Count; i++)
                    {
                        cell = row.Cells[i];
                        cellValue = cell.StringCellValue;
                        if (titlePropertyDic.ContainsKey(cellValue))
                        {
                            titleIndexDic.Add(cellValue, i);
                        }
                    }
                }
                //从第2行数据开始获取
                while (rows.MoveNext())
                {
                    IRow row = (XSSFRow)rows.Current;
                    t = new T();

                    foreach (var titleIndexItem in titleIndexDic)
                    {
                        var cell = row.GetCell(titleIndexItem.Value);
                        if (cell != null)
                        {
                            propertyInfo = titlePropertyDic[titleIndexItem.Key];
                            if (propertyInfo.PropertyType == typeof(int))
                            {
                                propertyInfo.SetValue(t, Convert.ToInt32(cell.NumericCellValue));
                            }
                            else if (propertyInfo.PropertyType == typeof(decimal))
                            {
                                propertyInfo.SetValue(t, Convert.ToDecimal(cell.NumericCellValue));
                            }
                            else if (propertyInfo.PropertyType == typeof(double))
                            {
                                propertyInfo.SetValue(t, Convert.ToDouble(cell.NumericCellValue));
                            }
                            else if (propertyInfo.PropertyType == typeof(bool))
                            {
                                propertyInfo.SetValue(t, Convert.ToBoolean(cell.StringCellValue));
                            }
                            else if (propertyInfo.PropertyType == typeof(DateTime))
                            {
                                propertyInfo.SetValue(t, Convert.ToDateTime(cell.StringCellValue));
                            }
                            else
                            {
                                propertyInfo.SetValue(t, cell.StringCellValue);
                            }

                        }
                    }
                    tList.Add(t);
                }
            }
            return tList ?? new List<T>(0);
        }

        /// <summary>
        /// 根据属性名顺序获取对应的属性对象
        /// </summary>
        /// <param name="fieldNameList"></param>
        /// <returns></returns>
        private Dictionary<string, PropertyInfo> GetIndexPropertyDic<T>(Dictionary<string, string> fieldNameAndShowNameDic)
        {
            Dictionary<string, PropertyInfo> titlePropertyDic = new Dictionary<string, PropertyInfo>(fieldNameAndShowNameDic.Count);

            List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList();
            PropertyInfo propertyInfo = null;

            foreach (var item in fieldNameAndShowNameDic)
            {
                propertyInfo = tPropertyInfoList.Find(m => m.Name.Equals(item.Key, StringComparison.OrdinalIgnoreCase));
                titlePropertyDic.Add(item.Value, propertyInfo);
            }
            return titlePropertyDic;
        }

    }
}

原文地址:https://www.cnblogs.com/lonelyxmas/p/12065751.html

时间: 2024-10-22 02:49:12

C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)的相关文章

数学建模论文赏析_第二版_韩中庚_扫描版_高清

链接:https://pan.baidu.com/s/1zKjfrnqTVUjm9BD_qQX4IQ 提取码:vfge 如需要其它资料,可邮箱[email protected]联系我. 原文地址:https://www.cnblogs.com/onepublic/p/11491425.html

框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

知识点: 批量导入(ocupload插件,pinyin4J /POI解析Excel(apache POI) /区域分页查询 /Combobox下拉框 /分区组合条件分页查询(ajax) /分区数据导出(Excel下载) BOS项目笔记第4天 1.    区域批量导入功能 *Ajax不支持文件上传. *上传并且不刷新上传页面原理: Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象 <form target="myIframe" action="ab

站在巨人的肩膀上——人事项目数据导出word

最近在做人事项目中的,数据导出word,具体的说就是从web客户端页面获取信息,添加到信函模板中,再导出为word文档.总结一下,学会了两种方法,1.通过将word模板转换为html文件,输出word.2.利用第三方组件Aspose.Words操作word模板,输出word. 一.通过将word模板转换为html文件,输出word 1.制作word模板,在word文档中要添加内容的地方输入占位符. 2.把word模板另存为html文件. 文件-另存为-网页htm文件. 3前台代码 <asp:Bu

【基于WinForm+Access局域网共享数据库的项目总结】之篇二:WinForm开发扇形图统计和Excel数据导出

篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库完成一个法律咨询管理系统.本系统要求类似网页后台管理效果,并且基于局域网内,完成多客户端操作同一数据库,根据权限不同分别执行不同功能模块.核心模块为级联统计类型管理.数据库咨询数据扇形统计.树的操作.咨询数据的管理.手写分页.Excel数据的导出.多用户操作服务器数据等.并支持多用户同时操作,远程连

项目中生成器应用,解决量级数据导出excel内存溢出

应用场景:全量数据导出excel 遇到问题: PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 41007872 bytes) 很明显是内存溢出. 网上给出了很多治标不治本的解决方案: 1.直接修改PHP.INImemory_limit = xxxx M ;2.修改.htaccessphp_value memory_limit xxx M3.直接在程序页面上修改.ini_set(

asp.net 将repeater上数据导出到excel

1,首先得到一个DataTable public DataTable GetTable(string sql) { SqlConnnection con=new SqlConnection(ConfigurationManager.ConnectionStrings["connectionstringname"].ConnectionString); con.Open(); SqlCommand cmd = new SqlCommand(sql, con); SqlDataAdapte

使用JDBC+POI把Excel中的数据导出到MySQL

POI是Apache的一套读MS文档的API,用它还是可以比较方便的读取Office文档的.目前支持Word,Excel,PowerPoint生成的文档,还有Visio和Publisher的. http://poi.apache.org/download.html 具体的用法可以查阅文档里面您的quickguide,我给出我自己的范例,从xls文件把数据导出到MySQL. 这里面我总是假定excel在第一个sheet并且第一行是字段名,能够自动从第一行读取字段名建立一个表然后导入数据. pack

list数据导出excel并且下载到本地

最近做grid列表相关数据导出到excel功能,根据自己选择的列导出成excel 并且下载到本地.下载位置根据配置文件进行的配置.废话不说 直接上关键代码: 需要引入相关的包: compile 'net.sourceforge.jexcelapi:jxl:2.6.12'这是我项目中gradle的配置. @Override public void exportExcel(Integer[] ids,HttpServletResponse response) { List<WithdrawDepos

百度地图里面搜索到的公司商家电话导出表格?怎样将把百度地图里面搜索到的公司 电话 地址 等数据导出excel里?

好多人在问:如何将百度地图里面搜索到的公司商家电话导出表格?怎样将把百度地图里面搜索到的公司 电话 地址 等数据导出excel里? 现在,很多人都在网络上找商家,联系业务. 百度地图里有很多的商家联系方式地址等数据,这便成为很多人的便捷方式.但是一个个地复制出来商家的电话,地址是一件很痛苦的事情, 于是想到开发一个程序,模拟人的操作,将所有的数据提取保存到EXCEL里. 交流学习QQ:3125547039 主要代码思路: m_objConnection.Open();             b