Vue 前端框架框架中采用树结构打印表头,为了前后端适配NPOI导出。

这里重点做树结构转换 NPOI 复杂表头的结构数据( 跨行、跨列),其它具体导出功能请参考  https://www.cnblogs.com/lwk9527/p/17374291.html

导出后实际效果

源数据 json 版

[
{
"Title":"账号",
"Childrens":null
},
{
"Title":"姓名",
"Childrens":null
},
{
"Title":"语文",
"Childrens":[
{
"Title":"成绩",
"Childrens":null
},
{
"Title":"用时",
"Childrens":null
},
{
"Title":"完成次数",
"Childrens":null
}
]
},
{
"Title":"数学",
"Childrens":[
{
"Title":"成绩",
"Childrens":null
},
{
"Title":"用时",
"Childrens":null
},
{
"Title":"完成次数",
"Childrens":null
}
]
}
]

转换后的到的数据 json 版

[
{
"FirstRow":0,
"LastRow":1,
"FirstCol":0,
"LastCol":0,
"Value":"账号"
},
{
"FirstRow":0,
"LastRow":1,
"FirstCol":1,
"LastCol":1,
"Value":"姓名"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":2,
"LastCol":2,
"Value":"成绩"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":3,
"LastCol":3,
"Value":"用时"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":4,
"LastCol":4,
"Value":"完成次数"
},
{
"FirstRow":0,
"LastRow":0,
"FirstCol":2,
"LastCol":4,
"Value":"语文"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":5,
"LastCol":5,
"Value":"成绩"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":6,
"LastCol":6,
"Value":"用时"
},
{
"FirstRow":1,
"LastRow":1,
"FirstCol":7,
"LastCol":7,
"Value":"完成次数"
},
{
"FirstRow":0,
"LastRow":0,
"FirstCol":5,
"LastCol":7,
"Value":"数学"
}
]

c# 案例

