在网页中利用第三方 JavaScript 插件——SheetJS,可以在浏览器中对 excel 文件进行轻量级操作,实现 excel 文件导入网页,网页表格保存为 excel 文件功能。复杂的表格样式设置需要付费的 VIP 版插件,但普通版本的功能已经足够我们使用,本文是一个入门级操作示例。

  • SheetJS 开源项目在 github 上地址为 https://github.com/SheetJS/sheetjs/tree/master/dist
  • 本例主要使用了 XLSX 对象的两个 api 函数 XLSX.utils.sheet_to_html 和 XLSX.utils.table_to_sheet
  • HTML5 的 input-file 控件在本例中有一个 bug 百思不得其姐,希望过路高人不吝赐教,拜谢。

效果图

在这里插入图片描述

源代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>EXCEL 操作示例</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.4/xlsx.core.min.js"></script>
    <style>
        table, tr, td {
            border: 1px solid #666;
            border-collapse: collapse;
            min-width: 56px;
            height: 18px;
            text-align: center;
        }
        a.btn {
            text-decoration: none;
            padding: 0 6px;
            border: 1px solid #333;
        }
        a.btn:hover {
            font-weight: bold;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <button onclick="ipt.click()">导入 Excel 到网页</button>
    <button onclick="table2excel()">网页表格保存 Excel</button>
    <input type="file" accept=".xls,.xlsx"><span id="filesName"></span>
    <div id="sheetName" style="padding-left:-6px;margin-top:6px;"></div>
    <div id="sheet"></div>
    <script>
        //隐藏文件控件并绑定按钮 change 事件
        var ipt = $('input').hide().on('change', function (e) {
            //input-file 控件事件传回的参数
            var files = event.target.files[0];
            if (files) {
                $("#filesName").text(files.name);
                //创建浏览器 FileReader 对象,以读入本地文件
                var reader = new FileReader();
                reader.readAsBinaryString(files);
                reader.onload = function (event) {
                    //XLSX 插件二进制读入 excel 文件
                    var workbook = XLSX.read(this.result, { type: 'binary' });
                    var wss = workbook.SheetNames, shs = "";
                    for (var i = 0; i < wss.length; i++)
                        shs += '<a herf="javascript:;" class="btn">' + wss[i] + '</a>';
                    $("#sheetName").html(shs);
                    $("a").bind("click", function () {
                        $("a").css('background-color', '#ddd');
                        $(this).css('background-color', '#fff');
                        var sht = workbook.Sheets[this.innerText];
                        if (Object.keys(sht).length > 2) {
                            var htm = XLSX.utils.sheet_to_html(sht);
                            //默认输出有多余信息,以下用正则提取 table 内容,也可以直接输出 htm
                            var sheets = /<table>(.+?)<\/table>/gi.exec(htm);
                            $("#sheet").html(sheets[0]);
                        } else {
                            $("#sheet").html('');
                            alert(this.innerText + ' 内容为空');
                        }
                    });
                    $("a:first").click();
                };
            }
        });

        //导出 html 表格为 excel 文件
        function table2excel() {
            var tbl = $('#sheetName')[0];
            if (!tbl) return;
            var sht = XLSX.utils.table_to_sheet(tbl);
            var blob = sheet2blob(sht);
            openDownloadDialog(blob, $("#filesName").text());
        }

        //将一个 sheet 转成最终的 excel 文件的 blob 对象,利用 URL.createObjectURL 下载
        function sheet2blob(sheet, sheetName) {
            sheetName = sheetName || 'sheet1';
            //生成 excel 的配置项
            var workbook = {
                SheetNames: [sheetName],
                Sheets: {}
            };
            workbook.Sheets[sheetName] = sheet;
            var wopts = {
                bookType: 'xlsx', //要生成的文件类型
                bookSST: false,  //是否生成 Shared String Table
                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;
        }

        //生成下载连接 download
        function openDownloadDialog(url, saveName) {
            if (typeof url == 'object' && url instanceof Blob) url = URL.createObjectURL(url);
            var aLink = document.createElement('a');
            aLink.href = url;
            aLink.download = saveName || '';
            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);
        }
    </script>
</body>
</html>
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