场景
最近公司开了个新项目,需要在线做财务损益报表,经调研需要支持如下:
功能
- Excel报表的导入导出
- 报表的数据存档
- 在线编辑公式
- sheet 和单元格的权限控制(与系统权限挂钩)
- 多人同时编辑
经过技术选型,目前定位了通过 SpreadJS 实现。并与 SpreadJS 工程师进行了多轮电话沟通(再次感谢 Spread 工程师的细心回答)。
(注:在今年 8 月份,SpreadJS 最新版已经提供了 Vue 组件的支持,可自行选择官方 Demo,本文中实现的是采用非 Vue 组件集成的方式。)
本文初步实现 1、2、3 的需求,并在文章最后附注 4、5 的实现思路希望能帮到你们。
实现后效果如下:
实现步骤如下
1、环境介绍
1.后台:spring boot
2.前台:vue、vue-element、webpack、iview
3.插件:SpreadJS V12
2、 SpreadJS 插件下载
操作步骤如下图:填写完成后会收到官方发送的邮件。
下载后目录结构如下:
3、插件初始化
首先将下载后的文件中的 css 和 js 提取出来放到前端项目的 static 目录下面,如下图:
其次在项目根路径index.html中全局引入Spread插件的JS和CSS,如下图红色标记的内容。
4、代码实现
思路如下:
4.1 定义div 承载 SpreadJS 的 Canvas 视图
<div ref="excelView" id="excelView" :style="spreadStyle"></div>
4.2 在 default 对象中初始化 Spread 和 excelIo 对象,并在 mounted 生命周期函数中初始化,代码结构见图片1:
4.3 定义文件上传组件,可采用 ivew 的上传组件或定义原生的 <input type="file"/>
,本文采用的是原生的 html 文件上传。
(注:不要采用 Vue-element 的上传组件,因为获取到的文件对象类型不适配 SpreadJS 格式要求,请自行 console 打印查看效果)
4.4 构建 FormData 对象,将文件以及文件名称附加进去,并通过 axios 上传到后台指定方法中,代码见图二:
4.5 编写后台代码接收前台传递的文件,并存档到文件服务器且在关系型数据库中添加标记,记录文件在服务器的路径。
整体前端代码如下:
<template xmlns="http://www.w3.org/1999/html" xmlns:v-on="http://www.w3.org/1999/xhtml">
<div class="app-container pull-auto">
<basic-container>
<div class="filter-container crud-menu">
<div class="crud-menu_left">
<input type="file" class="form-control" id="upload_file" name="upload_file" accept=".xlsx"
style="display: none;" @change='changeExcel'>
<Input placeholder="请选择文件..." v-model="fileName" id="upload_file_tmp" style="width: 250px"
onclick="upload_file.click();" readonly/>
<Button type="primary" icon="md-arrow-round-up" @click="selectExcel">浏览</Button>
<Button type="primary" icon="md-arrow-round-down" @click="saveExcel">导出</Button>
<Button type="primary" icon="ios-egg" @click="saveTemplate">保存模板</Button>
</div>
</div>
<div ref="excelView" id="excelView" :style="spreadStyle"></div>
</basic-container>
</div>
</template>
<style scoped>
</style>
<script>
import axios from '@/router/axios'
export default {
data () {
return {
fileName: "",
excelIo: {},
spread: {},
spreadStyle: {
width: '100%',
height: '430px'
}
};
},
mounted () {
this.spread = new GC.Spread.Sheets.Workbook(document.getElementById("excelView"), {sheetCount: 1});
this.excelIo = new GC.Spread.Excel.IO();
},
methods: {
//上传EXCEL
upExcel(){
var excelFile = document.getElementById("upload_file").files[0];
this.excelIo.open(excelFile, (json) => {
var workbookObj = json;
this.spread.fromJSON(workbookObj);
}, function (e) {
alert('文件读取失败,仅支持xlsx类型');
});
},
//选择文件
selectExcel(){
upload_file.click();
},
changeExcel(){
var excelFile = document.getElementById("upload_file").files[0];
this.fileName = document.getElementById("upload_file").files[0].name;
this.upExcel();
},
//保存EXCEL
saveExcel(){
//生成时间戳
var fileName = new Date().getTime() + '.xlsx';
var json = this.spread.toJSON();
this.excelIo.save(json, (blob) => {
saveAs(blob, fileName);
}, function (e) {
console.log(e);
});
},
//保存模板
saveTemplate(){
//生成时间戳
var fileName = new Date().getTime() + '.json';
var json = this.spread.toJSON();
var jsontext = JSON.stringify(json);
//前台保存
saveAs(new Blob([jsontext], {type: "text/plain;charset=utf-8"}), fileName);
//保存后台
let formData = new FormData();
var thefile = document.getElementById("upload_file").files[0];
formData.append("file", thefile);
formData.append("fileName", thefile.name);
axios.post('/admin/excelup/doImport', formData).then(function (response) {
alert("模板保存成功");
}).catch(function (error) {
alert("上传失败");
console.log(error);
});
}
}
}
</script>
最后为以下两个需求提供下解决思路:
- sheet 和单元格的权限控制(与系统权限挂钩) spreadjs支持sheet的隐藏与展示功能,通过前台获取后台传递的权限表示,在spreadjs 对象初始化的时候进行 api调用控制。
- 多人同时编辑 首先,spreadjs是不提供此类功能,需要自己定制化开发,实现思路是 多人同时编辑时,根据spreadjs 提供的事件或脏数据功能与后台进行接口交互,然后通过websocket通信将数据同步到其他端。
作者:T_T海
链接:https://www.jianshu.com/p/0152c6b73884
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。