基于LAY-EXCEL的公共列表导出方法

目录

 导出方法实现

 获取导出数据列表  

后台数据列表

 layui未分页数据列表

easyui treegrid数据列表

 简单表头获取

 获取LAYUI表头 

 获取EASYUI表头   

 易用

 使用 

layui表格

easyui treegrid 树表

需修改数据显示

 通过表头设置格式化数据

修改获取的表头数据

多个sheet页导出

 拓展 

判断字符串以数字结尾

 替换字符串中括号及内容

 存在问题

 参考链接


 需求

        layui/easyui表格的公共导出方法,能自动获取表头配置

        顺便写了无表格的数据导出方法

 导出方法实现

  LAY-EXCEL官方文档 

/**
 * 导出excel列表数据
 * @param {*} data 数据列表
 * @param {*} dataFieldMap 数据对应字段 {field1: 'field1'}
 * @param {*} unshiftMap 表头字段名
 *   单行表头                  {field1: '标题1'}
 *   多行,空值也需要设置字段   [{field1: '标题1','field2': '标题2'},{field1: '标题1-1','field2': ''}]
 * @param {*} fileName 导出文件名 不带后缀
 * @param {*} headN 表头行数 不传默认1
 * @param {*} mergeM 导出合并单元格设置 [['A1', 'E1'],['A2', 'D4']]
 * @param {*} colW 导出列宽设置 不传默认defaultW {'A': 40,'C': 120}
 * @param {*} defaultW 导出默认列宽 不传默认150
 */
function exportExcelL(data, dataFieldMap, unshiftMap, fileName, headN, mergeM, colW, defaultW) {
    layui.config({
        base: '你的excel.js位置'
    }).use(['jquery', 'excel', 'layer'], function () {
        var $ = layui.jquery, layer = layui.layer, excel = layui.excel;
        // 列数
        var colnum = countProps(dataFieldMap);
        data = exportDataSetting(data, dataFieldMap, unshiftMap, headN, excel);
        if(undefined == mergeM || "" == mergeM || null == mergeM){
            mergeM = [];
        }
        var mergeConf = excel.makeMergeConfig(mergeM);
        if(undefined == defaultW || "" == defaultW || null == defaultW){
            defaultW = 150;
        }
        if(undefined == colW || "" == colW || null == colW){
            colW = {};
            for(var i=0; i < colnum; i++){
                colW[createCellPos(i)] = defaultW;
            }
        } else {
            if(!colW.hasOwnProperty(createCellPos(colnum - 1))){
                colW[createCellPos(colnum - 1)] = defaultW;
            }
        }
        var colConf = excel.makeColConfig(colW, defaultW);
        excel.exportExcel({
                sheet1: data
            }, fileName + '.xlsx', 'xlsx', {
                extend: {
                    '!merges': mergeConf,
                    '!cols': colConf
                }
            }
        )
    })
}

/**
 * 导出表格设置
 * 默认样式表格加框线,表头加粗
 * @param {*} data 数据列表
 * @param {*} dataFieldMap 数据对应字段 {field1: 'field1'}
 * @param {*} unshiftMap 表头字段名
 *   单行表头                  {field1: '标题1'}
 *   多行,空值也需要设置字段   [{field1: '标题1','field2': '标题2'},{field1: '标题1-1','field2': ''}]
 * @param {*} headN 表头行数 不传默认1
 * @param {*} excel layui excel对象
 */
function exportDataSetting(data, dataFieldMap, unshiftMap, headN, excel) {
    if(undefined == headN || "" == headN || null == headN){
        headN = 1;
    }
    // 总行数
    var size = data.length + headN;
    // 列数
    var colnum = countProps(dataFieldMap);
    // 最后一列对应excel列号
    var col = createCellPos(colnum - 1);
    data = excel.filterExportData(data, dataFieldMap);
    if(undefined == unshiftMap.length){
        data.unshift(unshiftMap);
    } else {
        $.each(unshiftMap.reverse(), function (i, map) {
            data.unshift(map);
        });
    }
    excel.setExportCellStyle(data, 'A1:' + col + size, {
        s: {
            border: {
                top: {style: 'THIN'},
                bottom: {style: 'THIN'},
                left: {style: 'THIN'},
                right: {style: 'THIN'}
            },
            alignment: {
                vertical: 'center',
                wrapText: true
            }
        }
    });
    excel.setExportCellStyle(data, 'A1:' + col + headN, {
        s: {
            font: {bold: 'bold'},
            alignment: {
                horizontal: 'center',
                vertical: 'center'
            }
        }
    });
    return data;
}

