工作中需要不少的Excel表格的导入导出,今天就给大家安利一个Excel导入比较好用的工具类easypoi,因为是中国人编写的所有里面的注释都是中文的,对我这种英语不好的人非常友好。能够支持使用注解导入导出,复杂的导入检验,模板导出等功能

该工具类的官方文档

easypoi :http://doc.wupaas.com/docs/easypoi/easypoi-1c0u6ksp2r091

easypoi依赖引入

  <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-web</artifactId><version>3.2.0</version></dependency>

easypoi之Excel导入

首先我们创建个实体类,在每个字段上加上相对应的注解 @Excel

    @Excel(name = "姓名")private String name;@Excel(name = "性别", replace = {"男_0", "女_1"})private String sex;@Excel(name = "年龄", fixedIndex = 2)private Integer age;

@Excel常用值解释
name 对应是Excel每一列的列明
replace 可以进行值的替换 如Excel中输入为男解析后可改变为0
fixedIndex 固定的某一列 可以解决name值不好解析的问题,默认从0开始
其他有需要的大家可以去官方文档或者进注解查看

Conroller层的代码也很简单
  @PostMapping("/upload")public String upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {ImportParams params = new ImportParams();// 表头设置为1行params.setHeadRows(1);ExcelImportResult<ExcelUser> result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), ExcelUser.class, params);System.out.println(result.getList().toString());return null;}


可以看到图片已经正常的被解析到 并且性别已经解析为我们定义的编码

导入之数据校验

因为excel表格都是给用户输入的,所以用户导入的表格有一些并不符合我们数据库存入的规则 所以我们要对用户导入的表格内容进行一些简单的数据校验

首先我们要创建一个检验类并且实现IExcelVerifyHandler接口重写该接口的verifyHandler方法在方法体里做具体的检验
@Component
public class UserVerifyHandler implements IExcelVerifyHandler<ExcelUser> {//    private final ThreadLocal<List<ExcelUser>> threadLocal = new ThreadLocal<>();@AutowiredUserService userService;@Overridepublic ExcelVerifyHandlerResult verifyHandler(ExcelUser excelProduct) {StringJoiner joiner = new StringJoiner(",");//检验名字是否存在boolean flag = userService.checkout(excelProduct.getName());if (flag) {joiner.add("该名字已存在");}if (joiner.length() != 0) {return new ExcelVerifyHandlerResult(false, joiner.toString());}return new ExcelVerifyHandlerResult(true);}

这里我们实验检验名字是否已经在数据库重复

改造我们的实体类 实体类要实现IExcelDataModel IExcelModel这两个接口改造后的实体类是这个样子

@Data
public class ExcelUser implements IExcelDataModel, IExcelModel {/*** 行号*/private int rowNum;/*** 错误消息*/private String errorMsg;@Excel(name = "姓名")@NotBlank(message = "[姓名]不能为空")private String name;@Excel(name = "性别", replace  = {"男_0", "女_1"})@NotBlank(message = "[性别]不能为空")@Pattern(regexp = "[01]", message = "性别输入错误")private String sex;@Excel(name = "年龄", fixedIndex = 2)@NotBlank(message = "[年龄]不能为空")private String age;

这里检验了哪些参数不能为空,rowNum代表的是第几行 errorMsg代表的是错误消息
需要注意的是加入校验时要把字段类型改为String

Controller层改造

  @Autowiredprivate UserVerifyHandler userVerifyHandler;@PostMapping("/upload")public String upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {ImportParams params = new ImportParams();// 表头设置为1行params.setHeadRows(1);// 标题行设置为0行,默认是0,可以不设置params.setTitleRows(0);//开启检验params.setNeedVerfiy(true);params.setVerifyHandler(userVerifyHandler);ExcelImportResult<ExcelUser> result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), ExcelUser.class, params);System.out.println(result.getFailList().toString());System.out.println(result.getList().toString());return null;}

这里就改了三行代码 首先注入UserVerifyHandler 并且开启校验需要注意的是导入检验的错误数据会放到这个集合里result.getFailList()
params.setNeedVerfiy(true);
params.setVerifyHandler(userVerifyHandler);

可以看到,我们的校验是成功的一些不能校验通过的数据我们存放在了一个专门的集合里面,里面有我们设置的一些校验失败的一些提示语句,模仿数据库数据存在的校验也成功了因为并没有真正的去数据库查该名字是否存在,为了演示效果统一设置为存在了。并且在性别那里我们在也控制了只能输入男或女。

我们不允许数据库出现两个相同的名字 那么导入表格也不能存在相同的名字下面介绍怎么校验导入表格里校验数据是否重复

校验类更改

@Component
public class UserVerifyHandler implements IExcelVerifyHandler<ExcelUser> {private final ThreadLocal<List<ExcelUser>> threadLocal = new ThreadLocal<>();@AutowiredUserService userService;@Overridepublic ExcelVerifyHandlerResult verifyHandler(ExcelUser excelProduct) {StringJoiner joiner = new StringJoiner(",");//检验名字是否存在boolean flag = userService.checkout(excelProduct.getName());if (flag) {joiner.add("该名字已存在");}List<ExcelUser> threadLocalVal = threadLocal.get();if (threadLocalVal == null) {threadLocalVal = new ArrayList<>();}threadLocalVal.forEach(e -> {if (e.getName().equals(excelProduct.getName())) {int lineNumber = e.getRowNum() + 1;joiner.add("名字与" + lineNumber + "行重复");}});// 添加本行数据对象到ThreadLocal中threadLocalVal.add(excelProduct);threadLocal.set(threadLocalVal);if (joiner.length() != 0) {return new ExcelVerifyHandlerResult(false, joiner.toString());}if (joiner.length() != 0) {return new ExcelVerifyHandlerResult(false, joiner.toString());}return new ExcelVerifyHandlerResult(true);}}

Controller更改

@PostMapping("/upload")public String upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {ImportParams params = new ImportParams();ExcelImportResult<ExcelUser> result;try {// 表头设置为1行params.setHeadRows(1);// 标题行设置为0行,默认是0,可以不设置params.setTitleRows(0);//开启检验params.setNeedVerfiy(true);params.setVerifyHandler(userVerifyHandler);result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), ExcelUser.class, params);} finally {// 清除threadLocal 防止内存泄漏ThreadLocal<List<ExcelUser>> threadLocal = userVerifyHandler.getThreadLocal();if (threadLocal != null) {threadLocal.remove();}}System.out.println(result.getFailList().toString());System.out.println(result.getList().toString());return null;}

threadLocal 一定要记得清除,否则可能造成内存泄漏


第二条错误数据中已经提示名字与第几行重复

上面的一些导入功能基本上已经能够满足大部分需求了,下面介绍一下导出功能

easypoi之Excel导出

 @GetMapping("/getList")public String getList(HttpServletRequest request, HttpServletResponse response) {List<ExcelUser> list = new ArrayList<>();ExcelUser excelUser = new ExcelUser();excelUser.setName("张三");excelUser.setAge("20");excelUser.setSex("男");ExcelUser excelUser1 = new ExcelUser();excelUser1.setName("李四");excelUser1.setAge("30");excelUser1.setSex("女");list.add(excelUser);list.add(excelUser1);Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("计算机一班学生", "学生"),ExcelUser.class, list);// 判断数据if(workbook == null) {return "fail";}// 设置excel的文件名称String excelName = "测试导出";// 重置响应对象response.reset();// 指定下载的文件名--设置响应头response.setHeader("Content-Disposition", "attachment;filename=" +excelName+".xls");response.setContentType("application/vnd.ms-excel;charset=UTF-8");response.setHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);// 写出数据输出流到页面try {OutputStream output = response.getOutputStream();BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output);workbook.write(bufferedOutPut);bufferedOutPut.flush();bufferedOutPut.close();output.close();} catch (IOException e) {e.printStackTrace();}return "success";}


easypoi还支持一对多的导出并且可以设置导出的Excel格式

导出改造

ExportParams exportParams = new ExportParams("计算机一班学生", "学生");exportParams.setStyle(ExcelStyleUtil.class);    Workbook workbook = ExcelExportUtil.exportExcel(exportParams,ExcelUser.class, list);

ExcelStyleUtil 需要继承IExcelExportStyler接口,代码如下可以根据自己需求进行修改

public class ExcelStyleUtil implements IExcelExportStyler {private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");private static final short FONT_SIZE_TEN = 9;private static final short FONT_SIZE_ELEVEN = 10;private static final short FONT_SIZE_TWELVE = 10;/*** 大标题样式*/private CellStyle headerStyle;/*** 每列标题样式*/private CellStyle titleStyle;/*** 数据行样式*/private CellStyle styles;public ExcelStyleUtil(Workbook workbook) {this.init(workbook);}/*** 初始化样式** @param workbook*/private void init(Workbook workbook) {this.headerStyle = initHeaderStyle(workbook);this.titleStyle = initTitleStyle(workbook);this.styles = initStyles(workbook);}/*** 大标题样式** @param color* @return*/@Overridepublic CellStyle getHeaderStyle(short color) {return headerStyle;}/*** 每列标题样式** @param color* @return*/@Overridepublic CellStyle getTitleStyle(short color) {return titleStyle;}/*** 数据行样式** @param parity 可以用来表示奇偶行* @param entity 数据内容* @return 样式*/@Overridepublic CellStyle getStyles(boolean parity, ExcelExportEntity entity) {return styles;}/*** 获取样式方法** @param dataRow 数据行* @param obj     对象* @param data    数据*/@Overridepublic CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {return getStyles(true, entity);}/*** 模板使用的样式设置*/@Overridepublic CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {return null;}/*** 初始化--大标题样式** @param workbook* @return*/private CellStyle initHeaderStyle(Workbook workbook) {CellStyle style = getBaseCellStyle(workbook);style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));return style;}/*** 初始化--每列标题样式** @param workbook* @return*/private CellStyle initTitleStyle(Workbook workbook) {CellStyle style = getBaseCellStyle(workbook);style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));//背景色style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);return style;}/*** 初始化--数据行样式** @param workbook* @return*/private CellStyle initStyles(Workbook workbook) {CellStyle style = getBaseCellStyle(workbook);style.setFont(getFont(workbook, FONT_SIZE_TEN, false));style.setDataFormat(STRING_FORMAT);return style;}/*** 基础样式** @return*/private CellStyle getBaseCellStyle(Workbook workbook) {CellStyle style = workbook.createCellStyle();//下边框style.setBorderBottom(BorderStyle.THIN);//左边框style.setBorderLeft(BorderStyle.THIN);//上边框style.setBorderTop(BorderStyle.THIN);//右边框style.setBorderRight(BorderStyle.THIN);//水平居中style.setAlignment(HorizontalAlignment.CENTER);//上下居中style.setVerticalAlignment(VerticalAlignment.CENTER);//设置自动换行style.setWrapText(true);return style;}/*** 字体样式** @param size   字体大小* @param isBold 是否加粗* @return*/private Font getFont(Workbook workbook, short size, boolean isBold) {Font font = workbook.createFont();//字体样式font.setFontName("宋体");//是否加粗font.setBold(isBold);//字体大小font.setFontHeightInPoints(size);return font;}

因为导出比较简单而且官方文档写的也比较详细,这里不做过多赘诉,大家有其他导出需求的可以参考官方文档。

下篇文章将为大家介绍使用模板导出Excel表格的方法

创作不易转载应注明出处

源码地址 :https://github.com/Flyingntothesky/easypoi.git

大家有什么问题可以下方评论交流

Excel导入导出之easypoi用法相关推荐

  1. 推荐一款非常好用的Excel导入导出工具EasyPoi

    EasyPoi简介 用惯了SpringBoot的朋友估计会想到,有没有什么办法可以直接定义好需要导出的数据对象,然后添加几个注解,直接自动实现Excel导入导出功能? EasyPoi正是这么一款工具, ...

  2. Excel导入导出之easypoi工具之模板复杂表格导出

    工作中难免会遇到一些复杂的表格导出需求,这样普通的Excel表格难免会无法满足我们的需要,easypoi就提供了模板导出的功能,以方便我们导出更加复杂的Excel表格,这篇文章就为大家介绍一下模板导出 ...

  3. SpringBoot实现Excel导入导出,好用到爆,POI可以扔掉了!

    在我们平时工作中经常会遇到要操作Excel的功能,比如导出个用户信息或者订单信息的Excel报表.你肯定听说过POI这个东西,可以实现.但是POI实现的API确实很麻烦,它需要写那种逐行解析的代码(类 ...

  4. easypoi 多sheet导入_程序员接私活利器 玩转excel导入导出

    为什么会写Easypoi 以前的以前(岁月真TMD的快)我虽然写了不少代码但还是很少写poi,然后跳到一家公司之后就和业务人员聊上了,来这个需要个报表,这个报表样式是这样的,这个表头是这样的,就这样我 ...

  5. java超级简单到爆的Excel导入导出(easypoi)

    场景: 在日常工作中,excel导入导出,是十分常见的,有两种主流的技术,一种是jxl,另一种是poi,而easypoi就是对poi进行了封装,使得导入导出变得更加的简单,阿里巴巴也有封装的工具名叫E ...

  6. SpringBoot集成EasyPoi实现Excel导入导出

    作者介绍: 本人Java特工,代号:Cris Li : 中文名:克瑞斯理 简书地址: 消失的码农 - 简书 CSDN地址: https://blog.csdn.net/jianli95 个人纯洁版博客 ...

  7. easypoi 多sheet导入_easy-poi: Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件。...

    Easy-POI Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件. 如果喜欢或愿意使用, 请star并且Watch本项目或者移步码云捐赠我们 https://gitee.com/ ...

  8. [Java中实现Excel表导入导出]基于easy-poi和EasyExcel两种方式实现

    第一种:基于easy-poi实现Excel导入导出 1.导出Excel表格 第一步:在pom文件中导入依赖 <!--基于easy-poi实现Excel导入导出--><dependen ...

  9. easypoi导入校验跳过空行_Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件...

    Excel-Boot是一款Excel导入导出解决方案组成的轻量级开源组件. 如果喜欢或愿意使用, 请star本项目或者点击donate图标捐赠我们 如果是企业使用, 为了产品推广, 请通过评论.Iss ...

  10. 注解+反射优雅的实现Excel导入导出(通用版)

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/youzi1394046585/ article/details/86670203 日常在做后 ...

最新文章

  1. php id归零,帝国CMS怎样删除清空栏目和文章数据后新建的栏目和文章ID从1开始
  2. js怎么把按钮往下移_js 实现单行数据上下移动
  3. JDBC连接数据库经验集萃
  4. selenium的使用教程2
  5. React-引领未来的用户界面开发框架-读书笔记(五)
  6. 笔记《javascript高级程序设计》 第12章 DOM2和DOM3
  7. linux系统内存缓冲和磁盘预留
  8. rebase冲突解决
  9. poj 2395 prime的递归实现
  10. “全国住房公积金”微信小程序正式上线 快速办理“异地转移”
  11. java如何集成dubbo_boot集成dubbo踩过的坑
  12. vue-router parmas与query的区别
  13. CentOS6.5 调整 /home 挂载 分区大小
  14. mysql 使用gzip 压缩 文件,本地对 gzip 压缩的文件解压缩
  15. 每日一题/009/微积分/极限/连续
  16. Android编译环境搭建
  17. 普通马甲包app上架App Store5.2.1或3.21被拒原因解析
  18. vue父组给子子组件传html,vue组件之间互相传值:父传子,子传父
  19. 如何快速搭建一个简单图像搜索引擎
  20. 【搬运工】值得一提的生活窍门

热门文章

  1. Linux 上格式化ssd硬盘方法
  2. java8 treemap 排序_TreeSet 和TreeMap 排序
  3. C语言数组排序——选择排序
  4. 计算机专业 在职跨英语,英语在职研究生跨专业可以吗?
  5. 三星Note3开发者模式
  6. 淘宝店铺店名起、分类如何定【太原网络营销师】教你
  7. 【通信原理】第四章 -- 信道
  8. UTF-8编码占几个字节?
  9. java一个字符几个字节_Java 语言中一个字符占几个字节?
  10. 一次性搞懂JavaScript正则表达式之方法