vue js-table2excel + xlsx 文件导入导出 (导出包含图片)

依赖包

需要安装以下这两个依赖包 js-table2excel 用于文件导出  xlsx 用于文件导入

npm i js-table2excel
npm i xlsx
文件导出
type值对应值
text文本类型
image图片类型可写宽和高

如果做文件的小批量导出不用转换base64 直接用http url即可 文件量或者图片过大可能会出现加载失败的情况 避免这个问题 是跑all方法去请求url资源转换成base64 再渲染就能够全部导出 转base64的时候做了一个图片压缩 不需要的可以去掉

        async getphoto() {
            const column = [
                {

                    title: 'ID',
                    key: 'id',
                    type: 'text'

                },
                {
                    title: '标准图片',
                    key: 'img-base64',
                    type: 'image',
                    width: 200,
                    height: 100
                },
                 {
                    title: '标准图片地址',
                    key: 'img',
                    type: 'text',
                },
              

            ]
            const data = _.cloneDeep(this.tableData);
            var datas = await this.Format(data)
            const excelName = '文件名字'
            console.log(datas, 'xxxy')        
            table2excel(column, datas, excelName)    //生成Excel表格,自动下载
        },
        async Format(res1) {
            this.startLoading()
            var list = res1
            let cytlist = []
            let cytlistindex = []
            for (let index = 0; index < list.length; index++) {
                let tp1 = list[index]["img"]
                if (tp1 && tp1.includes('range_file')) {
                    //我这里后台给的图片路径不全需要我自己拼一下 不用拼的直接写地址就行了
                    cytlist.push(await this.toBase64(this.mybaseUrl + '/media/' + tp1))
                    list[index]["img"] = this.mybaseUrl + '/media/' + tp1
                    cytlistindex.push(index)
                }
               
            }
            await Promise.all(cytlist).then(res => {
                for (let index = 0; index < cytlistindex.length; index++) {
                    list[cytlistindex[index]]["img-base64"] = res[index]
                }
            })
       
            return list;

        },
        getBase64(url, callback) {
            let _that = this
            var Img = new Image(),
                dataURL = '';
            Img.src = url + "?v=" + Math.random();
            Img.setAttribute("crossOrigin", 'Anonymous')
            Img.onload = function () {
                var canvas = document.createElement("canvas"),
                    width = Img.width,
                    height = Img.height;
                if (Math.max(width, height) > _that.maximg) {
                    if (width > height) {
                        canvas.width = _that.maximg;
                        canvas.height = _that.maximg * height / width
                    } else {
                        canvas.height = _that.maximg
                        canvas.width = _that.maximg * width / height
                    }
                } else {
                    canvas.width = width;
                    canvas.height = height;

                }

                canvas.getContext("2d").drawImage(Img, 0, 0, canvas.width, canvas.height);
                dataURL = canvas.toDataURL('image/jpeg');
                callback ? callback(dataURL) : null;
            };
        },
        toBase64(url) {
            return new Promise((resolve, reject) => {
                this.getBase64(url, (data) => {
                    resolve(data)
                })
            })
        },
文件导入

代码中掺杂着文本匹配Id 的逻辑 不需要的可以忽略 #@是个人习惯 可以换成别的 表格头文本描述和字段值的分隔符

const xlsx = require("xlsx");


