翼度科技»论坛 编程开发 .net 查看内容

c#树结构转npoi复杂表头

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
Vue 前端框架框架中采用树结构打印表头,为了前后端适配NPOI导出。
这里重点做树结构转换 NPOI 复杂表头的结构数据( 跨行、跨列),其它具体导出功能请参考  https://www.cnblogs.com/lwk9527/p/17374291.html
 
导出后实际效果

 源数据 json 版
  1. [
  2.     {
  3.         "Title":"账号",
  4.         "Childrens":null
  5.     },
  6.     {
  7.         "Title":"姓名",
  8.         "Childrens":null
  9.     },
  10.     {
  11.         "Title":"语文",
  12.         "Childrens":[
  13.             {
  14.                 "Title":"成绩",
  15.                 "Childrens":null
  16.             },
  17.             {
  18.                 "Title":"用时",
  19.                 "Childrens":null
  20.             },
  21.             {
  22.                 "Title":"完成次数",
  23.                 "Childrens":null
  24.             }
  25.         ]
  26.     },
  27.     {
  28.         "Title":"数学",
  29.         "Childrens":[
  30.             {
  31.                 "Title":"成绩",
  32.                 "Childrens":null
  33.             },
  34.             {
  35.                 "Title":"用时",
  36.                 "Childrens":null
  37.             },
  38.             {
  39.                 "Title":"完成次数",
  40.                 "Childrens":null
  41.             }
  42.         ]
  43.     }
  44. ]
复制代码
转换后的到的数据 json 版
  1. [
  2.     {
  3.         "FirstRow":0,
  4.         "LastRow":1,
  5.         "FirstCol":0,
  6.         "LastCol":0,
  7.         "Value":"账号"
  8.     },
  9.     {
  10.         "FirstRow":0,
  11.         "LastRow":1,
  12.         "FirstCol":1,
  13.         "LastCol":1,
  14.         "Value":"姓名"
  15.     },
  16.     {
  17.         "FirstRow":1,
  18.         "LastRow":1,
  19.         "FirstCol":2,
  20.         "LastCol":2,
  21.         "Value":"成绩"
  22.     },
  23.     {
  24.         "FirstRow":1,
  25.         "LastRow":1,
  26.         "FirstCol":3,
  27.         "LastCol":3,
  28.         "Value":"用时"
  29.     },
  30.     {
  31.         "FirstRow":1,
  32.         "LastRow":1,
  33.         "FirstCol":4,
  34.         "LastCol":4,
  35.         "Value":"完成次数"
  36.     },
  37.     {
  38.         "FirstRow":0,
  39.         "LastRow":0,
  40.         "FirstCol":2,
  41.         "LastCol":4,
  42.         "Value":"语文"
  43.     },
  44.     {
  45.         "FirstRow":1,
  46.         "LastRow":1,
  47.         "FirstCol":5,
  48.         "LastCol":5,
  49.         "Value":"成绩"
  50.     },
  51.     {
  52.         "FirstRow":1,
  53.         "LastRow":1,
  54.         "FirstCol":6,
  55.         "LastCol":6,
  56.         "Value":"用时"
  57.     },
  58.     {
  59.         "FirstRow":1,
  60.         "LastRow":1,
  61.         "FirstCol":7,
  62.         "LastCol":7,
  63.         "Value":"完成次数"
  64.     },
  65.     {
  66.         "FirstRow":0,
  67.         "LastRow":0,
  68.         "FirstCol":5,
  69.         "LastCol":7,
  70.         "Value":"数学"
  71.     }
  72. ]
