Bootstrap-table实现动态合并相同行(表格同名合并)

摘要:
对于特定的要求,假设有三条记录,它们在后台按x的顺序排列,然后转移到前台页面进行显示。记录每列旁边相同元素的时间,然后获取这些时间。最后,使用bootstrapTable的mergeCells方法进行合并。DOCTYPEHtml˃实现表同名合并˂!

写在前面:

  有时候表格的需求就是奇奇怪怪的,最近要做的表格需要实现当紧挨着的记录的某一列的行元素内容相同,就将其合并。要是不是相同的就不合并。如果表格数据的顺序不需要被改变,这个样子是可以很简单就完成的(只需要计算出所有相同元素出现的次数即可,不需要考虑是否紧挨着),但是当可以改变排序的时候,这个时候就有点儿问题了。可能表述的有点儿不明白,下面具体看图描述问题吧。

  具体的需求,假设现在有三条记录,后台按照顺序x排好后传递给前台页面进行显示。

Bootstrap-table实现动态合并相同行(表格同名合并)第1张

  页面拿到数据后将相同行进行合并后可以得到右边图的效果,但是如果现在在页面选择了一个排序按钮后,现在的排序被打乱了,又该怎样去实现合并?

Bootstrap-table实现动态合并相同行(表格同名合并)第2张

  这里值得思考的是,后面每个列的最多的合并次数是基于前一个列的合并的次数来的,所以这里是个切入点,记录下第一列所有紧挨着的相同行内容出现的次数,然后遍历,去计算第二列所有紧挨着的相同行内容出现的次数,然后遍历,去计算第三列所有紧挨着的相同行内容出现的次数,依次下去。。。。。将每一列紧挨着的相同元素的次数都记录下来,然后拿到了这些次数,最后使用bootstrapTable自带的mergeCells方法去合并即可。越来越觉得数据结构以及算法重要性,最近太多写的程序都涉及到一些逻辑的算法,还是上学时要把这两个学好呀~~~~~~~

  2018.12.7晕死了晕死了,之前写的测出了bug,还是之前太大意了,又将代码修改了一下,花了三个小时才跟踪到问题,真的是晕死了。。。然后放在ie8上又出了问题,最后还是知道了问题的所在,完美的解决了。。。。。今天要请他们吃饭,目测是要大出血!!!!!!

  下面看看代码:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2018/6/20
  Time: 14:21
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String scheme = request.getScheme();
    String serverName = request.getServerName();
    String contextPath = request.getContextPath();
    int port = request.getServerPort();
    //网站的访问跟路径
    String baseURL = scheme + "://" + serverName + ":" + port
            + contextPath;
    request.setAttribute("baseURL", baseURL);
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <%--设置IE渲染方式(文档)默认为最高(这部分可以选择添加也可以不添加)--%>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>实现表格同名合并</title>
    <!--图标样式-->
    <link rel="stylesheet" type="text/css" href="${baseURL}/Bootstrap/bootstrap/css/bootstrap.min.css" />
    <link href="${baseURL}/Bootstrap/bootstrap-table/bootstrap-table.css" rel="stylesheet" />
    <script src="${baseURL}/Bootstrap/bootstrap/assets/js/jquery-1.10.2.min.js"></script>
    <script src="${baseURL}/Bootstrap/bootstrap/assets/js/bootstrap.min.js"></script>
    <script src="${baseURL}/Bootstrap/bootstrap-table/bootstrap-table.js"></script>
    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="http://t.zoukankan.com/${baseURL}/Bootstrap/bootstrap/assets/js/html5shiv.js"></script>
    <script src="http://t.zoukankan.com/${baseURL}/Bootstrap/bootstrap/assets/js/respond.min.js"></script>
    <![endif]-->
    <style type="text/css">

    </style>

</head>
<body>
    <div>
        <table id="table"></table>
    </div>
</body>