// 数字转换为EXCEL列号 从0开始
function createCellPos(n){
	var ordA = 'A'.charCodeAt(0);
	var ordZ = 'Z'.charCodeAt(0);
 	var len = ordZ - ordA + 1;
 	var s = "";
	while( n >= 0 ) {
		s = String.fromCharCode(n % len + ordA) + s;
		n = Math.floor(n / len) - 1;
	}
	return s;
}

// 获取对象中字段个数
function countProps(obj) {
    var l = 0;
    for (p in obj) l++;
    return l;
}

 获取导出数据列表  

  • 后台数据列表

       表格分页后只能直接获取当前页的数据,所以从后台获取全部数据。

       也可以用来获取非表格导出数据。

//导出数据列表
function exportList(url, params){
    // 分页参数默认传最大值
    // 也可以在表格加载成功后获取到全部数据条数传到后台
    // pageSize 为后台分页查询时接收的查询条数限制参数名
    params.pageSize = 2147483647;
    var result;
    if("" != url){
        $.ajax({
            url: url,
            data: params,
            async: false,
            success: function (data) {
                // layui表格返回数据格式
                result = data.data;
                if (undefined === result) {
                    // easyui表格返回数据格式
                    result = data.records;
                }
                if (undefined === result) {
                    // 非表格返回数据格式
                    result = data;
                }
            }
        });
    }
    delete params.pageSize;
    return result;
}
//导出数据列表 layui
//listTable 全局变量 layuitable实例
function exportListLay(){
    if(undefined === listTable){
        return;
    }
    var listUrl = listTable.config.url;
    var listParams = listTable.config.where;
    return exportList(listUrl, listParams);
}
  •  layui未分页数据列表

var data = layui.table.cache["layTableId"];
  • easyui treegrid数据列表

//treegrid数据列表
function getTreeGridList(obj) {
    var rows = [];
    var datas = $(obj).treegrid("getData");
    $.each(datas, function (i, data) {
        rows.push(data);
        getTreeGridRows(data);
    });

    /**
     * 获取easyui treegrid所有节点数据
     * @param data 所有第一级数据 treegrid("getData");
     */
    function getTreeGridRows(data){
        if(data.children != undefined && data.children != null){
            for(var i = 0; i < data.children.length;i++){
                rows.push(data.children[i]);
                getTreeGridRows(data.children[i]);
            }
        }
    }
    return rows;
}

没有贴easyui datagrid数据获取方法,但跟layui思路是一样的,不分页的表格直接获取页面数据,分页的表格通过url和传参到后台查询数据。

 简单表头获取

//导出数据表头配置 自定义属性exHide 为true时不导出该列
//只能获取单行表头
function exportHead(tableId, type){
    var headMap = [];
    var dataFieldMap = {};
    var unshiftMap = {};
    if(undefined === type || "layui" === type) {
        layui.table.eachCols(tableId, function (index, item) {
            if (item.field && item.type === 'normal' && !item.hide && !item.exHide) {
                dataFieldMap[item.field] = item.field;
                if(item.title.indexOf("<") > 0){
                    item.title = item.title.substring(0, item.title.indexOf("<"))
                }
                unshiftMap[item.field] = item.title;
            }
        });
    } else if("easyui" === type) {
        var cols = $(tableId).datagrid('options').columns;
        $.each(cols, function (index, col) {
            $.each(col, function (i, item) {
                if (item.field && !item.checkbox && !item.hidden && !item.exHide) {
                    dataFieldMap[item.field] = item.field;
                    if(item.title.indexOf("<") > 0){
                        item.title = item.title.substring(0, item.title.indexOf("<"))
                    }
                    unshiftMap[item.field] = item.title;
                }
            });
        });
    }
    headMap["dataFieldMap"] = dataFieldMap;
    headMap["unshiftMap"] = unshiftMap;
    return headMap;
}

 获取LAYUI表头 

/**
 * 导出数据表头配置Layui表格
 * 自定义属性exHide 为true时不导出该列
 * 自定义属性exShow 为true时不判断类型和字段名field
 * 支持Layui多行表头
 * @param tableModel layui table实例
 * @returns {Array} 表头配置map
 */
