1. 导入Excel表格

Java后端代码

一、导入easyExcel的jar包依赖

 <!-- excel 导入导出 --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.3</version></dependency>

二、创建对应的数据模型,字段需求相同时,可复用

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;/*** @ApiNote : 用于接收 解析 Excel 的行数据* 在类上的样式注解代表本类全局作用*/
@ContentRowHeight(26) // 内容的行高
@HeadRowHeight(30) //表头的行高
@Data
public class DrugsDTO {@ColumnWidth(16) //具体字段导出后表格的列宽@ExcelProperty(value = "药品编码")private String drugsCode;@ColumnWidth(26)@ExcelProperty(value = "药品名称")private String drugsName;@ColumnWidth(18)@ExcelProperty(value = "药品规格")private String drugsFormat;@ColumnWidth(14)@ExcelProperty(value = "药品剂型")private String drugsDosage;@ColumnWidth(14)@ExcelProperty(value = "药品类型")private String drugsType;@ColumnWidth(14)@ExcelProperty(value = "药品单价")private Double drugsPrice;@ColumnWidth(18)@ExcelProperty(value = "拼音助记码")private String mnemonicCode;@ColumnWidth(14)@ExcelProperty(value = "包装单位")private String drugsUnit;
}

三、创建读取excel表格的监听器

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import org.neuedu.entity.HisDrugs;
import org.neuedu.entity.dto.DrugsDTO;
import org.neuedu.service.IHisConstantCategoryService;
import org.neuedu.service.IHisDrugsService;
import org.springframework.beans.BeanUtils;import java.util.ArrayList;
import java.util.List;
@Slf4j //用于日志打印
public class DrugsDataListener extends AnalysisEventListener<DrugsDTO> {//注意:AnalysisEventListener不支持Spring 管理,需要通过构造的形式注入private IHisConstantCategoryService constantCategoryService;private IHisDrugsService drugsService;//通过构造器获取所需要的执行对象public DrugsDataListener(IHisConstantCategoryService constantCategoryService,IHisDrugsService drugsService){this.constantCategoryService = constantCategoryService;this.drugsService = drugsService;}//每隔1000条存储数据库,实际使用中可以3000条,然后清理list,方便内存回收private static final Integer BATCH_COUNT = 1000;//存储读取的行数据,用于批量插入数据库List<HisDrugs> list = new ArrayList<>();/*** @ApiNote 解析 excel 每一行数据都会调用的方法* @param drugsDTO 把excel 中的每一行数据注入到data 对象* @param analysisContext 上下文*/@Overridepublic void invoke(DrugsDTO drugsDTO, AnalysisContext analysisContext) {log.debug("读取的行数据:{}",drugsDTO);HisDrugs drugs = new HisDrugs();//转换处理,通过excel 中获取的药品剂型和药品类型,到数据库中查询对应的ID,用于入库Integer drugsDosageId = constantCategoryService.getIdByConstantCategoryName(drugsDTO.getDrugsDosage());if(drugsDosageId != -1){drugs.setDrugsDosageId(drugsDosageId);}Integer drugsTypeId = constantCategoryService.getIdByConstantCategoryName(drugsDTO.getDrugsType());if(drugsTypeId != -1){drugs.setDrugsTypeId(drugsTypeId);}//把 DrugsDTO 中的其他数据存储到 HisDrugs 对象中,注意:名称和类型匹配才会执行,不匹配则不管BeanUtils.copyProperties(drugsDTO,drugs);list.add(drugs);//达到BATCH_COUNT 了,需要去存储一次数据库,防止几万条数据在内存,容易OOMif(list.size() >= BATCH_COUNT){this.saveData();//存储完成清理listlist.clear();}}/*** @ApiNote 执行批量保存操作*/public void saveData(){log.debug("开始执行批量插入~");drugsService.saveBatch(list);log.debug("批量插入执行完毕~");}/*** @ApiNote excel 中的所有数据解析完毕后会执行的方法* @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {//这里也要保存数据,确保最后遗留的数据已存储到数据库if(list.size() > 0){this.saveData();}log.debug("所有数据解析完成!");}
}

