该文针对的是关于树结构的数据的导出,每一个节点都可以创建不定数的子节点,在选择好某个节点进行导出

时,会把该节点以及子节点的数据都导出来。导出后的excel的格式大概如下图的形式,这个是一个比较理想

的状态,合并的空单元格也比较顺利,但实际的子节点数肯定不可能是一样的,合并必要的单元格也肯定不会

这么简单。

难点就在于得到数据和合并必要的空单元格。其实现在的数据导出有很多的博文,并且有关的一些坑也踩了好

多。导出像上图的excel格式的话,首先需要通过深度优先得到该子节点下的数据,然后得到不合并单元格的

excel格式,再然后通过从得到的树的深度的倒数第二层来看看得到需要合并的范围。依据就是首先查出该节

点的子节点数,在遍历子节点的一列,记录下合并的起始位置,结束位置来进行合并

通过深度优先得到要导出的数据

       //遍历tree
public List<Dictionary<string, object>> getTree(string id, int width)
{
List<ft_topic> list = getChild(id);
width++;
int hex = height + 1;
Dictionary<string, object> map = new Dictionary<string, object>();
ft_topic entity = db.ft_topic.Where(t => t.id == id).Single();
map.Add("name", entity.name);
map.Add("id", entity.id);
map.Add("width", width);
map.Add("height", height);
entities.Add(map);
for (int i = 0; i < list.Count; i++)
{
getTree(list[i].id, width);
}
if(list.Count == 0)
{
height++;
}
if (depth < width)
{
depth = width;
}
return entities;
}

合并必要的空单元格

        //合并单元格sheet, depth, height
public void mergeCell(HSSFSheet sheet, int depth, int height)
{
//合并单元格, 起始行号,终止行号, 起始列号,终止列号
if (depth >= 3)
{
for (int j = depth - 2; j >= 0; j--)
{
if (j == 0)
{
sheet.AddMergedRegion(new CellRangeAddress(1, height, 0, 0));
}
else
{
int cell = 2 * j - 1;
for (int i = 1; i <= height; i++)
{
String id = sheet.GetRow(i).GetCell(cell).StringCellValue;
if (id != null && !"".Equals(id))
{
List<ft_topic> topics = db.ft_topic.Where(o => o.pid == id).Where(o => o.status == "A").ToList();
if (topics.Count() > 0)
{
//得到merge范围
List<int> range = mergeCellRange(sheet, id, cell + 2, height, topics.Count());
range = getRealRanage(range);
if (range[0] != range[1])
{
sheet.AddMergedRegion(new CellRangeAddress(range[0], range[1], cell, cell));
String duplicateId = sheet.GetRow(range[0]).GetCell(cell).StringCellValue;
for (int k = range[0] + 1; k <= range[1]; k++)
{
String tmpId = sheet.GetRow(k).GetCell(cell).StringCellValue;
if (tmpId == null || "".Equals(tmpId))
{
sheet.GetRow(k).GetCell(cell).SetCellValue(duplicateId);
}
}
sheet.AddMergedRegion(new CellRangeAddress(range[0], range[1], cell + 1, cell + 1));
} }
}
} } }
}
else
{
sheet.AddMergedRegion(new CellRangeAddress(1, height, 0, 0));
}
}

得到合并范围

     //得到合并范围
public List<int> mergeCellRange(HSSFSheet sheet, String pid, int cell, int height, int childnum)
{
List<int> res = new List<int>();
List<String> ids = new List<string>();
for (int i = 1; i <= height; i++)
{
String id = sheet.GetRow(i).GetCell(cell).StringCellValue;
if (!ids.Contains(id))
{
if (db.ft_topic.Where(o => o.pid == pid).Where(t => t.id == id).Where(t => t.status == "A").SingleOrDefault() != null)
{
ids.Add(id);
if (ids.Count() == 1)
{
res.Add(i);
}
if (ids.Count() == childnum)
{
res.Add(i);
//break;
}
}
}
else
{
res.Add(i);
} }
return res;
}

注意点需要知道上面得到的范围内容有多个,因此还需要在这多个值里面得到最大,最小的值,来合并。

