lucksheet表格操作插件的使用

 实现导入、导出、存储、回显

项目地址:https://gitee.com/fei-feather-all-over-the-sky/lucksheet-use

将lucksheet表格数据以elementui格式呈现

效果图:

前提 是拿到lucksheet保存的excel格式文件  ,再通过sheetjs解析

sheetjs:https://github.com/SheetJS/sheetjs#the-zen-of-sheetjs

1.单独拿到表头数据

主要是给数据添加label 和prop属性 用来在table中显示

获取到后台返回的表头数据后,二次处理格式调用以下方法;如果不确定级别可以使用递归来写;使用titleArr盛放 末级表头,用于表格内容与表头一一对应。

   /* 操作表头 */
        handleTitle(arr){
            arr.forEach(item=>{
                item.label = item.title;
                item.prop = `prop${item.id}`;

                if(!item.child || item.child.length===0){
                    this.titleArr.push(`prop${item.id}`)
                }

                if(item.child && item.child.length>0){
                    this.handleTitle(item.child);
                }
            })
        },



//数据格式
[
    {
        "title": "a", 
        "id": 1, 
        "child": [
            {
                "title": "a1", 
                "id": 2
            }
        ]
    }, 
    {
        "title": "b", 
        "id": 3, 
        "child": [
            {
                "title": "b1", 
                "id": 4
            }
        ]
    }
]

 

2.处理除表头外其他数据

解析为一行一行的数据,再处理合并信息,我们拿到的是一个Excel表格,所以得先解析数据。接收来得是blob格式数据。此代码中把表头固定为2行做的。

       getExcelFile(res){
            let _this = this;
            let fileName = "实验室测试数据.xlsx"
            if(res.headers["content-disposition"]){
                fileName = res.headers["content-disposition"].split("=")[1];
            }

            fileName = decodeURI(fileName); //文件名称解码
            fileName = fileName.replace(/\+/g, ""); //文件名称修改
            let a = fileName.split('.');
            this.excelTitle = a[0];   //文件名称


            let file = new File([res.data], fileName);

            const reader = new FileReader();
            reader.readAsBinaryString(file);  //以二进制读取
            reader.onload = function(){
                const excelFile = XLSX.read(this.result, {  //sheetjs插件
                    type: 'binary'
                });
                console.log("====excelFile====",excelFile);
                _this.resultData = _this.handleData(excelFile.Sheets,_this.titleArr)
                console.log("====this.resultData====",_this.resultData);
            }

        },
