首页 > 编程语言 >C# 使用NPOI 导出文件到Excel.支持分页及自定义排序

C# 使用NPOI 导出文件到Excel.支持分页及自定义排序

时间:2024-09-14 20:24:08浏览次数:1  
标签:自定义 C# 列名 Excel System private new using public

导出帮助类

using NPOI.HSSF.UserModel;
using NPOI.OpenXmlFormats.Spreadsheet;
using NPOI.OpenXmlFormats.Vml;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;

namespace Test.Test.BusinessCommon
{
    /// <summary>
    /// 导出Excel帮助类
    /// </summary>
    public class ExportExcelHelper<T> where T : class
    {
        private readonly int _page;
        private readonly int _pageSize;
        private bool _horizontalCenter;
        private bool _verticalCenter;
        private readonly List<T> _list;
        private readonly ISheet _sheet;
        private readonly bool _isExistFile;
        private readonly string _savePath;

        private readonly ICellStyle _style;
        private readonly HSSFWorkbook _hSSFWorkbook;
        private readonly List<Action<T, ICell>> _actions = new List<Action<T, ICell>>();
        public ExportExcelHelper(ExportParam<T> exportParam)
        {
            _list = exportParam.ExportDatas;
            _isExistFile = exportParam.IsExistFile;
            _savePath = exportParam.SavePath;
            _page = exportParam.Page;
            _pageSize = exportParam.PageSize;


            if (_list == null || _list.Count == 0)
            {
                throw new Exception("导出数据不能为空");
            }


            if (!_isExistFile)
            {
                _hSSFWorkbook = new HSSFWorkbook();
                _sheet = _hSSFWorkbook.CreateSheet("Sheet1");
            }
            else
            {
                var file = new FileStream(_savePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                _hSSFWorkbook = new HSSFWorkbook(file);
                _sheet = _hSSFWorkbook.GetSheetAt(0);
            }
            _style = _hSSFWorkbook.CreateCellStyle();
        }

        [Obsolete("还没写完")]
        public ExportExcelHelper<T> SetFormat()
        {
            return this;
        }
        /// <summary>
        /// 设置水平居中
        /// </summary>
        /// <returns></returns>
        public ExportExcelHelper<T> SetHorizontalCenter()
        {
            _style.Alignment = HorizontalAlignment.Center;
            _horizontalCenter = true;
            return this;
        }

        /// <summary>
        /// 设置水平居中
        /// </summary>
        /// <returns></returns>
        public ExportExcelHelper<T> SetVerticalCenter()
        {
            _style.VerticalAlignment = VerticalAlignment.Center;
            _verticalCenter = true;
            return this;
        }

        /// <summary>
        /// 添加列
        /// </summary>
        /// <param name="func"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public ExportExcelHelper<T> AddField(Func<T, object> func, string fieldName, int columnWidth = 0)
        {
            if (!_isExistFile)
            {
                IRow headerRow = _sheet.GetRow(0) ?? _sheet.CreateRow(0);
                ICell headerCell = headerRow.CreateCell(_actions.Count);
                headerCell.SetCellValue(fieldName);

                if (columnWidth != 0)
                {
                    _sheet.SetColumnWidth(_actions.Count, columnWidth);
                }

                if (_horizontalCenter || _verticalCenter)
                {
                    headerCell.CellStyle = _style;
                }
            }
            _actions.Add((item, cell) =>
            {
                cell.SetCellValue(Convert.ToString(func(item)));
            });
            return this;
        }

        /// <summary>
        /// 保存
        /// </summary>
        public void Save()
        {
            int rowIndex = _isExistFile ? ((_page - 1) * _pageSize) + 1 : 1;//+1 是因为第一行是表头 如果是特殊的表头需要单独处理
            foreach (var item in _list)
            {
                IRow row = _sheet.GetRow(rowIndex) ?? _sheet.CreateRow(rowIndex);
                for (int i = 0; i < _actions.Count; i++)
                {
                    ICell cell = row.GetCell(i) ?? row.CreateCell(i);
                    _actions[i](item, cell);

                    if (_horizontalCenter || _verticalCenter)
                    {
                        cell.CellStyle = _style;
                    }
                }
                rowIndex++;
            }

            using (var fileStream = new FileStream(_savePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                _hSSFWorkbook.Write(fileStream);
            }
        }
    }
}

输入参数

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Test.test.BusinessCommon.Model
{
    /// <summary>
    /// 导出参数
    /// </summary>
    public class ExportParam<T> where T : class
    {
        /// <summary>
        /// 需要导出的数据
        /// </summary>
        public List<T> ExportDatas { get; set; }
        /// <summary>
        /// 文件路径
        /// </summary>
        public string FilePath { set; get; }
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { set; get; }
        /// <summary>
        /// 分页Index
        /// </summary>
        public int Page { set; get; }
        /// <summary>
        /// 分页大小
        /// </summary>
        public int PageSize { set; get; }
        /// <summary>
        /// 是否存在文件
        /// </summary>
        public bool IsExistFile => File.Exists(SavePath);
        /// <summary>
        /// 保存的全路径
        /// </summary>
        public string SavePath => Path.Combine(FilePath, FileName);
    }
}

调用的地方

