.Net Core NPOI 导出多级表头

 
想要导出这样的表格

 

数据准备格式

 

 

 

附上源码

  1 using NPOI.HSSF.UserModel;
  2 using NPOI.SS.UserModel;
  3 using NPOI.SS.Util;
  4 using System.Data;
  5 using System.Text.RegularExpressions;
  6 
  7 namespace TestConsoleApp
  8 {
  9     /// <summary>
 10     /// 导出Excel
 11     /// </summary>
 12     public static class ExportHelper
 13     {
 14         public static void Export()
 15         {
 16             var dt = CreteTable();
 17             var titles = GetExcelTitles(dt.Columns, out int maxTitleLevel);
 18 
 19             HSSFWorkbook workbook = new HSSFWorkbook();
 20             ISheet sheet = workbook.CreateSheet("Sheet1");
 21 
 22             var allRowCount = dt.Rows.Count + maxTitleLevel;
 23             //创建所有单元格
 24             for (int i = 0; i < allRowCount; i++)
 25             {
 26                 var row = sheet.CreateRow(i);
 27                 for (int j = 0; j < dt.Columns.Count; j++)
 28                 {
 29                     row.CreateCell(j);
 30                 }
 31             }
 32 
 33             //合并创建表头
 34             foreach (var tit in titles)
 35             {
 36                 sheet.GetRow(tit.StartRow).GetCell(tit.StartColumn).SetCellValue(tit.Title);
 37                 if (tit.MergeColumnCount + tit.MergeRowCount > 0)
 38                 {
 39                     sheet.AddMergedRegion(new CellRangeAddress(tit.StartRow, tit.StartRow + tit.MergeRowCount, tit.StartColumn, tit.StartColumn + tit.MergeColumnCount));
 40                 }
 41             }
 42 
 43             //生成数据行 
 44             for (int i = 0; i < dt.Rows.Count; i++)
 45             {
 46                 for (int j = 0; j < dt.Columns.Count; j++)
 47                 {
 48                     string cellValue = dt.Rows[i][j].ToString();
 49                    sheet.GetRow(maxTitleLevel + i).Cells[j].SetCellValue(cellValue);
 50                 }
 51             }
 52 
 53             using FileStream stm = File.OpenWrite(@"D:\Drivers\Merge.xls");
 54             workbook.Write(stm);
 55         }
 56 
 57         private static DataTable CreteTable()
 58         {
 59             DataTable dt = new DataTable();
 60             dt.Columns.Add("编号");
 61             dt.Columns.Add("收入-线上采购-数量");
 62             dt.Columns.Add("收入-线上采购-金额");
 63 
 64             dt.Columns.Add("收入-线下采购-数量");
 65             dt.Columns.Add("收入-线下采购-金额");
 66 
 67             dt.Columns.Add("回收-数量");
 68             dt.Columns.Add("回收-金额");
 69 
 70             dt.Columns.Add("支出-测试01-数量");
 71             dt.Columns.Add("支出-测试01-金额");
 72 
 73             dt.Columns.Add("支出-测试02-数量");
 74             dt.Columns.Add("支出-测试02-金额");
 75 
 76             dt.Columns.Add("其它-数量");
 77             dt.Columns.Add("其它-金额");
 78 
 79             dt.Columns.Add("备注");
 80 
 81             for (int i = 1; i <= 100; i++)
 82             {
 83                 var row = dt.NewRow();
 84 
 85                 row["编号"] = "编号" + i;
 86                 row["收入-线上采购-数量"] = i;
 87                 row["收入-线上采购-金额"] = i;
 88                 row["收入-线下采购-数量"] = i;
 89                 row["收入-线下采购-金额"] = i;
 90                 row["回收-数量"] = i;
 91                 row["回收-金额"] = i;
 92                 row["支出-测试01-数量"] = i;
 93                 row["支出-测试01-金额"] = i;
 94                 row["支出-测试02-数量"] = i;
 95                 row["支出-测试02-金额"] = i;
 96                 row["其它-数量"] = i;
 97                 row["其它-金额"] = i;
 98                 row["备注"] = i;
 99                 dt.Rows.Add(row);
100             }
101 
102             return dt;
103         }
104 
105 
106         private static List<ExcelTitle> GetExcelTitles(DataColumnCollection columns, out int maxTitleLevel)
107         {
108             maxTitleLevel = 0;
109             List<LevelExcelTitle> levelExcelTitles = new List<LevelExcelTitle>();
110 
111             for (var index = 0; index < columns.Count; index++)
112             {
113                 var column = columns[index].ToString();
114 
115                 var arr = column.Split("-");
116 
117 
118                 if (maxTitleLevel < arr.Length)
119                 {
120                     maxTitleLevel = arr.Length;
121                 }
122 
123                 for (int i = 0; i < arr.Length; i++)
124                 {
125                     levelExcelTitles.Add(new LevelExcelTitle()
126                     {
127                         Title = arr[i],
128                         LevelCode = string.Join("-", arr[..(i + 1)]),
129                         RowIndex = i,
130                         ColumnIndex = index,
131                         TotalLevel = arr.Length
132                     });
133                 }
134             }
135 
136             var titleLevel = maxTitleLevel;
137             var excelTitles = levelExcelTitles
138                 .GroupBy(b => new
139                 {
140                     b.LevelCode,
141                     b.Title
142                 })
143                .Select(b => new ExcelTitle()
144                {
145                    Title = b.Key.Title,
146                    StartRow = b.Min(c => c.RowIndex),
147                    MergeRowCount = b.Min(c => c.RowIndex) + 1 == b.Max(c => c.TotalLevel) ? titleLevel - b.Max(c => c.TotalLevel) : 0,
148 
149                    StartColumn = b.Min(c => c.ColumnIndex),
150                    MergeColumnCount = b.Count() - 1,//排除自身
151                }).ToList();
152 
153             return excelTitles;
154         }
155     }
156 
157     public class ExcelTitle
158     {
159         /// <summary>
160         /// 标题
161         /// </summary>
162         public string Title { get; set; }
163 
164         /// <summary>
165         /// 开始行
166         /// </summary>
167         public int StartRow { get; set; }
168 
169         /// <summary>
170         /// 合并行
171         /// </summary>
172         public int MergeRowCount { get; set; }
173 
174 
175         /// <summary>
176         /// 开始列
177         /// </summary>
178         public int StartColumn { get; set; }
179 
180         /// <summary>
181         /// 合并列
182         /// </summary>
183         public int MergeColumnCount { get; set; }
184     }
185 
186     public class LevelExcelTitle
187     {
188         /// <summary>
189         /// 标题
190         /// </summary>
191         public string Title { get; set; }
192 
193         public string LevelCode { get; set; }
194 
195         /// <summary>
196         /// 第几行
197         /// </summary>
198         public int RowIndex { get; set; }
199 
200         /// <summary>
201         /// 第几列
202         /// </summary>
203         public int ColumnIndex { get; set; }
204 
205         /// <summary>
206         /// 总层
207         /// </summary>
208         public int TotalLevel { get; set; }
209     }
210 }

 

 

 
 
 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/827507.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nacos原理汇总

