vue中使用js-xlsx导出excel文件(可以修改样式)

前端vue中使用js-xlsx导出excel文件(可以修改样式)

使用js-xlsx是因为有个需求是要把用户上传的xmind文件转excel文件导出,当时有点懵,在网上找了许多资料发现了前端有如下几种方法可导出excel文件 (方法有许多但原理都是一样的)

1.通过js的Blob与Object URL把html表格直接导出 参考此处

注意:只能导出为xls格式的excel文件,且实际导出的就是一个html文档。
但是因为导出的是html所以就可以在保留html表格原有的样式了。

2.使用ActiveXObject对象来创建excel文件写入数据导出 参考此处

注意:只能在ie下使用因为只有ie下有ActiveXObject对象

3.使用jquery的tabletoexcle.js库来导出 参考此处
4.使用js-xlsx来导出excel文件修改样式需要使用xlsx-style

vue中使用xlsx的详细步骤

  • 安装xlsx插件 (需要修改样式的话安装xlsx-style)
$ npm install --save xlsx
$ npm install --save xlsx-style
  • 在需要使用的vue文件中引入
import XLSX from "xlsx"

如果引入xlsx-style的话可能会报错:
This relative module was not found:
./cptable in ./node_modules/xlsx-style@0.8.13@xlsx-style/dist/cpexcel.js
我也不知道是啥问题一引入就报错 有点搞不懂 (有大佬知道可以回复下(*^
_^*))

后面找到原因了…: 是因为 在 ode_modulesxlsx-styledistcpexcel.js 807行 的 var cpt = require(’./cpt’ + ‘able’); 这里的require("./cptable") 其实没有这个文件 我参照了xlsx的cpexcel.js这个文件的 同一地方是 var cpt = cptable; 所以后面改成这个以后引入就没问题了 具体咋回事也不清楚。

如果引入没问题的这段可以跳过。。
  • 解决
    1.在index.html中引入它的源文件 路径 node_modulesxlsx-styledistxlsx.full.min.js
    2.需要把该文件放在static静态文件目录下才可以引入。

<script src="./static/xlsx.full.min.js"></script>

3.全局中有XLSX变量就引入成功了

  • 使用方法 调用downloadExl()传入数据
  • 主要功能代码 在vue中可自行修改

样式修改 参考文档

    // 下载功能
        function saveAs(obj, fileName) {
             var tmpa = document.createElement("a");
              tmpa.download = fileName || "未命名";
              // 兼容ie 
              if ("msSaveOrOpenBlob" in navigator) {
                window.navigator.msSaveOrOpenBlob(obj, "下载的文件名"+ ".xlsx");
              } else {
                tmpa.href = URL.createObjectURL(obj);
              }
              tmpa.click();
              setTimeout(function() {
                URL.revokeObjectURL(obj);
              }, 100);
        }
      // 模拟数据
        var data = [{"功能模块与路径":"\APP接口测试示例\登录接口","用例编号":"s_001","前置条件":"第一个为前置条件,最后一个为预期结果,需要带相应关键字","用例名称":"用例编写示例,用例必须有叶子结节","操作步骤":"操作步骤直接填写,每个步骤一行","预期结果":"用例必须有叶子结点","标记":"","优先级":"3","用例属性":"","编制人员":"","用例设计时间":"2019-02-15","备注":""},{"功能模块与路径":"","用例编号":"","前置条件":"","用例名称":"","操作步骤":"操作步骤需要按顺序排序","预期结果":"","标记":"","优先级":"","用例属性":"","编制人员":"","用例设计时间":"","备注":""},{"功能模块与路径":"\APP接口测试示例\登录接口\身份证类型登录","用例编号":"s_002","前置条件":"我是前置条件,需要“前置条件”为关键字","用例名称":"身份证登录","操作步骤":"1,操作步骤1,按次序排列","预期结果":"我是预期结果","标记":"","优先级":"3","用例属性":"","编制人员":"","用例设计时间":"2019-02-15","备注":""},{"功能模块与路径":"","用例编号":"","前置条件":"","用例名称":"","操作步骤":"2,操作步骤2","预期结果":"","标记":"","优先级":"","用例属性":"","编制人员":"","用例设计时间":"","备注":""},{"功能模块与路径":"","用例编号":"","前置条件":"","用例名称":"","操作步骤":"3,我是操作步骤3,按次序排列","预期结果":"","标记":"","优先级":"","用例属性":"","编制人员":"","用例设计时间":"","备注":""},{"功能模块与路径":"\APP接口测试示例\登录接口\身份证类型登录","用例编号":"s_003","用例名称":"用例名称一定要长-登录失败","操作步骤":"我是操作步骤","预期结果":"如果这个是预期结果,则上层为用例","标记":"","优先级":"3","用例属性":"","编制人员":"","用例设计时间":"2019-02-15","备注":""},{"功能模块与路径":"\APP接口测试示例\登录接口","用例编号":"s_004","用例名称":"账户类型登录","预期结果":"账户为空3","标记":"","优先级":"3","用例属性":"","编制人员":"","用例设计时间":"2019-02-15","备注":""}]
      // 配置文件类型
        const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true };
        function downloadExl(json, type) {
            var tmpdata = json[0];
            json.unshift({});
            var keyMap = []; //获取keys
            for (var k in tmpdata) {
                keyMap.push(k);
                json[0][k] = k;
            }
            var tmpdata = [];//用来保存转换好的json 
            json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
                v: v[k],
                position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
            }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
                v: v.v
            });
            var outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
            tmpdata["B1"].s = { font: { sz: 14, bold: true, color: { rgb: "FFFFAA00" } }, fill: { bgColor: { indexed: 64 }, fgColor: { rgb: "FFFF00" } } };//<====设置xlsx单元格样式
            tmpdata["!merges"] = [{
                s: { c: 1, r: 0 },
                e: { c: 4, r: 0 }
            }];//<====合并单元格 
            var tmpWB = {
                SheetNames: ['mySheet'], //保存的表标题
                Sheets: {
                    'mySheet': Object.assign({},
                        tmpdata, //内容
                        {
                            '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
                        })
                }
            };
            tmpDown = new Blob([s2ab(XLSX.write(tmpWB,
                { bookType: (type == undefined ? 'xlsx' : type), bookSST: false, type: 'binary' }//这里的数据是用来定义导出的格式类型
            ))], {
                    type: ""
                });
            saveAs(tmpDown, "下载的文件名" + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));
        }
      // 获取26个英文字母用来表示excel的列
        function getCharCol(n) {
            let temCol = '',
                s = '',
                m = 0
            while (n > 0) {
                m = n % 26 + 1
                s = String.fromCharCode(m + 64) + s
                n = (n - m) / 26
            }
            return s
        }
        function s2ab(s) {
            if (typeof ArrayBuffer !== 'undefined') {
                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;
            } else {
                var buf = new Array(s.length);
                for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
                return buf;
            }
        }
  • 最后贴个效果图


     
    effect.PNG

总结

其实以上都是参考网上查阅的一些资料 如有什么问题还望海涵 只是写下来就当做学习笔记了。。

原文地址:https://www.cnblogs.com/xinxihua/p/12623063.html