关于layui的一些故事(三):导出Excel文件


一、普通表格导出

1.普通的导出,就是先将表格转换为csv,然后再讲csv转sheet对象,最后将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载

2.需要引入一个xlsx.core.min.js,链接:xlsx.core.min.js

3.需要额外引入jquery,链接:BootCDN

4.封装的方法,链接:封装的方法

<table id="tbShow">
    <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>性别</th>
            <th>专业</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>李记</td>
            <td></td>
            <td>计算机科学与技术</td>
        </tr>
        <tr>
            <td>2</td>
            <td>李诗涵</td>
            <td></td>
            <td>工商行政管理</td>
        </tr>
        <tr>
            <td>3</td>
            <td>王涵</td>
            <td></td>
            <td>金融管理</td>
        </tr>
    </tbody>
</table>
<button id="out" onclick="btn_export()" class="layui-btn">导出文件</button>
/* 导出excel*/
function btn_export() {
    var table = document.querySelector("#tbShow"); //document.getElementById("tbShow");
    var sheet = XLSX.utils.table_to_sheet(table); //将一个table对象转换成一个sheet对象
    var blob = sheet2blob(sheet, document.title);
    openDownloadDialog(blob, `${document.title}.xlsx`);
}
/**
 *以下内容为封装的方法
 *若是不想复制以下js,可以引入上文中第四个链接。
 */
// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
    sheetName = sheetName || "sheet1";
    var workbook = {
        SheetNames: [sheetName],
        Sheets: {},
    };
    workbook.Sheets[sheetName] = sheet;
    // 生成excel的配置项
    var wopts = {
        bookType: "xlsx", // 要生成的文件类型
        bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
        type: "binary",
    };
    var wbout = XLSX.write(workbook, wopts);
    var blob = new Blob([s2ab(wbout)], {
        type: "application/octet-stream",
    });
    // 字符串转ArrayBuffer
    function s2ab(s) {
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
        return buf;
    }
    return blob;
}

/**
 * 通用的打开下载对话框方法,没有测试过具体兼容性
 * @param url 下载地址,也可以是一个blob对象,必选
 * @param saveName 保存文件名,可选
 */
function openDownloadDialog(url, saveName) {
    if (typeof url == "object" && url instanceof Blob) {
        url = URL.createObjectURL(url); // 创建blob地址
    }
    var aLink = document.createElement("a");
    aLink.href = url;
    aLink.download = saveName || ""; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    var event;
    if (window.MouseEvent) event = new MouseEvent("click");
    else {
        event = document.createEvent("MouseEvents");
        event.initMouseEvent(
            "click",
            true,
            false,
            window,
            0,
            0,
            0,
            0,
            0,
            false,
            false,
            false,
            false,
            0,
            null
        );
    }
    aLink.dispatchEvent(event);
}

二、使用layui表格导出表格

由于layui表格的表头layui-table-header和表身layui-table-body分开的,所以在导出的时候,需要分别把表头和表身一起转换,在组装到一起导出。

<button id="exports" class="layui-btn">导出Excel</button>
<table id="tableList" lay-filter="tableList"></table>

js部分:

/**
 *layui数据表格渲染,自行引入即可。
 *document.title为html的`title`标签
 */
$("#exports").click(function () {
    var csv1 = tableHead2csv($("#layuiTable .layui-table-header table")[0]);
    var csv2 = tableBody2csv($("#layuiTable .layui-table-body table")[0]);
    var csv = csv1 + "\n" + csv2;
    //console.log(csv)
    var sheet = csv2sheet(csv);
    var blob = sheet2blob(sheet, document.title);
    openDownloadDialog(blob, `${document.title}.xlsx`);
});
/**
 *封装的js,若是不想复制,可以直接引用
 *引用链接://static.mingxuan.tech/assets/sheetjs/js/exports.js
 */
function tableHead2csv(table) {
    //导出表头
    var csv = [];
    $(table)
        .find("tr")
        .each(function () {
            var temp = [];
            $(this)
                .find("th")
                .each(function () {
                    if ($(this).data("field") == "operate") {
                        return;
                    } else {
                        $(this)
                            .find("div span")
                            .each(function () {
                                temp.push($(this).html());
                            });
                    }
                });
            csv.push(temp.join(","));
        });
    return csv.join("\n");
}

