乐趣区

关于前端:产品说要让excel在线编辑我是这样做的

背景

最近公司我的项目有需要, 某导入性能, 想让客户选完 excel 文件, 间接将加载到 web 的 excel 编辑器中, 批改、确认, 之后上传导入。

以此来记录我的开发过程。

成果查看

抉择

  • Luckysheet(https://dream-num.github.io/LuckysheetDocs/zh/guide/#demo),一款纯前端相似 excel 的在线表格,功能强大、配置简略、齐全开源。
  • x-sheet

就看到了这两个, 最初抉择了Luckysheet, 看他的 star 比拟多, 哈哈。

需要实现剖析

剖析一下整个流程。

其实大体就两步,搞进去,抽离进去。

一、加载本地 excel 到 web 编辑器中

1、拿到本地 excel 文件流

2、转换为 Luckysheet 要的格局

3、new 一个 Luckysheet 实例, 挂在到对应标签上

实现以上就把 excel 加载进去了, 显示进去了。

在线编辑的事就是这个库帮咱们搞定了.

二、从 web 编辑器导出文件流 上传

等客户在线编辑实现, 就须要点击一个按钮,导出文件流,确认并调接口上传

1、获取 Luckysheet里工作表的数据

luckysheet.getAllSheets()

2、将数据加工并应用 xlsx 或者 exceljs 导出文件流

导出为为 arrayBuffer, 再将 arrayBuffer 转为 Blob

3、调后端接口上传

开发实际

一、引入 lucky-sheet

有两种形式

1、官网文档里的 cdn

这种加载有点慢

<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/plugins.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/css/luckysheet.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/assets/iconfont/iconfont.css' />
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/luckysheet.umd.js"></script>

2、本人打包, 传到 oss, 引入(举荐)

第一种第三方的 cdn 不稳固, 有时候很慢,还是倡议,拉他的仓库,而后打个包,传到本人动态资源库, 来应用

clone 这个仓库 https://gitee.com/mengshukeji/Luckysheet

npm run builddist 传上去应用。

二、指定容器

这个是挂载 luckysheet 的容器, 它确保了被展现在何处。

id="luckysheet" 能够自定义, 和上面提到的
container: 'luckysheet' 保持一致即可

<div id="luckysheet"></div>

三、导入本地文件

1、用 elment 的上传文件组件 抉择文件

然而这里不上传,仅仅是用它抉择文件拿到文件对象File

<div class="import-okr">
    <!-- ,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet -->
    <el-upload
        v-model:file-list="fileList"
        accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        class="upload-demo"
        :before-upload="beforeUpload"
        action="":show-file-list="false"
    >
        <button @click="uploadFile"> 上传数据 </button>
    </el-upload>
</div>

2、beforeUpload 办法拿到文件

const beforeUpload = (file) => {console.log(file)
}

3、将文件流转换为 lucky 要的格局

这个是官网文档里举荐的转换包

https://github.com/dream-num/Luckyexcel#es-import

装置转换工具
npm install luckyexcel
应用

file是文件对象, 回调函数里的 exportJson 是转换玩的 luckySheet 对象

// After getting the xlsx file
LuckyExcel.transformExcelToLucky(file, 
    function(exportJson, luckysheetfile){// exportJson 就是转换后的数据},
    function(error){// handle error if any thrown}

4、将转换后的数据创建表格

// 将拿到的数据创建表格
luckysheet.create({
    container: 'luckysheet', // 挂载的 dom 的 id 名
    data:exportJson.sheets,
    title:exportJson.info.name,
    userInfo:exportJson.info.creator,
    lang: 'zh', // 设定表格语言
    myFolderUrl: window.location.href,
    showtoolbarConfig: {
        pivotTable: false,  //'数据透视表'
        // protection: false, // '工作表爱护'
        print:false, // '打印'
        image: false, // 插入图片
    },
    showinfobar: false,
    options: {
        // 其余配置
        userImage:'http://qzz-static.forwe.store/public-assets/pgy_kj_pic_logo.png?x-oss-process=image/resize,m_fill,w_72,h_72', // 头像 url
        userName:'Lucky', // 用户名
    }
});

残缺代码

const beforeUpload = (file) => {console.log(file)
    // 转换工具, 将文件流转换为 lucky 要的格局
    LuckyExcel2.transformExcelToLucky(
        file,
        function(exportJson, luckysheetfile){
            isShowExcel.value = true
            console.log(exportJson)
            nextTick(() => {window.luckysheet.destroy();
                // 将拿到的数据创建表格
                luckysheet.create({
                    container: 'luckysheet', // luckysheet is the container id
                    data:exportJson.sheets,
                    title:exportJson.info.name,
                    userInfo:exportJson.info.creator,
                    lang: 'zh', // 设定表格语言
                    myFolderUrl: window.location.href,
                    showtoolbarConfig: {
                        pivotTable: false,  //'数据透视表'
                        // protection: false, // '工作表爱护'
                        print:false, // '打印'
                        image: false, // 插入图片
                    },
                    showinfobar: false,
                    options: {
                        // 其余配置
                        userImage:'http://qzz-static.forwe.store/public-assets/pgy_kj_pic_logo.png?x-oss-process=image/resize,m_fill,w_72,h_72', // 头像 url
                        userName:'Lucky', // 用户名
                    }
                });
            })
        },
        function(err){logger.error('Import failed. Is your fail a valid xlsx?');
        });
}

四、导出

1、利用 luckysheet.getAllSheets() 获取表数据

console.log(luckysheet.getAllSheets())

2、exceljs 将上述对象转换为 excel 文件流

import Excel  from 'exceljs'
// 导出 excel
const exportExcel  = async function (luckysheet) {// 参数为 luckysheet.getluckysheetfile()获取的对象
    // 1. 创立工作簿,能够为工作簿增加属性
    const workbook = new Excel.Workbook()
    // 2. 创建表格,第二个参数能够配置创立什么样的工作表
    luckysheet.every(function (table) {if (table.data.length === 0) return true
        const worksheet = workbook.addWorksheet(table.name)
        // 3. 设置单元格合并, 设置单元格边框, 设置单元格款式, 设置值
        setStyleAndValue(table.data, worksheet)
        setMerge(table.config.merge, worksheet)
        setBorder(table.config.borderInfo, worksheet)
        return true
    })
    // 4. 写入 buffer
    const buffer = await workbook.xlsx.writeBuffer()
    return buffer
}

3、写个办法,执行上述两步

// 保留文件
const onClickSaveFile = async ( ) => {console.log(luckysheet.getAllSheets())
    const buf = await exportExcel(luckysheet.getAllSheets())
    const blob = new Blob([buf]);
    // $emit('file', blob)
    handleUpload(blob)
}

4、上传办法

从上一步拿到文件, 利用 formData, 将生成的文件二进制流发给后端

const handleUpload = async(file) => {
    // isShowExcel.value = false
    const loading = ElLoading.service({
        fullscreen: true,
        text: '上传中,请稍等',
        background: 'rgba(0,0,0,0.1)'
    });
    try {const formData = new FormData()
        formData.append('file', file)
        // 伪代码
        const {code, data, message} = await IMPORT_OKR(formData)
        if(code === 1) {//...}
        loading.close()} catch (error) {console.log(error)
        loading.close()}
}

遇到问题

1、iconfont 抵触

lucky-sheet 这个我的项目里的 iconfont 类名和我我的项目里一样,导致有些被笼罩了.

解决: 将他我的项目里 iconfont 换成 lucky-sheet, 相干类名也全副替换, 而后从新打包,再引入,即可解决

2、lucky-sheet 层级不够高,无奈编辑

elmentui 和 antd 的一些组件层级比拟高,所以, 让 kucky 的层级更高即可

解决: 减少下述 css 即可

.luckysheet-input-box {z-index: 2000;} .luckysheet-cols-menu {z-index: 2001;}

用过 lucky-sheet 的敌人们还遇到了什么坑?评论区通知我

最初

妥妥的都是站在伟人的肩膀上,感激开发 luckySheet 的大佬们。

那么你们说产品下次是不筹备搞协同编辑?

欢送各位评论区交换

求赞

退出移动版