
Springboot与easypoi(1):介绍、注解、基础使用
ApiModel("用户实体类")@Data@ApiModelProperty("用户id")@Excel(name = "用户id", orderNum = "0")@ApiModelProperty("用户名")@Excel(name = "用户名", orderNum = "1")@ApiModelProperty("密码")@Excel(name = "密码", orderNum = "2
1 介绍
Easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。在项目中添加依赖即可:
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
2 相关注解
注解有5类分别是:
- @Excel 作用到filed上面,是对Excel一列的一个描述
- @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
- @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
- @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
- @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
2.1 @Excel
这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求。
属性 | 类型 | 默认值 | 功能 | 强调说明 |
---|---|---|---|---|
name | String | null | 列名 | |
groupName | String | null | 列名组 | @Excel(name="语文", groupName="分数")。分数则为一级标题,语文则为二级标题。 |
needMerge | boolean | fasle | 是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row) | |
orderNum | String | "0" | 列的排序 | |
replace | String[] | {} | 值的替换,导出是{"a_1", "b_2"} 导入反过来。1和2是要被替换的值。a和b则是替换后的值。 | @Excel(replace={"男_1",“女_2”}),当导出时,对象属性值是1则导出的Excel对应单元格为男;导入Excel时,单元格为男则对应的对象属性值为1。如果没有对应的值,则不会进行转换。 |
savePath | String | "upload" | 导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/ | |
type | int | 1 | 导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 | 拥有排名字段时请勿将该值设置成10。这样会导致合计这种无需排名的列也会显式成0。 |
width | double | 10 | 列宽 | |
height | double | 10 | 列高,后期打算统一使用@ExcelTarget的height,这个会被废弃 | |
isStatistics | boolean | fasle | 自动统计数据,在追加一行统计,把所有数据都和输出。这个处理会吞没异常,请注意这一点 | |
isHyperlink | boolean | false | 超链接,如果是需要实现接口返回对象 | |
isImportField | boolean | true | 校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败 | |
exportFormat | String | "" | 导出的时间格式,以这个是否为空来判断是否需要格式化日期 | |
importFormat | String | "" | 导入的时间格式,以这个是否为空来判断是否需要格式化日期 | Excel时间会固定显示成yyyy/MM/dd格式,需要使用该属性转换成想要的格式。 |
format | String | "" | 时间格式,相当于同时设置了exportFormat 和 importFormat | |
databaseFormat | String | "yyyyMMddHHmmss" | 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 | |
numFormat | String | "" | 数字格式化,参数是Pattern,使用的对象是DecimalFormat | |
imageType | int | 1 | 导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 | |
suffix | String | "" | 文字后缀,如% 90 变成90% | |
isWrap | boolean | true | 是否换行 即支持\n | |
mergeRely | int[] | {} | 合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了 | |
mergeVertical | boolean | fasle | 纵向合并内容相同的单元格 | |
fixedIndex | int | -1 | 对应excel的列,忽略名字 | |
isColumnHidden | boolean | false | 导出隐藏列 |
2.2 @ExcelTarget
限定一个导出实体的注解,以及一些通用设置,作用于最外面的实体。
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
value | String | null | 定义ID |
height | double | 10 | 设置行高 |
fontSize | short | 11 | 设置文字大小 |
2.3 @ExcelEntity
标记是不是导出excel 标记为实体类,标记是否继续穿透,可以自定义内部id。
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
2.4 @ExcelCollection
一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
id | String | null | 定义ID |
name | String | null | 定义集合列名 |
orderNum | int | 0 | 排序 |
type | Class<?> | ArrayList.class | 导入时创建对象使用 |
2.5 @ExcelIgnore
忽略这个属性,多使用需循环引用中。
3 easypoi提供的类
3.1 ExportParams
导出参数,主要来定义 Excel的一些信息,在ExcelExportUtil 里面进行文件导出的,都是使用这个参数来作为导出参数。
/**
* Excel 导出参数
*/
@Data
public class ExportParams extends ExcelBaseParams {
/**
* 表格第一行title名称
*/
private String title;
/**
* 表格第一行title高度
*/
private short titleHeight = 10;
/**
* 表格第一行子title名称
*/
private String secondTitle;
/**
* 表格第一行子title高度
*/
private short secondTitleHeight = 8;
/**
* sheetName
*/
private String sheetName;
/**
* 过滤的属性
*/
private String[] exclusions;
/**
* 是否添加index
*/
private boolean addIndex;
/**
* index名称
*/
private String indexName = "序号";
/**
* 冰冻列
*/
private int freezeCol;
/**
* 表头颜色 & 标题颜色
*/
private short color = HSSFColor.HSSFColorPredefined.WHITE.getIndex();
/**
* 第二行标题颜色
* 属性说明行的颜色 例如:HSSFColor.SKY_BLUE.index 默认
*/
private short headerColor = HSSFColor.HSSFColorPredefined.SKY_BLUE.getIndex();
/**
* Excel 导出版本
*/
private ExcelType type = ExcelType.HSSF;
/**
* Excel 导出style
*/
private Class<?> style = ExcelExportStylerDefaultImpl.class;
/**
* 表头高度
*/
private double headerHeight = 9D;
/**
* 是否创建表头
*/
private boolean isCreateHeadRows = true;
/**
* 是否动态获取数据
*/
private boolean isDynamicData = false;
/**
* 是否追加图形
*/
private boolean isAppendGraph = true;
/**
* 是否固定表头
*/
private boolean isFixedTitle = true;
/**
* 单sheet最大值
* 03版本默认6W行,07默认100W
*/
private int maxNum = 0;
/**
* 导出时在excel中每个列的高度 单位为字符,一个汉字=2个字符
* 全局设置,优先使用
*/
private short height = 0;
/**
* 只读
*/
private boolean readonly = false;
/**
* 列宽自适应,如果没有设置width 也自适应宽度
*/
private boolean autoSize = false;
public ExportParams() {
}
public ExportParams(String title, String sheetName) {
this.title = title;
this.sheetName = sheetName;
}
public ExportParams(String title, String sheetName, ExcelType type) {
this.title = title;
this.sheetName = sheetName;
this.type = type;
}
public ExportParams(String title, String secondTitle, String sheetName) {
this.title = title;
this.secondTitle = secondTitle;
this.sheetName = sheetName;
}
public short getSecondTitleHeight() {
return (short) (secondTitleHeight * 50);
}
public short getTitleHeight() {
return (short) (titleHeight * 50);
}
public short getHeight() {
return height == -1 ? -1 : (short) (height * 50);
}
public short getHeaderHeight() {
return (short) (titleHeight * 50);
}
}
3.2 ExcelExportUtil
导出工具类。构造导出需要的参数ExportParams,用该类中的静态方法进行导出指定excel文件。源码中对应的方法与参数含义如下:
/**
* excel 导出工具类
*/
public final class ExcelExportUtil {
public static int USE_SXSSF_LIMIT = 1000000;
public static final String SHEET_NAME = "sheetName";
private ExcelExportUtil() {
}
/**
* 大数据量导出
*
* @param entity 表格标题属性
* @param pojoClass Excel对象Class
*/
public static IWriter<Workbook> exportBigExcel(ExportParams entity, Class<?> pojoClass) {
ExcelBatchExportService batchServer = new ExcelBatchExportService();
batchServer.init(entity, pojoClass);
return batchServer;
}
/**
* 大数据量导出
*
* @param entity 表格标题属性
* @param excelParams cell映射类参数list
* @return
*/
public static IWriter<Workbook> exportBigExcel(ExportParams entity, List<ExcelExportEntity> excelParams) {
ExcelBatchExportService batchServer = new ExcelBatchExportService();
batchServer.init(entity, excelParams);
return batchServer;
}
/**
* 大数据量导出
*
* @param entity 表格标题属性
* @param pojoClass Excel对象Class
* @param server 查询数据的接口
* @param queryParams 查询数据的参数
*/
public static Workbook exportBigExcel(ExportParams entity, Class<?> pojoClass,
IExcelExportServer server, Object queryParams) {
ExcelBatchExportService batchServer = new ExcelBatchExportService();
batchServer.init(entity, pojoClass);
return batchServer.exportBigExcel(server, queryParams);
}
/**
* 大数据量导出
* @param entity 表格标题属性
* @param excelParams 表格标题属性
* @param server 查询数据的接口
* @param queryParams 查询数据的参数
* @return
*/
public static Workbook exportBigExcel(ExportParams entity, List<ExcelExportEntity> excelParams,
IExcelExportServer server, Object queryParams) {
ExcelBatchExportService batchServer = new ExcelBatchExportService();
batchServer.init(entity, excelParams);
return batchServer.exportBigExcel(server, queryParams);
}
/**
* @param entity 表格标题属性
* @param pojoClass Excel对象Class
* @param dataSet Excel对象数据List
*/
public static Workbook exportExcel(ExportParams entity, Class<?> pojoClass,
Collection<?> dataSet) {
Workbook workbook = getWorkbook(entity.getType(), dataSet.size());
new ExcelExportService().createSheet(workbook, entity, pojoClass, dataSet);
return workbook;
}
private static Workbook getWorkbook(ExcelType type, int size) {
if (ExcelType.HSSF.equals(type)) {
return new HSSFWorkbook();
} else {
return new XSSFWorkbook();
}
}
/**
* 根据Map创建对应的Excel
*
* @param entity 表格标题属性
* @param entityList Map对象列表
* @param dataSet Excel对象数据List
*/
public static Workbook exportExcel(ExportParams entity, List<ExcelExportEntity> entityList,
Collection<?> dataSet) {
Workbook workbook = getWorkbook(entity.getType(), dataSet.size());
;
new ExcelExportService().createSheetForMap(workbook, entity, entityList, dataSet);
return workbook;
}
/**
* 根据Map创建对应的Excel(一个excel 创建多个sheet)
*
* @param list 多个Map key title 对应表格Title key entity 对应表格对应实体 key data
* Collection 数据
*/
public static Workbook exportExcel(List<Map<String, Object>> list, ExcelType type) {
Workbook workbook = getWorkbook(type, 0);
for (Map<String, Object> map : list) {
ExcelExportService service = new ExcelExportService();
ExportParams params = (ExportParams) map.get("title");
params.setType(type);
service.createSheet(workbook,params,
(Class<?>) map.get("entity"), (Collection<?>) map.get("data"));
}
return workbook;
}
/**
* 导出文件通过模板解析,不推荐这个了,推荐全部通过模板来执行处理
* @param params 导出参数类
* @param pojoClass 对应实体
* @param dataSet 实体集合
* @param map 模板集合
* @return
*/
@Deprecated
public static Workbook exportExcel(TemplateExportParams params, Class<?> pojoClass,
Collection<?> dataSet, Map<String, Object> map) {
return new ExcelExportOfTemplateUtil().createExcelByTemplate(params, pojoClass, dataSet,
map);
}
/**
* 导出文件通过模板解析只有模板,没有集合
*
* @param params 导出参数类
* @param map 模板集合
* @return
*/
public static Workbook exportExcel(TemplateExportParams params, Map<String, Object> map) {
return new ExcelExportOfTemplateUtil().createExcelByTemplate(params, null, null, map);
}
/**
* 导出文件通过模板解析只有模板,没有集合
* 每个sheet对应一个map,导出到处,key是sheet的NUM
*
* @param params 导出参数类
* @param map 模板集合
* @return
*/
public static Workbook exportExcel(Map<Integer, Map<String, Object>> map,
TemplateExportParams params) {
return new ExcelExportOfTemplateUtil().createExcelByTemplate(params, map);
}
/**
* 导出文件通过模板解析只有模板,没有集合
* 每个sheet对应一个list,按照数量进行导出排序,key是sheet的NUM
*
* @param params 导出参数类
* @param map 模板集合
* @return
*/
public static Workbook exportExcelClone(Map<Integer, List<Map<String, Object>>> map,
TemplateExportParams params) {
return new ExcelExportOfTemplateUtil().createExcelCloneByTemplate(params, map);
}
}
3.3 ImportParams
导入的参数设置,主要根据你文件里面的内容的格式来进行设置。
/**
* 导入参数设置
*/
@Data
public class ImportParams extends ExcelBaseParams {
public static final String SAVE_URL = "/excel/upload/excelUpload";
/**
* 表格标题行数,默认0
*/
private int titleRows = 0;
/**
* 表头行数,默认1
*/
private int headRows = 1;
/**
* 字段真正值和列标题之间的距离 默认0
*/
private int startRows = 0;
/**
* 主键设置,如何这个cell没有值,就跳过 或者认为这个是list的下面的值
* 大家不理解,去掉这个
*/
private Integer keyIndex = null;
/**
* 开始读取的sheet位置,默认为0
*/
private int startSheetIndex = 0;
/**
* 上传表格需要读取的sheet 数量,默认为1
*/
private int sheetNum = 1;
/**
* 是否需要保存上传的Excel,默认为false
*/
private boolean needSave = false;
/**
* 校验组
*/
private Class[] verifyGroup = null;
/**
* 是否需要校验上传的Excel,默认为false
*/
private boolean needVerify = false;
/**
* 返回文件是否分割,默认是分割
*/
private boolean verifyFileSplit = true;
/**
* 校验处理接口
*/
private IExcelVerifyHandler verifyHandler;
/**
* 保存上传的Excel目录,默认是 如 TestEntity这个类保存路径就是
* upload/excelUpload/Test/yyyyMMddHHmss_***** 保存名称上传时间_五位随机数
*/
private String saveUrl = SAVE_URL;
/**
* 最后的无效行数
*/
private int lastOfInvalidRow = 0;
/**
* 手动控制读取的行数
*/
private int readRows = 0;
/**
* 导入时校验数据模板,是不是正确的Excel
*/
private String[] importFields;
/**
* 导入时校验excel的标题列顺序。依赖于importFields的配置顺序
*/
private boolean needCheckOrder = false;
/**
* Key-Value 读取标记,以这个为Key,后面一个Cell 为Value,多个改为ArrayList
*/
private String keyMark = ":";
/**
* 按照Key-Value 规则读取全局扫描Excel,但是跳过List读取范围提升性能
* 仅仅支持titleRows + headRows + startRows 以及 lastOfInvalidRow
*/
private boolean readSingleCell = false;
/**
* 是否并行计算
*/
private boolean concurrentTask = false;
/**
* 最小截取大小
*/
private Integer critical = 1000;
}
3.4 ExcelImportUtil
导入工具。传入的文件、导出的entity的类,对应的import的参数来进行文件的导入。
/**
* Excel 导入工具
*/
@SuppressWarnings({ "unchecked" })
public class ExcelImportUtil {
private ExcelImportUtil() {
}
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelImportUtil.class);
/**
* Excel 导入 数据源本地文件,不返回校验结果 导入 字 段类型 Integer,Long,Double,Date,String,Boolean
*
* @param file 导入的文件
* @param pojoClass 需要导入数据成的entity类
* @param params 导入的参数
* @return
*/
public static <T> List<T> importExcel(File file, Class<?> pojoClass, ImportParams params) {
FileInputStream in = null;
try {
in = new FileInputStream(file);
return new ExcelImportService().importExcelByIs(in, pojoClass, params, false).getList();
} catch (ExcelImportException e) {
throw new ExcelImportException(e.getType(), e);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(in);
}
}
/**
* Excel 导入 数据源IO流,不返回校验结果 导入 字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param inputstream 文件流
* @param pojoClass 需要导入数据成的entity类
* @param params 导入的参数
*/
public static <T> List<T> importExcel(InputStream inputstream, Class<?> pojoClass,
ImportParams params) throws Exception {
return new ExcelImportService().importExcelByIs(inputstream, pojoClass, params, false).getList();
}
/**
* Excel 导入 数据源IO流 字段类型 Integer,Long,Double,Date,String,Boolean
* 支持校验,支持Key-Value
*
* @param inputstream 文件流
* @param pojoClass 需要导入数据成的entity类
* @param params 导入的参数
*/
public static <T> ExcelImportResult<T> importExcelMore(InputStream inputstream,
Class<?> pojoClass,
ImportParams params) throws Exception {
return new ExcelImportService().importExcelByIs(inputstream, pojoClass, params, true);
}
/**
* Excel 导入 数据源本地文件 字段类型 Integer,Long,Double,Date,String,Boolean
* 支持校验,支持Key-Value
* @param inputstream 文件流
* @param pojoClass 需要导入数据成的entity类
* @param params 导入的参数
*/
public static <T> ExcelImportResult<T> importExcelMore(File file, Class<?> pojoClass,
ImportParams params) {
FileInputStream in = null;
try {
in = new FileInputStream(file);
return new ExcelImportService().importExcelByIs(in, pojoClass, params, true);
} catch (ExcelImportException e) {
throw new ExcelImportException(e.getType(), e);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
throw new ExcelImportException(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(in);
}
}
/**
* Excel 通过SAX解析方法,适合大数据导入,不支持图片
* 导入 数据源本地文件,不返回校验结果 导入字段类型 Integer,Long,Double,Date,String,Boolean
*
* @param inputstream 文件流
* @param pojoClass 需要导入数据成的entity类
* @param params 导入的参数
* @param handler 接口自定义处理类,用来解析对象
*/
public static void importExcelBySax(InputStream inputstream, Class<?> pojoClass,
ImportParams params, IReadHandler handler) {
new SaxReadExcel().readExcel(inputstream, pojoClass, params, handler);
}
}
4 使用案例
4.1 自定义easypoi工具类
package com.ywz.utils;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* 类描述 -> EasyPoi工具类
*
* @Author: ywz
* @Date: 2024/08/20
*/
@Slf4j
public class EasyPoiUtils {
/**
* 方法描述 -> 复杂导出Excel,包括文件名以及表名,不创建表头
*
* @param list 数据源
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param fileName 导出的文件名
* @param tailInfo 尾部信息,可以为null
* @Author: ywz
* @Date: 2024/08/20
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response, String tailInfo) {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName), tailInfo);
}
/**
* 方法描述 -> 动态表头导出
*
* @param list 数据源
* @param fileName 文件名
* @param exportParams 导出参数
* @param titleList 标题集合
* @param response 响应
* @param tailInfo 尾部信息,可以为null
* @Author: ywz
* @Date: 2024/11/02
*/
public static void dynamicExportExcel(List<?> list, String fileName, ExportParams exportParams, List<ExcelExportEntity> titleList, HttpServletResponse response, String tailInfo) {
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, titleList, list);
downLoadExcel(fileName, response, sheets, tailInfo);
}
/**
* 方法描述 -> 导出数据源属性不为空的列。
* <p>
* 此方法会根据数据源中第一个对象的属性进行导出表头统计。
* 对象的属性为null则不会作为表单的表头进行导出。
* 数据源类型必须要有@Excel注解且存在name值。
* </p>
* @param list 数据源
* @param pojoClass 数据源类型
* @param fileName 文件名
* @param exportParams 导出参数
* @param response 响应
* @param tailInfo 尾部信息,可以为null
* @Author: ywz
* @Date: 2024/11/03
*/
public static <T> void exportExcelByPropertyNotNull(List<T> list, Class<T> pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response, String tailInfo) {
if (list == null || list.isEmpty()) {
throw new RuntimeException("数据源为空!");
}
// 创建需要导出的标题集合
List<ExcelExportEntity> entityList = new ArrayList<>();
// 获取第一个对象
T t = list.get(0);
// 获取数据源对象所有属性
Field[] declaredFields = pojoClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
Object o = null;
try {
o = field.get(t);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
if (o != null) {
// 获取Excel注解
Excel annotation = field.getAnnotation(Excel.class);
if (annotation != null) {
ExcelExportEntity excelExportEntity = new ExcelExportEntity(annotation.name(), field.getName());
excelExportEntity.setGroupName(annotation.groupName());
excelExportEntity.setOrderNum(Integer.parseInt(annotation.orderNum()));
excelExportEntity.setWidth(annotation.width());
entityList.add(excelExportEntity);
}
}
}
// 动态导出
dynamicExportExcel(list, fileName, exportParams, entityList, response, tailInfo);
}
/**
* 方法描述 -> 默认导出方法
*
* @param list 数据源
* @param pojoClass pojo实体
* @param fileName 导出的文件名
* @param exportParams ExportParams封装实体
* @param tailInfo 尾部信息,可以为null
* @Author: ywz
* @Date: 2024/08/20
*/
public static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams, String tailInfo) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, response, workbook, tailInfo);
}
}
/**
* 方法描述 -> Excel下载
*
* @param fileName 文件名称
* @param workbook Excel对象
* @param tailInfo 尾部信息,可以为null
* @Author: ywz
* @Date: 2024/08/20
*/
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook, String tailInfo) {
Workbook responseWorkbook = setWorkbookTailInfo(workbook, tailInfo);
if (!fileName.endsWith(".xlsx"))
fileName += ".xlsx";
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
responseWorkbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 方法描述 -> 根据文件路径来导入Excel
*
* @param filePath 文件路径
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @Author: ywz
* @Date: 2024/08/20
*/
public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
//判断文件是否存在
if (StringUtils.isBlank(filePath)) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("模板不能为空");
} catch (Exception e) {
log.error(e.getMessage());
}
return list;
}
/**
* 方法描述 -> 根据接收的Excel文件来导入Excel,并封装成实体类
*
* @param file 上传的文件
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @Author: ywz
* @Date: 2024/08/20
*/
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
if (file == null) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
InputStream is = null;
try {
is = file.getInputStream();
list = ExcelImportUtil.importExcel(is, pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("excel文件不能为空");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
log.error(e.getMessage());
}
}
return list;
}
/**
* 方法描述 -> 导出表格设置自定义尾部信息
*
* @param workbook 工作簿
* @param tailInfo 尾部信息
* @Author: ywz
* @Date: 2024/11/03
*/
private static Workbook setWorkbookTailInfo(Workbook workbook, String tailInfo) {
if (tailInfo == null)
return workbook;
// 获取最后一页
Sheet sheetAt = workbook.getSheetAt(workbook.getNumberOfSheets() - 1);
// 获取最后一行
Row tailRow = sheetAt.createRow(sheetAt.getLastRowNum() + 1);
tailRow.createCell(0);
tailRow.getCell(0).setCellValue(tailInfo);
return workbook;
}
}
4.2 简单的导入导出
4.2.1 定义实体类
package com.ywz.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@ApiModel("用户实体类")
@Data
public class User {
@ApiModelProperty("用户id")
@Excel(name = "用户id", orderNum = "0")
private Integer id;
@ApiModelProperty("用户名")
@Excel(name = "用户名", orderNum = "1")
private String name;
@ApiModelProperty("密码")
@Excel(name = "密码", orderNum = "2")
private String password;
@ApiModelProperty("年龄")
@Excel(name = "年龄", orderNum = "3")
private Integer age;
@ApiModelProperty("状态")
@Excel(name = "状态", orderNum = "6", replace = {"正常_1", "禁用_0"})
private Integer status;
@ApiModelProperty("创建时间")
@Excel(name = "创建时间", orderNum = "4", exportFormat = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}
4.2.2 测试
准备个excel文件进行导入:
测试方法:
package com.ywz;
import com.ywz.entity.User;
import com.ywz.utils.EasyPoiUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class EasyPoiTest {
@Test
public void importExcel() {
// 导入测试
String file = "D:\\用户表.xlsx";
List<User> users = EasyPoiUtil.importExcel(file, 0, 1, User.class);
System.out.println(users);
// 导出假代码
List<User> list = new ArrayList<>();
User user = new User();
user.setId(1);
user.setName("张三");
user.setPassword("123456");
user.setAge(18);
user.setStatus(1);
user.setCreateTime(LocalDateTime.now());
list.add(user);
User user2 = new User();
user2.setId(2);
user2.setName("李四");
user2.setPassword("111111");
user2.setAge(20);
user2.setStatus(1);
user2.setCreateTime(LocalDateTime.now());
list.add(user2);
}
}
在控制台查看导入成功:
5 注意事项
导入时,被@Excel标记的对象属性最好使用String类型,这样可以避免在导入时因为Excel内容不标准导致出现对象属性赋值异常。更复杂的Excel操作请查看Springboot与easypoi(2):合并单元格、二级表头、动态导出_easypoi合并单元格-CSDN博客
更多推荐
所有评论(0)