当前位置:   article > 正文

SpringBoot整合EasyExcel实现复杂Excel表格的导入&导出功能_springboot读取复杂的excel

springboot读取复杂的excel

在后端管理系统的开发中,经常有导出当前表格数据的功能,有些前端表格组件可以直接做到,但是不够灵活。因为前端拿到的数据始终是经过处理的,如果想拿到原版数据,必须后端处理。 另外,Excel的导入同样也很常见,对于数据的处理也是一件麻烦的事情,常见的工具包如Apache POI可以帮我们简化这些流程,但是它也有一些缺点,比如要创建的类实在是太多了。

那么,除了使用Apache POI包,还有没有其他的选择?当然有! 这里我给大家推荐一款非常简单且容易上手的开源组件:Alibaba EasyExcel

首先放出官网地址,欢迎大家star(目前已经24K): https://alibaba-easyexcel.github.io/docs/current/

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

64M内存20秒读取75M(46W行25列)的Excel(3.0.2+版本)

Alibaba EasyExcel的核心类是EasyExcel

  1.   
  2.      * 最简单的读
  3.      * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  4.      * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
  5.      * <p>3. 直接读即可
  6.      */
  7.     @Test
  8.     public void simpleRead() {
  9.         String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
  10.         
  11.         EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  12.     }
  1.      * 最简单的写
  2.      * <p>1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.DemoData}
  3.      * <p>2. 直接写即可
  4.      */
  5.     @Test
  6.     public void simpleWrite() {
  7.         String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx";
  8.         
  9.         
  10.         EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
  11.     }

1. 项目基本信息

(1)项目结构

(2)pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>org.springframework.boot</groupId>
  7.         <artifactId>spring-boot-starter-parent</artifactId>
  8.         <version>2.7.1</version>
  9.         <relativePath/> 
  10.     </parent>
  11.     <groupId>com.example</groupId>
  12.     <artifactId>SpringBoot-easyexcel</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>SpringBoot-easyexcel</name>
  15.     <description>Demo project for Spring Boot</description>
  16.     <properties>
  17.         <java.version>1.8</java.version>
  18.     </properties>
  19.     <dependencies>
  20.         
  21.         <dependency>
  22.             <groupId>org.springframework.boot</groupId>
  23.             <artifactId>spring-boot-starter-web</artifactId>
  24.         </dependency>
  25.         
  26.         <dependency>
  27.             <groupId>com.alibaba</groupId>
  28.             <artifactId>easyexcel</artifactId>
  29.             <version>3.1.1</version>
  30.         </dependency>
  31.         
  32.         <dependency>
  33.             <groupId>org.apache.commons</groupId>
  34.             <artifactId>commons-lang3</artifactId>
  35.             <version>3.8.1</version>
  36.         </dependency>
  37.         
  38.         <dependency>
  39.             <groupId>org.projectlombok</groupId>
  40.             <artifactId>lombok</artifactId>
  41.             <version>1.18.12</version>
  42.         </dependency>
  43.     </dependencies>
  44.     <build>
  45.         <plugins>
  46.             <plugin>
  47.                 <groupId>org.springframework.boot</groupId>
  48.                 <artifactId>spring-boot-maven-plugin</artifactId>
  49.             </plugin>
  50.         </plugins>
  51.     </build>
  52. </project>

2. 文件导出

先展示一下效果。

(1)单个sheet&表头合并

(2)多个sheet导出

下面是导出相关的类代码