树结构关系的数据导出为excel的更多相关文章

  1. 学习笔记 DataGridView数据导出为Excel

    DataGridView数据导出为Excel   怎样把WinForm下的“DGV”里的绑定数据库后的数据导出到Excel中. 比如:在窗体里有个一“DGV”,DataGridView1,绑定了数据源 ...

  2. 将C1Chart数据导出到Excel

    大多数情况下,当我们说将图表导出到Excel时,意思是将Chart当成图片导出到Excel中.如果是这样,你可以参考帮助文档中保存和导出C1Chart章节. 不过,也有另一种情况,当你想把图表中的数据 ...

  3. vb.net-三种将datagridview数据导出为excel文件的函数

    第一种方法较慢,但是数据格式都比较好,需要引用excel的 Microsoft.Office.Interop.Excel.dll  office.dll #Region "导出excel函数 ...

  4. 数据导出至Excel文件--好库编程网http://code1.okbase.net/codefile/SerializeHelper.cs_2012122018724_118.htm

    using System; using System.IO; using System.Data; using System.Collections; using System.Data.OleDb; ...

  5. 数据导出到Excel中

    自己修改后的一个数据导出到Excel的方法,粘出来与大家共享. 只需要将             System.Web.HttpContext.Current.Response.Charset =   ...

  6. asp.net将数据导出到excel

    本次应用datatable导出,若用gridview(假设gridview设为了分页显示)会出现只导出当前页的情况. protected void btnPrn_Click(object sender ...

  7. 将datagrid中数据导出到excel中 -------<<工作日志2014-6-6>>

    前台datagrid数据绑定 #region 导出到excel中    /// <summary>    /// 2014-6-6    /// </summary>    / ...

  8. 机房收费系统——在VB中将MSHFlexGrid控件中的数据导出到Excel

    机房收费系统中,好多查询的窗体都包含同一个功能:将数据库中查询到的数据显示在MSHFlexGrid控件中,然后再把MSHFlexGrid控件中的数据导出到Excel表格中. 虽然之前做过学生信息管理系 ...

  9. Qt中将QTableView中的数据导出为Excel文件

    如果你在做一个报表类的程序,可能将内容导出为Excel文件是一项必须的功能.之前使用MFC的时候我就写过一个类,用于将grid中的数据导出为Excel文件.在使用了QtSql模块后,我很容易的将这个类 ...

随机推荐

  1. hive之size函数和cast转换函数

    size返回map集合中元素的个数: cast函数将一种类型的数据转换成其他格式的数据

  2. awk骚操作

    一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...

  3. 简单比较init-method,afterPropertiesSet和BeanPostProcessor

    一.简单介绍 1.init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置.init-method需要在applicationContext.xml配置文档中bean的 ...

  4. Yii2控制台命令

    Yii2控制台表格输出: 例如: $in_sheet_number_queue = []; $wms_material_in_sheet_list = \core\models\WmsMaterial ...

  5. C-Lodop对大小写敏感 不要使用大小混写

    C-Lodop是对大小写敏感的,而以前的Lodop控件,对于大小混写有可能可以用,而目前由于高版本的火狐谷歌不再支持np插件,为了兼容所有浏览器,就要使用c-lodop,或像Lodop官网的样例一样, ...

  6. js中的异常处理

    js中的异常处理语句有两个,一个是try……catch……,一个是throw. try……catch用于语法错误,错误有name和message两个属性.throw用于逻辑错误. 对于逻辑错误,js是 ...

  7. Express学习(2) ------ 中间件

    TJ Holowaychuck 将 “中间件”描述为易于挂载和调用的模块,可以“无序”使用,并有利于应用的快速开发. 1, 中间件是一个模块.在js中,模块意味着函数,所以中间件是一个函数.那么这个函 ...

  8. Nginx 反向代理如何连接上游服务器

    L:92 想上游服务器先建立TCP连接 如三次握手 下面指令可以控制握手时间 proxy_next_upstream  指令当出现502可以换个上游服务器 Tcp keepalive 一般都是由进程在 ...

  9. BZOJ5475 WC2019数树(prufer+容斥原理+树形dp+多项式exp)

    因为一大堆式子实在懒得写题解了.首先用prufer推出CF917D用到的结论,然后具体见前言不搭后语的注释. #include<iostream> #include<cstdio&g ...

  10. windows电脑连接蓝牙耳机的正确步骤

    前言 我使用的是小米运动蓝牙耳机,操作系统为win7,废话少说直接上教程 是否支持蓝牙功能 按住win+R,打开[运行],输入devmgmt.msc,回车. 只要有Bluetooth 无线电收发器,那 ...