function exportHeadLay(tableModel){
    var headMap = [];
    // 字段对应值
    var dataFieldMap = {};
    // 显示的表头字段数组
    var dataFieldValues = [];
    // 字段对应表头名
    var unshiftMaps = [];
    // 计算合并单元格map
    var mergeMaps = [];
    // 计算列宽度map
    var colW = {};
    layui.table.eachCols(tableModel.config.id, function (index, item) {
        if (((item.field && item.type === 'normal') || item.exShow) && !item.hide && !item.exHide) {
            // 获取最终显示列字段
            dataFieldMap[item.field] = item.field;
            dataFieldValues.push(item.field);
        }
    });
    var cols = tableModel.config.cols;
    $.each(cols, function (index, col) {
        var unshiftMap = {};
        //表头顺序设置为数据顺序
        for (var key in dataFieldMap) {
            unshiftMap[key] = "";
        }
        var ri = index + 1; //当前单元格行号
        var ci = 0; //当前单元格列号
        $.each(col, function (i, item) {
            if (((item.field && item.type === 'normal') || item.exShow) && !item.hide && !item.exHide) {
                if(item.title.indexOf("<") > 0){
                    item.title = item.title.substring(0, item.title.indexOf("<"))
                }
                if (dataFieldMap.hasOwnProperty(item.field)) {
                    unshiftMap[item.field] = item.title;
                } else {
                    // 当前字段不在导出显示列中,说明是合并单元格字段,在相同位置写入表头名,合并单元格后才能显示表头名字
                    unshiftMap[dataFieldValues[ci]] = item.title;
                }
                // 通过列设置width计算表格宽度
                if(typeof(item.width) === "string" && item.width.endsWith("%")){
                    item.width = Number(item.width.replace("%","")) * 10;
                }
                if(typeof(item.minWidth) === "string" && item.minWidth.endsWith("%")){
                    item.minWidth = Number(item.minWidth.replace("%","")) * 10;
                }
                var width = item.width;
                if((item.minWidth && width < item.minWidth) || width === undefined){
                    width = item.minWidth;
                }
                if(width > 150 && (!colW.hasOwnProperty(createCellPos(ci)) || width > colW[createCellPos(ci)])){
                    colW[createCellPos(ci)] = width;
                } else if(width === 0 && !colW.hasOwnProperty(createCellPos(ci))){
                    colW[createCellPos(ci)] = 260;
                }
                var mergeMap = [];
                item.rowspan = parseInt(item.rowspan) || 1;   //跨行默认1行
                item.colspan = parseInt(item.colspan) || 1;   //跨列默认1列
                // 通过列设置colspan/rowspan计算表格合并单元格号
                if(item.colspan > 1 || item.rowspan > 1) {
                    var startCell = createCellPos(ci) + ri;
                    if (item.colspan > 1) {
                        ci = ci + item.colspan;
                    } else {
                        ci++;
                    }
                    if (item.rowspan > 1) {
                        ri = ri + item.rowspan - 1;
                    }
                    var endCell = createCellPos(ci - 1) + ri;
                    mergeMap.push(startCell);
                    mergeMap.push(endCell);
                    mergeMaps.push(mergeMap);
                } else {
                    ci++;
                }
                ri = index + 1;
            }
        });
        unshiftMaps.push(unshiftMap);
    });
    headMap["dataFieldMap"] = dataFieldMap;
    if(unshiftMaps.length > 1){
        headMap["unshiftMap"] = unshiftMaps;
    } else {
        headMap["unshiftMap"] = unshiftMaps[0];
    }
    headMap["headN"] = cols.length;
    headMap["mergeM"] = mergeMaps;
    headMap["colW"] = colW;
    return headMap;
}

 获取EASYUI表头   

/**
 * 导出数据表头配置Easyui表格
 * 自定义属性exHide 为true时不导出该列
 * 支持Easyui多行表头
 * @param tableId easyui 表格页面元素选择器 例'#id'
 * @returns {Array} 表头配置map
 */