ExportController.java

  1. package com.example.springbooteasyexcel.controller;
  2. import com.alibaba.excel.EasyExcel;
  3. import com.alibaba.excel.ExcelWriter;
  4. import com.alibaba.excel.write.metadata.WriteSheet;
  5. import com.example.springbooteasyexcel.data.Mock;
  6. import com.example.springbooteasyexcel.sheet.CitySheet;
  7. import com.example.springbooteasyexcel.sheet.CompanySheet;
  8. import com.example.springbooteasyexcel.sheet.UserSheet;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RestController;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. import java.net.URLEncoder;
  14. @RestController
  15. @RequestMapping("/export")
  16. public class ExportController {
  17.     
  18.      * @param response
  19.      * @url <a>http://localhost:8080/export/test1</a>
  20.      * 在Excel中写入单个sheet
  21.      */
  22.     @RequestMapping("/test1")
  23.     public void test1(HttpServletResponse response) {
  24.         
  25.         try {
  26.             
  27.             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  28.             
  29.             response.setCharacterEncoding("utf-8");
  30.             
  31.             String fileName = URLEncoder.encode("用户信息表""UTF-8").replaceAll("\\+""%20");
  32.             
  33.             response.setHeader("Content-disposition""attachment;filename*=utf-8''" + fileName + ".xlsx");
  34.             
  35.             EasyExcel.write(response.getOutputStream(), UserSheet.class).inMemory(true).sheet("用户信息表").doWrite(Mock.userList());
  36.         } catch (IOException e) {
  37.             throw new RuntimeException("数据或文件损坏,无法下载");
  38.         }
  39.     }
  40.     
  41.      * 在Excel中写入多个sheet
  42.      *
  43.      * @url <a>http://localhost:8080/export/test2</a>
  44.      */
  45.     @RequestMapping("/test2")
  46.     public void test2(HttpServletResponse response) throws Exception {
  47.         
  48.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  49.         
  50.         response.setCharacterEncoding("utf-8");
  51.         
  52.         String fileName = URLEncoder.encode("信息表""UTF-8").replaceAll("\\+""%20");
  53.         
  54.         response.setHeader("Content-disposition""attachment;filename*=utf-8''" + fileName + ".xlsx");
  55.         
  56.         try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).inMemory(true).build()) {
  57.             
  58.             WriteSheet userInfoSheet = EasyExcel.writerSheet(0"用户信息表").head(UserSheet.class).build();
  59.             excelWriter.write(Mock.userList(), userInfoSheet);
  60.             
  61.             WriteSheet cityInfoSheet = EasyExcel.writerSheet(1"城市信息表").head(CitySheet.class).build();
  62.             excelWriter.write(Mock.cityList(), cityInfoSheet);
  63.             
  64.             WriteSheet companyInfoSheet = EasyExcel.writerSheet(2"公司信息表").head(CompanySheet.class).build();
  65.             excelWriter.write(Mock.companyList(), companyInfoSheet);
  66.         }
  67.     }
  68. }

Mock.java