四、Controller前端控制器代码

    /*** @ApiNote 非药品目录Excel文件导入* @param file excel文档* @return* @throws Exception*/@ApiOperation("非药品目录Excel文件导入")@ApiImplicitParam(name = "file",value = "excel文档",required = true)@PostMapping("/fileUpload")public ResponseEntity excelImport(MultipartFile file) throws Exception{//使用 阿里巴巴 提供的 EasyExcel 完成 Excel 读取EasyExcel.read(file.getInputStream(), DrugsDTO.class, new DrugsDataListener(constantCategoryService,drugsService)).sheet() //指定读取的 sheet ,sheet -> 表格.doRead();return ResponseEntity.ok("非药品目录导入成功");}

vue前端代码

五、axios异步请求的统一处理httpAxios.js

在判断请求方式为post或put的基础上,增加了文件上传的判断

import axios from 'axios'  //异步请求
import qs from 'qs' //用于post请求的数据转换
import router from "@/router" //页面跳转 replace  push
//elementUI中的按需加载 :Message用于消息提示,Loading 请求加载层
import {Loading,Message} from 'element-ui'// axios 全局配置
axios.defaults.timeout = 5000; // 5s没响应则认为该请求失败
// 配置请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.baseURL = '/api';  //跨域配置可以添加上它,就不用每一个请求都以api开头了let loadingInstance; //加载对象,设置为全局的对象
// 添加请求拦截器
axios.interceptors.request.use(request => {//TODO 开始请求,日志打印console.log("开始请求:",request.url,",参数:",JSON.stringify(request.params));//加载层:数据加载中。。loadingInstance = Loading.service({lock: true,text: '数据加载中,请稍后...',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'});//如果是post 或者 put 请求,需要做数据转换if (request.method === 'post' || request.method === 'put') {//如果是文件上传,则不需要进行数据转换//约定,如果是文件上传,则请求地址以 fileUpload 结尾let currentUrl = request.url.split('/')[request.url.split('/').length-1];if(currentUrl !== 'fileUpload'){//不是文件上传,才做处理request.data = qs.stringify(request.data)  //这里使用qs对data进行处理,转为json数据}}if(request.method === 'get'){//如果是下载,需要指定下载格式为 blob 或者二进制//约定,如果是文件下载,则请求地址以 downLoad 结尾let curUrl = request.url.split('/')[request.url.split('/').length - 1];if(curUrl === 'downLoad'){request.responseType = 'blob';return request; //这里对上传文件的api 不做传序列化处理}}return request;},err => {loadingInstance.close();Message.error('请求超时!');return Promise.reject(err)}
);
//添加响应拦截器
axios.interceptors.response.use(response => {//TODO 请求完毕数据输出,后续添加后端返回的对应状态判断console.log("请求完毕数据:",response.data);loadingInstance.close(); //关闭加载层// 这里是前后端分离,下载的时候需要通过下载链接来操作//把下载的 blob 数据转为 excelif(response.config.responseType === 'blob'){ // 下载excel类型let blob = new Blob([response.data],{type:'application/vnd.ms-excel;charset=utf-8'});let downloadElement = document.createElement('a');let href = window.URL.createObjectURL(blob); //创建下载的连接downloadElement.href = href;downloadElement.download = decodeURI(response.headers['content-disposition'].split('=')[1]); //处理文件名乱问题, 下载后文件document.body.appendChild(downloadElement);downloadElement.click(); //点击下载document.body.removeChild(downloadElement); //下载完成移除元素window.URL.revokeObjectURL(href); //释放掉blob对象return;}if (response.data.code === 200) {return response.data}else if (response.data.code === 504) {Message.error('服务器被吃了⊙﹏⊙∥');} else if(response.data.code === 404){Message.error('请求地址不存在!');router.replace({path:'/404'})}else if (response.data.code === 403) {Message.error('权限不足,请联系管理员!');router.replace({path:'/403'})} else if (response.data.code === 401) { //未登录// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath}});}else{//操作失败后的显示信息,不用这里直接弹出//Message.error(response.data.msg);}return response.data},err => {loadingInstance.close();Message.error('请求失败,请稍后再试');return Promise.reject(err)}
);//对 axios 的所有请求进行参数统一规格
let http = {get(url, params = {}){return axios.get(url, {params})},post(url, params = {}){return axios.post(url, params)},del(url, params = {}){return axios.delete(url, {params})},put(url, params = {}){return axios.put(url, params)},upload(url, params = {}){return axios.post(url, params,{headers: { // 这里指定的是多文件二进制上传'Content-Type': 'multipart/form-data'}})}
};export default http;

六、具体发请求的drugs.js

import http from './httpAxios';export default {importExcel(file){ //非药品目录Excel文件导入return http.upload('/his-drugs/fileUpload',file);}
}

七、js的路由index.js

import drugs from './drugs.js';// 统一管理,后缀.js可以省略// 统一导出
export default {//drugs:drugs, //取名和导入的名字一样时,可简写drugs,
}

八、vue部分,Drugs.vue

<template><div id="drugs"><div class="container"><!-- 导入导出部分 --><el-form :inline="true" :model="query" class="demo-form-inline" size="mini"><el-form-item><el-input v-model="query.search" clearable placeholder="药品编码/名称/拼音助记码"></el-input></el-form-item><el-form-item><el-button type="primary" @click="pageSearchHandler" icon="el-icon-search">查询</el-button><!-- 根据查询结果导出查询出来所有的数据 --><el-button type="info" @click="exportPageHandler" icon="el-icon-download">导出</el-button></el-form-item><el-form-item><!--action:上传的地址,这里我们通过axios 进行代理,不直接写http-request:覆盖默认的上传行为,可以自定义上传的实现show-file-list:是否显示已上传的文件列表--><el-upload action="" :http-request="importHandler" :show-file-list="false"><el-button type="info" icon="el-icon-upload2">导入</el-button></el-upload></el-form-item></el-form></div></div>
</template><script>export default {name: 'Drugs',data(){return {query:{search: '', //查询条件:药品编码 或 药品名称 或 拼音助记码}}},methods:{// 导入,这里会自动把上传的文件带过来importHandler(data){// - 通过异步的形式上传文件,需要模拟表单的形式//创建表单对象let form = new FormData();//后端接收参数,可以接收多个参数form.append('file',data.file);this.$api.drugs.importExcel(form).then(res=>{//提示信息if(res.code === 200){this.$message.success(res.msg);//重新加载数据this.pageSearchHandler();}});}}};
</script><style scoped></style>

2.导出excel表格

后端Java部分

一、和导入excel的操作相同的部分,导入jar包相同,数据模型drugsDTO复用

二、使用MyBatisPlus 的条件构造器,在Mapper接口中编写方法

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.neuedu.entity.HisDrugs;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.neuedu.entity.dto.DrugsDTO;import java.util.List;/*** <p>* 非药品目录收费项目 Mapper 接口* </p>** @author WHLin* @since 2020-03-30*/
public interface HisDrugsMapper extends BaseMapper<HisDrugs> {//使用MyBatisPlus 的条件构造器//这里drugs_dosage_id 和drugs_type_id使用的是外键的形式完成的查询@Select("SELECT drugs_code,drugs_name,drugs_format,\n" +"(select constant_name from his_constant_category where id = his_drugs.drugs_dosage_id) drugs_dosage,\n" +"(select constant_name from his_constant_category where id = his_drugs.drugs_type_id) drugs_type,\n" +"drugs_price,mnemonic_code,drugs_unit FROM his_drugs ${ew.customSqlSegment}")List<DrugsDTO> excelExport(@Param(Constants.WRAPPER) Wrapper<DrugsDTO> wrapper);
}

三、在service中编写对应的方法接口

import org.neuedu.entity.HisDrugs;
import com.baomidou.mybatisplus.extension.service.IService;
import org.neuedu.entity.dto.DrugsDTO;import java.util.List;/*** <p>* 非药品目录收费项目 服务类* </p>** @author WHLin* @since 2020-03-30*/
public interface IHisDrugsService extends IService<HisDrugs> {List<DrugsDTO> excelExport(String search);
}

四、在service实现类中实现方法,并完成条件构造的逻辑

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.neuedu.entity.HisDrugs;
import org.neuedu.entity.dto.DrugsDTO;
import org.neuedu.mapper.HisDrugsMapper;
import org.neuedu.service.IHisDrugsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import java.util.List;/*** <p>* 非药品目录收费项目 服务实现类* </p>** @author WHLin* @since 2020-03-30*/
@Service
public class HisDrugsServiceImpl extends ServiceImpl<HisDrugsMapper, HisDrugs> implements IHisDrugsService {@Overridepublic List<DrugsDTO> excelExport(String search) {//查询的条件构造器QueryWrapper<DrugsDTO> wrapper = new QueryWrapper<>();wrapper.like(StringUtils.isNotBlank(search),"drugs_code",search).or().like(StringUtils.isNotBlank(search),"drugs_name",search).or().like(StringUtils.isNotBlank(search),"mnemonic_code",search).eq("del_mark",0);return baseMapper.excelExport(wrapper);}
}

五、Controller前端控制器的编写

    @ApiOperation("非药品目录导出")@ApiImplicitParam(name = "search",value = "查询条件:药品编码 或 药品名称 或 拼音助记码")@GetMapping("/downLoad")public void excelExport(HttpServletResponse response, String search) throws Exception{//写入excel 的数据List<DrugsDTO> list = drugsService.excelExport(search);//这里注意 有同学反映使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.ms-excel;charset=utf-8");//response.setCharacterEncoding("utf-8");//这里URLEncoder.encode 可以防止中文乱码,当然和easyexcel 没有关系String fileName = URLEncoder.encode("非药品目录-" + LocalDate.now().toString(), "utf-8");//设置为手动下载,不让浏览器自动下载response.setHeader("Content-disposition","attachment;filename=" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(),DrugsDTO.class).sheet("非药品目录").doWrite(list); // 这是需要写入的数据}

前端部分代码

六、在httpAxios.js中判断为get请求之后,再判断是否为文件下载;下载的时候需要通过创建下载链接来操作,把下载的 blob 数据转为 excel,上面代码已经展示出来了

七、具体发请求的drugs.js

import http from './httpAxios';export default {excelExport(search){ // 非药品目录导出return http.get('his-drugs/downLoad',search);}
}

八、drugs.vue文件中js使用

methods:{// 导出exportPageHandler(){console.log(this.query.search);this.$api.drugs.excelExport({search:this.query.search});}
},

后端springboot、mybatisplus,前端vue-cli3、elementUI、axios,使用阿里巴巴提供的easyExcel导入导出excel表格相关推荐

  1. springboot+mybatisplus+thymeleaf导入导出excel表格和制作饼状图,柱状图

    这是我们的项目结构. 我们导入的依赖.  application.yml配置文件. goods实体类 type实体类 1.导出 前端代码: JavaScript代码: 通过这里跳转到后端  导出的工具 ...

  2. Java前端笔记-后端Springboot,前端vue,Nginx使前后端分离

    目录 基本概念 代码实例 基本概念 这是一个很6的模式,以目前本人C++ Qt的技术,是做不出的,但Java已经有雏形了. 后端采用Spring Boot主要是回json数据,如下所示: 这里的数据都 ...

  3. 后端SpringBoot和前端vue

    前端框架:vue 前端的主流是js,vue是js库,js库还有angular.react,过时的有jQuery; 组件库也就是css样式的封装库,其中有element.Bootstrap 后端框架:S ...

  4. springboot整合easyexcel 导入导出excel案例及文件无法打开

    前端请求 vue3+axios+typescript downloadByUrlStream({url:process.env.VUE_APP_API_URL1+"/MeshDevice/u ...

  5. Springboot 整合 easyexcel导入导出excel

    1. 引入核心依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel< ...

  6. SpringBoot使用poi或EasyExcel导入导出Excel文件

    使用poi导入导出Excel 首先引入poi依赖包 03版本的Excel和07版本的Excel所需要的依赖不同,都需要导入. 记录问题: 最初导入的poi包为3.6版本.WorkBook类和Sheet ...

  7. SpringBoot后端框架整合前端Vue系统框架

    SpringBoot后端框架整合前端Vue系统框架 本节内容服务于SpringBoot + Vue 搭建 JavaWeb 增删改查项目. 在IDEA中整合前后端框架,实现前后端分离,人不分离,方便项目 ...

  8. VUE纯前端导出excel表格功能《转载》

    插件:使用vue-json-excel插件实现Vue纯前端导出简单的Excel表格功能. 使用方法 1. 安装依赖 npm install vue-json-excel 2. 引入组件 a. 全局引入 ...

  9. 基于SpringBoot+EasyExcel+vue3实现excel表格的导入和导出

    目录 基于SpringBoot+EasyExcel+vue3实现excel表格的导入和导出 一.导入和导出 二.导出数据为excel实现过程 三.将excel中的数据导入到数据库中 基于SpringB ...

  10. html实现pdf导出excel表格,一篇文章详解:Vue框架下轻松实现Excel、PDF导出

    项目需求:开发一套基于Vue框架的工程档案管理系统,用于工程项目资料的填写.编辑和归档,经调研需支持如下功能: Excel报表的导入.导出 PDF文件的导出 打印表格 经过技术选型,项目组一致决定通过 ...

最新文章

  1. MS 的SPACE很不好的说
  2. github:已经提交并push后再次追加提交
  3. 设置二进制或者16/32位的某一位的值
  4. Codeforces Round 261 Div.2 D Pashmak and Parmida's problem --树状数组
  5. C语言灵魂篇|指针作为函数返回值
  6. asp.net mvc 包含了一个 html 的助手类在哪里,c# - 在App_Code中使用@HTML的ASP.NET MVC Razor Helper - 堆栈内存溢出...
  7. spring接口 BeanFactoryAware,动态获取IOC容器里面的对象(多例)
  8. 使用 Kotlin , Groovy ,Java 开发一个自己的 Gradle 插件
  9. 【高等数学笔记】闭包、孤立点、导集、内点、边界的关系
  10. Tableau学习摘录总结①(层次、聚合度和颗粒度层次、聚合度和颗粒度,字段(离散和连续),小建议)
  11. 全面吃透JAVA Stream流操作,让代码更加的优雅
  12. 「 C/C++疑难杂症 」warning: ISO C++ forbids converting a string constant to ‘CHAR*’ {aka ‘char*’} [-Wwrite
  13. Laravel + EasyWeChat 微信登陆功能
  14. Jetson嵌入式系列模型部署-3
  15. TM4C123G学习记录(6)--UART
  16. 什么软件可以测试音乐速度,测算歌曲速度有什么好用的编曲软件
  17. python-机器学习-决策树算法
  18. app应用下的公司名称错误
  19. “COMSOL Multiphysics多物理场仿真技术与应用”光电专题(二十九期)
  20. 国家贫困县75万重奖矿工拳王 称其他方面可省点

热门文章

  1. Python常用英文单词
  2. 雷电3接口能干嘛_【分享帖】3块钱一斤的水泥能干嘛?600多万网友看完后都跪了:水泥竟然这么神…...
  3. goldendict for linux,GoldenDict(for Linux)配置无道词典
  4. 服务器没有系统能配置ip地址嘛,win10系统没有有效的ip配置怎么解决
  5. Flask-mongoengine分页bug
  6. adb关闭手机系统自动更新
  7. wifi虚拟服务器怎么设置方法,虚拟路由器如何设置
  8. Pycharm, 生成可执行文件,Unhandled exception in script报错
  9. excel中插入的图表保存时提示 无法保存 html,Excel技巧:将图表另存为GIF文件
  10. 京东注册页面简单html代码,(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看...