function exportHeadEasy(tableId){
    var headMap = [];
    var dataFieldMap = {};
    var dataFieldValues = [];
    var unshiftMaps = [];
    var mergeMaps = [];
    var colW = {};
    var fields = $(tableId).datagrid('getColumnFields');
    $.each(fields, function (i, field) {
        var option = $(tableId).datagrid('getColumnOption', field);
        if (option.field && !option.checkbox && !option.hidden && !option.exHide) {  //过滤勾选框和隐藏列
            dataFieldMap[field] = field;
            dataFieldValues.push(field);
        }
    });
    var cols = $(tableId).datagrid('options').columns;
    $.each(cols, function (index, col) {
        var unshiftMap = {};
        //表头顺序设置为数据顺序
        for (var key in dataFieldMap) {
            unshiftMap[key] = "";
        }
        var ri = index + 1; //当前单元格行号
        var ci = 0; //当前单元格列号
        $.each(col, function (i, item) {
            if (item.field && !item.checkbox && !item.hidden && !item.exHide) {
                if(item.title.indexOf("<") > 0){
                    item.title = item.title.substring(0, item.title.indexOf("<"))
                }
                if (dataFieldMap.hasOwnProperty(item.field)) {
                    unshiftMap[item.field] = item.title;
                } else {
                    unshiftMap[dataFieldValues[ci]] = item.title;
                }
                if(item.width && item.width > 150 && (!colW.hasOwnProperty(createCellPos(ci) || item.width > colW[createCellPos(ci)]))){
                    colW[createCellPos(ci)] = item.width;
                }
                var mergeMap = [];
                item.rowspan = parseInt(item.rowspan) || 1;   //跨行默认1行
                item.colspan = parseInt(item.colspan) || 1;   //跨列默认1列
                if(item.colspan > 1 || item.rowspan > 1) {
                    var startCell = createCellPos(ci) + ri;
                    if (item.colspan > 1) {
                        ci = ci + item.colspan;
                    } else {
                        ci++;
                    }
                    if (item.rowspan > 1) {
                        ri = ri + item.rowspan - 1;
                    }
                    var endCell = createCellPos(ci - 1) + ri;
                    mergeMap.push(startCell);
                    mergeMap.push(endCell);
                    mergeMaps.push(mergeMap);
                } else {
                    ci++;
                }
                ri = index + 1;
            }
        });
        unshiftMaps.push(unshiftMap);
    });
    headMap["dataFieldMap"] = dataFieldMap;
    if(unshiftMaps.length > 1){
        headMap["unshiftMap"] = unshiftMaps;
    } else {
        headMap["unshiftMap"] = unshiftMaps[0];
    }
    headMap["headN"] = cols.length;
    headMap["mergeM"] = mergeMaps;
    headMap["colW"] = colW;
    return headMap;
}

 易用

       这边需求是所有列表页面都需要加导出,页面较多为方便需要的页面新增按钮,写了一个增加按钮的方法,按需修改。只要调用导出方法就行。

//增加导出按钮
function exportBtn(){
    $(".btns:last-child").after(' <button type="button" id="exportList" onclick="exportTable()" class="btns importBtn">\n' +
        '    <i class="layui-icon layui-icon-export"></i>导出\n' +
        '</button>');
}

        为了方便不同需求调用,抽出来一些公共方法

/**
 * 导出数据默认方法 layui表格
 * listTable layui表格实例对象
 * document.title 默认页面名
 * 需自定义在页面重写exportTable方法
 */
function exportTable(){
    exportTableLay(document.title);
}

//导出数据 layui表格自定义文件名
function exportTableLay(fileName){
    var data = exportListLay();
    if (data == null || data.length == 0) {
        Msg.error("未获取到数据");
        return;
    }
    exportExcelLay(data, fileName);
}

/**
 * 导出数据 easyui TreeGrid表格
 * @param tableId easyui表格id 例:'#id'
 * @param fileName 导出文件名 不传默认html页面名
 */
function exportTreeGrid(tableId, fileName){
    var data = getTreeGridList(tableId);
    if (data == null || data.length == 0) {
        Msg.error("未获取到数据");
        return;
    }
    exportExcelEasy(data, tableId, fileName);
}

//导出数据 layui表格自定义文件名
function exportExcelLay(data, fileName){
    var headMap = exportHeadLay(listTable);
    if(undefined === fileName){
        fileName = document.title;
    }
    exportExcelL(data, headMap.dataFieldMap, headMap.unshiftMap, fileName, headMap.headN, headMap.mergeM, headMap.colW);
}

//导出数据 easyui表格自定义文件名
function exportExcelEasy(data, tableId, fileName){
    var headMap = exportHeadEasy(tableId);
    if(undefined === fileName){
        fileName = document.title;
    }
    exportExcelL(data, headMap.dataFieldMap, headMap.unshiftMap, fileName, headMap.headN, headMap.mergeM, headMap.colW);
}

 使用 

  • layui表格

//自定义文件名
function exportTable(){
    exportTableLay("文件名");
}
  • easyui treegrid 树表

function exportTable(){
    exportTreeGrid('#treeId');
}
//自定义文件名
function exportTable(){
    exportTreeGrid('#treeId',"文件名");
}
  • 需修改数据显示

       easyui同理 