今天就应某位小伙伴的要求,来讲一讲Nacos作为服务注册中心底层的实现原理不知你是否跟我一样,在使用Nacos时有以下几点疑问:临时实例和永久实例是什么?有什么区别? 服务实例是如何注册到服务端的? 服务实例和服务端之间是如何保活的? 服务订阅是如何实现的? 集群间数据…

人工智能模型训练中的数据之美——探索TFRecord

上一篇:《构建人工智能模型基础:TFDS和Keras的完美搭配》 序言:在人工智能模型的训练过程中,如何高效管理和处理大量数据是一个重要的课题。TensorFlow 的 TFRecord 格式为大规模数据存储和处理提供了一种灵活且高效的解决方案。在本节知识中,我们将介绍如何利用 TFRecord…

教师提前批试讲-注意事项

教师提前批试讲-注意事项

大白菜装系统

在平时工作中,作为程序员,最苦逼的是公司的电脑坏了,都找你。我想说我是程序员,不是修电脑的,但是架不住小姐姐的热情,还是做了。 装系统流程: 第一步:前期准备 1、使用【大白菜】制作U盘启动盘。 2、查询机型的U盘启动快捷键。 3、准备一个ISO/GHO镜像。 第二步:插入…

实验11:装饰模式

本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解装饰模式的动机,掌握该模式的结构; 2、能够利用装饰模式解决实际问题。[实验任务一]:手机功能的升级用装饰模式模拟手机功能的升级过程:简单的手机(SimplePhone)在接收来电时,会发出声音提醒主人;而Ja…

Pbootcms网站,从Apache切换为Nginx后网站打不开

打开网站设置登录宝塔面板。 选择需要配置的网站,点击“设置”。进入伪静态设置在网站设置页面中,找到并点击“伪静态”选项卡。添加Nginx伪静态规则在伪静态设置中,清空原有规则或选择自定义规则。 输入以下Nginx伪静态规则:location / {if (!-e $request_filename){rewri…

2024/11/06

软件设计 实验10:组合模式 用透明组合模式实现教材中的“文件夹浏览”这个例子。 类图 public abstract class AbstractFile {public abstract void add(AbstractFile element);public abstract void remove(AbstractFile element);public abstract void display(int depth); …

SQLSTATE[HY000] [1045] Access denied for user ‘root‘@‘localhost‘ (using password: YES)

错误解析错误代码:SQLSTATE[HY000] [1045] 错误信息:Access denied for user ‘root’@‘localhost’ (using password: YES)可能的原因密码错误:提供的密码与数据库中存储的密码不匹配。 用户权限问题:用户root可能没有从localhost访问数据库的权限。 配置文件问题:MySQL…

帝国CMS更改域名后信息地址中的域名不变解决方法

修改系统参数设置进入“系统参数设置 - 基本属性 - 网站地址”,设置为 /。 不要填写具体的域名,以避免信息地址变成绝对地址。更新信息页地址进入“系统 - 数据更新 - 更新信息页地址”,选择相应的数据表,点击“扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年…

帝国CMS系统后台批量删除不带标题图片信息

执行SQL语句删除不带标题图片的信息:delete from [表前缀]_ecms_news where titlepic = ; delete from [表前缀]_ecms_news_index where id not in (select id from [表前缀]_ecms_news); delete from [表前缀]_ecms_news_data_1 where id not in (select id from [表前缀]_ec…

帝国CMS留言模板提示请输入姓名,邮箱与留言内容解决方法

检查表单提交:确认提交地址、POST 数据和表单字段正确。 在表单中添加隐藏字段 bid: <input name="bid" type="hidden" value="分类ID" />扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉各种CMS,精通PHP+MYSQL、HT…

信息安全新篇章:车企图纸安全外发创新方案!

车企的图纸在其业务流程中会与多个环节产生交集,并涉及到图纸安全外发传输。以下是主要涉及的环节及图纸传输发送的相关情况: 1.市场分析报告、概念草图、初步布置图等图纸:需要在设计团队内部进行传输,以供讨论和修改。同时,需要发送给供应商或合作伙伴进行初步评估和反馈…