以下数据均来自于网络,如有侵权,请联系删除

  1. package com.example.springbooteasyexcel.data;
  2. import com.alibaba.excel.enums.CellDataTypeEnum;
  3. import com.alibaba.excel.metadata.data.RichTextStringData;
  4. import com.alibaba.excel.metadata.data.WriteCellData;
  5. import com.alibaba.excel.write.metadata.style.WriteFont;
  6. import com.example.springbooteasyexcel.sheet.CitySheet;
  7. import com.example.springbooteasyexcel.sheet.CompanySheet;
  8. import com.example.springbooteasyexcel.sheet.UserSheet;
  9. import org.apache.poi.ss.usermodel.IndexedColors;
  10. import java.util.ArrayList;
  11. import java.util.Calendar;
  12. import java.util.List;
  13. public class Mock {
  14.     public static List<UserSheet> userList() {
  15.         List<UserSheet> list = new ArrayList<>(10);
  16.         list.add(UserSheet.builder().userId(001L).userName("张三").userPhone("11112223123").userEmail("zhansan@163.com").userAddress("北京朝阳区").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build());
  17.         list.add(UserSheet.builder().userId(002L).userName("李四").userPhone("11112223123").userEmail("lisi@qq.com").userAddress("南京玄武门").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build());
  18.         list.add(UserSheet.builder().userId(003L).userName("王五").userPhone("11112223123").userEmail("wangwu@google.com").userAddress("杭州未来科技城").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build());
  19.         list.add(UserSheet.builder().userId(004L).userName("赵六").userPhone("11112223123").userEmail("zhaoliu@baidu.com").userAddress("上海徐家汇").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build());
  20.         return list;
  21.     }
  22.     private static WriteCellData<String> buildCellData(String gender) {
  23.         
  24.         WriteCellData<String> cellData = new WriteCellData<>();
  25.         
  26.         cellData.setType(CellDataTypeEnum.RICH_TEXT_STRING);
  27.         
  28.         RichTextStringData richTextStringData = new RichTextStringData();
  29.         cellData.setRichTextStringDataValue(richTextStringData);
  30.         richTextStringData.setTextString(gender);
  31.         WriteFont writeFont = new WriteFont();
  32.         if ("男".equalsIgnoreCase(gender)) {
  33.          
  34.             writeFont.setColor(IndexedColors.RED.getIndex());
  35.         } else if ("女".equalsIgnoreCase(gender)) {
  36.          
  37.             writeFont.setColor(IndexedColors.GREEN.getIndex());
  38.         }
  39.         
  40.         richTextStringData.applyFont(writeFont);
  41.         return cellData;
  42.     }
  43.     public static List<CitySheet> cityList() {
  44.         List<CitySheet> list = new ArrayList<>(10);
  45.         list.add(CitySheet.builder().cityName("杭州市").cityDesc("杭州市一般指杭州。 杭州,简称“杭”,古称临安、钱塘,浙江省辖地级市、省会、副省级市、特大城市、国务院批复确定的浙江省经济、文化、科教中心,长江三角洲中心城市之一,环杭州湾大湾区核心城市、G60科创走廊中心城市。").build());
  46.         list.add(CitySheet.builder().cityName("合肥市").cityDesc("合肥市一般指合肥。 合肥,简称“庐”或“合”,古称庐州、庐阳、合淝,安徽省辖地级市、省会,是合肥都市圈中心城市,国务院批复确定的中国长三角城市群副中心城市,全国四大科教基地、现代制造业基地和综合交通枢纽。").build());
  47.         list.add(CitySheet.builder().cityName("武汉市").cityDesc("武汉市一般指武汉。 武汉,简称“汉”,别称江城,是湖北省省会,中部六省唯一的副省级市,超大城市,中国中部地区的中心城市,全国重要的工业基地、科教基地和综合交通枢纽,联勤保障部队机关驻地。").build());
  48.         list.add(CitySheet.builder().cityName("深圳市").cityDesc("深圳市一般指深圳。 深圳,简称“深”,别称鹏城,广东省辖地级市,是广东省副省级市,国家计划单列市,超大城市,国务院批复确定的中国经济特区、全国性经济中心城市、国际化城市、科技创新中心、区域金融中心、商贸物流中心。").build());
  49.         return list;
  50.     }
  51.     public static List<CompanySheet> companyList() {
  52.         List<CompanySheet> list = new ArrayList<>(10);
  53.         list.add(CompanySheet.builder().companyName("阿里巴巴").companyBoss("马云").companyBase("杭州市").companyDesc("阿里巴巴集团经营多项业务,另外也从关联公司的业务和服务中取得经营商业生态系统上的支援。业务和关联公司的业务包括:淘宝网、天猫、聚划算、全球速卖通、阿里巴巴国际交易市场、1688、阿里妈妈、阿里云、蚂蚁集团 [408]  、菜鸟网络等。").build());
  54.         list.add(CompanySheet.builder().companyName("字节跳动").companyBoss("张一鸣").companyBase("北京市").companyDesc("字节跳动的全球化布局始于2015年 [3]  ,“技术出海”是字节跳动全球化发展的核心战略 [4]  ,其旗下产品有今日头条、西瓜视频、抖音、头条百科、皮皮虾、懂车帝、悟空问答等。").build());
  55.         list.add(CompanySheet.builder().companyName("腾讯").companyBoss("马化腾").companyBase("深圳市").companyDesc("社交和通信服务QQ及微信/WeChat、社交网络平台QQ空间、腾讯游戏旗下QQ游戏平台、门户网站腾讯网、腾讯新闻客户端和网络视频服务腾讯视频等。").build());
  56.         list.add(CompanySheet.builder().companyName("百度").companyBoss("李彦宏").companyBase("北京市").companyDesc("百度(Baidu)是拥有强大互联网基础的领先AI公司。百度愿景是:成为最懂用户,并能帮助人们成长的全球顶级高科技公司。").build());
  57.         return list;
  58.     }
  59. }

CitySheet.java

  1. package com.example.springbooteasyexcel.sheet;
  2. import com.alibaba.excel.annotation.ExcelProperty;
  3. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  4. import lombok.Builder;
  5. import lombok.Data;
  6. @Data
  7. @Builder
  8. public class CitySheet {
  9.     @ExcelProperty(value = "城市名称", index = 0)
  10.     @ColumnWidth(10)
  11.     private String cityName;
  12.     @ExcelProperty(value = "城市介绍", index = 1)
  13.     @ColumnWidth(60)
  14.     private String cityDesc;
  15. }