function exportTable(){
    var data = exportListLay();
    if (data == null || data.length == 0) {
        Msg.error("未获取到数据");
        return;
    }
    $.each(data, function (index, item) {
        //修改数据代码
    });
    exportExcelLay(data);
}
  •  通过表头设置格式化数据

        根据配置自行修改,这边这个显示值是加了<span>标签以及一些style,所以去掉所有的html标签即可。

function exportTable(){
    var data = getTreeGridList("#treeId");
    if (data == null || data.length == 0) {
        Msg.error("未获取到数据");
        return;
    }
    $.each(data, function (index, item) {
        for (var key in item) {
            var option = $("#treeId").datagrid('getColumnOption', key);
            if(option) {
                var result = option.formatter(item[key], item, index);
                if(result){
                    //删除html标签
                    item[key] = result.replace(/\<.*?\>/g,'');
                } else {
                    item[key] = "默认值";
                }
            } else {
                item[key] = "默认值";
            }
        }
    });
    exportExcelEasy(data, "#treeId");
}
  • 修改获取的表头数据

        有些表格在渲染完成后可能通过js代码hide或者修改了表头名,这种情况下通过cols设置是获取不到这些表头的,只能在获取之后手动修改了

function exportTable(){
    var data = exportListLay();
    if (data == null || data.length == 0) {
        Msg.error("未获取到数据");
        return;
    }
    $.each(data, function (index, item) {
        //修改数据代码
    });
    var headMap = exportHeadLay(listTable);
    if(删除条件){
        delete headMap.dataFieldMap.字段名;
        delete headMap.unshiftMap.字段名;
    }
    if(修改条件){
        headMap.dataFieldMap["字段名"] = "字段名";
        headMap.unshiftMap["字段名"] = "表头名";
    }
    exportExcelL(data, headMap.dataFieldMap, headMap.unshiftMap, document.title, headMap.headN, headMap.mergeM, headMap.colW);
}
  • 多个sheet页导出

        这种页面很少,所以没有去封装方法

function exportTable(){
    var data1 = layui.table.cache["table1"];
    var data2 = getTreeGridList('#table2');
    if ((data1 == null || data1.length == 0)
        && (data2 == null || data2.length == 0)) {
        Msg.error("未获取到数据");
        return;
    }
    var headMap1 = exportHead("table1");
    var headMap2 = exportHead("#table2", "easyui");
    layui.config({
        base: '你的excel.js位置'
    }).use(['jquery', 'excel', 'layer'], function () {
        var $ = layui.jquery, layer = layui.layer, excel = layui.excel;
        data1 = exportDataSetting(data1, headMap1.dataFieldMap, headMap1.unshiftMap, 1, excel);
        data2 = exportDataSetting(data2, headMap2.dataFieldMap, headMap2.unshiftMap, 1, excel);
        var colConf = excel.makeColConfig({
            'A': 240,
            'G': 180,
        }, 150);
        var colConf2 = excel.makeColConfig({
            'B': 240,
            'E': 240,
            'I': 240,
            'J': 240,
        }, 150);
        excel.exportExcel({
                'sheet1': data1,
                'sheet2': data2,
            }, '文件名.xlsx', 'xlsx', {
                extend: {
                    'sheet1': {
                        '!cols': colConf
                    },
                    'sheet2': {
                        '!cols': colConf2
                    }
                }
            }
        )
    });
}
}

 拓展 

  • 判断字符串以数字结尾

var reg = new RegExp("(\\d+)$");
var keyEnd = reg.test(key);
if(keyEnd){
    //do
}
  •  替换字符串中括号及内容

// js
// 将<>及内容替换为空
str.replace(/\<.*?\>/g,'');

// java
// 匹配[]中内容
String regex = "\\[.*?\\]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
List<String> keys = new ArrayList<>();
while (matcher.find()) {
    if (!keys.contains(matcher.group())) {
        keys.add(matcher.group());
    }
}
for (String key : keys) {
    //[]内容
    String content = key.substring(1, key.length() - 1);
    //替换为空
    str = str.replace(key, "");
}

 存在问题

当合并表头有隐藏列时无法正确计算合并单元格,目前需求中没有这种列表数据,之后有时间再试着解决

有时间再放点示例图

 参考链接

 js获取Excel表格中横向表头的字母

JavaScript中将Excel的Cell单元格列标字母转化为数字

Easyui Datagrid 数据网格_EasyUI 插件

表格组件 table - Layui 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值