赞
踩
在后端管理系统的开发中,经常有导出当前表格数据的功能,有些前端表格组件可以直接做到,但是不够灵活。因为前端拿到的数据始终是经过处理的,如果想拿到原版数据,必须后端处理。 另外,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
类
-
- * 最简单的读
- * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
- * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
- * <p>3. 直接读即可
- */
- @Test
- public void simpleRead() {
- String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
-
- EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
- }
-
- * 最简单的写
- * <p>1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.DemoData}
- * <p>2. 直接写即可
- */
- @Test
- public void simpleWrite() {
- String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx";
-
-
- EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
- }
-
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.7.1</version>
- <relativePath/>
- </parent>
- <groupId>com.example</groupId>
- <artifactId>SpringBoot-easyexcel</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>SpringBoot-easyexcel</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
-
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
-
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>easyexcel</artifactId>
- <version>3.1.1</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.8.1</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.12</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- </project>
-
-
先展示一下效果。
下面是导出相关的类代码
- package com.example.springbooteasyexcel.controller;
-
- import com.alibaba.excel.EasyExcel;
- import com.alibaba.excel.ExcelWriter;
- import com.alibaba.excel.write.metadata.WriteSheet;
- import com.example.springbooteasyexcel.data.Mock;
- import com.example.springbooteasyexcel.sheet.CitySheet;
- import com.example.springbooteasyexcel.sheet.CompanySheet;
- import com.example.springbooteasyexcel.sheet.UserSheet;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.net.URLEncoder;
-
- @RestController
- @RequestMapping("/export")
- public class ExportController {
-
-
- * @param response
- * @url <a>http://localhost:8080/export/test1</a>
- * 在Excel中写入单个sheet
- */
- @RequestMapping("/test1")
- public void test1(HttpServletResponse response) {
-
- try {
-
- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-
- response.setCharacterEncoding("utf-8");
-
- String fileName = URLEncoder.encode("用户信息表", "UTF-8").replaceAll("\\+", "%20");
-
- response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
-
- EasyExcel.write(response.getOutputStream(), UserSheet.class).inMemory(true).sheet("用户信息表").doWrite(Mock.userList());
- } catch (IOException e) {
- throw new RuntimeException("数据或文件损坏,无法下载");
- }
- }
-
-
- * 在Excel中写入多个sheet
- *
- * @url <a>http://localhost:8080/export/test2</a>
- */
- @RequestMapping("/test2")
- public void test2(HttpServletResponse response) throws Exception {
-
- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-
- response.setCharacterEncoding("utf-8");
-
- String fileName = URLEncoder.encode("信息表", "UTF-8").replaceAll("\\+", "%20");
-
- response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
-
- try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).inMemory(true).build()) {
-
- WriteSheet userInfoSheet = EasyExcel.writerSheet(0, "用户信息表").head(UserSheet.class).build();
- excelWriter.write(Mock.userList(), userInfoSheet);
-
- WriteSheet cityInfoSheet = EasyExcel.writerSheet(1, "城市信息表").head(CitySheet.class).build();
- excelWriter.write(Mock.cityList(), cityInfoSheet);
-
- WriteSheet companyInfoSheet = EasyExcel.writerSheet(2, "公司信息表").head(CompanySheet.class).build();
- excelWriter.write(Mock.companyList(), companyInfoSheet);
- }
- }
- }
-
以下数据均来自于网络,如有侵权,请联系删除
- package com.example.springbooteasyexcel.data;
-
-
- import com.alibaba.excel.enums.CellDataTypeEnum;
- import com.alibaba.excel.metadata.data.RichTextStringData;
- import com.alibaba.excel.metadata.data.WriteCellData;
- import com.alibaba.excel.write.metadata.style.WriteFont;
- import com.example.springbooteasyexcel.sheet.CitySheet;
- import com.example.springbooteasyexcel.sheet.CompanySheet;
- import com.example.springbooteasyexcel.sheet.UserSheet;
- import org.apache.poi.ss.usermodel.IndexedColors;
-
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.List;
-
- public class Mock {
-
- public static List<UserSheet> userList() {
- List<UserSheet> list = new ArrayList<>(10);
- list.add(UserSheet.builder().userId(001L).userName("张三").userPhone("11112223123").userEmail("zhansan@163.com").userAddress("北京朝阳区").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build());
- list.add(UserSheet.builder().userId(002L).userName("李四").userPhone("11112223123").userEmail("lisi@qq.com").userAddress("南京玄武门").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build());
- list.add(UserSheet.builder().userId(003L).userName("王五").userPhone("11112223123").userEmail("wangwu@google.com").userAddress("杭州未来科技城").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build());
- list.add(UserSheet.builder().userId(004L).userName("赵六").userPhone("11112223123").userEmail("zhaoliu@baidu.com").userAddress("上海徐家汇").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build());
- return list;
- }
-
- private static WriteCellData<String> buildCellData(String gender) {
-
- WriteCellData<String> cellData = new WriteCellData<>();
-
- cellData.setType(CellDataTypeEnum.RICH_TEXT_STRING);
-
- RichTextStringData richTextStringData = new RichTextStringData();
- cellData.setRichTextStringDataValue(richTextStringData);
- richTextStringData.setTextString(gender);
- WriteFont writeFont = new WriteFont();
- if ("男".equalsIgnoreCase(gender)) {
-
- writeFont.setColor(IndexedColors.RED.getIndex());
- } else if ("女".equalsIgnoreCase(gender)) {
-
- writeFont.setColor(IndexedColors.GREEN.getIndex());
- }
-
- richTextStringData.applyFont(writeFont);
- return cellData;
- }
-
- public static List<CitySheet> cityList() {
- List<CitySheet> list = new ArrayList<>(10);
- list.add(CitySheet.builder().cityName("杭州市").cityDesc("杭州市一般指杭州。 杭州,简称“杭”,古称临安、钱塘,浙江省辖地级市、省会、副省级市、特大城市、国务院批复确定的浙江省经济、文化、科教中心,长江三角洲中心城市之一,环杭州湾大湾区核心城市、G60科创走廊中心城市。").build());
- list.add(CitySheet.builder().cityName("合肥市").cityDesc("合肥市一般指合肥。 合肥,简称“庐”或“合”,古称庐州、庐阳、合淝,安徽省辖地级市、省会,是合肥都市圈中心城市,国务院批复确定的中国长三角城市群副中心城市,全国四大科教基地、现代制造业基地和综合交通枢纽。").build());
- list.add(CitySheet.builder().cityName("武汉市").cityDesc("武汉市一般指武汉。 武汉,简称“汉”,别称江城,是湖北省省会,中部六省唯一的副省级市,超大城市,中国中部地区的中心城市,全国重要的工业基地、科教基地和综合交通枢纽,联勤保障部队机关驻地。").build());
- list.add(CitySheet.builder().cityName("深圳市").cityDesc("深圳市一般指深圳。 深圳,简称“深”,别称鹏城,广东省辖地级市,是广东省副省级市,国家计划单列市,超大城市,国务院批复确定的中国经济特区、全国性经济中心城市、国际化城市、科技创新中心、区域金融中心、商贸物流中心。").build());
- return list;
- }
-
- public static List<CompanySheet> companyList() {
- List<CompanySheet> list = new ArrayList<>(10);
- list.add(CompanySheet.builder().companyName("阿里巴巴").companyBoss("马云").companyBase("杭州市").companyDesc("阿里巴巴集团经营多项业务,另外也从关联公司的业务和服务中取得经营商业生态系统上的支援。业务和关联公司的业务包括:淘宝网、天猫、聚划算、全球速卖通、阿里巴巴国际交易市场、1688、阿里妈妈、阿里云、蚂蚁集团 [408] 、菜鸟网络等。").build());
- list.add(CompanySheet.builder().companyName("字节跳动").companyBoss("张一鸣").companyBase("北京市").companyDesc("字节跳动的全球化布局始于2015年 [3] ,“技术出海”是字节跳动全球化发展的核心战略 [4] ,其旗下产品有今日头条、西瓜视频、抖音、头条百科、皮皮虾、懂车帝、悟空问答等。").build());
- list.add(CompanySheet.builder().companyName("腾讯").companyBoss("马化腾").companyBase("深圳市").companyDesc("社交和通信服务QQ及微信/WeChat、社交网络平台QQ空间、腾讯游戏旗下QQ游戏平台、门户网站腾讯网、腾讯新闻客户端和网络视频服务腾讯视频等。").build());
- list.add(CompanySheet.builder().companyName("百度").companyBoss("李彦宏").companyBase("北京市").companyDesc("百度(Baidu)是拥有强大互联网基础的领先AI公司。百度愿景是:成为最懂用户,并能帮助人们成长的全球顶级高科技公司。").build());
- return list;
- }
- }
-
-
- package com.example.springbooteasyexcel.sheet;
-
- import com.alibaba.excel.annotation.ExcelProperty;
- import com.alibaba.excel.annotation.write.style.ColumnWidth;
- import lombok.Builder;
- import lombok.Data;
-
- @Data
- @Builder
- public class CitySheet {
-
- @ExcelProperty(value = "城市名称", index = 0)
- @ColumnWidth(10)
- private String cityName;
-
- @ExcelProperty(value = "城市介绍", index = 1)
- @ColumnWidth(60)
- private String cityDesc;
-
- }
-
-
- package com.example.springbooteasyexcel.sheet;
-
-
- import com.alibaba.excel.annotation.ExcelProperty;
- import com.alibaba.excel.annotation.write.style.ColumnWidth;
- import lombok.Builder;
- import lombok.Data;
-
- @Data
- @Builder
- public class CompanySheet {
-
- @ExcelProperty(value = "公司名称", index = 0)
- @ColumnWidth(10)
- private String companyName;
-
- @ExcelProperty(value = "公司创始人", index = 1)
- @ColumnWidth(10)
- private String companyBoss;
-
- @ExcelProperty(value = "公司总基地", index = 2)
- @ColumnWidth(10)
- private String companyBase;
-
- @ExcelProperty(value = "公司简介", index = 3)
- @ColumnWidth(50)
- private String companyDesc;
- }
-
-
- package com.example.springbooteasyexcel.sheet;
-
- import com.alibaba.excel.annotation.ExcelIgnore;
- import com.alibaba.excel.annotation.ExcelProperty;
- import com.alibaba.excel.annotation.write.style.ColumnWidth;
- import com.alibaba.excel.metadata.data.WriteCellData;
- import lombok.Builder;
- import lombok.Data;
-
- import java.util.Date;
-
- @Data
- @Builder
- public class UserSheet {
-
- @ExcelProperty(value = "用户ID", index = 0)
- @ColumnWidth(10)
- private Long userId;
-
- @ExcelProperty(value = "用户名称", index = 1)
- @ColumnWidth(10)
- private String userName;
-
- @ExcelProperty(value = {"基本信息", "手机号码"}, index = 2)
- @ColumnWidth(20)
- private String userPhone;
-
- @ExcelProperty(value = {"基本信息", "电子邮箱"}, index = 3)
- @ColumnWidth(20)
- private String userEmail;
-
- @ExcelProperty(value = {"基本信息", "地址"}, index = 4)
- @ColumnWidth(20)
- private String userAddress;
-
- @ExcelProperty(value = "注册时间", index = 5)
- @ColumnWidth(20)
- private Date registerTime;
-
- @ExcelProperty(value = "性别,男:红色/女:绿色")
- @ColumnWidth(30)
- private WriteCellData<String> gender;
-
-
- * 忽略这个字段
- */
- @ExcelIgnore
- private Integer age;
- }
-
-
- package com.example.springbooteasyexcel;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
- @SpringBootApplication
- public class SpringBootEasyexcelApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(SpringBootEasyexcelApplication.class, args);
- }
-
- }
-
-
Excel导入到数据库,我用一张流程图展示一下如何使用EasyExcel进行导入。
EasyExcel有一个AnalysisEventListener,可以自定义一个Listener继承AnalysisEventListener,里面有一个invoke方法,每条数据都会进入这个方法。我们可以在这里做校验、存储、抛异常等动作,EasyExcel将这些都流程化了,写起代码来非常舒服。当然也有一些点需要注意下,比如自定义Listener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去。
下面是导入相关的一些类代码,最关键的是就是UserExcelReadListener这个,大家可以仔细看看。
- package com.example.springbooteasyexcel.read;
-
- import java.util.Date;
-
- import com.alibaba.excel.annotation.ExcelIgnore;
- import com.alibaba.excel.annotation.ExcelProperty;
- import com.alibaba.excel.annotation.write.style.ColumnWidth;
- import com.alibaba.excel.metadata.data.WriteCellData;
-
- import lombok.AllArgsConstructor;
- import lombok.Builder;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.ToString;
-
- @Data
- @Builder
- @ToString
- @AllArgsConstructor
- @NoArgsConstructor
- public class UserData {
-
- private Long userId;
-
- private String userName;
-
- private Integer age;
-
- private String userPhone;
-
- private String userEmail;
-
- private String userAddress;
-
- private Date registerTime;
-
- private String gender;
-
- }
-
-
- package com.example.springbooteasyexcel.read;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.regex.Pattern;
-
- import com.alibaba.excel.context.AnalysisContext;
- import com.alibaba.excel.event.AnalysisEventListener;
- import com.alibaba.excel.util.ListUtils;
- import com.alibaba.excel.util.StringUtils;
-
- import lombok.extern.slf4j.Slf4j;
-
-
- * 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
- */
- @Slf4j
- public class UserExcelReadListener extends AnalysisEventListener<UserData> {
-
-
- * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
- */
- private static final int BATCH_COUNT = 100;
-
-
- * 创建一个Pattern对象,使用正则表达式校验手机号格式
- */
- private static final Pattern PHONE_REGEX = Pattern.compile("^1[0-9]{10}$");
-
-
- * 缓存的数据
- */
- private List<UserData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
-
-
- * 错误信息列表
- */
- private final List<String> errorMsgList = new ArrayList<>(BATCH_COUNT);
-
- @Override
- public void invoke(UserData userData, AnalysisContext analysisContext) {
- log.info("解析到一条数据:{}", userData);
- int rowIndex = analysisContext.readRowHolder().getRowIndex();
- String name = userData.getUserName();
- String phone = userData.getUserPhone();
- String gender = userData.getGender();
- String email = userData.getUserEmail();
- Integer age = userData.getAge();
- String address = userData.getUserAddress();
-
- if (nameValid(rowIndex, name) && phoneValid(rowIndex, phone) && genderValid(rowIndex, gender) &&
- emailValid(rowIndex, email) && ageValid(rowIndex, age) && addressValid(rowIndex, address)) {
- cachedDataList.add(userData);
- }
-
- if (cachedDataList.size() >= BATCH_COUNT) {
-
-
- cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
- }
- }
-
- @Override
- public void doAfterAllAnalysed(AnalysisContext analysisContext) {
- log.info("所有数据解析完成!全部校验通过的数据有{}条", cachedDataList.size());
-
-
-
- }
-
- @Override
- public void onException(Exception exception, AnalysisContext context) throws Exception {
- if (exception instanceof RuntimeException) {
- throw exception;
- }
- int index = context.readRowHolder().getRowIndex() + 1;
- errorMsgList.add("第" + index + "行解析错误");
- }
-
- @Override
- public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
- int totalRows = context.readSheetHolder().getApproximateTotalRowNumber() - 1;
- int maxNum = 2000;
- if (totalRows > maxNum) {
- errorMsgList.add("数据量过大,单次最多上传2000条");
- throw new RuntimeException("数据量过大,单次最多上传2000条");
- }
- }
-
- public List<String> getErrorMsgList() {
- return errorMsgList;
- }
-
-
- * 名称的校验
- *
- * @param rowIndex 行数
- * @param name 名称
- */
- private Boolean nameValid(Integer rowIndex, String name) {
- if (StringUtils.isBlank(name)) {
- errorMsgList.add("第" + rowIndex + "行,'姓名'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
-
- private Boolean phoneValid(int rowIndex, String phone) {
- if (StringUtils.isBlank(phone)) {
- errorMsgList.add("第" + rowIndex + "行,'手机号'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
-
-
- * 性别的校验
- *
- * @param rowIndex 行数
- * @param gender 性别
- */
- private Boolean genderValid(int rowIndex, String gender) {
- if (StringUtils.isBlank(gender)) {
- errorMsgList.add("第" + rowIndex + "行,'性别'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
-
-
- * 地址校验
- *
- * @param rowIndex 行数
- * @param address 地址
- */
- private Boolean addressValid(int rowIndex, String address) {
-
- if (StringUtils.isBlank(address)) {
- errorMsgList.add("第 " + rowIndex + " 行,'地址'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
-
-
- * 年龄的校验
- *
- * @param rowIndex 行数
- * @param age 年龄
- */
- private Boolean ageValid(int rowIndex, Integer age) {
-
- if (Objects.isNull(age)) {
- errorMsgList.add("第 " + rowIndex + " 行'年龄'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
-
-
- * 邮箱的校验
- *
- * @param rowIndex 行数
- * @param email 邮箱
- */
- private Boolean emailValid(int rowIndex, String email) {
-
- if (StringUtils.isBlank(email)) {
- errorMsgList.add("第 " + rowIndex + " 行'邮箱'不能为空");
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- }
- }
-
-
- package com.example.springbooteasyexcel.read;
-
- import com.alibaba.excel.EasyExcel;
-
- public class ReadExcelTest {
-
- public static void main(String[] args) {
- UserExcelReadListener userExcelReadListener = new UserExcelReadListener();
- EasyExcel.read("用户信息表.xlsx", UserData.class, userExcelReadListener).sheet().doRead();
- System.out.println(userExcelReadListener.getErrorMsgList());
- }
- }
-
-
1、Alibaba EasyExcel不仅支持写Excel,还支持读Excel和填充Excel,有兴趣的话可以自己去研究,官网地址已经贴在上面了,我这里只做一个引路的。
2、常用注解有三个@ExcelProperty
、@ColumnWidth
、@ExcelIgnore
。 (1)@ExcelProperty
不仅确定表头,还可以合并行,用法如下:
- @ExcelProperty(value = {"基本信息", "手机号码"}, index = 2)
- @ColumnWidth(20)
- private String userPhone;
-
- @ExcelProperty(value = {"基本信息", "电子邮箱"}, index = 3)
- @ColumnWidth(20)
- private String userEmail;
-
- @ExcelProperty(value = {"基本信息", "地址"}, index = 4)
- @ColumnWidth(20)
- private String userAddress;
-
效果如下:
(2)@ColumnWidth
主要是控制列宽
(3)@ExcelIgnore
忽略不需要输出的字段 3、写有两种形式 (1)写到文件
-
- * 最简单的写
- * <p>
- * 1. 创建excel对应的实体对象 参照{@link DemoData}
- * <p>
- * 2. 直接写即可
- */
- @Test
- public void simpleWrite() {
-
-
-
-
- String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
-
-
- EasyExcel.write(fileName, DemoData.class)
- .sheet("模板")
- .doWrite(() -> {
-
- return data();
- });
-
-
- fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
-
-
- EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
-
-
- fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
-
- try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
- WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
- excelWriter.write(data(), writeSheet);
- }
- }
-
(2)写到Web流,这里的ContentType和CharacterEncoding不要乱码,否则很容易乱码或者文件损坏
-
- * 文件下载(失败了会返回一个有部分数据的Excel)
- * <p>
- * 1. 创建excel对应的实体对象 参照{@link DownloadData}
- * <p>
- * 2. 设置返回的 参数
- * <p>
- * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
- */
- @GetMapping("download")
- public void download(HttpServletResponse response) throws IOException {
-
- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
- response.setCharacterEncoding("utf-8");
-
- String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
- response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
- EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
- }
-
(3)用好自定义Listener可以很好的优化代码,并且逻辑也可以变得更清晰。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。