CompanySheet.java

  1. package com.example.springbooteasyexcel.sheet;
  2. import com.alibaba.excel.annotation.ExcelProperty;
  3. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  4. import lombok.Builder;
  5. import lombok.Data;
  6. @Data
  7. @Builder
  8. public class CompanySheet {
  9.     @ExcelProperty(value = "公司名称", index = 0)
  10.     @ColumnWidth(10)
  11.     private String companyName;
  12.     @ExcelProperty(value = "公司创始人", index = 1)
  13.     @ColumnWidth(10)
  14.     private String companyBoss;
  15.     @ExcelProperty(value = "公司总基地", index = 2)
  16.     @ColumnWidth(10)
  17.     private String companyBase;
  18.     @ExcelProperty(value = "公司简介", index = 3)
  19.     @ColumnWidth(50)
  20.     private String companyDesc;
  21. }

UserSheet.java

  1. package com.example.springbooteasyexcel.sheet;
  2. import com.alibaba.excel.annotation.ExcelIgnore;
  3. import com.alibaba.excel.annotation.ExcelProperty;
  4. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  5. import com.alibaba.excel.metadata.data.WriteCellData;
  6. import lombok.Builder;
  7. import lombok.Data;
  8. import java.util.Date;
  9. @Data
  10. @Builder
  11. public class UserSheet {
  12.     @ExcelProperty(value = "用户ID", index = 0)
  13.     @ColumnWidth(10)
  14.     private Long userId;
  15.     @ExcelProperty(value = "用户名称", index = 1)
  16.     @ColumnWidth(10)
  17.     private String userName;
  18.     @ExcelProperty(value = {"基本信息""手机号码"}, index = 2)
  19.     @ColumnWidth(20)
  20.     private String userPhone;
  21.     @ExcelProperty(value = {"基本信息""电子邮箱"}, index = 3)
  22.     @ColumnWidth(20)
  23.     private String userEmail;
  24.     @ExcelProperty(value = {"基本信息""地址"}, index = 4)
  25.     @ColumnWidth(20)
  26.     private String userAddress;
  27.     @ExcelProperty(value = "注册时间", index = 5)
  28.     @ColumnWidth(20)
  29.     private Date registerTime;
  30.     @ExcelProperty(value = "性别,男:红色/女:绿色")
  31.     @ColumnWidth(30)
  32.     private WriteCellData<String> gender;
  33.     
  34.      * 忽略这个字段
  35.      */
  36.     @ExcelIgnore
  37.     private Integer age;
  38. }

SpringBootEasyexcelApplication.java

  1. package com.example.springbooteasyexcel;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class SpringBootEasyexcelApplication {
  6.     public static void main(String[] args) {
  7.         SpringApplication.run(SpringBootEasyexcelApplication.class, args);
  8.     }
  9. }

3. 文件导入

Excel导入到数据库,我用一张流程图展示一下如何使用EasyExcel进行导入。

EasyExcel有一个AnalysisEventListener,可以自定义一个Listener继承AnalysisEventListener,里面有一个invoke方法,每条数据都会进入这个方法。我们可以在这里做校验、存储、抛异常等动作,EasyExcel将这些都流程化了,写起代码来非常舒服。当然也有一些点需要注意下,比如自定义Listener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去。

下面是导入相关的一些类代码,最关键的是就是UserExcelReadListener这个,大家可以仔细看看。

UserData.java

  1. package com.example.springbooteasyexcel.read;
  2. import java.util.Date;
  3. import com.alibaba.excel.annotation.ExcelIgnore;
  4. import com.alibaba.excel.annotation.ExcelProperty;
  5. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  6. import com.alibaba.excel.metadata.data.WriteCellData;
  7. import lombok.AllArgsConstructor;
  8. import lombok.Builder;
  9. import lombok.Data;
  10. import lombok.NoArgsConstructor;
  11. import lombok.ToString;
  12. @Data
  13. @Builder
  14. @ToString
  15. @AllArgsConstructor
  16. @NoArgsConstructor
  17. public class UserData {
  18.     private Long userId;
  19.     private String userName;
  20.     private Integer age;
  21.     private String userPhone;
  22.     private String userEmail;
  23.     private String userAddress;
  24.     private Date registerTime;
  25.     private String gender;
  26. }