function tableBody2csv(table) {
    //导出表身
    var csv = [];
    $(table)
        .find("tr")
        .each(function () {
            var temp = [];
            $(this)
                .find("td")
                .each(function () {
                    // console.log($(this).data('field'));
                    if ($(this).data("field") == "operate") {
                        return;
                    } else {
                        $(this)
                            .find("div")
                            .each(function () {
                                // console.log($(this).html());
                                temp.push($(this).html());
                            });
                    }
                });
            // console.log(temp)
            // console.log(temp.join(','))
            csv.push(temp.join(","));
        });
    // console.log(csv)
    // console.log(csv.join('\n'))
    return csv.join("\n");
}

// csv转sheet对象
function csv2sheet(csv) {
    var sheet = {}; // 将要生成的sheet
    csv = csv.split("\n");
    csv.forEach(function (row, i) {
        row = row.split(",");
        if (i == 0) sheet["!ref"] = "A1:" + String.fromCharCode(65 + row.length - 1) + csv.length;
        row.forEach(function (col, j) {
            sheet[String.fromCharCode(65 + j) + (i + 1)] = {
                v: col,
            };
        });
    });
    return sheet;
}

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
    sheetName = sheetName || "sheet1";
    var workbook = {
        SheetNames: [sheetName],
        Sheets: {},
    };
    workbook.Sheets[sheetName] = sheet;
    // 生成excel的配置项
    var wopts = {
        bookType: "xlsx", // 要生成的文件类型
        bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
        type: "binary",
    };
    var wbout = XLSX.write(workbook, wopts);
    var blob = new Blob([s2ab(wbout)], {
        type: "application/octet-stream",
    });
    // 字符串转ArrayBuffer
    function s2ab(s) {
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
        return buf;
    }
    return blob;
}

/**
 * 通用的打开下载对话框方法,没有测试过具体兼容性
 * @param url 下载地址,也可以是一个blob对象,必选
 * @param saveName 保存文件名,可选
 */
function openDownloadDialog(url, saveName) {
    if (typeof url == "object" && url instanceof Blob) {
        url = URL.createObjectURL(url); // 创建blob地址
    }
    var aLink = document.createElement("a");
    aLink.href = url;
    aLink.download = saveName || ""; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    var event;
    if (window.MouseEvent) event = new MouseEvent("click");
    else {
        event = document.createEvent("MouseEvents");
        event.initMouseEvent(
            "click",
            true,
            false,
            window,
            0,
            0,
            0,
            0,
            0,
            false,
            false,
            false,
            false,
            0,
            null
        );
    }
    aLink.dispatchEvent(event);
}

三、layui框架中导出表格

1.通过内置按钮导出数据

最新layuijs添加了表格的导出功能,开启defaultToolbar即可。

var tableIns = table.render({
    elem: "#tableList",
    id: "layuiID",
    data: data,
    title: "数据表",
    toolbar: true,
    defaultToolbar: [
        "filter",
        "exports",
        "print",
        {
            //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
            title: "提示",
            layEvent: "LAYTABLE_TIPS",
            icon: "layui-icon-tips",
        },
    ],
    page: true,
    limit: 10,
    cols: [[{}]],
    done: function (res, curr, count) {
        console.log(res);
    },
});

2.通过方法导出

语法:table.exportFile(id, data, type)

var ins1 = table.render({
    elem: "#demo",
    id: "test",
    //,…… //其它参数
});

//将上述表格示例导出为 csv 文件
table.exportFile(ins1.config.id, data); //data 为该实例中的任意数量的数据

四、结束语

前端在导出表格的时候,由于是导出当前表格的内容,所以只能导出当前数据量的信息,若是要全部导出,可以通过后台导出,或是一次性请求全部数据,然后导出。

若是一次性请求后台数据量过大,且需要对数据重组后才能导出的话,可以通过tableBody2csv()csv2sheet()sheet2blob()openDownloadDialog()方法。

最后:附上一个可以导入和导出测试的链接: SheetJS


文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录