<script type="text/javascript">

    $(function () {
        //初始化Table
        $('#table').bootstrapTable({
            url: '${baseURL}/Views/cc.json',//请求后台的URL(*) 这里我用的是一个json文件
            method: 'get',//请求方式(*)
            toolbar: '#toolbar',//工具按钮用哪个容器
            striped: true,//是否显示行间隔色
            cache: false,//是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
            pagination: true,//是否显示分页(*)
            sortable: false,//是否启用排序
            sortOrder: "asc",//排序方式
            //queryParams: queryParams,//传递参数(*)
            sidePagination: "server",//分页方式:client客户端分页,server服务端分页(*)
            pageNumber: 1,//初始化加载第一页,默认第一页
            pageSize: 10,//每页的记录行数(*)
            pageList: [10, 25, 50, 100],//可供选择的每页的行数(*)
            // search: true,//是否显示表格搜索,此搜索是客户端搜索,不会进服务端
            contentType: "application/x-www-form-urlencoded",
            strictSearch: true,
            showColumns: true,//是否显示内容列下拉框
            showRefresh: true,//是否显示刷新按钮
            minimumCountColumns: 2,//最少允许的列数
            clickToSelect: true,//是否启用点击选中行
            //这里如果要固定表头的话 就把height开启
            //height: 700,//行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度
            '50%',
            uniqueId: "id",//每一行的唯一标识,一般为主键列
            showToggle: true,//是否显示详细视图和列表视图的切换按钮
            cardView: false,//是否显示详细视图
            detailView: false,//是否显示父子表
            onLoadSuccess: function (data) {
                //数据加载成功后 进行合并  这里我只是同名合并projName subProj phase 如果需要合并更多的字段 仿照添加对应的代码就可以了
                mergeTable(data,"table");
            },
            columns: [
                {
                    field: 'projName',
                    title: 'projName',
                }, {
                    field: 'subProj',
                    title: 'subProj'
                }, {
                    field: 'phase',
                    title: 'phase'
                }, {
                    field: 'workItem',
                    title: 'workItem',
                },
                {
                    field: 'completion',
                    title: 'completion',
                },
            ],
        });
    });


    //全局变量 ***如果每次只是发送ajax请求对table进行局部更新,则每次要合并前前都应该清空这三个变量 不然全局变量会一值追加结果
    var projNameCount="";
    var subProjNameCount="";
    var phaseCount="";

    //合并表格
    function mergeTable(data,tableId){
        //每次合并表格前 都要将全局变量清空
        projNameCount="";
        subProjNameCount="";
        phaseCount="";
        mergeCells(data.rows,0,data.rows.length,"projName",$('#'+tableId));
        //对projName,subProjName,phase的次数进行分割
        //去掉末尾的逗号 有时候也可以不用去掉 还是去掉了我这里
        projNameCount = projNameCount.substring(0,projNameCount.length-1);
        subProjNameCount = subProjNameCount.substring(0,subProjNameCount.length-1);
        phaseCount = phaseCount.substring(0,phaseCount.length-1);
        //console.log(projNameCount+"+"+subProjNameCount+"+"+phaseCount);
        var strArr1 = projNameCount.split(",");
        var strArr2 = subProjNameCount.split(",");
        var strArr3 = phaseCount.split(",");
        //根据次数进行表格合并
        //合并projName
        var index = 0;
        for(var i=0;i<strArr1.length;i++){
            var count = strArr1[i] * 1;
            $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"projName", colspan: 1, rowspan: count});
            index += count;
        }
        //合并subProjName
        var index = 0;
        for(var i=0;i<strArr2.length;i++){
            var count = strArr2[i] * 1;
            $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"subProjName", colspan: 1, rowspan: count});
            index += count;
        }
        //合并phaseName
        var index = 0;
        for(var i=0;i<strArr3.length;i++){
            var count = strArr3[i] * 1;
            $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"phaseName", colspan: 1, rowspan: count});
            index += count;
        }
    }


    //排序后紧挨在一起 进行同名合并
    /**
     * 对于表格合并,首先要进行排序,即将同名的属性的记录排序紧挨在一起,这样才能最好的显示出合并想要的效果。
     * 因为此方法是拿第一个数据与后面的数据依次比较,
     * 例如,第一条记录的projName与第二条记录的projName来进行比较,两者相同,则继续第一条记录的projName与第三条记录的projName来进行比较,
     * 当不相同时,记录下此projName对应的值出现的次数,然后再开始从第三条记录的projName与第四条记录的projName来进行比较,依次循环下去,记
     * 录下相同内容的值出现的次数,到时候,再根据这些次数来进行合并
     *
     * 此方法主要是先拿到每个同名属性的值的相等次数,把次数利用全局变量存下来
     *
     * @param datas --表格数据,一般为表格的rows数据
     * @param startIndex --开始下标
     * @param size --从开始下标起,到size结束,遍历合并多少个
     * @param fieldName --计算算哪个列
     * @param target --table表格对象
     */
    function mergeCells(datas,startIndex,size,fieldName,target) {
        //console.log("startIndex:"+startIndex+"size:"+size+"---合并列:"+fieldName)
        //声明一个数组计算相同属性值在data对象出现的次数和
        //这里不能使用map,因为如果涉及到排序后,相同的属性并不是紧挨在一起,那么后面的次数会覆盖前面的次数,故这里用数组
        var sortArr = new Array();
        for (var i = startIndex; i < size ; i++) {
            for (var j = i + 1; j < size; j++) {
                if (datas[i][fieldName] != datas[j][fieldName]){
                    //相同属性值不同
                    if (j - i > 1) {
                        sortArr.push(j - i);
                        i = j - 1;
                        //如果是最后一个元素 把最后一个元素的次数也装进去
                        if(i == size-1-1){
                            sortArr.push(1);
                        }
                    }else{
                        sortArr.push(j - i);
                        //如果j是最后一个元素 把最后一个元素的次数装进去
                        if(j == size - 1){
                            sortArr.push(1);
                        }
                    }
                    break;

                }else {
                    //相同属性值相同 直到最后一次的时候才会装 否则在他们的值不同时再装进去
                    if (j == size - 1) {
                        sortArr.push(j - i+1);
                        //这里的赋值感觉有点多余 算了现就这个样子吧 不影响功能
                        i = j;
                    }
                }
            }
        }

        //遍历数组,将值装追加到对应的字符串后面
        for(var prop in sortArr){
            /*这里在ie8上运行的时候 出现坑 最好遍历数组不要用for in 这里我用了就懒得换了
            下面加上如果prop是indexOf就停止 就解决了ie8出现的问题*/
            if(prop == "indexOf"){
                continue;
            }
            if(fieldName == "projName"){
                var count = sortArr[prop] * 1;
                projNameCount += count +",";
            }

            if(fieldName == "subProjName"){
                var count = sortArr[prop] * 1;
                subProjNameCount += count +",";
            }

            if(fieldName == "phaseName"){
                var count = sortArr[prop] * 1;
                phaseCount += count +",";
            }
        }

        for(var prop in sortArr){
            if(prop == "indexOf"){
                continue;
            }
            if(fieldName == "projName"){
                //console.log("进入projName--此时开始index-"+startIndex+"--结束index--"+(startIndex+sortArr[prop])*1);
                startIndex = 0;
                //subProjName每次进去的startIndex为前面次数的和
                if(subProjNameCount.length>0){
                    //console.log("subProjNameCount-"+subProjNameCount);
                    var temp = subProjNameCount.substring(0,subProjNameCount.length-1);
                    var strArr1 = temp.split(",");
                    for(var i=0;i<strArr1.length;i++){
                        var count = strArr1[i] * 1;
                        startIndex += count;
                    }
                }

                if(sortArr[prop] >1){
                    mergeCells(datas,startIndex,startIndex+sortArr[prop],"subProjName",target);
                }else{
                    //当projName的次数为1就不进入循环
                    subProjNameCount +=1+",";
                    phaseCount +=1+",";
                }
            }
            if(fieldName == "subProjName"){
                startIndex = 0;
                if(phaseCount.length>0){
                    //console.log("phaseCount-"+phaseCount);
                    var temp  = phaseCount.substring(0,phaseCount.length-1);
                    //phaseCount = phaseCount + ",";
                    var strArr1 = temp.split(",");
                    for(var i=0;i<strArr1.length;i++){
                        var count = strArr1[i] * 1;
                        startIndex += count;
                    }
                }
                if(sortArr[prop] >1){
                    //console.log("进入subProj--此时开始index-"+startIndex+"--结束index--"+(startIndex+sortArr[prop])*1);
                    mergeCells(datas,startIndex,startIndex+sortArr[prop],"phaseName",target)
                }else{
                    phaseCount +=1+",";
                }
            }
        }
    }
