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流式导出)

将列表导出成excel表格图片下载(vue中使用)

若依管理系统前后端分离版基于ElementUI和SpringBoot怎样实现Excel导入和导出

关于springboot通过jxls用模板导出excel的前后台实现

HBuilder X怎么和pycharm前后端连接?