/* 整理表格内容 */
        handleData(sheets,title) {
            let sheetsFinal = []
            let sheetsKeys = Object.keys(sheets)
            for (let i = 0; i < sheetsKeys.length; i++) {
                let sheet = sheets[sheetsKeys[i]]
                const arr = [];
                this.handleMerge(sheet['!merges'],arr)
                this.excelMergeData.push(arr);  // 合并数据

                console.log(this.excelMergeData,"====excelMergeData")
                sheetsFinal.push(
                    {
                        sheetName:sheetsKeys[i],
                        data:this.handleSheet(sheet,title)
                    }

                )

            }
            return sheetsFinal
        },
        /* 将数据按行解析出来  */
        handleSheet(sheet,title) {
            const heardRows = 2;   //表头行数
            let sheetDataArr = [];    //每个工作表的数据
            if(!sheet['!ref']){
                return sheetDataArr
            }
            let totleRows = this.screenRows(sheet);    //有效行
            let columnArr = this.screenColumn(sheet);   //有效列
            if(title && title.length>0 && title.length!==columnArr.length){
                // alert("标题列数与内容列数不符")
                return []
            }
            for (let i = heardRows+1; i <= totleRows; i++) {  /* 循环行 只循环除表头之外的数据 heardRows:表头所占行数*/
                let obj = {};
                for (let j = 0; j < columnArr.length; j++) {    /* 循环列 */
                    let key = title && title.length>0?title[j]:columnArr[j];

                    if (sheet[columnArr[j] + i]) {
                        obj[key] = sheet[columnArr[j] + i].w;
                    }else{
                        obj[key] = "";
                    }

                }
                sheetDataArr.push(obj)

            }

            return sheetDataArr

        },
        /* 处理合并信息 */
        handleMerge(merge,arr){
            if(!merge){
                return
            }
            merge.forEach((item,index)=>{
                const start = item.s;
                const end = item.e;

                if(start.r>1){
                    start.r = start.r - 2;    // 减去前两行标题
                    end.r = end.r - 2;    // 减去前两行标题
                    const key = `${start.c}_${start.r}`;   "列_行"
                    const obj1 = {}

                    obj1[key] = {
                        cs: end.c - start.c===0?1:end.c - start.c+1,  //列合并数
                        rs: end.r - start.r===0?1:end.r - start.r+1,  //行合并数
                    }
                    arr.push(obj1)
                    for(let i=start.r+1;i<end.r+1;i++){     //合并时需要去掉的单元格  按行
                        const key = `${start.c}_${i}`;   "列_行"
                        const obj1 = {}
                        obj1[key] = {
                            cs: 0,  //列合并数
                            rs: 0,  //行合并数
                        }
                        arr.push(obj1)
                    }
                    for(let i=start.c+1;i<end.c+1;i++){     //合并时需要去掉的单元格  按列
                        const key = `${i}_${start.r}`;   "列_行"
                        const obj1 = {}
                        obj1[key] = {
                            cs: 0,  //列合并数
                            rs: 0,  //行合并数
                        }
                        arr.push(obj1)
                    }




                }

            })

        },
        /* 整理出有效列 : 即如果没有数据则不统计*/
        screenColumn(sheet){   //过滤列
            let sheetKeys = Object.keys(sheet)
            let columnArr = []
            if(!sheet['!ref']){
                return columnArr;
            }
            let range = XLSX.utils.decode_range(sheet['!ref'])
            for (let c = range.s.c; c <= range.e.c; c++) {
                const columnName = XLSX.utils.encode_col(c);
                const isExist = sheetKeys.some(item=>{
                    return item.replace(/[1-9]/g,"")==columnName
                })
                if(!isExist){
                    break;
                }
                columnArr.push(columnName)
            }
            return columnArr;
        },
        /* 整理出有效行 : 即如果没有数据则不统计*/
        screenRows(sheet){
            let sheetKeys = Object.keys(sheet)
            let totleRows=0;
            const reg = /[1-9]/g;

            for(let key of sheetKeys){
                if(key.indexOf("!")==-1){

                    const number = key.match(reg)?key.match(reg).join("")*1:0;
                    totleRows = Math.max(totleRows,number);
                }
            }
            return totleRows
        }

3.页面显示 

依靠table的  span-method 

      <div  v-if="resultData ||  resultData.length>0" v-for="(sheet,index) in resultData" :key="index">
                    <div v-if="resultData.length>1" style="padding: 10px;color:#495BA6;font-weight: 700">
                        {{sheet.sheetName}}
                    </div>
                    <el-table class="mytable"
                              :data="sheet.data" :header-cell-style="{borderColor:'#AE91F5',color:'#6649A6',background:'#E1E7FF'}" :cell-style="{borderColor:'#CED4EB',color:'#333'}" :span-method="objectSpanMethod(index)" border
                              style="width: 100%">
                        <el-table-column  v-for="(item,index) in excelTableTitles" :key="Math.random()" align="center"  min-width="120"
                                          :prop="item.prop"
                                          :label="item.label"
                        >
                            <el-table-column  v-for="(val,index) in item.child" :key="Math.random()" align="center"  min-width="120"
                                              :prop="val.prop"
                                              :label="val.label"
                            >
                                <el-table-column  v-for="(val1,index) in val.child" :key="Math.random()" align="center"  min-width="120"
                                                  :prop="val1.prop"
                                                  :label="val1.label"
                                >

                                </el-table-column>
                            </el-table-column>
                        </el-table-column>

                    </el-table>
                </div>
     
objectSpanMethod(index) {

            return ({ row, column, rowIndex, columnIndex })=>{
                const arr = this.excelMergeData[index];
                const key = `${columnIndex}_${rowIndex}`;

                if(arr.length>0){
                    let flag = false;
                    for(let item of arr){
                        console.log(key,item)
                        if(item[key]){
                            flag=true;
                            console.log(key,[item[key].rs,item[key].cs])
                            return [item[key].rs,item[key].cs]    // [行合并数,列合并数]
                        }
                    }
                    if(!flag){
                        return [1,1]
                    }
                }
                else{
                    return [1,1]
                }


            }

        },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值