UserExcelReadListener.java

  1. package com.example.springbooteasyexcel.read;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Map;
  5. import java.util.Objects;
  6. import java.util.regex.Pattern;
  7. import com.alibaba.excel.context.AnalysisContext;
  8. import com.alibaba.excel.event.AnalysisEventListener;
  9. import com.alibaba.excel.util.ListUtils;
  10. import com.alibaba.excel.util.StringUtils;
  11. import lombok.extern.slf4j.Slf4j;
  12.  * 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
  13.  */
  14. @Slf4j
  15. public class UserExcelReadListener extends AnalysisEventListener<UserData> {
  16.     
  17.      * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
  18.      */
  19.     private static final int BATCH_COUNT = 100;
  20.     
  21.      * 创建一个Pattern对象,使用正则表达式校验手机号格式
  22.      */
  23.     private static final Pattern PHONE_REGEX = Pattern.compile("^1[0-9]{10}$");
  24.     
  25.      * 缓存的数据
  26.      */
  27.     private List<UserData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
  28.     
  29.      * 错误信息列表
  30.      */
  31.     private final List<String> errorMsgList = new ArrayList<>(BATCH_COUNT);
  32.     @Override
  33.     public void invoke(UserData userData, AnalysisContext analysisContext) {
  34.         log.info("解析到一条数据:{}", userData);
  35.         int rowIndex = analysisContext.readRowHolder().getRowIndex();
  36.         String name = userData.getUserName();
  37.         String phone = userData.getUserPhone();
  38.         String gender = userData.getGender();
  39.         String email = userData.getUserEmail();
  40.         Integer age = userData.getAge();
  41.         String address = userData.getUserAddress();
  42.         
  43.         if (nameValid(rowIndex, name) && phoneValid(rowIndex, phone) && genderValid(rowIndex, gender) &&
  44.             emailValid(rowIndex, email) && ageValid(rowIndex, age) && addressValid(rowIndex, address)) {
  45.             cachedDataList.add(userData);
  46.         }
  47.         
  48.         if (cachedDataList.size() >= BATCH_COUNT) {
  49.             
  50.             
  51.             cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
  52.         }
  53.     }
  54.     @Override
  55.     public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  56.         log.info("所有数据解析完成!全部校验通过的数据有{}条", cachedDataList.size());
  57.         
  58.         
  59.     }
  60.     @Override
  61.     public void onException(Exception exception, AnalysisContext context) throws Exception {
  62.         if (exception instanceof RuntimeException) {
  63.             throw exception;
  64.         }
  65.         int index = context.readRowHolder().getRowIndex() + 1;
  66.         errorMsgList.add("第" + index + "行解析错误");
  67.     }
  68.     @Override
  69.     public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
  70.         int totalRows = context.readSheetHolder().getApproximateTotalRowNumber() - 1;
  71.         int maxNum = 2000;
  72.         if (totalRows > maxNum) {
  73.             errorMsgList.add("数据量过大,单次最多上传2000条");
  74.             throw new RuntimeException("数据量过大,单次最多上传2000条");
  75.         }
  76.     }
  77.     public List<String> getErrorMsgList() {
  78.         return errorMsgList;
  79.     }
  80.     
  81.      * 名称的校验
  82.      *
  83.      * @param rowIndex 行数
  84.      * @param name     名称
  85.      */
  86.     private Boolean nameValid(Integer rowIndex, String name) {
  87.         if (StringUtils.isBlank(name)) {
  88.             errorMsgList.add("第" + rowIndex + "行,'姓名'不能为空");
  89.             return Boolean.FALSE;
  90.         }
  91.         return Boolean.TRUE;
  92.     }
  93.     private Boolean phoneValid(int rowIndex, String phone) {
  94.         if (StringUtils.isBlank(phone)) {
  95.             errorMsgList.add("第" + rowIndex + "行,'手机号'不能为空");
  96.             return Boolean.FALSE;
  97.         }
  98.         return Boolean.TRUE;
  99.     }
  100.     
  101.      * 性别的校验
  102.      *
  103.      * @param rowIndex 行数
  104.      * @param gender   性别
  105.      */
  106.     private Boolean genderValid(int rowIndex, String gender) {
  107.         if (StringUtils.isBlank(gender)) {
  108.             errorMsgList.add("第" + rowIndex + "行,'性别'不能为空");
  109.             return Boolean.FALSE;
  110.         }
  111.         return Boolean.TRUE;
  112.     }
  113.     
  114.      * 地址校验
  115.      *
  116.      * @param rowIndex 行数
  117.      * @param address  地址
  118.      */
  119.     private Boolean addressValid(int rowIndex, String address) {
  120.         
  121.         if (StringUtils.isBlank(address)) {
  122.             errorMsgList.add("第 " + rowIndex + " 行,'地址'不能为空");
  123.             return Boolean.FALSE;
  124.         }
  125.         return Boolean.TRUE;
  126.     }
  127.     
  128.      * 年龄的校验
  129.      *
  130.      * @param rowIndex 行数
  131.      * @param age      年龄
  132.      */
  133.     private Boolean ageValid(int rowIndex, Integer age) {
  134.         
  135.         if (Objects.isNull(age)) {
  136.             errorMsgList.add("第 " + rowIndex + " 行'年龄'不能为空");
  137.             return Boolean.FALSE;
  138.         }
  139.         return Boolean.TRUE;
  140.     }
  141.     
  142.      * 邮箱的校验
  143.      *
  144.      * @param rowIndex 行数
  145.      * @param email    邮箱
  146.      */
  147.     private Boolean emailValid(int rowIndex, String email) {
  148.         
  149.         if (StringUtils.isBlank(email)) {
  150.             errorMsgList.add("第 " + rowIndex + " 行'邮箱'不能为空");
  151.             return Boolean.FALSE;
  152.         }
  153.         return Boolean.TRUE;
  154.     }
  155. }
  1. package com.example.springbooteasyexcel.read;
  2. import com.alibaba.excel.EasyExcel;
  3. public class ReadExcelTest {
  4.     public static void main(String[] args) {
  5.         UserExcelReadListener userExcelReadListener = new UserExcelReadListener();
  6.         EasyExcel.read("用户信息表.xlsx"UserData.class, userExcelReadListener).sheet().doRead();
  7.         System.out.println(userExcelReadListener.getErrorMsgList());
  8.     }
  9. }