复制代码
c# 案例
  1. public void TestMethod0()
  2.         {
  3.             //源数据
  4.             List<HeadData> headDatas = new List<HeadData>();
  5.             headDatas.Add(new HeadData() { Title= "账号" });
  6.             headDatas.Add(new HeadData() { Title = "姓名" });
  7.             List<HeadData> subHeadDatas = new List<HeadData>();
  8.             subHeadDatas.Add(new HeadData() { Title = "成绩" });
  9.             subHeadDatas.Add(new HeadData() { Title = "用时" });
  10.             subHeadDatas.Add(new HeadData() { Title = "完成次数"});
  11.             headDatas.Add(new HeadData() { Title = "语文",Childrens= subHeadDatas });
  12.             List<HeadData> subHeadDatas2 = new List<HeadData>();
  13.             subHeadDatas2.Add(new HeadData() { Title = "成绩" });
  14.             subHeadDatas2.Add(new HeadData() { Title = "用时" });
  15.             subHeadDatas2.Add(new HeadData() { Title = "完成次数" });
  16.             headDatas.Add(new HeadData() { Title = "数学", Childrens = subHeadDatas2});
  17.             //转换后数据集
  18.             List<ExcelHeader> headers = new List<ExcelHeader>();
  19.             int firstRow = 0;
  20.             int firstCol = 0;
  21.             //获取树最大层次深度 (用于计算跨行)
  22.             int maxLevel= CalculateMaxLevel(headDatas);
  23.             DataConvert(headDatas, headers, firstRow, firstCol, maxLevel);//初始化
  24.             IWorkbook workbook = new HSSFWorkbook();
  25.             //工作簿
  26.             ISheet sheetTable = workbook.CreateSheet();
  27.             //生成表头
  28.             foreach (var item in headers)
  29.             {
  30.                 IRow headerRow = sheetTable.GetRow(item.FirstRow);
  31.                 if (headerRow == null)
  32.                 {
  33.                     headerRow = sheetTable.CreateRow(item.FirstRow);
  34.                     //行高,避免自动换行的内容将行高撑开
  35.                     headerRow.HeightInPoints = 24;
  36.                 }
  37.                 ICell headerCell = headerRow.CreateCell(item.FirstCol);
  38.                 headerCell.SetCellValue(item.Value);
  39.                 //设置跨行
  40.                 if (item.FirstRow != item.LastRow || item.LastCol != item.FirstCol)
  41.                 {
  42.                     //CellRangeAddress(开始行,结束行,开始列,结束列)
  43.                     //行列索引由0开始
  44.                     var region = new CellRangeAddress(item.FirstRow, item.LastRow, item.FirstCol, item.LastCol);
  45.                     sheetTable.AddMergedRegion(region);
  46.                 }
  47.               // headerCell.CellStyle = HeaderStyle(workbook);
  48.             }
  49.             // 创建一个工作表
  50.             ISheet sheet = workbook.CreateSheet("ComplexHeader");
  51.             // 将工作簿写入文件
  52.             using (var fileStream = new System.IO.FileStream("ComplexHeader.xlsx", System.IO.FileMode.Create, System.IO.FileAccess.Write))
  53.             {
  54.                 workbook.Write(fileStream, true);
  55.             }
  56.         }
  57.         /// <summary>
  58.         /// 数据转换
  59.         /// </summary>
  60.         /// <param name="HeadDatas"></param>
  61.         /// <param name="headers"></param>
  62.         /// <param name="startRow"></param>
  63.         /// <param name="startCol"></param>
  64.         /// <param name="maxLevel"></param>
  65.         /// <param name="level"></param>
  66.         public void DataConvert(List<HeadData> HeadDatas, List<ExcelHeader> headers,int startRow, int startCol,int maxLevel=2,int level=0)
  67.         {
  68.             foreach (var head in HeadDatas)
  69.             {
  70.                 int LastCol = startCol;
  71.                 int LastRow = startRow;
  72.                
  73.                 if (head.Childrens != null && head.Childrens.Count > 0)
  74.                 {
  75.                     DataConvert(head.Childrens, headers, startRow + 1, startCol, maxLevel,level+1);
  76.                 }
  77.                 else
  78.                 {
  79.                     LastRow =startRow+(maxLevel - level);
  80.                 }
  81.                 int lastCol = startCol;
  82.                 int colLength = GetTotalChildrenCount(head);
  83.                 if (colLength > 0)
  84.                 {
  85.                     lastCol= startCol + colLength-1;
  86.                 }
  87.                 headers.Add(new ExcelHeader() { FirstRow = startRow, LastRow = LastRow, FirstCol = startCol, LastCol = lastCol, Value = head.Title });
  88.                 startCol= lastCol+1;
  89.             }
  90.         }
  91.         /// <summary>
  92.         /// 获取树结构最大深度
  93.         /// </summary>
  94.         /// <param name="nodes"></param>
  95.         /// <param name="level"></param>
  96.         /// <returns></returns>
  97.         static int CalculateMaxLevel(List<HeadData> nodes, int level=0)
  98.         {
  99.             int maxLevel = level; // 初始级别为当前级别  
  100.             foreach (var node in nodes)
  101.             {
  102.                 if (node.Childrens != null) // 检查是否有子节点  
  103.                 {
  104.                     int childLevel = CalculateMaxLevel(node.Childrens, level + 1); // 递归调用以获取子节点的最大级别  
  105.                     maxLevel = Math.Max(maxLevel, childLevel); // 更新最大级别值  
  106.                 }
  107.             }
  108.             return maxLevel;
  109.         }
  110.         /// <summary>
  111.         /// 获取所有子节点数量
  112.         /// </summary>
  113.         /// <param name="node"></param>
  114.         /// <returns></returns>
  115.         public static int GetTotalChildrenCount(HeadData node)
  116.         {
  117.             if (node == null) return 0; // 基础情况:节点为空,返回0  
  118.             if (node.Childrens == null) return 0; // 基础情况:子节点列表为空,返回0  
  119.             return node.Childrens.Count + node.Childrens.Sum(child => GetTotalChildrenCount(child)); // 递归调用  
  120.         }<br><br>
复制代码
 

来源:https://www.cnblogs.com/xiaobao6652/p/17997229
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具