Excel 模板下载功能 + 前后端解析 Excel 文件代码封装 + 前端上传 Excel 至数据库(SpringBoot + Vue 版)
Posted 无恙_z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Excel 模板下载功能 + 前后端解析 Excel 文件代码封装 + 前端上传 Excel 至数据库(SpringBoot + Vue 版)相关的知识,希望对你有一定的参考价值。
最近做需求时遇到一个可向导的文件上传功能,现在做完了来分享下,基本能满足大伙80%的需求了
一、Excel 模板下载功能
后端代码(这是07版的Excel,需要03版的修改 XSSFWorkbook workbook = new XSSFWorkbook(fis);
这行代码即可):
public void download(HttpServletResponse response) throws IOException {
FileInputStream fis = new FileInputStream("文件路径");
ServletOutputStream out = null;
try {
XSSFWorkbook workbook = new XSSFWorkbook(fis);
response.setContentType("application/binary;charset=ISO8859-1");
String fileName = java.net.URLEncoder.encode("模板文件名字", "UTF-8");
response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xlsx");
out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件输出流
fis.close();
}
return;
}
前端代码:
main.js:
引入跨域请求依赖axios
import axios from 'axios'
挂载axios
Vue.prototype.$http = axios
设置访问根路径
axios.defaults.baseURL = "http://localhost:端口号看后端"
JS代码:
downloadFile() {
this.$http({
method: "get",
headers: {
"content-type": "application/json", // 默认值
Authorization: "Bearer " + sessionStorage.getItem("access_token"),
},
url: '后端接口地址',
params: {'name':'Jack'},
responseType: "blob",
}).then(function (res) {
let blob = new Blob([res.data]); // { type: "application/vnd.ms-excel" }
let url = window.URL.createObjectURL(blob); // 创建一个临时的url指向blob对象
// 创建url之后可以模拟对此文件对象的一系列操作,例如:预览、下载
let a = document.createElement("a");
a.href = url;
a.download = "上传模板.xlsx";
a.click();
// 释放这个临时的对象url
window.URL.revokeObjectURL(url);
}).catch(function (res) {
console.log("error", res);
});
}
二、前端解析 Excel 并展示在页面的功能(需要去下载xlsx 依赖)
html:
按钮部分:
<el-upload action accept=".xlsx, .xls" :auto-upload="false" :show-file-list="false" :on-change="handle">
<el-button slot="trigger" type="primary">选取EXCEL文件</el-button>
</el-upload>
数据展示部分:
<div v-show="show">
<el-table :data="dataList" stripe style="width:100%" :height="height" border>
<el-table-column type="index" width="50" align="center"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" width="180" align="center"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" width="100" align="center"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" width="180" align="center"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" width="90" align="center"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" align="center" width="120"></el-table-column>
<el-table-column prop="按需填写" label="按需填写" align="center" width="100"></el-table-column>
</el-table>
</div>
JS:
data(){
return {
dataList: [],
show: false
}
},
methods: {
async handle(ev) {
let file = ev.raw; // 获取上传的文件
if(!file) return;
// 隐藏表格
this.show = false;
// 读取文件中的数据
let data = await readFile(file);
// workbook:创建一个EXCEL表,并读取二进制数据,worksheet:默认拿第一张表的数据
let workbook = xlsx.read(data,{type:'binary'}), worksheet = workbook.Sheets[workbook.SheetNames[0]];
// 数据转JSON格式
data = xlsx.utils.sheet_to_json(worksheet);
// 把读取出来的数据变为对应后端的字段
let arr = [];
data.forEach(item => {
let obj = {};
for(let key in character){
if(!character.hasOwnProperty(key)) break;
let v = character[key], text = v.text, type = v.type;
v = item[text] || "";
type === "string" ? (v = String(v)) : null;
type === "number" ? (v = Number(v)) : null;
obj[key] = v;
}
arr.push(obj);
});
// 解析完毕后展示数据
this.show = true;
this.dataList = arr;
},
}
三、前端上传 Excel 至数据库
后续就给核心实现代码了
// 将数据一条一条传给后端
let n = 0;
let send = async () => {
if(n > this.dataList.length - 1){
this.$message({
message: "亲,文件已经上传完毕!",
type: 'success',
showClose: true
});
this.show = false;
return;
}
let body = this.dataList[n];
const {data:res} = await this.$http.post("后端接口地址",body);
if(res=="success"){
n++;
}
send();
};
send();
四、后端读取 Excel 工具类
/* 封装一个读取文件的工具类 */
public void read(FileInputStream inputStream) throws Exception{
// 1、创建工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 2、获取表
Sheet sheet = workbook.getSheetAt(0);
// 3、获取数据
int rowCount = sheet.getPhysicalNumberOfRows();
for(int rowNum = 1; rowNum < rowCount; rowNum++){
Row rowData = sheet.getRow(rowNum);
if(rowData != null){
//获得该行的列的数目
int lineCount = rowData.getPhysicalNumberOfCells();
for(int lineNum = 0; lineNum < lineCount ;lineNum++){
System.out.print("第" + rowNum +"行,第" + lineNum +"列:");
Cell cell = rowData.getCell(lineNum);
//判断数据类型
if(cell != null){
CellType cellType = cell.getCellTypeEnum();
switch (cellType){
case STRING:
System.out.println("字符串:" + cell.getStringCellValue()); break;
case BOOLEAN:
System.out.println("布尔:" + cell.getBooleanCellValue()); break;
case BLANK:
System.out.println("空"); break;
case ERROR:
System.out.println("没有该数据类型"); break;
case NUMERIC:
//如果是日期就直接输出,否则就装换为String,然后输出
if(HSSFDateUtil.isCellDateFormatted(cell)){
System.out.println("时间:"+new DateTime(cell.getDateCellValue()).toString("yyyy-MM-dd"));
}else{
cell.setCellType(CellType.STRING);
System.out.println("整型:" + cell.toString()); break;
}
default:
System.out.println("其他位置没有数据");break;
}
}
}
}
}
inputStream.close();
}
以上是关于Excel 模板下载功能 + 前后端解析 Excel 文件代码封装 + 前端上传 Excel 至数据库(SpringBoot + Vue 版)的主要内容,如果未能解决你的问题,请参考以下文章
Excel 模板下载功能 + 前后端解析 Excel 文件代码封装 + 前端上传 Excel 至数据库(SpringBoot + Vue 版)
从零开始搭建django前后端分离项目 系列五(实战之excel流式导出)
若依管理系统前后端分离版基于ElementUI和SpringBoot怎样实现Excel导入和导出