最近公司项目有需求, 某导入功能, 想让客户选完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不稳定, 有时候很慢,还是建议,拉他的仓库,然后打个包,传到自己静态资源库, 来使用
clone 这个仓库 gitee.com/mengshukeji…
npm run build后dist 传上去使用。
二、指定容器这个是挂载 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)
}
这个是官方文档里推荐的转换包
github.com/dream-num/L…
安装转换工具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() 获取表数据
arduino
复制代码
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的大佬们。
那么你们说产品下次是不准备搞协同编辑?
欢迎各位评论区交流
作者:浏览器API调用工程师_Taylor
链接:https://juejin.cn/post/7221368910139342907
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。