使用js-xlsx简单实现一个导入excel

6,965 阅读2分钟

使用js-xlsx之前需要下载,地址如下 github.com/SheetJS/js-…

vue项目推荐使用xlsx-js-style

因为是老项目,所以我用的是jquery,css库是bootsharp。

需求是点击按钮实现上传excel转换成表格,代码如下

html

 <input class="btn btn-file" type="file" data-type="2" value="导入Excel"></input>
 <button class="btn btn-danger btn-express" type="button">导入Excel</button>
 <table id="demo"  class="table"></table>

js

 $(".btn-express").on("click", function (e) {//将input[file]隐藏,点击按钮才触发上传文件
        $(".btn-file").trigger("click")
  })
  
   $(".btn-file").on("change", function (ev) {//当文件上传
        // console.log(ev.target.files)
        var reader = new FileReader();
        reader.onload = function (e) {
            try {
                var data = e.target.result;
                var workbook = XLSX.read(data, { type: 'binary' });
                var sheetNames = workbook.SheetNames; // 工作表名称集合
                var worksheet = workbook.Sheets[sheetNames[0]]; // 只读取第一张sheet
                var html = XLSX.utils.sheet_to_html(worksheet);//解析成html
                console.log(html)
                $("#demo").html(html)//将解析的html放入表格
            } catch (err) {
                console.log(err)
                Anim.msg("文件类型不正确");
                return false;
            }

        };
        reader.readAsBinaryString(ev.target.files[0]);

    })

解析

读取excel需要通过XLSX.read(data, {type: type})方法来实现,返回一个叫WorkBook的对象,type主要取值如下:

  • base64: 以base64方式读取;
  • binary: BinaryString格式(byte n is data.charCodeAt(n))
  • string: UTF8编码的字符串;
  • buffer: nodejs Buffer;
  • array: Uint8Array,8位无符号数组;
  • file: 文件的路径(仅nodejs下支持);

返回的格式如图:

可以使用插件自身写好工具类XLSX.utils来对worksheet进行解析,常用的方法如下:

  • XLSX.utils.sheet_to_csv:生成CSV格式
  • XLSX.utils.sheet_to_txt:生成纯文本格式
  • XLSX.utils.sheet_to_html:生成HTML格式
  • XLSX.utils.sheet_to_json:输出JSON格式

通过sheet_to_json解析会返回数组,html虽然会返回html格式,但也会把html,meta,body给打印出来

项目用到的是jq+layUI 完整代码如下:

html:

   <div class="title">
            <span>寄件信息 :</span>
            <input class="btn btn-file" name="upfile" type="file" data-type="2" value="导入Excel"></input>
            <button class="btn btn-danger btn-express" type="button">导入Excel</button>
            <span class="download">
                <a href="__PUBLIC__/static/images/寄件模板.xlsx">下载寄件导入模板</a>
            </span>
        </div>

        <table id="demo" class="table table-bordered">
            <thead></thead>
            <tbody></tbody>
        </table>
        <div class="box-footer">
            <div>合计运费:<span style="color: red"><span class="sumNum">0</span></span></div>
            <div style="text-align: center;">
                <button class="btn btn-footer reset" type="button">重置</button>
                <button class="btn btn-footer save" type="button">提交订单</button>
            </div>
        </div>

js:

    var fileExcel = null;//需要发送的file
    var skipType=1//订单类型
    var tbodyArr=null
    //获取传递过来的excel
    $(".btn-express").on("click", function (e) {
        $(".btn-file").trigger("click")
    })
        //触发上传excel
    $(".btn-file").on("change", function (ev) {
        var files = new FormData();
        files.append("file", ev.target.files[0])
        files.append("kdid", $("#expressType").val())
        $.ajax({
            url: "{上传upload接口}",
            type: "POST",
            data: files,
            async: false,
            cache: false,
            contentType: false,
            processData: false,
            success: function (returndata) {
                if (returndata.success == false) {
                    layer.msg(returndata.m, {
                        time: 1000 //1秒关闭(如果不配置,默认是3秒)
                    }, function () {
                        location.reload();
                    });
                } else {
                    var arr=returndata.d
                    tbodyArr=returndata.d
                     var  shipSum=0//运费总和
                    // console.log(arr)
                   
                    for(var i=0;i<arr.length;i++){
                        shipSum+=parseFloat(arr[i].M)
                    }
                    $(".sumNum").text(shipSum)
                }
            },
            error: function (returndata) {

            }
        });
        // return false;
        var files = ev.target.files
        var rawFile = files[0] // only use files[0]
        fileExcel = files[0]
        if (!rawFile) return
        var reader = new FileReader();
        reader.onload = function (e) {
            var msg = ""
            loading = layer.load(1, {
                shade: [0.1, '#000'] //1透明度的白色背景
            });
            try {
                var data = e.target.result;
                var workbook = XLSX.read(data, { type: 'binary' });
                var firstSheetName = workbook.SheetNames[0]
                var worksheet = workbook.Sheets[firstSheetName]
                var headers = getHeaderRow(worksheet)//表头
                var results = XLSX.utils.sheet_to_json(worksheet);//表主体
                setThead(headers)
                setTbody(tbodyArr)
                $(".box-footer").show()
                if (reader.onload) {
                 reader.onload = null
                 }
                // console.log(headers, results)
                layer.closeAll('loading');
            } catch (err) {
                console.log(err)
                Anim.msg("文件类型不正确");
                layer.closeAll('loading');
                return false;
            }

        };
        reader.readAsBinaryString(rawFile);
    })
    
       //渲染表格thead
    function setThead(headers) {
        headers.push("运费")
        $("#demo thead").html("")
        if (headers.length == 0) {
            return false
        }
        var tr = $("<tr></tr>")
        for (var i = 0; i < headers.length; i++) {
            var td = $("<td data-index=" + i + ">" + headers[i] + "</td>")
            tr.append(td)
        }
        $("#demo thead").append(tr)
    }
    //渲染表格tbody
    function setTbody(data) {
        $("#demo tbody").html("")
        if (data.length == 0) {
            return false
        }
        for (var j = 0; j < data.length; j++) {
            var tr = $("<tr data-id=" + j + "></tr>")
            for (key in data[j]) {
                var item=data[j][key]?data[j][key]:''
                var td = $("<td>" + item+ "</td>")
                tr.append(td)
            }
            $("#demo tbody").append(tr)
        }


    }
    //对数据进行过滤
    function getHeaderRow(sheet) {
        var headers = []
        var range = XLSX.utils.decode_range(sheet['!ref'])
        var C
        var R = range.s.r
        /* start in the first row */
        for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
            const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
            /* find the cell in the first row */
            let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
            if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
            headers.push(hdr)
        }
        return headers
    }

最终结果如下:

如果本篇文章有什么没有表达好的地方请见谅(ˇˍˇ)