EasyExcel快速上手
1、导入jar包
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.9</version></dependency>
2、编写文本模板类
内容高度:@ContentRowHeight(14) 标题行高度:@HeadRowHeight(14) 列宽:@ColumnWidth(23)
在需要导入和导出的字段上加上以下注解,其中value代表标题,index代表列的索引值
@ExcelProperty(value= {"楼号"},index = 1)
再不需要导入和导出的字段上加上以下注解:
@ExcelIgnore
/*** 隔离房间信息管理(IsolationPeopleDetail)实体类的导入导出格式** @author zyw* @since 2022-10-11 18:43:33*/
@Data
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 53)
@ContentRowHeight(14)
@HeadRowHeight(14)
@ColumnWidth(23)
@AllArgsConstructor
@NoArgsConstructor
public class HotelRoomTemplate {/*** ID*/
// @ExcelIgnore@ExcelProperty(value= {"序号"},index = 0)private String id;/*** 隔离人员姓名*/@ExcelProperty(value= {"楼号"},index = 1)private String buildingNo;/*** 国籍*/@ExcelProperty(value= {"楼层"},index = 2)private String floor;/*** 证件类型 1:身份证 2: 护照*/@ExcelProperty(value= {"房间号"},index = 3)private String roomId;
}
3、编写模板下载接口
**所有Excle导入都需要用统一的模板进行数据导入,且我们在程序中也需要对于导入Excle文件的格式和内容规范进行校验,同时我们还可以再导入业务逻辑中加入生成导入日志的功能,方便使用者尽快得知提交的文件中具体哪个位置的内容填写不规范,也可以使后台维护的工作人员能及时发现恶意的导入行为**
(1)通过解析文本模板类生成Excle对象
@GetMapping(value = "/download")@ApiOperation(value="下载隔离酒店信息Excel模板",notes="下载隔离酒店信息Excel模板后端接口",response = String.class)public String download(HttpServletResponse response){try {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码String fileName = URLEncoder.encode("隔离点房间模板", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), HotelRoomTemplate.class).registerWriteHandler(new HotelRoomWriteHandler()).sheet().doWrite(service.data());return buildResultStr(buildSuccessResultData("下载隔离点房间信息Excel模板成功"));}catch (Exception e){log.error("下载隔离点房间信息模板失败",e);return buildResultStr(buildErrorResultData(e));}}
(2)编写一个模板修饰类,可以给模板增加下拉框,调整样式
//注册该普通Java类
@Component
public class HotelRoomWriteHandler implements SheetWriteHandler {@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { }//声明init()方法,进行初始化挂载@PostConstructpublic void initJ(){
// isoSpinnerWriteHandler = this;
// isoSpinnerWriteHandler.jdEnterArriveTypeDao = this.jdEnterArriveTypeDao;
// jdEnterArriveTypeDao = SpringUtil.getApplicationContext().getBean(JdEnterArriveTypeDao.class);}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
// String[] nationality = new String[]{"中国", "中国港澳台", "外籍"};
// String[] certificatesType = new String[]{"身份证", "港澳台通行证", "护照"};
// String[] otherCertificatesType = new String[]{"港澳台通行证", "护照"};/*入境集中隔离、入境集中居家监测、入境密接、入境次密接、国内中高风险区、国内密接、国内次密接、其他*/
// String [] personType = new String[]{"入境集中隔离","入境集中居家监测","入境密接","入境次密接","国内中高风险区","国内密接","国内次密接","其他"};//使用声明的该类的静态类变量,调用Dao层;
// List<PersonType> personType1 = isoSpinnerWriteHandler.jdEnterArriveTypeDao.getPersonType();
// List<String> list = new ArrayList<>();
// for (int i = 0; i < personType1.size(); i++) {
// list.add(personType1.get(i).getMeasures());
// }
// String[] personType = list.toArray(new String[list.size()]);/*String data = HttpUtil.get("https://www.jiankangjiande.cn/gateway/sysinfo/office/pub/getOfficeListByParentId?parentId=616fb07c6bb1499a8212829142bc0303");Map map = JSONObject.parseObject(data, Map.class);String rvs = JSONArray.toJSONString(map.get("resultData"));List<SystemOfficeVo> officeVoList = JSON.parseArray(rvs, SystemOfficeVo.class);*/
//
// IsolatedPointHotelService isolatedPointHotelService = SpringUtil.getApplicationContext().getBean(IsolatedPointHotelService.class);
// List<IsolatedPointHotel> isolatedPointHotels = isolatedPointHotelService.findList(new IsolatedPointHotel());// String[] isolatedPoint = new String[isolatedPointHotels.size()];
// for (int i = 0; i < isolatedPointHotels.size(); i++) {
// isolatedPoint[i] = isolatedPointHotels.get(i).getName();
// }//String[] isolatedPoint = isolationPeopleDetailService.findHotelName();//String [] isolatedPoint = new String[]{"寿昌皇爵君廷","洋溪皇爵精品","寿昌秋林阁A","寿昌秋林阁B","寿昌玉温泉酒店","党校隔离点","红塘水库隔离点","梅城隔离点","乾潭隔离点"};
// Map<Integer, String[]> mapDropDown = new HashMap<>();
// mapDropDown.put(1, nationality);
// mapDropDown.put(2, certificatesType);
// mapDropDown.put(4, otherCertificatesType);
// mapDropDown.put(10, personType);
// mapDropDown.put(17, isolatedPoint);
// Sheet sheet = writeSheetHolder.getSheet();// ///开始设置下拉框
// DataValidationHelper helper = sheet.getDataValidationHelper();//设置下拉框
// for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
// /***起始行、终止行、起始列、终止列**/
// CellRangeAddressList addressList = new CellRangeAddressList(2, 1000, entry.getKey(), entry.getKey());
// /***设置下拉框数据**/
// DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
// DataValidation dataValidation = helper.createValidation(constraint, addressList);
// /***处理Excel兼容性问题**/
// if (dataValidation instanceof XSSFDataValidation) {
// dataValidation.setSuppressDropDownArrow(true);
// dataValidation.setShowErrorBox(true);
// } else {
// dataValidation.setSuppressDropDownArrow(false);
// }
// sheet.addValidationData(dataValidation);
// }}}
(3)在doWrite()方法中我们可以在模板中填入默认值
public List<HotelRoomTemplate> data(){List<HotelRoomTemplate> list = new ArrayList<>();HotelRoomTemplate hrtOne = new HotelRoomTemplate("1","可不填","1楼","101");HotelRoomTemplate hrtTwo = new HotelRoomTemplate("2","可不填","1楼","102");HotelRoomTemplate hrtThree = new HotelRoomTemplate("3","可不填","1楼","103");HotelRoomTemplate hrtFour = new HotelRoomTemplate("4","可不填","1楼","104");list.add(hrtOne);list.add(hrtTwo);list.add(hrtThree);list.add(hrtFour);return list;}
(4)模板下载效果
4、编写Excle导入接口
思路:1、将Excle文件中我们需要的数据转换成对应的模板类泛型的Lsit集合
2、再将其依次经过层层校验后插入数据库
3、在校验的同时记录校验的过程,生成导入日志,插入日志表
4、如果导入失败,接口中返回给用户文件内容错误的具体位置提示
@PostMapping(value = "/uploadFile")@ApiOperation(value="上传Excel文件导入隔离酒店信息",notes="上传Excel文件导入隔离酒店信息",response = String.class)public String uploadFile(@ApiParam(name = "file",value = "选择文件", required = true) MultipartFile file,@RequestParam @ApiParam(name="id",value="隔离点ID",required=true)String id){List<HotelRoomTemplate> list = new ArrayList<HotelRoomTemplate>();try {Assert.notNull(file,"文件不能为空");InputStream inputStream = file.getInputStream();//读数据try {list = EasyExcel.read(inputStream, HotelRoomTemplate.class, new HotelRoomDataListener()).head(HotelRoomTemplate.class).sheet().doReadSync();Assert.notEmpty(list,"解析出的数据集为空,请检查文件的数据格式是否正确");}catch (Exception e){return buildResultStr(buildErrorResultData("导入数据格式不正确,请下载导入模板"));}//保存数据list = {ArrayList@8848} size = 7return buildResultStr(buildSuccessResultData(service.saveData(list,id)));}catch (Exception e){log.error("上传文件失败",e);return buildResultStr(buildErrorResultData(e));}}
(1)编写数据侦听器
//注册该普通Java类
@Component
public class HotelRoomDataListener extends AnalysisEventListener<HotelRoomTemplate> {private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);//声明该类自身的静态类变量private static HotelRoomDataListener hotelRoomDataListener;/*** 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<IsolationPeopleDetail> list = new ArrayList<IsolationPeopleDetail>();@Autowiredprivate IsolationPeopleDetailService isolationPeopleDetailService;private static IsolationPeopleDetailService iisolationPeopleDetailService; //接收注入的service@Autowiredprivate JudgeUtil judgeUtil;@PostConstructpublic void initJ() {hotelRoomDataListener = this;hotelRoomDataListener.judgeUtil = this.judgeUtil;iisolationPeopleDetailService = isolationPeopleDetailService; //进行赋值,实际上调用的是ssysUserService}// @PostConstruct
// public void initM(){
// judgeUtil = SpringUtil.getApplicationContext().getBean(JudgeUtil.class);
// }/*private IsolationPeopleDetailService isolationPeopleDetailService;*//*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param*//*public DemoDataListener(IsolationPeopleDetailService iso) {this.isolationPeopleDetailService = iso;}*/@SneakyThrows@Overridepublic void invoke(HotelRoomTemplate data, AnalysisContext context) {//解析数据,对数据内容进行排查Map<String,Object> map = hotelRoomDataListener.judgeUtil.judgeHotelRoom(data);//检查数据是否正确String result = (String) map.get("result");if (StringUtils.isBlank(result)){//数据判断没问题,可以添加数据库IsolationPointRoom room = (IsolationPointRoom) map.get("room");saveData(room);}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {LOGGER.info("所有数据解析完成!");}/** 将数据保存在表中*//*** 加上存储数据库*/private void saveData(IsolationPointRoom iso) {/*//添加隔离对象if (iso.getIsolatedPoint().equals("洋溪皇爵精品酒店")){iso.setIsolatedPoint("2");}else {iso.setIsolatedPoint("1");}iso.setId(IdGen.uuid());iso.setInFrequency(1);isolationPeopleDetailService.addIsoD(iso);//改变隔离对象所在房间状态isolationPeopleDetailService.updateStatus(iso.getIsolatedPoint(),iso.getRoomNum());*/}
}
(2)封装具体的数据排查业务逻辑
//对隔离对象数据的判断public Map<String,Object> judgeHotelRoom(HotelRoomTemplate data) throws Exception {Map<String, Object> map1 = new HashMap<>();String result = "";IsolationPointRoom room = new IsolationPointRoom();Map map = JSONObject.parseObject(JSON.toJSONString(data), Map.class);//楼层号String floor = (String) map.get("floor");if(StringUtils.isNotNullString(floor)){floor=floor.trim();room.setFloor(floor);}else {result+=",楼层不能为空";}//房间号String roomId = (String) map.get("roomId");if(StringUtils.isNotNullString(roomId)){roomId=roomId.trim();room.setRoomId(roomId);}else {result+=",房间号不能为空";}String buildingNo = (String) map.get("buildingNo");if(StringUtils.isNotNullString(buildingNo)){buildingNo=buildingNo.trim();room.setBuildingNo(buildingNo);}map1.put("result",result);if (result.equals("")){map1.put("room",room);}return map1;}
(3)编写数据插入以及生成导入日志的业务层方法
public String saveData(List<HotelRoomTemplate> list,String id) throws Exception {//成功数 失败数 数据长度Integer success = 0,fail = 0, daLength = 10;List<HotelRoomTemplateJournal> das = new ArrayList<HotelRoomTemplateJournal>();HotelRoomTemplate hotelRoomTemplate = new HotelRoomTemplate();//批次号String bath = IdGen.uuid();String hotel = isolationPeopleDetailDao.getHotel(id).getName();IntegratedServicePoint integratedServicePoint = new IntegratedServicePoint();integratedServicePoint.preInsert();UserBase createBy = integratedServicePoint.getCreateBy();int i = isolationPointRoomDao.deleteForId(id);System.out.println("清除"+i+"条旧房间数据");//处理导入的数据try{Iterator<HotelRoomTemplate> iterator = list.iterator();while (iterator.hasNext()){HotelRoomTemplate data = iterator.next();hotelRoomTemplate.setRoomId(data.getRoomId());Map<String, Object> map = new JudgeUtil().judgeHotelRoom(data);//判断是否有数据错误String result = (String) map.get("result");if (result.equals("")){success+=1;IsolationPointRoom room = (IsolationPointRoom) map.get("room");room.setName(hotel);room.setStatus("1");room.setHotelType(Integer.parseInt(id));room.setDelFlag("0");room.setCreateBy(createBy);room.setCreateDate(new Date());room.setUpdateBy(createBy);room.setUpdateDate(new Date());//添加隔离对象room.setId(IdGen.uuid());room.setFloor(room.getFloor().replaceAll("楼",""));//覆盖之前的该酒店数据System.out.println("room = " + room);int insert = isolationPointRoomDao.insertRoom(room);result = "导入成功";}else {//截取第一个,字符串result=result.substring(1);fail+=1;}//转换数据类HotelRoomTemplateJournal db = new HotelRoomTemplateJournal(null,data.getBuildingNo(),data.getFloor(),data.getRoomId(),result);//将数据放入新的集合,方便存入数据库以及写Excel表das.add(db);//一次最多添加10条数据if (das.size() >= daLength) {// 存储完成清理 list//将导入数据存入错误日志表
// this.dao.addErrorLog(das);das.clear();}}//统计导入成功和导入失败数据,存入日志表importLogService.addImpLog("隔离房间信息导入",bath,success,fail);//将导入数据存入错误日志表if (das!=null&&das.size()!=0){
// this.dao.addErrorLog(das);}//创建临时文件return "共导入"+(success+fail)+"条记录: "+"导入成功"+success+"条,导入失败"+fail+"条";}catch (Exception e){//统计导入成功和导入失败数据,存入日志表importLogService.addImpLog("隔离房间信息导入",bath,success,fail);//将导入数据存入错误日志表if (das!=null&&das.size()!=0){
// this.dao.addErrorLog(das);}//创建临时文件return "共导入"+(success+fail)+"条记录: "+"导入成功"+success+"条,导入失败"+fail+"条,导入到:"+hotelRoomTemplate.getRoomId()+"时数据出错";}}
5、导入效果
原始文件:
导入后的展示效果:
EasyExcel快速上手相关推荐
- EasyExcel快速上手~读取
对象 // 如果没有特殊说明,下面的案例将默认使用这个实体类 public class DemoData {private String string;private Date date;privat ...
- 【快速上手mac必备】常用优质mac软件推荐(音视频、办公、软件开发、辅助工具、系统管理、云存储)
本文章的主要内容是我作为一名大四学生.准程序员.up主这三种身份来给大家推荐一下 mac 上好用的软件以及工具.本人也是从去年9月份开始从windows阵营转移到了mac阵营,刚开始使用的时候,也曾主 ...
- 【转】Vue.js 2.0 快速上手精华梳理
Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...
- 『转载』Debussy快速上手(Verdi相似)
『转载』Debussy快速上手(Verdi相似) Debussy 是NOVAS Software, Inc(思源科技)发展的HDL Debug & Analysis tool,这套软体主要不是 ...
- [转载]ESFramework 4.0 快速上手(15) -- 客户端登录验证
ESFramework 4.0 快速上手(15) -- 客户端登录验证 在之前版本的Rapid引擎中,是没有提供客户端登陆验证的机制的,如果要验证用户的帐号密码信息,我们只有自己手动通过自定义信息来实 ...
- WijmoJS 2019V1正式发布:全新的在线 Demo 系统,助您快速上手,开发无忧
2019独角兽企业重金招聘Python工程师标准>>> 下载WijmoJS 2019 v1 WijmoJS是为企业应用程序开发而推出的一系列包含HTML5和JavaScript的开发 ...
- react 快速上手开发_React中测试驱动开发的快速指南
react 快速上手开发 by Michał Baranowski 通过MichałBaranowski React中测试驱动开发的快速指南 (A quick guide to test-driven ...
- 《Android App开发入门:使用Android Studio 2.X开发环境》——1-3 Android Studio 快速上手...
1-3 Android Studio 快速上手
- Keras快速上手:基于Python的深度学习
Keras快速上手:基于Python的深度学习 谢梁,鲁颖,劳虹岚 著 ISBN:9787121318726 包装:平装 开本:16开 正文语种:中文 出版社: 电子工业出版社 出版时间:2017-0 ...
最新文章
- DUILIB中获取flash,webbrowser control的方法
- 人工神经网络发展历史及算法应用综述
- Visual C++2005库的十项突破性变化
- 5G NR — Massive MIMO 与波束赋形
- 访问云服务器储存的mp4_服务器如何存储视频文件格式
- python界面编程和网口通信_Python—网络通信编程之tcp通信编程
- 祖父元素_帮助祖父母建立Skype帐户的UX经验教训
- ASP.NET 5 - $.ajax post JSON.stringify(para) is null
- Android生成keystore方法
- 没有为此文件配置应用程序上下文_如何在macOS中管理文件关联?
- Google Protocol Buffer
- 怎么做装修预算?装修预算需要注意的三大事项
- 如何在eclipse里使用git
- wordpress提高访问速度
- Java 通过银行卡号获取银行名称
- 简述Java运行环境
- Hash表的初步认识
- 物质模拟器5.0版 新增炸药及可以连续爆炸
- java如何避免恶意连续点击_浅谈一下如何避免用户多次点击造成的多次请求
- nefuoj1487时空乱流
热门文章
- 柱状图中xy轴怎么出现_『怎样设置excel图标的x、y轴』excel图表xy轴名称
- 测试人员如何区分前端和后台BUG方法流程
- Allegro-CRTL键的使用
- 政策解读 | 传言PayPal要封杀独立站卖家?绝对不可能!
- 51单片机常用波特率初值表(11.0592M和12M)
- b计划撸站--内容采集筛选
- SpringBoot 自动配置初探
- 在浏览器中嵌入播放器
- 【华为OD机试真题】1023 - 按身高和体重排队(JAVA C++ Python JS) | 机试题+算法思路+考点+代码解析
- 自动化JS效果---第五集--永洪BI