执行结果

1、Alibaba EasyExcel不仅支持写Excel,还支持读Excel和填充Excel,有兴趣的话可以自己去研究,官网地址已经贴在上面了,我这里只做一个引路的。

2、常用注解有三个@ExcelProperty@ColumnWidth@ExcelIgnore。 (1)@ExcelProperty不仅确定表头,还可以合并行,用法如下:

  1.   @ExcelProperty(value = {"基本信息""手机号码"}, index = 2)
  2.     @ColumnWidth(20)
  3.     private String userPhone;
  4.     @ExcelProperty(value = {"基本信息""电子邮箱"}, index = 3)
  5.     @ColumnWidth(20)
  6.     private String userEmail;
  7.     @ExcelProperty(value = {"基本信息""地址"}, index = 4)
  8.     @ColumnWidth(20)
  9.     private String userAddress;

效果如下:

(2)@ColumnWidth主要是控制列宽

(3)@ExcelIgnore忽略不需要输出的字段 3、写有两种形式 (1)写到文件

  1.   
  2.      * 最简单的写
  3.      * <p>
  4.      * 1. 创建excel对应的实体对象 参照{@link DemoData}
  5.      * <p>
  6.      * 2. 直接写即可
  7.      */
  8.     @Test
  9.     public void simpleWrite() {
  10.         
  11.         
  12.         
  13.         String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  14.         
  15.         
  16.         EasyExcel.write(fileName, DemoData.class)
  17.             .sheet("模板")
  18.             .doWrite(() -> {
  19.                 
  20.                 return data();
  21.             });
  22.         
  23.         fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  24.         
  25.         
  26.         EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
  27.         
  28.         fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  29.         
  30.         try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
  31.             WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
  32.             excelWriter.write(data(), writeSheet);
  33.         }
  34.     }

(2)写到Web流,这里的ContentType和CharacterEncoding不要乱码,否则很容易乱码或者文件损坏

  1.  
  2.      * 文件下载(失败了会返回一个有部分数据的Excel)
  3.      * <p>
  4.      * 1. 创建excel对应的实体对象 参照{@link DownloadData}
  5.      * <p>
  6.      * 2. 设置返回的 参数
  7.      * <p>
  8.      * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
  9.      */
  10.     @GetMapping("download")
  11.     public void download(HttpServletResponse response) throws IOException {
  12.         
  13.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  14.         response.setCharacterEncoding("utf-8");
  15.         
  16.         String fileName = URLEncoder.encode("测试""UTF-8").replaceAll("\\+""%20");
  17.         response.setHeader("Content-disposition""attachment;filename*=utf-8''" + fileName + ".xlsx");
  18.         EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
  19.     }

(3)用好自定义Listener可以很好的优化代码,并且逻辑也可以变得更清晰。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码艺术家/article/detail/61118
推荐阅读
相关标签
  

闽ICP备14008679号