</script>
</html>

  上面就是完整的代码了,效果图如下:(此代码只需要计算projName,subProj,phase的合并就可以了,后面workitem不需要再合并了,因为后台查询的就是每一条workitem记录)

Bootstrap-table实现动态合并相同行(表格同名合并)第3张

  其中对于bootstrap-table自带的合并单元格的方法,也是很好用的,也是基于此基础上才能完成。

$('#table').bootstrapTable('mergeCells',{index:index, field:"projName", colspan: 1, rowspan: count});

  参考连接:https://blog.csdn.net/qq_30641447/article/details/80772574

免责声明:文章转载自《Bootstrap-table实现动态合并相同行(表格同名合并)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 20.04.2如何root登录pl/sql下DBMS_OUTPUT.PUT_LINE的输出位置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

(转)HBase 常用Shell命令

转自:http://my.oschina.net/u/189445/blog/595232 hbase shell命令 描述 alter 修改列族(column family)模式 count 统计表中行的数量 create 创建表 describe 显示表相关的详细信息 delete 删除指定对象的值(可以为表,行,列对应的值,...

PowerDesinger15设置字体大小

使用PowerDesigner时,它默认table的字体大小颜色等很难看; 假设通过 Symbol ---> Format进行设置。仅仅能对选中的最改动,新建的Table无效。能够通过例如以下改动。让你的设置永久保存: Tools -----> Display Preference.... ------> Format ------...

