上一篇文章介绍了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>&nbsp;";
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);
}

最新文章

  1. 【shell 大系】Linux Shell常用技巧
  2. poj1062 昂贵的聘礼
  3. 2034-人见人爱A-B(c++实现)
  4. Win10添加简体中文美式键盘的方法
  5. Pyqt Smtplib实现Qthread多线程发送邮件
  6. Java 对象的串行化(Serialization)
  7. 简单实现兼容各大浏览器的js复制内容到剪切板
  8. C# 实现对窗体(Form)换肤
  9. 1067: spark.components:NavigatorContent 类型值的隐式强制指令的目标是非相关类型 String
  10. Mysql re-set password, mysql set encode utf8 mysql重置密码,mysql设置存储编码格式
  11. strut2配置文件属性介绍
  12. 条形码--JsBarcode
  13. 关机和重启Linux命令
  14. C#默认参数原理探究
  15. kuangbin带你飞dp专题-基础dp
  16. inux中ifreq 结构体分析和使用(转)
  17. verilog实现两个数的最大公因数
  18. SuperMap 三维产品资料一览表
  19. 教你优化yum源。配置阿里云的yum镜像源(base和epel)
  20. js中Math之random,round,ceil,floor的用法总结

热门文章

  1. java线程数过高原因分析
  2. [javascript] visible - 待写
  3. Verilog 任意(奇数/偶数)分频器
  4. 灵玖软件Nlpir Parser语义智能内容过滤
  5. tomcat 日志 按天自动分割 设定时任务定时清除
  6. for’ loop initial declarations are only allowed in C99 mode
  7. 6-最基础的服务-es6写法
  8. iOS上机题(附个人见解)
  9. PyCharm 去掉自动保存功能
  10. Handler案例-简易打地鼠游戏(延时处理消息)