async onChange(file) {
            /**
             * 1. 使用原生api去读取好的文件
             * */
            // console.log("原始上传的文件", file);
            // 读取文件不是立马能够读取到的,所以是异步的,使用Promise
            let dataBinary = await new Promise((resolve) => {
                // Web API构造函数FileReader,可实例化对象,去调用其身上方法,去读取解析文件信息
                let reader = new FileReader(); // https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
                // console.log("实例化对象有各种方法", reader);
                reader.readAsBinaryString(file.raw); // 读取raw的File文件
                reader.onload = (ev) => {
                    // console.log("文件解析流程进度事件", ev);
                    resolve(ev.target.result); // 将解析好的结果扔出去,以供使用
                };
            });

            // console.log(dataBinary,'xxx')
            // console.log("读取出的流文件", dataBinary);
            /**
             * 2. 使用xlsx插件去解析已经读取好的二进制excel流文件
             * */
            let workBook = xlsx.read(dataBinary, { type: "binary", cellDates: true });
            // excel中有很多的sheet,这里取了第一个sheet:workBook.SheetNames[0]
            let firstWorkSheet = workBook.Sheets[workBook.SheetNames[0]];
            // 分为第一行的数据,和第一行下方的数据
            const header = this.getHeaderRow(firstWorkSheet);
            // console.log("读取的excel表头数据(第一行)", header);
            const data = xlsx.utils.sheet_to_json(firstWorkSheet);
            const datayy = xlsx.utils.sheet_to_formulae(firstWorkSheet);
            //console.log(xlsx,'看看xlsx',datayy)
            //console.log("读取所有excel数据", data);
            let res = []
            let obj1 = Object.keys(this.viewoptions)
            let res1 = []
            //设置导出的模版时将表格头用#@分隔 这个看个人习惯 然后我这里还做了一个表格内容文本匹配id 不需要的可以忽略
            for (let i = 0; i < data.length; i++) {
                let str = {}
                let notfindid = false
                for (let j = 0; j < header.length; j++) {
                    if (header[j].includes('#@')) {
                        let temp = header[j].split('#@')
                        if (temp.length == 2) {
                            let idxmy = obj1.indexOf(temp[1])
                            if (idxmy != -1) {
                                let tttc = this.viewoptions[`${obj1[idxmy]}`][`${data[i][header[j]]}`]
                                // console.log(this.viewoptions[`${obj1[idxmy]}`], 'ycta', data[i][header[j]])
                                if (tttc) {
                                    str[temp[1]] = tttc
                                    //notfindid=false
                                } else {
                                    str[temp[1]] = data[i][header[j]]
                                    notfindid = true
                                }
                            } else {
                                str[temp[1]] = data[i][header[j]]
                            }
                            if (temp[1] == 'standard_pic') {
                                if (data[i][header[j]] == 'null' || !data[i][header[j]]) {
                                    str[temp[1]] = undefined
                                }
                            }

                        } else {
                            continue
                        }
                    }
                }
                str.notfindid = notfindid
                if (!notfindid) {
                    res1.push(str)
                }
                if (data.length == ansimg.length) {
                    //alert(1)
                    str.standard_pic = ansimg[i]
                }
                res.push(str)
            }
            this.tableData = res

            this.resdata = res1
        },
        getHeaderRow(sheet) {
            const headers = []; // 定义数组,用于存放解析好的数据
            const range = xlsx.utils.decode_range(sheet["!ref"]); // 读取sheet的单元格数据
            let C;
            const 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
                //console.log(hdr, C, 'popo')
                //let tempheader
                if (cell && cell.t) {
                    hdr = xlsx.utils.format_cell(cell);
                    /* tempheader=hdr.split('#@')
                     if(tempheader.length==2){
                         hdr=tempheader[1]
                     }*/
                }

                headers.push(hdr);
            }
            return headers; // 经过上方一波操作遍历,得到最终的第一行头数据
        },

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用vue-json-excel导出xlsx的步骤: 1.首先,安装vue-json-excel依赖包: ```shell npm install vue-json-excel --save ``` 2.在main.js中引入vue-json-excel并注册为全局组件: ```javascript import Vue from 'vue' import App from './App.vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import JsonExcel from "vue-json-excel"; // 引入vue-json-excel Vue.component("downloadExcel", JsonExcel); // 注册为全局组件 Vue.use(ElementUI); new Vue({ render: h => h(App), }).$mount('#app') ``` 3.在需要导出Excel的组件中,使用downloadExcel组件并传入数据和表头信息: ```html <template> <div> <download-excel :data="tableData" :columns="tableColumns" :filename="'excel文件名'" :sheetname="'sheet名称'" :title="'表格标题'" :autoWidth="true" :mergeCell="[]" > <el-button type="primary">导出Excel</el-button> </download-excel> </div> </template> <script> export default { data() { return { tableData: [ { name: '张三', age: 18, gender: '男' }, { name: '李四', age: 20, gender: '女' }, { name: '王五', age: 22, gender: '男' } ], tableColumns: [ { label: '姓名', field: 'name' }, { label: '年龄', field: 'age' }, { label: '性别', field: 'gender' } ] } } } </script> ``` 其中,data为需要导出的数据,columns为表头信息,filename为导出Excel文件名,sheetname为sheet名称,title为表格标题,autoWidth为是否自动调整列宽,mergeCell为需要合并的单元格信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值