                var param = new ExportParam<Model>
                {
                    ExportDatas = new List<Model>,
                    Page = page,//分页情况下需要传入
                    PageSize = rows,//分页情况下需要传入
                    FilePath = "",
                    FileName = "xxx.xls",
                };
                new ExportExcelHelper<Model>(param)
                                .SetHorizontalCenter()
                                .SetVerticalCenter()
                                .AddField(x => x.Property1, "列名", 20 * 256)//属性-列名-列宽
                                .AddField(x => x.Property2, "列名", 20 * 256)
                                .AddField(x => x.Property3, "列名", 20 * 256)
                                .AddField(x => x.Property4, "列名", 20 * 256)
                                .AddField(x => x.Property5, "列名", 20 * 256)
                                .AddField(x => x.Property6, "列名", 20 * 256)
                                .AddField(x => x.Property7, "列名", 20 * 256)
                                .Save();
  • 支持前端循环调用,处理数据量很大的场景
  • 可随意调整导出列的顺序,自定义列名及列宽
  • 只支持列名下面直接是数据的场景,如果需要合并表头等负责操作,就需要重新扩展

标签:自定义,C#,列名,Excel,System,private,new,using,public
From: https://www.cnblogs.com/nedy/p/18414647

相关文章

  • ics1
    202400914hw1122.173010010014600101110-115100011012.24010110109011110110-1010000110-1223\((11)_B+(01010101)_B=1+85=86\)\((01001)_B-(111010)_B=9-6=3\)\((1010)_B-(01011)_B=6-11=-5\)4\((1111111)_B=(127)_D\)......
  • 2024-09-14:用go语言,给定一个正整数数组 nums,定义一个加密函数 encrypt(x),其将一个整数
    2024-09-14:用go语言,给定一个正整数数组nums,定义一个加密函数encrypt(x),其将一个整数x的每一位数字都替换为x中的最大数字,然后返回加密后的数字。例如,encrypt(523)会返回555,encrypt(213)会返回333。现在需要计算数组中所有元素加密后的和,然后返回这个和。输入:nums=[10,2......
  • C++:初始化列表、友元、static
    目录一、初始化列表​二、static成员三、友元函数一、初始化列表•之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有一种方 式,就是初始化列表,初始化列表的使用方式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后......
  • ITD102: Computer Technology Fundamentals
    ITD102:ComputerTechnologyFundamentalsWorkbook2:HighLevelTechnologiesThisdocumentcontainsthe practicalexercises questionsrelevanttothesecondpartofthisunit.RaspberryPi:AllstudentsneedaRaspberryPi.Thereisnotextbooktopurchas......
  • c语言快递小项目
    structpack_head{  intfd;//通信的文件描述符  unsignedchartype; //消息类型  unsignedcharusertype;//用户类型:1:用户 2:快递员   charname[32]; //用户名  charpaaswd[32];//密码  charbuf[32]; //调试信息  stru......
  • 解码3D数字人及AIGC产品,如何赋能医美行业全场景业务增长
    9月13日,第六届“医美小小聚”暨医美信息与服务创新发展大会在热烈的氛围中拉开帷幕。此次盛会汇聚了医美行业的顶尖精英与前瞻者,他们围绕“聚焦营销,合规增长,融合共创”的主题,深入剖析了行业的新趋势、新机遇与新挑战。在这场前瞻观点与前沿技术的碰撞中,魔珐科技凭借领先的3D数......
  • CS/INFO 6850 The Structure of Information Networks
    TheStructureofInformationNetworksHomework1CS/INFO6850Fall2024Due6pm,Wednesday,Sept.18,2024Thegoalofthisproblemsetistoprovidepracticeimplementingsomebasicnetworkanalysistechniquesonamoderate-sizednetworkdataset—specif......
  • OpenAI的ChatGPT各个模型有什么区别?
    ChatGPT版本历史/区别特点对比以下是OpenAI 公司ChatGPT 各主要模型版本的详细描述,说明了每个版本中的显著变化:GPT-3.5发布日期:2022年11月描述:GPT-3.5是第一个用于ChatGPT的版本,基于GPT-3.5模型。此版本在准确性和理解能力上有所提升,但仍在GPT-3的基础......
  • 「数学::质数」埃氏筛|欧拉筛(埃拉托斯特尼筛法|线性筛法)/ LeetCode 204(C++)
    目录概述1.埃氏筛思路复杂度Code2.欧拉筛(线性筛)思路复杂度Code总结概述上一节我们介绍了对判断一个数是否为质数的方法:「数学::质数」试除法/LuoguP5736(C++)那如果我们期望输出一个范围内的所有质数,使用试除法的时间复杂度是n√n,怎么办呢?LeetCode204:给定整......
  • vite tailwindcss@next omi
    pnpmi@tailwindcss/vite@[email protected]:{ "type":"module", "dependencies":{ "@tailwindcss/vite":"4.0.0-alpha.24", "omi":"^7.7.0", "tailwi......