精华内容
下载资源
问答
  • 2022-03-11 11:02:07

    需求:

    今日遇到一个需求:table重载后展示动态表头

    问题:

    碰到一个问题:
    表格重载后,表头没有按照重载方法传入的cols参数展示,而是还是展示原先的表头

    原因:

    经过一番排查后发现原因,layui中 table.reload(ID, options) 在接收options中的参数中,如果参数是数组形式,那并不会完全替换历史参数,而是覆盖到对应长度。如果之前传入参数是[1,2,3,4],重载传入参数是[a,b.c],那后台获取到的参数是[a,b,c,4]

    解决:

    这个问题解决起来并不复杂,而是复杂在了发现问题的原因,实际解决只需要一行关键代码就好,在table的render方法的回调函数中,将cols字段初始化就可以了: this.cols = [ ];

    实例

    1.表头重载的方法

      //执行重载
       form.on('select(interest)', function(data){
    		  console.log(data);
    		  let v=data.value;
    		   table.reload('tableId', {
    	               page: {curr: 1 },//重新从第 1 页开始 
    	               //where:[],
    	               cols: objCol[v]//新的表头
    	           });
    	});
    

    2.关键代码!!!!!

    
    //表格渲染
    table.render({
        elem:"#tableId",
        cols:cols,
        url:"....",
        defaultToolbar:[],
        data:[],
        done:function (res,curr,count) {
            this.cols = []; //(关键代码)将cols初始化,否则表格重载时无法正确重新渲染表头
        }
    
    更多相关内容
  • 又get到一种思路,不光是layui。 外面这层table,就是用原生拼接的。 @Override public List<Map>> distribution(String begin,String end,String name,String hospitalCode) { HashMap<String> params = new ...
  • 今天小编就为大家分享一篇layui table动态表头 改变表格头部 重新加载表格的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 今天小编就为大家分享一篇layui中table表头样式修改方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • layui 复杂表头多层表头表格数据非后台导出excel

    万次阅读 多人点赞 2019-08-28 16:20:38
    用过layui table的都了解,layui表格自带导出功能,只要在属性toolbar里配置即可。 如果嫌toolbar里的导出按钮不够美观,layui也友好的提供了自行定义按钮后调用导出页面数据的方法,详见:[官方文档] `遗憾的`是...

    用过layui table的都了解,layui的表格自带导出功能,只要在属性toolbar里配置即可。
    如果嫌toolbar里的导出按钮不够美观,layui也友好的提供了自行定义按钮后调用导出页面数据的方法,详见:官方文档
    遗憾的是:该方法暂时并不支持对多层表头的导出。
    而多层复杂表头在很多系统中都有体现,而若不想通过后台代码去做导出,只在前端页面上该如何做呢?



    1 史前

    1.1 直接使用(两种方式)

    1.下载插件:
    地址:github table2excel
    下载下来项目后,在项目的dist中就有该js,在自己表格html页面引用即可使用。

    链接:百度云下载js
    提取码:1f52

    /**
     * 使用方法该js的方法(两行代码)
     */
    let table2excel = new Table2Excel();
    // 传入你的tableId即可导出
    table2excel.export($('#tableId'), "your filename");
    
    1. 一个解析页面元素方法:复制走即可使用
    /**
     * 
     * @param id:表格的id
     * @param fileName:导出的excel的名字
     */
     function  exportForExcle(id,fileName){
            var table = $(document.getElementById(id)).clone();
            table.attr('id','datatab');
            table.appendTo('body');
            method5('datatab');
            datatab.remove();
            function method5(tableid) {
                var idTmr;
                var tableToExcel = (function() {
                    var uri = 'data:application/vnd.ms-excel;base64,',
                        template = '<html><head><meta charset="UTF-8"></head><body><table border="1px">{table}</table></body></html>',
                        base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) },
                        format = function(s, c) {return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }
                    return function(table, name) {
                        if (!table.nodeType) table = document.getElementById(table)
                        var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
                        var aTag = document.createElement('a');
                        aTag.download = fileName;
                        aTag.href = uri + base64(format(template, ctx));
                        document.body.appendChild(aTag);
                        aTag.onclick = function () {
                            document.body.removeChild(aTag);
                        }
                        aTag.click();
                    }
                })()
                if(getExplorer()=='ie')
                {
                    var curTbl = document.getElementById(tableid);
                    var oXL = new ActiveXObject("Excel.Application");
                    var oWB = oXL.Workbooks.Add();
                    var xlsheet = oWB.Worksheets(1);
                    var sel = document.body.createTextRange();
                    sel.moveToElementText(curTbl);
                    sel.select();
                    sel.execCommand("Copy");
                    xlsheet.Paste();
                    oXL.Visible = true;
                    try {
                        var fname = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
                    } catch (e) {
                        print("Nested catch caught " + e);
                    } finally {
                        oWB.SaveAs(fname);
                        oWB.Close(savechanges = false);
                        oXL.Quit();
                        oXL = null;
                        idTmr = window.setInterval("Cleanup();", 1);
                    }
                }
                else
                {
                    tableToExcel(tableid)
                }
                function Cleanup() {
                    window.clearInterval(idTmr);
                    CollectGarbage();
                }
                function  getExplorer() {
                    var explorer = window.navigator.userAgent ;
                    //ie
                    if (explorer.indexOf("MSIE") >= 0) {
                        return 'ie';
                    }
                    //firefox
                    else if (explorer.indexOf("Firefox") >= 0) {
                        return 'Firefox';
                    }
                    //Chrome
                    else if(explorer.indexOf("Chrome") >= 0){
                        return 'Chrome';
                    }
                    //Opera
                    else if(explorer.indexOf("Opera") >= 0){
                        return 'Opera';
                    }
                    //Safari
                    else if(explorer.indexOf("Safari") >= 0){
                        return 'Safari';
                    }
                }
            }
        }
    

    1.2 上述插件使用场景解析

    可用的情况:表格的渲染方式为静态渲染,即在html的table标签中渲染好了表头与数据。
    不可用的情况:表格的渲染方式为动态渲染,即从后台查询数据来渲染表格,包括渲染动态的表头。
    不可用的情况原因:用layui.table动态渲染的表格,不会在页面的html table标签中添加doom元素。
    如下图的表格(表头和数据均为动态渲染),layui渲染数据后,并不会在table标签中append doom元素,而是会在table 标签的下面追加一个新的div,将tr th td 和数据全部存放在里面。
    这也就导致了上述的两种方法均无法下载excel,就是因为:该插件在页面上找不到插件所需的doom节点与数据。
    在这里插入图片描述
    在这里插入图片描述


    1.3 不可用场景处理

    在表格渲染完成后的done方法中,去遍历页面上layui生成的div,抓取里面的格式与数据,来手动append到table中,再控制该table隐藏,来为导出做准备。

    1. 分析doom元素:能清晰看到表头和body的doom结构,里面有你需要的所有信息,包括表头的各种合并操作。

    在这里插入图片描述

    1. 手动向table标签里append html。
    table.render({
    	...          
        done: function (res, curr, count) {
            let header_tr = $("#tableId").next().find(".layui-table-header").find("tr");
            let body_tr = $("#tableId").next().find(".layui-table-body").find("tr");
            let header_html = "";
            let body_html = "";
            // 获取表头html,包括单元格的合并
            $.each(header_tr,function (i,tr) {
                let header_th = $(tr).find("th");
                header_html += "<tr>";
                $.each(header_th,function (j,th) {
                    let rowspan_num = $(th).attr("rowspan");// 行合并数
                    let colspan_num = $(th).attr("colspan");// 列合并数
                    if (rowspan_num && !colspan_num){// 只有行合并时
                        header_html += '<th rowspan= "'+ rowspan_num +'">';
                    } else if (colspan_num && !rowspan_num){// 只有列合并时
                        header_html += '<th colspan= "'+ colspan_num +'">';
                    } else if (rowspan_num && colspan_num){// 行列合并均有时
                        header_html += '<th rowspan= "'+ rowspan_num +'" colspan="'+ colspan_num +'">';
                    } else {// 没有发生单元格合并
                        header_html += '<th>';
                    }
                    header_html += $(th).children().children().text() + '</th>';// 获取表头名称并拼接th标签
                })
                header_html += '</tr>';
            })
            // 获取表格body数据
            $.each(body_tr,function (i,tr) {
                let body_td = $(tr).find("td");
                body_html += '<tr>';
                $.each(body_td,function (j,td) {
                    body_html += '<td>' + $(td).children().text() + '</td>';
                })
                body_html += '</tr>';
            })
            $("#tableId tr").remove();// 清除之前的doom结构
            $("#tableId").append(header_html).append(body_html);
            $("#tableId").hide();
        }
    });
    

    如果把最后hide()方法去掉,可以看到表格doom元素已经添加到table标签中。

    在这里插入图片描述
    在这里插入图片描述


    1.4 处理后的使用

    做了上面的处理后,就可使用第一步的方法做导出了
    下面是导出方法和导出后的截图
    导出的时候需要做一点小小的处理:

    let table2excel = new Table2Excel();
     /**
     * 此处的show()是为了避免table2excel将hide属性带入excel中
     * 导致下载后的excel中所有数据被隐藏
     */
    $('#tableId').show();
    table2excel.export($('#tableId'), "your filename");
    $('#tableId').hide();
    

    在这里插入图片描述
    说明:
    1、上面在导出的时候如果不先把表格show显示出来。wps的excel会正常显示,而office的excel则会把所有数据隐藏。这也是这个插件强大的地方,属性也会copy到excel中去。
    2、可能有的同学会觉得在这里显示出来自己添加的表格doom元素,会在页面上有一闪而过的视觉效果,亲测过,并没有。可能在网速超级卡顿的时候会出现。
    3、当然,这并不是最佳的解决方法。欢迎讨论。

    ----------------------------------------------我是分割线------------------------------------------------

    更新时间:2019年10月17日 10点00分
    感谢:@weixin_40915415 同学提出的固定列的特殊情况

    1.5 新的情况兼容:固定列

    layui在处理固定列时候的doom渲染跟活动列是不同的

    如下所示:我们将第一列承揽组固定,再用之前版本的js去append html时会发现,固定列的header和body发生了重复(两次)

    在这里插入图片描述
    分析doom元素:
    在这里插入图片描述
    我们看到这里出现了两个header
    原来layui在渲染有固定列的表头时,会把固定列的header和body再多渲染一次,放到样式为layui-table-fixeddiv里。
    知道这种结构,我们就好做新的处理了。
    新的获取header和body doom元素的js更改如下以兼容有固定列的layui table:

    let header_tr = $($("#tableId").next().find(".layui-table-header")[0]).find("tr");
    let body_tr = $($("#tableId").next().find(".layui-table-body")[0]).find("tr");
    

    ----------------------------------------------我是分割线------------------------------------------------

    2 蜕变

    2.1 table2excel_ext.js的诞生

    更新时间:2020年07月28日
    💕能耐心看到这儿的同学真的是爱学习的好同学,不过这儿我也给你准备了惊喜(本来觉得上面的那些是不是可以删掉了,后来一想也是自己当初的一个思路历程,就先留着吧)💕
    笔者将上诉的相关操作抽出了两个方法appendexportLayTable添加到了table2excel.js中,直接将该修改后的js引入到需导出excel数据的页面使用即可。

    链接:百度云下载 table2excel_ext.js
    提取码:4lsc

    使用方法:

    var table2Excel ;
    table.render({
    	elem: '#tableId',
    	...          
    	done: function (res, curr, count) {
    		table2Excel = new Table2Excel();
    		table2Excel.append($("#tableId"));
    	})    
    });
    // 导出excel点击事件
    $('#exportElemId').click(function(){
    	let fileName = 'XXX-20200728';
    	table2Excel.exportLayTable($('#tableId'),fileName);
    });
    

    ----------------------------------------------我是分割线------------------------------------------------

    2.2 新的情况兼容:合计行

    更新时间:2020年10月16日
    感谢:@zhang_pengpeng 同学提出的合计行的情况

    layui table 自动在前端计算添加的合计行(关于怎么开启合计行,请自行查看layui 官网文档)会在body的下面重新渲染一段新的dom结构。如下图所示:

    在这里插入图片描述

    在这里插入图片描述
    针对此种情况,笔者已经将table2excel_ext.js做了新的兼容,请返回目录2.1进行下载使用即可。
    ----------------------------------------------我是分割线------------------------------------------------

    2.3 新的情况兼容:排除列

    更新时间:2020年11月25日
    感谢:@qq_26097713 同学提出的排除列(列表中一些不想被导出的列)的情况。

    对于表格中的操作列,或者一些隐藏的列,又或者是一些不想导出的列。笔者对table2excel_ext.js做了新的兼容,来处理这种情况,下面将给出示例代码。
    ps:引入新的js不会对以前的调用产生任何影响。

    var table2Excel ;
    table.render({
    	elem: '#tableId',
    	...          
    	done: function (res, curr, count) {
    		// 排除掉的列的field数组(此参数可以不传,默认导出所有列)
    		let exceptColumns = ["field1","field2"];
    		table2Excel = new Table2Excel();
    		table2Excel.append($("#tableId"), exceptColumns);
    	})    
    });
    

    说明:

    1. table2Excel.append(table,exceptColumns)方法中的第二个参数exceptColumns可以不传,不传表示导出所有列。
    2. 其中exceptColumns数组中的值对应为渲染表格列时的field的值(表格中的操作列也请添加上一个field值,用于定位),如下:
    ...
    {
        title : "姓名",
        field : "username",// 此处的field
        width : "10",
        align : "center"
    }
    ...
    
    1. js下载链接已做更新,请返回目录2.1进行下载。
    展开全文
  • Layui动态表头

    千次阅读 2022-01-22 20:26:43
    动态表头是在数据表格的基础上进行的变化,那么我们就要引入Layui进行辅助,先把数据表格做出来再进行表头的动态。 二、数据表格 1.引入Layui 2.表格渲染 三、动态表头 动态表头改变的不多,也就是是表头可变...

    一、简介
    动态表头,就是表头单元格可变。不再是固定,不可变的。这是在渲染表格的基础上,对表头进行改变。
    动态表头带来的效果是很好的,更利于数据进行交互,更加的灵活。
    动态表头是在数据表格的基础上进行的变化,那么我们就要引入Layui进行辅助,先把数据表格做出来再进行表头的动态。
    二、数据表格
    1.引入Layui
    在这里插入图片描述
    在这里插入图片描述

    2.表格渲染
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    三、动态表头
    动态表头改变的不多,也就是是表头可变而已,可以通过点击改变表头,以及改变表格数据。
    1.绑定重载方法。
    在这里插入图片描述

    2.多个变量,多张表格,当然,只是改变了表头的数据。渲染不变。
    在这里插入图片描述

    3.方法调用重载,切换表格

    在这里插入图片描述

    展开全文
  • LayUI多级表头导出

    2022-03-04 17:05:25
    layUI方法渲染的数据表格导出前后端封装,业务变动增删改字段时,只需改动前端表格的cols参数即可,方便实用。

    用layUI方法渲染的数据表格导出前后端封装,业务变动增删改字段时,只需改动前端表格的cols参数即可,方便实用。

    前端代码:

    //每列属性上增加id,和parentId两个属性,用来组织表头的层级关系,方便java端导出封装
    var cols = [
        [
            {title:'地区',align:'center',field:'latnName',rowspan:2,id:'1'},
            {title:'张三编码',align:'center',field:'ZSCode',rowspan:2,id:'2'},
            {title:'李四编码',align:'center',field:'LSCode',rowspan:2,id:'3'},
            {title:'张三收入',align:'center',field:'',colspan:2,id:'4'},
            {title:'李四收入',align:'center',field:'',colspan:2,id:'5'},
        ],
        [
            {title:'大儿子',align:'center',field:'bigSon',id:'6',parentId:'4'},
            {title:'小儿子',align:'center',field:'samllSon',id: '7',parentId:'4'},
            {title:'大儿子',align:'center',field:'bigSon_',id:'8',parentId:'5'},
            {title:'小儿子',align:'center',field:'samllSon_',id:'9',parentId:'5'},
        ]
    ]
    
    //渲染表格
    table.render({
        elem: '#table', 
        url: “”, //接口地址
        method: 'post',
        page: true,
        cols: cols,
    });
    
    
    /**
    * 前端公共方法,查询参数较多,post 方式导出
    *
    * queryParam 查询参数
    * url 接口地址
    * titleList 表格的cols参数
    */
    function exportExcel(queryParam, url, titleList){
        var form = document.createElement("form");
        form.style.display = "none";
        form.action = url;
        form.method = "post";
        document.body.appendChild(form);
        for (var key in queryParam) {
            var input = document.createElement("input");
            input.type = "hidden";
            input.name = key;
            input.value = queryParam[key];
            form.appendChild(input);
        }
        var titleListInput = document.createElement("input");
        titleListInput.type = "hidden";
        titleListInput.name = "titleList";
        titleListInput.value = JSON.stringify(titleList);
        form.appendChild(titleListInput);
        form.submit();
        form.remove();
    }
    
    //调用
    exportExcel({}, "", cols)

    后端代码实体类

    package usi.dict.excelUtil;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Column {
    
        public String id; //当前列的id,根节点指定为0
    
        public String parentId; //当前列的父id, 一级表头父id指定为0
    
        public String enFieldName; //字段名称(英文)
    
        public String cnFieldName; //字段名称(中文)
    
        public boolean isHasChilren; //是否有子节点
    
        public int totalRow; //总行数
    
        public int totalCol; //总列数
    
        public int rowNum; //第几行
    
        public int colNum; //第几列
    
        public int rowSpan; //跨多少行
    
        public int colSpan; //跨多少列
    
        public List<Column> chilrenColumn = new ArrayList<>(); //子节点集合
    
        public Column(){};
    
        public Column(String id, String parentId, String enFieldName, String cnFieldName) {
            this.id = id;
            this.parentId = parentId;
            this.enFieldName = enFieldName;
            this.cnFieldName = cnFieldName;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getParentId() {
            return parentId;
        }
    
        public void setParentId(String parentId) {
            this.parentId = parentId;
        }
    
        public String getEnFieldName() {
            return enFieldName;
        }
    
        public void setEnFieldName(String enFieldName) {
            this.enFieldName = enFieldName;
        }
    
        public String getCnFieldName() {
            return cnFieldName;
        }
    
        public void setCnFieldName(String cnFieldName) {
            this.cnFieldName = cnFieldName;
        }
    
        public boolean isHasChilren() {
            return isHasChilren;
        }
    
        public void setHasChilren(boolean hasChilren) {
            isHasChilren = hasChilren;
        }
    
        public int getTotalRow() {
            return totalRow;
        }
    
        public void setTotalRow(int totalRow) {
            this.totalRow = totalRow;
        }
    
        public int getTotalCol() {
            return totalCol;
        }
    
        public void setTotalCol(int totalCol) {
            this.totalCol = totalCol;
        }
    
        public int getRowNum() {
            return rowNum;
        }
    
        public void setRowNum(int rowNum) {
            this.rowNum = rowNum;
        }
    
        public int getColNum() {
            return colNum;
        }
    
        public void setColNum(int colNum) {
            this.colNum = colNum;
        }
    
        public int getRowSpan() {
            return rowSpan;
        }
    
        public void setRowSpan(int rowSpan) {
            this.rowSpan = rowSpan;
        }
    
        public int getColSpan() {
            return colSpan;
        }
    
        public void setColSpan(int colSpan) {
            this.colSpan = colSpan;
        }
    
        public List<Column> getChilrenColumn() {
            return chilrenColumn;
        }
    
        public void setChilrenColumn(List<Column> chilrenColumn) {
            this.chilrenColumn = chilrenColumn;
        }
    }
    

    构建树结构工具类

    package usi.dict.excelUtil;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
    
    public class TreeTool {
    
        /**
         * 获取树的深度
         *
         * @param list
         * @return
         */
        public static int getMaxStep(List<Column> list) {
            List<Integer> nums = new ArrayList<>();
            for (Column column : list) {
                nums.add(getNodeStep(list, column.getId(), 0));
            }
            return Collections.max(nums);
        }
    
        /**
         * 获取节点的深度
         *
         * @param list
         * @param id   根节点
         * @param step
         * @return
         */
        public static int getNodeStep(List<Column> list, String id, int step) {
            if ("".equals(id) || id == null) {
                return step;
            }
            for (Column column : list) {
                if (id.equals(column.getId())) {
                    return getNodeStep(list, column.getParentId(), step + 1);
                }
            }
            return step;
        }
    
        /**
         * 获取所有叶子节点个数
         *
         * @param list
         * @param rootId
         * @return
         */
        public static int getLeafNode(List<Column> list, String rootId) {
            int sum = 0;
            for (Column column : list) {
                if (rootId.equals(column.getParentId())) {
                    sum++;
                    if (hasChild(list, column)) {
                        sum += getLeafNode(list, column.getId()) - 1;
                    }
                }
            }
            return sum;
        }
    
        /**
         * 获取父节点
         *
         * @param list
         * @param parentId
         * @return
         */
        public static Column getParentNode(List<Column> list, String parentId) {
            for (Column column : list) {
                if (parentId != null && parentId.equals(column.getId())) {
                    return column;
                }
                if (parentId == null && null == column.getId()) {
                    return column;
                }
            }
            return new Column() {{
                setColNum(0);
                setRowNum(0);
            }};
        }
    
        /**
         * 获取兄弟节点个数
         *
         * @param list
         * @param column
         * @return
         */
        public static int getBrotherNodeNum(List<Column> list, Column column) {
            int sum = 0;
            for (Column cc : list) {
                if (column.getId().equals(cc.getId())) break;
                if (!column.getParentId().equals(cc.getParentId())) continue;
                int temp = getLeafNode(list, cc.getId());
                if (temp == 0 || temp == 1)
                    sum++;
                else
                    sum += temp;
            }
            return sum;
        }
    
        /**
         * 判断是否有子节点
         *
         * @param list 遍历的数据
         * @param node 某个节点
         * @return
         */
        public static boolean hasChild(List<Column> list, Column node) {
            return getChildList(list, node).size() > 0;
        }
    
        /**
         * 获取子节点列表
         *
         * @param list 遍历的数据
         * @param node 某个节点
         * @return
         */
        public static List<Column> getChildList(List<Column> list, Column node) {
            List<Column> nodeList = new ArrayList<>();
            Iterator<Column> it = list.iterator();
            while (it.hasNext()) {
                Column n = (Column) it.next();
                if (n.getParentId() != null && n.getParentId().equals(node.getId())) {
                    nodeList.add(n);
                }
            }
            return nodeList;
        }
    
        /**
         * 建树
         *
         * @param list
         * @return
         */
        public static List<Column> buildTree(List<Column> list, String rootId) {
            List<Column> treeList = new ArrayList<>();
            for (Column column : list) {
                if (rootId != null && rootId.equals(column.getParentId())) {
                    treeList.add(findChildren(column, list));
                }
            }
            return treeList;
        }
    
        /**
         * 查找子节点
         *
         * @param treeNodes
         * @return
         */
        public static Column findChildren(Column treeNode, List<Column> treeNodes) {
            for (Column it : treeNodes) {
                if (treeNode.getId().equals(it.getParentId())) {
                    if (treeNode.getChilrenColumn() == null) {
                        treeNode.setChilrenColumn(new ArrayList<>());
                    }
                    treeNode.getChilrenColumn().add(findChildren(it, treeNodes));
                }
            }
            return treeNode;
        }
    }
    

    导出工具类

    package usi.dict.excelUtil;
    
    import com.spire.ms.System.Exception;
    import net.sf.json.JSONArray;
    import net.sf.json.JSONObject;
    import org.apache.commons.collections4.MapUtils;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.ss.util.CellRangeAddress;
    import org.apache.poi.xssf.usermodel.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.lang.reflect.Field;
    import java.net.URLEncoder;
    import java.nio.charset.StandardCharsets;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    public class ExcelTool {
        private final static Logger logger = LoggerFactory.getLogger(ExcelTool.class);
    
        private static XSSFWorkbook workbook; //excel对象
    
        private static XSSFCellStyle cellStyle; //单元格样式
    
        private static int rowHeight = 20; //行高
    
        private static int colWidth = 20; //列宽
    
        private static int sheetDataCount = 65535; //每个sheet页最多记录数
    
        private static String excelName; //导出的excel文件名
    
        private static String TITLE_LIST_KEY = "titleList";
    
        private static String ROOT_ID = "0";
    
        private static String ID = "id";
    
        private static String PARENT_ID = "parentId";
    
        private static String FIELD = "field";
    
        private static final String TITLE = "title";
    
    
        /**
         * 结合layUi封装导出excel公共方法,支持一级表头和多级表头导出
         *
         * @param request
         * @param response
         * @param excelName
         * @param paramMap
         * @param data
         * @throws IllegalAccessException
         */
        public static <T> void exportExcel(HttpServletRequest request, HttpServletResponse response, String excelName, Map<String, Object> paramMap, List<T> data) throws IllegalAccessException {
            if (data == null) {
                throw new RuntimeException("原始数据不能为null");
            }
            Object obj = MapUtils.getObject(paramMap, TITLE_LIST_KEY);
            if (obj == null) {
                throw new RuntimeException("表头数据不能为null");
            }
            List<Column> columnList = getColumnList(JSONArray.fromObject(obj));
            List<Column> treeList = TreeTool.buildTree(columnList, ROOT_ID);
            initWorkbook(excelName);
            setRowSpan(columnList);
            setColSpan(columnList, treeList);
            writeData(data, treeList);
            writeFile(request, response);
        }
    
        /**
         * 将layui表格的cols转换成List<Column>
         *
         * @param jsonArray
         * @return
         */
        private static List<Column> getColumnList(JSONArray jsonArray) {
            if (jsonArray.size() == 0) {
                throw new RuntimeException("没有表头数据,表头数据不能为空");
            }
            if (jsonArray.size() == 1) {
                JSONArray arr = jsonArray.getJSONArray(0);
                for (int i = 0; i < arr.size(); i++) {
                    if (!arr.getJSONObject(i).containsKey(ID)) arr.getJSONObject(i).put(ID, i + 1);
                }
            }
            List<Column> columnList = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                addCloumn(jsonArray.getJSONArray(i), columnList);
            }
            return columnList;
        }
    
        /**
         * 添加title
         *
         * @param jsonArray
         * @param columnList
         */
        private static void addCloumn(JSONArray jsonArray, List<Column> columnList) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jo = jsonArray.getJSONObject(i);
                String id = null, parentId = null, enFieldName = null, cnFieldName = null;
                if (jo.containsKey(ID)) {
                    id = jo.getString(ID);
                } else {
                    throw new RuntimeException("表头ID参数为必传");
                }
                if (jo.containsKey(PARENT_ID)) {
                    parentId = jo.getString(PARENT_ID);
                } else {
                    parentId = ROOT_ID;
                }
                if (jo.containsKey(FIELD)) {
                    enFieldName = jo.getString(FIELD);
                } else {
                    throw new RuntimeException("表头field参数为必传");
                }
                if (jo.containsKey(TITLE)) {
                    cnFieldName = jo.getString(TITLE);
                } else {
                    throw new RuntimeException("表头title参数为必传");
                }
                columnList.add(new Column(id, parentId, enFieldName, cnFieldName));
            }
        }
    
        /**
         * 设置excel单元格跨多少行
         *
         * @param columnlist
         */
        private static void setRowSpan(List<Column> columnlist) {
            int rowSpan = 0, totalRow = TreeTool.getMaxStep(columnlist), totalCol = TreeTool.getLeafNode(columnlist, ROOT_ID);
            for (Column column : columnlist) {
                int nodeStep = TreeTool.getNodeStep(columnlist, column.getParentId(), 0);
                column.setTotalRow(totalRow);
                column.setTotalCol(totalCol);
                column.setRowNum(nodeStep);
                column.setHasChilren(TreeTool.hasChild(columnlist, column));
                if (column.isHasChilren()) {
                    column.setRowSpan(0);
                } else {
                    if (nodeStep < totalRow) {
                        rowSpan = totalRow - nodeStep;
                    }
                    column.setRowSpan(rowSpan);
                }
            }
        }
    
        /**
         * 设置excel单元格跨多少列
         *
         * @param list
         * @param treeList
         */
        private static void setColSpan(List<Column> list, List<Column> treeList) {
            List<Column> newList = new ArrayList<>();
            for (Column column : treeList) {
                int colNum = TreeTool.getParentNode(list, column.getParentId()).getColNum(),
                        brotherColNum = TreeTool.getBrotherNodeNum(list, column),
                        colSpan = TreeTool.getLeafNode(list, column.getId());
                if (colSpan <= 1) {
                    colSpan = 0;
                }
                ;
                column.setColNum(colNum + brotherColNum);
                column.setColSpan(colSpan);
                if (column.getChilrenColumn().size() > 0) {
                    newList.addAll(column.getChilrenColumn());
                }
            }
            if (newList.size() > 0) {
                setColSpan(list, newList);
            }
        }
    
        /**
         * 将数据分页写入sheet,每个sheet不能超过sheetDataCount的值
         *
         * @param data
         * @param columns
         * @throws IllegalAccessException
         */
        private static <T> void writeData(List<T> data, List<Column> columns) throws IllegalAccessException {
            int dataTotalCount = data.size(), sheetCount = dataTotalCount / sheetDataCount;
            for (int i = 1; i <= sheetCount; i++) {
                writeSheet(workbook.createSheet(excelName + i), data.subList((i - 1) * sheetDataCount, i * sheetDataCount), columns);
            }
            writeSheet(workbook.createSheet(excelName + (sheetCount + 1)), data.subList(sheetCount * sheetDataCount, dataTotalCount), columns);
        }
    
        /**
         * 将数据写入sheet
         *
         * @param sheet
         * @param data
         * @param columns
         * @throws IllegalAccessException
         */
        private static <T> void writeSheet(XSSFSheet sheet, List<T> data, List<Column> columns) throws IllegalAccessException {
            int totaLRow = columns.get(0).getTotalRow(), totalCol = columns.get(0).getTotalCol();
            for (int i = 0; i < totaLRow; i++) {
                XSSFRow row = sheet.createRow(i);
                for (int j = 0; j < totalCol; j++) {
                    row.createCell(j);
                }
            }
            createExcelHead(columns, sheet, 0);
            setSheetValue(columns, data, sheet, totaLRow + 1);
        }
    
        /**
         * 递归写入表头数据 支持单级,多级表头的创建
         *
         * @param columns  表头数据
         * @param sheet    sheet页
         * @param rowIndex 当前Excel的第几行
         */
        private static void createExcelHead(List<Column> columns, XSSFSheet sheet, int rowIndex) {
            XSSFRow row = sheet.getRow(rowIndex);
            for (int i = 0; i < columns.size(); i++) {
                Column column = columns.get(i);
                int rowNum = column.getRowNum(), colNum = column.getColNum();
                int rowSpan = column.getRowSpan(), colSpan = column.getColSpan();
                int endRow = rowNum + rowSpan, endCol = colNum + colSpan;
                if (endCol > colNum) endCol--;
                XSSFCell cell = row.getCell(colNum);
                cell.setCellStyle(cellStyle);
                cell.setCellValue(new XSSFRichTextString(column.getCnFieldName()));
                sheet.setDefaultColumnWidth(colWidth);
                sheet.setDefaultRowHeightInPoints(rowHeight);
                sheet.setColumnWidth(i, Math.max(15 * 256, Math.min(255 * 256, sheet.getColumnWidth(i) * 12 / 10)));
                sheet.addMergedRegion(new CellRangeAddress(rowNum, endRow, colNum, endCol));
                if (column.isHasChilren()) {
                    rowIndex = rowNum + 1;
                    createExcelHead(column.getChilrenColumn(), sheet, rowIndex);
                }
            }
        }
    
        /**
         * 把数据写入到单元格
         *
         * @param columns
         * @param data
         * @param sheet
         * @param rowIndex
         * @throws IllegalAccessException
         */
        private static <T> void setSheetValue(List<Column> columns, List<T> data, XSSFSheet sheet, int rowIndex) throws IllegalAccessException {
            List<Column> newList = new ArrayList<>();
            filterColumn(columns, newList);
            for (int i = 0, index = rowIndex; i < data.size(); i++, index++) {
                XSSFRow row = sheet.createRow(index);
                for (int j = 0; j < newList.size(); j++) {
                    setCellValue(row, newList.get(j), data.get(i));
                }
            }
        }
    
        /**
         * 数据填入单元格
         *
         * @param row
         * @param column
         * @param obj
         * @throws IllegalAccessException
         */
        private static void setCellValue(XSSFRow row, Column column, Object obj) throws IllegalAccessException {
            XSSFCell cell = row.createCell(column.getColNum());
            cell.setCellStyle(cellStyle);
            Object value = null;
            if (obj instanceof Map) {
                Map<String, Object> map = (Map<String, Object>) obj;
                for (Map.Entry entry : map.entrySet()) {
                    if (column.getEnFieldName().equals(entry.getKey()) && !column.isHasChilren()) {
                        value = entry.getValue();
                    }
                }
            } else {
                for (Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    if (column.getEnFieldName().equals(field.getName()) && !column.isHasChilren()) value = field.get(obj);
                    if (value instanceof Date) value = parseDate((Date) value);
                }
            }
            if (value != null) {
                cell.setCellValue(new XSSFRichTextString(value.toString()));
            }
        }
    
        /**
         * 写入excel文件到OutputStream,给页面下载
         *
         * @param request
         * @param response
         */
        private static void writeFile(HttpServletRequest request, HttpServletResponse response) {
            setUserAgent(request, response);
            OutputStream out = null;
            try {
                out = response.getOutputStream();
                workbook.write(out);
            } catch (IOException e) {
                logger.error("写入流报错:{}", e.getMessage(), e);
            } finally {
                try {
                    if (out != null) {
                        out.flush();
                        out.close();
                    }
                } catch (IOException e) {
                    logger.error("关闭流出错:{}", e.getMessage(), e);
                }
            }
        }
    
        /**
         * 设置用户浏览器兼容
         *
         * @param response
         */
        private static void setUserAgent(HttpServletRequest request, HttpServletResponse response) {
            response.reset();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            try {
                String userAgent = request.getHeader("user-agent").toLowerCase(), filename = "";
                if (userAgent.contains("msie") || userAgent.contains("edge") || (userAgent.contains("gecko") && userAgent.indexOf("rv:11") > 0)) {
                    filename = URLEncoder.encode(excelName, String.valueOf(StandardCharsets.UTF_8));
                } else {
                    filename = new String(excelName.getBytes(), StandardCharsets.ISO_8859_1);
                }
                response.setHeader("Content-disposition", "attachment; filename=" + filename + ".xlsx");
            } catch (UnsupportedEncodingException e) {
                logger.error("设置浏览器兼容出错:{}", e.getMessage(), e);
            }
        }
    
        /**
         * 过滤表头的脏数据
         *
         * @param oldList
         * @param newList
         */
        private static void filterColumn(List<Column> oldList, List<Column> newList) {
            for (Column column : oldList) {
                if (column.getEnFieldName() != null) {
                    newList.add(column);
                }
                List<Column> chilrenColumn = column.getChilrenColumn();
                if (chilrenColumn.size() > 0) {
                    filterColumn(chilrenColumn, newList);
                }
            }
        }
    
        /**
         * 格式化日期
         *
         * @param date
         * @return String
         */
        private static String parseDate(Date date) {
            String dateStr = "";
            try {
                dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
            } catch (Exception e) {
                logger.error("日期转换出错:{}", e.getMessage(), e);
            }
            return dateStr;
        }
    
        /**
         * 初始化Workbook
         *
         * @param excelName
         */
        private static void initWorkbook(String excelName) {
            ExcelTool.excelName = excelName;
            ExcelTool.workbook = new XSSFWorkbook();
            ExcelTool.cellStyle = ExcelTool.workbook.createCellStyle();
            ExcelTool.cellStyle.setAlignment(HorizontalAlignment.CENTER);
            ExcelTool.cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        }
    }
    

    后端调用: 

    //后端调用
    @PostMapping("/")
    @ResponseBody
    public void exportReportTable(@RequestParam Map<String, Object> paramMap,         
                            HttpServletRequest request, HttpServletResponse response) {
        List<Map<String, Object>> list = service.qryData(paramMap);
        ExcelTool.exportExcel(request, response, "导出excel", paramMap, list);
    }

    应用实例截图:

     

     

    导出结果:

      

     

    总结:适用layUi方法级渲染的多级表头的数据表格,其核心就是cols这个数组,用id和parentId这个两个属性组织好多级表头关系,将cols传给后端,因业务需求变动,后期增删改字段,都无需修改后端代码。

    借鉴代码:JAVA POI 实现EXCEL 动态表头、动态添加数据(导入导出)、 Tree结构的遍历_嘻哈嘻哈-CSDN博客_poi动态表头

    展开全文
  • 今天小编就为大家分享一篇layui动态加载多表头的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • layui中table表头样式修改layui.use('table', function () {var table = layui.table;table.render({elem: '#desTable', url: '${ctx}/alarm/queryEventShowScatter', even: true, page: { //支持传入 laypage 组件...
  • 'numbers', rowspan: 3, fixed: 'left' },//fixed:left 当数据列太多时,滚动时固定在表格左侧 { type: "checkbox", width: 50, rowspan: 3 , fixed: 'left' }, { align: 'center', field: 'Id', width: 40, title:...
  • <style> .card-table { padding: 0; line-height: normal;...div class="layui-fluid"> <div class="layui-card"> <div class="layui-card-header"> <strong>好牌配置</stron.
  • layui表格有三种渲染方式,此文使用的是方法渲染。以下功能均是基于方法渲染。 一、排序 为某列排序,在table渲染时,首先要开启排序,然后添加initSort参数,并添加要排序的字段名: <table id="layTable" ...
  • layui 数据表格表头动态修改

    万次阅读 2019-06-20 10:21:48
    一般情况下,数据表格表头是固定的,不会轻易改变,但是由于业务的需要,表格表头需要动态修改,有很多方法: 1.在html页面分别设置成不同的数据表格,根据点击事件来show或者hide,这样可以达到我们的目的,但是,这样违法...
  • js相关:layui中table表头样式修改方法发布于 2020-7-25|复制链接分享一篇关于layui中table表头样式修改方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小妖过来看看吧如下所示:```javascriptlayui.use('...
  • 表头工具栏 ,select下拉框,随着下拉框的变化,切换下面表格的值;并且表格单元格内插入时间控件和实现可编辑。 (为了***,个别变量进行修改,可能不规范,理解一下意思) 代码如下: planPaymentTable= table...
  • 今天小编就为大家分享一篇layui table表格数据的新增,修改,删除,查询,双击获取行数据方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 使用layui动态表格时,用到复杂表头,如果colspan=1时,会出现一例空白列,根本问题应该是layui 在复杂表头时, colspan 必须大于1,解决办法是,修改colspan为2,然后添加一列空白列{title: '', field:'', hide: ...
  • 解决Layui表格表头固定悬浮的问题

    千次阅读 2020-09-24 16:24:05
    一、描述二、解决 一、描述 当表格内容过多:表头离开页面可视范围时,把表头固定悬浮在上面,如下图所示: ...先在Layui表格渲染完成的回调函数里写: done:function(res, curr, count){ let headerTop = $('.lay.
  • layui 复杂表头数据渲染的坑

    千次阅读 2019-08-22 14:07:00
    layui 复杂表头数据渲染的坑欢迎使用Markdown编辑器 欢迎使用Markdown编辑器 layui复杂表头渲染数据 出现的数据都是重复的
  • layui表格更改某列的背景颜色或者字体颜色 0 2877TSIM2019/6/26 15:29:11区分某个字段不同的情况下,显示成的某列的表格颜色不同做法为在layui表格layui.use('table', function () 函数里增加done函数具体代码...
  • 基于layui,js-xlsx的前台数据复杂表头导出到excel文件中layui table 加载如何改变文本插adsfadsfadsf如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义...
  • layui如何在表格重载时更改表头

    千次阅读 热门讨论 2019-09-11 17:07:27
    最近有个项目使用了layui框架,在实际的使用中...问题:在时间筛选的时候遇到了难题,表格重载后,表头没有按照重载方法传入的cols参数展示,而是还是展示原先的表头 原因:经过一番排查后发现原因,layui中 tab...
  • layui表格的样式设置

    2021-03-03 15:53:55
    该楼层疑似违规已被系统折叠隐藏此楼查看此楼layui表格的样式设置~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~开发工具与关键技术:Visual Studio 2015、作者:梁柏源撰写时间:2019/7/17~...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 904
精华内容 361
关键字:

layui 修改 表头 表格