分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限

大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码。

因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见。

一个系统开发出来,系统要运行起来,很多数据要初始化,这个时候也是需要客户提供各种业务的基础数据。客户提供的数据中,其中除了word、pdf,最常见的就是Excel。

废话不多说,直接上图上代码:

如图,

左侧三列,作为 一个系统 所有菜单的树状结构。

其他列 以用户的信息(如用户名、登录名) 作为表头,需要注意的是,在整理数据进行导出时,需保证列名不能重复。

 public static void DataTree(string path, DataTable table, int treeIndex = 10000)
        {
            using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                IWorkbook workBook = new HSSFWorkbook();
                //现在使用的仍然是生成Excel2003的Excel文件,由于03对行数(65535)和列数(255)有限制,所以当数据超出范围后难免出错
                //ArgumentException: Invalid column index (256). Allowable column range for BIFF8 is (0..255) or (‘A‘..‘IV‘) ...
                if (Path.GetExtension(path).Equals(".xlsx", System.StringComparison.OrdinalIgnoreCase))
                {
                    workBook = new XSSFWorkbook();
                }

                string sheetName = string.IsNullOrWhiteSpace(table.TableName) ? "Sheet1" : table.TableName;
                ISheet sheet = workBook.CreateSheet(sheetName);
                IRow row = null;
                int colNum = table.Columns.Count;
                if (treeIndex < table.Columns.Count || treeIndex > 0)
                {
                    colNum = treeIndex;
                }

                ICellStyle cellCenterStyle = GetCenter(workBook);

                int beginNum = 1;//排除列头,从1开始

                //处理表格列头
                row = sheet.CreateRow(beginNum - 1);
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    string strVal = table.Columns[i].ColumnName;
                    ICell cell = row.CreateCell(i);
                    cell.SetCellValue(strVal);
                    cell.CellStyle = cellCenterStyle;
                    row.Height = 350;
                    sheet.AutoSizeColumn(i);
                }

                //处理数据内容
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    row = sheet.CreateRow(beginNum + i);
                    row.Height = 250;
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        string strVal = table.Rows[i][j].ToString();
                        ICell currCell = row.CreateCell(j);
                        currCell.SetCellValue(strVal);
                        currCell.CellStyle = cellCenterStyle;
                        sheet.SetColumnWidth(j, 256 * 15);
                    }
                }

                for (int i = 0; i < colNum; i++)
                {
                    List<int> lstColWidth = new List<int>();
                    string currVal = string.Empty;
                    string nextVal = string.Empty;
                    for (int j = beginNum; j <= sheet.LastRowNum; j++)
                    {
                        currVal = sheet.GetRow(j).Cells[i].StringCellValue;

                        int mk = j;
                        if (!string.IsNullOrWhiteSpace(currVal))//排除 空值,空值不做合并处理
                        {
                            for (int k = j + 1; k <= sheet.LastRowNum; k++)
                            {
                                nextVal = sheet.GetRow(k).Cells[i].StringCellValue;

                                if (currVal != nextVal)
                                {
                                    //因为k 累加所以导致当前值与下个值 不相同,所以记录 当前行数要 减去1
                                    mk = k - 1;
                                    break;
                                }
                                else if (k == sheet.LastRowNum) //边界值,处理最后一行,则提前Break 并记录当前 k
                                {
                                    mk = k;
                                    break;
                                }
                            }
                        }

                        if (mk != j)//排除 空值外,下个值的行数不等于当前行数,则需要合并
                        {
                            sheet.AddMergedRegion(new CellRangeAddress(j, mk, i, i));
                        }

                        //if (i == 0) //如果是第一列,则 垂直水平居中
                        {
                            sheet.GetRow(j).Cells[i].CellStyle = cellCenterStyle;
                        }
                        //跳到执行下一个不同数据的行
                        j = mk;

                        //记录列长度
                        lstColWidth.Add(DataLength(currVal));
                    }

                    //设置列宽
                    int maxWidth = lstColWidth.Max() * 200;
                    sheet.SetColumnWidth(i, maxWidth);
                }
//固定列、行 滚动时不变
                sheet.CreateFreezePane(3, 1, 3, 1);

                //写入数据流
                workBook.Write(fs);
            }
        }

        private static ICellStyle GetCenter(IWorkbook workBook, short fontSize = 10)
        {
            ICellStyle cellStyle = workBook.CreateCellStyle();
            IFont font = workBook.CreateFont();
            font.FontName = "微软雅黑";
            font.FontHeightInPoints = fontSize;
            cellStyle.SetFont(font);
            cellStyle.VerticalAlignment = VerticalAlignment.Center;
            cellStyle.Alignment = HorizontalAlignment.Center;
            return cellStyle;
        }

        /// <summary>
        /// 获取字符串长度(中文按2个字节长度)
        /// </summary>
        /// <param name="stringWithEnglishAndChinese"></param>
        /// <returns></returns>
        private static int DataLength(string stringWithEnglishAndChinese)
        {
            int lng = 0;
            for (int i = 0; i < stringWithEnglishAndChinese.Length; i++)
            {
                byte[] b = System.Text.Encoding.Default.GetBytes(stringWithEnglishAndChinese.Substring(i, 1));
                if (b.Length > 1)
                    lng += 2;
                else
                    lng += 1;
            }
            return lng;
        }
