产品说要让excel在线编辑,我是这样做的。
背景
最近公司项目有需求, 某导入功能, 想让客户选完excel文件, 直接将加载到web的excel编辑器中, 修改、确认, 之后上传导入。
效果查看
选择
- Luckysheet(dream-num.github.io/LuckysheetD…) ,一款纯前端类似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不稳定, 有时候很慢,还是建议,拉他的仓库,然后打个包,传到自己静态资源库, 来使用
npm run build
后dist
传上去使用
二、指定容器
<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要的格式
安装转换工具
npm install luckyexcel
使用
// After getting the xlsx file
LuckyExcel.transformExcelToLucky(file,
function(exportJson, luckysheetfile){
// exportJson就是转换后的数据
},
function(error){
// handle error if any thrown
}
4、将转换后的数据创建表格
// 将拿到的数据创建表格
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', // 用户名
}
});
完整代码
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; }
最后
妥妥的都是站在巨人的肩膀上
求赞
作者:浏览器API调用工程师
来源:juejin.cn/post/7221368910139342907
来源:juejin.cn/post/7221368910139342907