新的表格展示利器 Bootstrap Table Ⅱ
上一篇文章介绍了Bootstrap Table的基本知识点和应用,本文针对上一篇文章中未解决的文件导出问题进行分析,同时介绍BootStrap Table的扩展功能,当行表格数据修改。
1.Bootstrap Bable 全部数据导出分析
在表格导出数据中,发现设置了分页参数,导出的数据仅为表格加载的分页参数数据,于是,针对这样的情况,通过设置分页参数的值,使表格可以加载更多的数据,可达到导出所有数据的功能需求。然而,在实际的实验中,发现此方案存在以下问题:
- 表格一次加载一千条数据时,网页响应速度太慢,加载数据等待时间严重过长。(一分钟左右)
- Bootsrtap Table 的文件导出是纯前端的js导出模式,它的数据源只能为表格中的数据集合
分析产生上述问题的原因,不难发现,html页面在渲染的时候,一次渲染过多的节点,网页性能必然降低。而通过去分析table-export.js中的导出源码,发现导出文件是以表格为数据源,导出多数据时,必然需要表格加载更多的数据,所以这样的循环,导致导出功能在实际项目中,导出特别耗时,应用不理想。要解决这样的问题,目前可采用如下两种方法:
- 修改table-export.js中的导出模块源码,当ajax从后台请求到数据成功后,不在渲染数据到Bootstrap Table中去,而是直接作为数据源提供给导出模块。(目前这样的方案,感觉编写js函数需要的逻辑比较复杂)
- 前端调用java程序中,成熟的导出文件功能,利用java程序处理文件导出。
本次测试文件导出时,采用了java后台程序处理的方案。具体操作如下:
- 前端界面仿造Bootstrap Table的js函数,编写一个导出所有文件的按钮
- 利用java程序,调用SXSSFWorkbook组件,导出指定数据到Excel表中
构建导出按钮
构建导出按钮,修改bootstrap-table.js中的定义事项,加入一个showExportAll参数,定义展示样式即可模拟一个导出按钮,重要实现代码如下:
//wanling add exportAll button 2017-8-7
if (this.options.showExportAll) {
html.push(sprintf('<button class="btn' +
sprintf(' btn-%s', this.options.buttonsClass) +
sprintf(' btn-%s', this.options.iconSize) +
'" type="button" name="exportAll" aria-label="exportAll" title="%s">',
this.options.formatExportAll()),
sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.exportAll),
'</button>');
}
最终实现效果如下:

java调用SXSSFWorkbook组件导出文件
SXSSFWorkbook官网介绍 http://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFWorkbook.html。它是专门用来处理大量数据写入 Excel2007的工具。通过在java后台获取到数据后,传入数据,展示列等信息到SXSSFWorkbook中,即可完成数据写入到excel并以文件流的方式输出。核心调用代码如下:
@Override
public Map perform(Map inMap) throws BizException, SysException {
inMap.put("start", Integer.valueOf(0));
inMap.put("limit", SysconfigHelper.getExportBatchSize());
Map result = overTime.QueryAction(inMap);
String exportFileName = "加班信息表";
List resutList = (List) result.get(CommonAttribute.ROWS);
List queryResultColumnNames = new ArrayList(Arrays.asList("createByDesc", "overTimeDate", "beginTime", "endTime", "overTimeHour", "checkPersonDesc", "overTimeStatus", "projectNameDesc", "overTimeAddressDesc", "eatMoney", "taxiMoney", "overTimeRemark"));
List queryResultColumnFriendlyNames = new ArrayList(Arrays.asList("加班人", "加班日期", "加班开始时间", "加班结束时间", "加班小时", "审核人", "审核状态", "所属项目", "加班地点", "加班餐费", "加班车费", "备注"));
//List<Double> queryResultColumnWidths = new ArrayList(Arrays.asList(65.00, 40.00, 100.00, 120.00, 65.00, 100.00, 65.00, 100.00));
HttpServletResponse response = (HttpServletResponse) inMap.get("http_response");
try {
ExportToExcelHelper.ExportExcel(queryResultColumnNames,queryResultColumnFriendlyNames,resutList,false,exportFileName,response);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
  protected static void exportExcel(List<Object> columnFriendlyNameList, List<Object> columnList, List<Double> columnWidths, Map inMap, OutputStream outputStream, boolean... hideSEQ) {
         boolean hideSeq = hideSEQ.length == 1 && hideSEQ[0];
         SXSSFWorkbook workbook = new SXSSFWorkbook(5000);
         Sheet sheet = workbook.createSheet("sheet1");
         initCellStyle(workbook);
         setHeaderLine(sheet, columnFriendlyNameList, hideSeq);
         setDataLine(sheet, columnList, inMap, hideSeq);
         setColumnWidth(sheet, columnWidths);
         outputWorkBook(workbook, outputStream);
         resetTimeStyleStr();
     }
导出数据效果
通过前端自定义的按钮,调用后台的导出文件action,即可导出数据到excel文本中。展示效果如下(部分列数据我手动删除了):

2.bootstrap table 数据行修改
通过调用Bootstrap Table的扩展js(bootstrap-table-editable.js,bootstrap-editable.js)可设置编辑表格行内数据。前端设置编辑表格数据,界面展示效果如下:

对于修改表格内容时的提示框样式,可修改bootstrap-table-editable.js中的源码处理noeditFormatter函数,修改样式参考代码如下:
var _dont_edit_formatter = false;
if (column.editable.hasOwnProperty('noeditFormatter')) {
var process = column.editable.noeditFormatter(value, row, index);
if(!process.hasOwnProperty('class')){
process.class = '';
}
if(!process.hasOwnProperty('style')){
process.style = 'color:#000;text-decoration:none;';
}
_dont_edit_formatter = ['<a href="javascript:void(0)"',
' data-name="'+process.filed+'"',
' data-pk="' + row[that.options.idField] + '"',
' data-value="' + process.value + '"',
' class="'+process.class+'" style="'+process.style+'"',
'>' + process.value + '</a>'
].join('');
} if (_dont_edit_formatter === false) {
return ['<a href="javascript:void(0)"',
' data-name="' + column.field + '"',
' data-pk="' + row[that.options.idField] + '"',
' data-value="' + result + '"',
editableDataMarkup.join(''),
'>' + value + '</a>'
].join('');
} else {
return _dont_edit_formatter;
}
前端页面调用时,参考代码如下:
  loadCharts: function () {
         var me = this;
         var tb_departments = me.getCmp("overtimeTable").bootstrapTable({
             method: 'post',                      //请求方式(*)
             height: MP.Const.dataGridHeight,
             toolbar: '#checkovertimeinfo_toolbar',                //工具按钮用哪个容器
             striped: true,                      //是否显示行间隔色
             cache: false,                       //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
             pagination: true,                   //是否显示分页(*)
             sortable: true,                     //是否启用排序
             sortOrder: "asc",                   //排序方式
             sidePagination: "server",           //分页方式:client客户端分页,server服务端分页(*)
             pageNumber: 1,                       //初始化加载第一页,默认第一页
             pageSize: 20,                       //每页的记录行数(*)
             pageList: [10, 20, 25, 30],        //可供选择的每页的行数(*)
             //search: true,                       //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
             strictSearch: true,
             singleSelect:false,
             showColumns: true,                  //是否显示所有的列
             showToggle:true,                    //是否显示详细视图和列表视图的切换按钮
             //showRefresh: false,                  //是否显示刷新按钮
             minimumCountColumns: 1,             //最少允许的列数
             //clickToSelect: true,                //是否启用点击选中行
             cardView: false,                    //是否显示详细视图
             detailView: false,                   //是否显示父子表
             showHeader: true,
             onEditableSave: function (field, row, oldValue, $el) {
                 //单行数据修改后,保存到后台
                 var param={};
                 var listUuid=[];
                 listUuid[0]=row.uuid;
                 param.listUuid=listUuid;
                 param.overTimeStatus=row.overTimeStatus;
                 MP.doAction("sccq-overtime-update", param, function(data)
                 {
                     if(data.success)
                     {
                         MP.Msg.info('审核操作完成');
                     }
                     me.ajaxGetData();
                 },null, true, true);
             },
             columns: [
                 {
                     title: "全选",
                     field: "select",
                     checkbox: true,
                     align: "left",//水平居中
                     halign: "left",//垂直居中
                 }, {
                     field: "uuid",
                     align: 'center',
                     title: "个人分析",
                     formatter: function (value) {
                         var html = "<a class='easyui-linkbutton l-btn l-btn-small l-btn-plain' name='" + value + "'>" +
                             "<span class='l-btn-left l-btn-icon-left'><span class='l-btn-icon icon-search'></span><span class='l-btn-text'>查看</span></span></a> ";
                         return html;
                     }
                 }, {
                     align: "left",//水平居中
                     halign: "left",//垂直居中
                     field: "createByDesc",
                     title: "加班人"
                 },{
                     align: "left",
                     halign: "left",
                     field: "overTimeDate",
                     sortable:true,
                     title: "加班日期",
                     formatter: function (value) {
                         return MP.dateFormatter(value);
                     }
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "beginTime",
                     title: "加班开始时间"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "endTime",
                     title: "加班结束时间"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "overTimeHour",
                     sortable:true,
                     title: "加班小时"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "overTimeStatus",
                     title: "审核状态",
                     editable: {
                         type: 'select',
                         title: "审核状态",
                         pk: 1,
                         source: [
                             {value: 2, text: '审核通过'},
                             {value: 3, text: '驳回'}
                         ],
                         noeditFormatter: function (value,row,index) {
                             var result;
                             if (value == '1' || value == '待审核') {
                                 result={filed:"overTimeStatus",value:"待审核",class:"badge bg-orange",style:"padding:5px 10px;"};
                             } else if (value == '2' || value == '审核通过'){
                                 result={filed:"overTimeStatus",value:"审核通过",class:"badge bg-green",style:"padding:5px 10px;"};
                             }
                             else if (value == '3' || value == '驳回'){
                                 result={filed:"overTimeStatus",value:"驳回",class:"badge bg-red",style:"padding:5px 10px;"};
                             }
                             return result;
                         }
                     }
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "projectNameDesc",
                     sortable:true,
                     title: "所属项目"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "overTimeAddressDesc",
                     sortable:true,
                     title: "加班地点"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "eatMoney",
                     sortable:true,
                     title: "加班餐费"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "taxiMoney",
                     sortable:true,
                     title: "加班车费"
                 },
                 {
                     align: "left",
                     halign: "left",
                     field: "overTimeRemark",
                     title: "备注"
                 }
             ],
             onPageChange:function(number, size)
             {
                 //设置在分页事件触发时,传递分页参数给后台,重新加载数据
                 me.queryBaseParam.limit=size;
                 me.queryBaseParam.start=number;
                 me.ajaxGetData();
             },
             onSort: function (name, order) {
                 me.queryBaseParam.sort=name;
                 me.queryBaseParam.order=order;
                 me.ajaxGetData();
             },
             onClickRow: function (row, $elepment, field) {
                 if (field == 'uuid') {
                     //alert("查看页面");
                     var params={};
                     params.createBy=row.createBy;
                     params.createByDesc=row.createByDesc;
                     me.controller.showOvertimeSingleDetail(params);
                 }
             }
         });
     },
     ajaxGetData: function () {
         //加载后台数据
         var me=this;
         var params=MP.getFormData("searchOverTimeForm_person",this.controller);
         params.QueryType=1;
         params.limit= me.queryBaseParam.limit;
         params.start= me.queryBaseParam.start;
         params.sort= me.queryBaseParam.sort;
         params.order= me.queryBaseParam.order;
         MP.doAction("sccq-overtime-query", params, function (datas) {
             if (datas.success) {
                 me.getCmp("overtimeTable").bootstrapTable('load', datas);
             }
         }, function (datas) {
             alert("数据加载失败");
         }, true, true);
     }
新的表格展示利器 Bootstrap Table Ⅱ的更多相关文章
- 新的表格展示利器 Bootstrap Table
		1.bootstrap table简介及特征 Bootstrap Table是国人开发的一款基于 Bootstrap 的 jQuery 表格插件,通过简单的设置,就可以拥有强大的单选.多选.排序.分 ... 
- 新的表格展示利器 Bootstrap Table Ⅰ
		1.bootstrap table简介及特征 Bootstrap Table是国人开发的一款基于 Bootstrap 的 jQuery 表格插件,通过简单的设置,就可以拥有强大的单选.多选.排序.分 ... 
- 【转载】BootStrap表格组件bootstrap table详解
		(转载,来源“脚本之家”,作者不详) 一.Bootstrap Table的引入 关于Bootstrap Table的引入,一般来说还是两种方法: 1.直接下载源码,添加到项目里面来.由于Bootstr ... 
- Bootstrap Table的例子(转载)
		转载自:http://wenzhixin.net.cn/p/bootstrap-table/docs/examples.html#classes-table 使用的API: data1.json da ... 
- [转]bootstrap table 动态列数
		原文地址:https://my.oschina.net/u/2356355/blog/1595563 据说bootstrap table非常好用,从入门教程中了解到它的以下主要功能: 由于固定表头意味 ... 
- Bootstrap Table使用方法详解
		http://www.jb51.net/article/89573.htm bootstrap-table使用总结 bootstrap-table是在bootstrap-table的基础上写出来的,专 ... 
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
		前言:上篇 JS组件系列——表格组件神器:bootstrap table 简单介绍了下Bootstrap Table的基础用法,没想到讨论还挺热烈的.有园友在评论中提到了父子表的用法,今天就结合Boo ... 
- JS组件系列——Bootstrap Table 表格行拖拽(二:多行拖拽)
		前言:前天刚写了篇JS组件系列——Bootstrap Table 表格行拖拽,今天接到新的需要,需要在之前表格行拖拽的基础上能够同时拖拽选中的多行.博主用了半天时间研究了下,效果是出来了,但是感觉不尽 ... 
- 使用bootstrap table小记(表格组件)
		前言 新的一年悄然到来,生活依旧.最近一周大热的赵雷风,一首<成都>,一首<理想>再次把民谣展示在国人面前.歌词着实写的不错. 理想,你今年几岁 你总是诱惑着年轻的朋友 你总是 ... 
随机推荐
- 面向接口编程详解-Java篇
			相信看到这篇文字的人已经不需要了解什么是接口了,我就不再过多的做介绍了,直接步入正题,接口测试如何编写.那么在这一篇里,我们用一个例子,让各位对这个重要的编程思想有个直观的印象.为充分考虑到初学者,所 ... 
- (转)Spring事务配置的五种方式
			前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ... 
- 快速搭建MySQL复制集
			快速搭建MySQL复制集 1 环境说明 MySQL版本 5.6 basedir :/u01/my3306 #MySQL软件目录 数据目录 :/u01/mysql/[实例名]/data 日志目录 :/u ... 
- ServletContext对象统计在线人数
			package com.zdsofe.servlet1; import java.io.IOException; import java.io.PrintWriter; import javax.se ... 
- Python爬虫初学(二)—— 爬百度贴吧
			Python爬虫初学(二)-- 爬百度贴吧 昨天初步接触了爬虫,实现了爬取网络段子并逐条阅读等功能,详见Python爬虫初学(一). 今天准备对百度贴吧下手了,嘿嘿.依然是跟着这个博客学习的,这次仿照 ... 
- 双向循环链表(C语言描述)(一)
			双向循环链表是链表的一种,它的每个节点也包含数据域和指针域.为了方便程序维护,可以单独为数据域定义一种数据类型,这里以整型为例: typedef int LinkedListData; 双向循环链表( ... 
- XML属性列表
			<?xml version="1.0" encoding="UTF-8"?> <Resources> <Include > ... 
- 案例:Oracle报错ASM磁盘组不存在或没有mount
			案例:Oracle报错ASM磁盘组不存在或没有mount 环境:RHEL 6.5 + Oracle Standby RAC 11.2.0.4 我做Standby RAC实验时,在恢复控制文件时,报错无 ... 
- Java 内存分配策略
			内存有分配,就有回收,Java 的 GC 算法在前一篇文章中已经介绍过了,这篇文章着重介绍 Java 的内存分配策略. 从大方向讲,除去 JIT ,对象的内存分配就是在堆上分配,对象主要分配在新生代的 ... 
- mybatis 详解(九)------ 一级缓存、二级缓存
			上一章节,我们讲解了通过mybatis的懒加载来提高查询效率,那么除了懒加载,还有什么方法能提高查询效率呢?这就是我们本章讲的缓存. mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解 ... 