时间: 2024-10-13 15:27:59

分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限的相关文章

纯CSS实现树状结构导航,纯CSS折叠菜单,简单粗暴,就是这么强大

在对网站进行mip改造的时候,使用百度的导航组件,很难有较好的展现形式. 百度又不允许自定义JS,所以,考虑增加CSS(是在百度组件的基础上增加JS),用css补充实现点击功能,实现精美的导航. 最终结果是为了实现以下三个样式 1.未展开状态 2.展开状态,有二级导航的,要出现+号 3.点击+号能展开二级菜单 参考以下树状CSS的设计思路,主要是使用 html5的 details summary标签,注意看注释 演示图如下  代码如下 <!DOCTYPE html> <html xmln

权限模块_分配权限_显示树状结构_页面中的选中效果

权限模块__分配权限__显示树状结构1 显示树状结构:依赖关系 setPrivilegeUI.jsp <!-- 显示权限树 --> <td> <!--用它回显 <s:checkboxlist name="privilegeIds" list="#privilegeList" listKey="id" listValue="name"></s:checkboxlist> --

数据库树状结构的关系表的删除方案

所谓的树状结构的关系,即是记录之间有id,parentId关系的数据.场景是这样的:业务中用到了一张分享表,表里的主要字段有分享人,和被分享人,以及分享任务ID,可以通过一系列的分享构造成树状的结构,需求是删除任意的节点,需要删除节点下面的所有分享关联的数据. 方案1:可以把每个节点用一个标识将分享关系串起来拼接成一个字符串,表里增加一个字段记录这个路径字符串,删除节点时条件是只有包含节点关系记录的路径就删除,这种方案的灵感来自于windows创建文件夹的模式,每个文件夹都对应一个唯一的路径,删

NPOI导出excel(带图片)

近期项目中用到Excel导出功能,之前都是用普通的office组件导出的方法,今天尝试用下NPOI,故作此文以备日后查阅. 1.NPOI官网http://npoi.codeplex.com/,下载最新工具包. 2.选择.net版本(例如dotnet4),引用其中的dll. 3.后台代码 using System; using System.Web; using System.Data; using System.Configuration; using System.IO; using Test

NPOI导出EXCEL 打印设置分页及打印标题

在用NPOI导出EXCEL的时候设置分页,在网上有查到用sheet1.SetRowBreak(i)方法,但一直都没有起到作用.经过研究是要设置  sheet1.FitToPage = false; 而这个属性默认是true的,怪不得一直设置都不起作用. 设置打印标题用 hssfworkbook.SetRepeatingRowsAndColumns(0, 0, 5, 0, 5); 但最新版本已经有新的方法了. Sheet sheet1 = hssfworkbook.CreateSheet("She

Android无限级树状结构

通过对ListView简单的扩展.再封装,即可实现无限层级的树控件TreeView. 1 package cn.asiontang.nleveltreelistview; 2 3 import android.annotation.TargetApi; 4 import android.content.Context; 5 import android.os.Build; 6 import android.util.AttributeSet; 7 import android.view.View

在Silverlight中使用HierarchicalDataTemplate为TreeView实现递归树状结构

将实体绑定到TreeView控件,实现树状结构的显示,如下图所示.这个功能通过HierarchicalDataTemplate实现. ? 1. 业务实体 作为举例,我定义了一个大家都很熟悉的Folder类型,即文件夹.我们都知道,文件夹又可以包含子文件夹,而且可以多层嵌套.所以,这是一个递归的结构体. public class Folder { public string Name { get; set; } public ObservableCollection<Folder> Folder

c# 递归、树状结构

1.树状结构 treeView.Nodes.Clear(); TreeNode tree = new TreeNode(); tree.Text = "字母"; treeView.Nodes.Add(tree); // tree.Nodes.Add("A"); TreeNode tree1 = new TreeNode(); tree1.Text = "汉字"; treeView.Nodes.Add(tree1); TreeNode a = ne

json格式转树状结构

转自:http://rockyuse.iteye.com/blog/1541308 /** * json格式转树状结构 * @param {json} json数据 * @param {String} id的字符串 * @param {String} 父id的字符串 * @param {String} children的字符串 * @return {Array} 数组 */ function transData(a, idStr, pidStr, chindrenStr){ var r = []