MySQL-死锁查询

1、查询是否锁表 show OPEN TABLES where In_use > 0; 查询到相对应的进程 === 然后 killid 2、查询进程 show processlist 补充: 查看正在锁的事务 SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 查看等待锁的事务 SELECT * FROM I...

ORACLE 数据、表误删恢复(转)

今天主要以oracle数据库为例,介绍关于表中数据删除的解决办法。(不考虑全库备份和利用归档日志)删除表中数据有三种方法:·delete(删除一条记录)·drop或truncate删除表格中数据 1.delete误删除的解决方法原理: 利用oracle提供的闪回方法,如果在删除数据后还没做大量的操作(只要保证被删除数据的块没被覆写),就可以利用闪回方式直接...

MySQL(一) 数据表数据库的基本操作

      序言         这类文章,记录我看《MySQL5.6从零开始学》这本书的过程,将自己觉得重要的东西记录一下,并有可能帮助到你们,在写的博文前几篇度会非常基础,只要动手敲,跟着我写的例子全部实现一遍,基本上就搞定了,前期很难理解的东西基本没有,所以写博文的内容,就是以练题的形式来呈现的。             需要用的资料以链接的形式给需...

python操作Excel读写--使用xlrd

一、安装xlrd模块 到python官网下载http://pypi.python.org/pypi/xlrd模块安装,前提是已经安装了python 环境。 二、使用介绍 1、导入模块 import xlrd 2、打开Excel文件读取数据 data = xlrd.open_workbook('excelFile.xls') 3、使用技巧 获取一个工作表 t...