public void TestMethod0()
{
//源数据
List<HeadData> headDatas = new List<HeadData>();
headDatas.Add(new HeadData() { Title= "账号" });
headDatas.Add(new HeadData() { Title = "姓名" });
List<HeadData> subHeadDatas = new List<HeadData>();
subHeadDatas.Add(new HeadData() { Title = "成绩" });
subHeadDatas.Add(new HeadData() { Title = "用时" });
subHeadDatas.Add(new HeadData() { Title = "完成次数"});
headDatas.Add(new HeadData() { Title = "语文",Childrens= subHeadDatas });
List<HeadData> subHeadDatas2 = new List<HeadData>();
subHeadDatas2.Add(new HeadData() { Title = "成绩" });
subHeadDatas2.Add(new HeadData() { Title = "用时" });
subHeadDatas2.Add(new HeadData() { Title = "完成次数" });
headDatas.Add(new HeadData() { Title = "数学", Childrens = subHeadDatas2});
//转换后数据集
List<ExcelHeader> headers = new List<ExcelHeader>();
int firstRow = 0;
int firstCol = 0;
//获取树最大层次深度 (用于计算跨行)
int maxLevel= CalculateMaxLevel(headDatas);
DataConvert(headDatas, headers, firstRow, firstCol, maxLevel);//初始化
IWorkbook workbook = new HSSFWorkbook();
//工作簿
ISheet sheetTable = workbook.CreateSheet();
//生成表头
foreach (var item in headers)
{
IRow headerRow = sheetTable.GetRow(item.FirstRow);
if (headerRow == null)
{
headerRow = sheetTable.CreateRow(item.FirstRow);
//行高,避免自动换行的内容将行高撑开
headerRow.HeightInPoints = 24;
}
ICell headerCell = headerRow.CreateCell(item.FirstCol);
headerCell.SetCellValue(item.Value);
//设置跨行
if (item.FirstRow != item.LastRow || item.LastCol != item.FirstCol)
{
//CellRangeAddress(开始行,结束行,开始列,结束列)
//行列索引由0开始
var region = new CellRangeAddress(item.FirstRow, item.LastRow, item.FirstCol, item.LastCol);
sheetTable.AddMergedRegion(region);
}
// headerCell.CellStyle = HeaderStyle(workbook);
} // 创建一个工作表
ISheet sheet = workbook.CreateSheet("ComplexHeader"); // 将工作簿写入文件
using (var fileStream = new System.IO.FileStream("ComplexHeader.xlsx", System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
workbook.Write(fileStream, true);
}
}
/// <summary>
/// 数据转换
/// </summary>
/// <param name="HeadDatas"></param>
/// <param name="headers"></param>
/// <param name="startRow"></param>
/// <param name="startCol"></param>
/// <param name="maxLevel"></param>
/// <param name="level"></param>
public void DataConvert(List<HeadData> HeadDatas, List<ExcelHeader> headers,int startRow, int startCol,int maxLevel=2,int level=0)
{
foreach (var head in HeadDatas)
{
int LastCol = startCol;
int LastRow = startRow; if (head.Childrens != null && head.Childrens.Count > 0)
{
DataConvert(head.Childrens, headers, startRow + 1, startCol, maxLevel,level+1);
}
else
{
LastRow =startRow+(maxLevel - level);
}
int lastCol = startCol;
int colLength = GetTotalChildrenCount(head);
if (colLength > 0)
{
lastCol= startCol + colLength-1;
}
headers.Add(new ExcelHeader() { FirstRow = startRow, LastRow = LastRow, FirstCol = startCol, LastCol = lastCol, Value = head.Title }); startCol= lastCol+1;
}
}
/// <summary>
/// 获取树结构最大深度
/// </summary>
/// <param name="nodes"></param>
/// <param name="level"></param>
/// <returns></returns>
static int CalculateMaxLevel(List<HeadData> nodes, int level=0)
{
int maxLevel = level; // 初始级别为当前级别
foreach (var node in nodes)
{
if (node.Childrens != null) // 检查是否有子节点
{
int childLevel = CalculateMaxLevel(node.Childrens, level + 1); // 递归调用以获取子节点的最大级别
maxLevel = Math.Max(maxLevel, childLevel); // 更新最大级别值
}
}
return maxLevel;
}
/// <summary>
/// 获取所有子节点数量
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public static int GetTotalChildrenCount(HeadData node)
{
if (node == null) return 0; // 基础情况:节点为空,返回0
if (node.Childrens == null) return 0; // 基础情况:子节点列表为空,返回0
return node.Childrens.Count + node.Childrens.Sum(child => GetTotalChildrenCount(child)); // 递归调用
}

c#树结构转npoi复杂表头的更多相关文章

  1. NPOI操作EXCEL(六)——矩阵类表头EXCEL模板的解析

    哈哈~~~很高兴还活着.总算加班加点的把最后一类EXCEL模板的解析做完了... 前面几篇文章介绍了博主最近项目中对于复杂excel表头的解析,写得不好,感谢园友们的支持~~~ 今天再简单讲诉一下另一 ...

  2. NPOI操作EXCEL(五)——含合并单元格复杂表头的EXCEL解析

    我们在第三篇文章中谈到了那些非常反人类的excel模板,博主为了养家糊口,也玩命做出了相应的解析方法... 我们先来看看第一类复杂表头: ...... 博主称这类excel模板为略复杂表头模板(蓝色部 ...

  3. npoi实现 从固定的行读取数据作为表头并返回datable

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  4. NPOI导出多表头Execl(通过html表格遍历表头)

    关于NPOI的相关信息,我想博客园已经有很多了,而且NPOI导出Execl的文章和例子也很多,但导出多表头缺蛮少的:今天要讲的通过自己画html表格:通过html表格来导出自定义的多表头: 先来看要实 ...

  5. NPOI 表头、页眉页脚重复设置

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. 使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 ...

  6. NPOI导出Excel合并表头写入公式

    protected void Btn1_Click(object sender, EventArgs e) { //建立空白工作簿 IWorkbook workbook = new HSSFWorkb ...

  7. C# NPOI Excel多级表头导出多个表

    下载地址:https://files.cnblogs.com/files/netlock/NPOIDemo.rar

  8. 免费高效实用的.NET操作Excel组件NPOI(.NET组件介绍之六)

    很多的软件项目几乎都包含着对文档的操作,前面已经介绍过两款操作文档的组件,现在介绍一款文档操作的组件NPOI. NPOI可以生成没有安装在您的服务器上的Microsoft Office套件的Excel ...

  9. C#通过NPOI操作Excel

    参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-post.html http://www.yuanjiaocheng.net/w ...

  10. NPOI导出Excel

    using System;using System.Collections.Generic;using System.Linq;using System.Text;#region NPOIusing ...

随机推荐

  1. 邀请报名|11月24日阿里云原生 Serverless 技术实践营 深圳站

    活动简介 "阿里云云原生 Serverless 技术实践营 " 是一场以 Serverless 为主题的开发者活动,活动受众以关注 Serverless 技术的开发者.企业决策人. ...

  2. element-ui实现部分引用

    1.首先安装 babel-plugin-component组件: 2.修改babel.js配置 1 module.exports = { 2 presets: [ 3 '@vue/app', 4 [' ...

  3. babel7 的配置加载逻辑

    babel.config.js 是对整个项目(父子package) 都生效的配置,但要注意babel的执行工作目录. .babelrc 是对 待编译文件 生效的配置,子package若想加载.babe ...

  4. Java面试——基础知识点

    JVM Jvm体系总体分四大块:类的加载机制.Jvm内存结构.GC算法垃圾回收.GC分析命令调优. 类的加载机制 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的 ...

  5. C# 几种常见数据结构(数组、链表、Hash表)

    一.内存上连续存储,节约空间,可以索引访问,读取快,增删慢 Array: 在内存上连续分配的,而且元素类型是一样的,可以坐标访问;读取快--增删慢,长度不变 { //Array:在内存上连续分配的,而 ...

  6. Python 学习笔记: 从变量到装饰器

    从变量开始 python 中全局变量在函数作用域内只能读,不能"写".如果要在函数作用域内实现修改全局变量值操作,需要使用关键字 global 显示指明该变量是全局变量. 但是,在 ...

  7. 使用 Woodpecker 与 Gitea 搭建纯开源的 CI 流程|极限降本

    最近开源了一个挂机冒险游戏<模拟龙生>,有热心同学不仅帮忙做优化,还连夜在给游戏加页面,泪目.详见文末小结部分. 一.前言 大家好,这里是白泽.这篇文章是<Woodpecker CI ...

  8. 基于Java 的商城网站系统设计与实现(8000字论文)

    摘要 随着我国经济活力的不断提升和互联网的快速发展,信息的重要性正在显现出来.电子商务作为经济发展的重要一环取得了突飞猛进的发展.由于具有高效便捷的优点,网上购物已经成为一种不可或缺的新型生活方式,近 ...

  9. Tidb 使用minio 进行br备份数据库的过程

    Tidb 使用minio 进行br备份数据库的过程 背景 br 备份恢复时一般需要共享存储. 前段时间一直使用的是nfs 进行共享文件备份. 这样需要所有的机器在 相同的目录下面挂载相同的nfs. 并 ...

  10. [转帖]Jmeter_jmeter-plugins插件的安装使用

    一.安装JMter Plugins 1.官网下载 JMeter Plugins 的jar包 2. 将下载的jar包复制到 %JMETER_HOME%\lib\ext 目录下 3. 启动 JMeter ...