原文网址:EasyExcel--导入和导出Excel的方法_IT利刃出鞘的博客-CSDN博客
简介
本文介绍SpringBoot整合EasyExcel导入和导出Excel的方法。
使用
Excel导入
实体类
java
@Data
public class OrderImportBO {
@ExcelProperty("订单号")
@NotBlank(message = "订单号不能为空")
private String scOrderPoolId;
@ExcelProperty("金额")
private String amount;
}
Controller
java
@PostMapping("importOrder")
public void importOrder(@RequestPart MultipartFile file) {
List<OrderImportBO> orderImportBOList = ExcelUtil.importExcel(file, OrderImportBO.class);
}
Excel导出
实体类
java
@Data
public class OrderExportBO {
@ExcelProperty("订单号")
@NotBlank(message = "订单号不能为空")
private String scOrderPoolId;
@ExcelProperty("金额")
private String amount;
}
Service
java
List<OrderExportVO> exportVOS = new ArrayList();
ExcelUtil.exportExcel(exportVOS, OrderExportVO.class);
详细代码
依赖
EasyExcel
XML
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.11</version>
</dependency>
整个pom.xml
XML
<?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.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knife</groupId>
<artifactId>demo_EasyExcel_SpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo_EasyExcel_SpringBoot</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>2.2.11</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
Excel配置
字符串转换器
java
package com.knife.excel.handler;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class StringConverter implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 将excel对象转成Java对象,这里读的时候会调用
*/
@Override
public String convertToJavaData(CellData cellData,
ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return cellData.getStringValue().trim();
}
/**
* 将Java对象转成String对象,写出的时候调用
*/
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return new CellData(value);
}
}
writeHandler
java
package com.knife.excel.halper;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExcelHandler extends AbstractColumnWidthStyleStrategy {
private static final int MAX_COLUMN_WIDTH = 255;
//因为在自动列宽的过程中,有些设置地方让列宽显得紧凑,所以做出了个判断
private static final int COLUMN_WIDTH = 20;
private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);
public ExcelHandler() {
}
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (needSetWidth) {
Map<Integer, Integer> maxColumnWidthMap = (Map)CACHE.get(writeSheetHolder.getSheetNo());
if (maxColumnWidthMap == null) {
maxColumnWidthMap = new HashMap(16);
CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
}
Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
if (columnWidth >= 0) {
if (columnWidth > MAX_COLUMN_WIDTH) {
columnWidth = MAX_COLUMN_WIDTH;
}else {
if(columnWidth<COLUMN_WIDTH){
columnWidth =columnWidth*2;
}
}
Integer maxColumnWidth = (Integer)((Map)maxColumnWidthMap).get(cell.getColumnIndex());
if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
((Map)maxColumnWidthMap).put(cell.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth* 256);
}
}
}
}
private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
if (isHead) {
return cell.getStringCellValue().getBytes().length;
} else {
CellData cellData = (CellData)cellDataList.get(0);
CellDataTypeEnum type = cellData.getType();
if (type == null) {
return -1;
} else {
switch(type) {
case STRING:
return cellData.getStringValue().getBytes().length;
case BOOLEAN:
return cellData.getBooleanValue().toString().getBytes().length;
case NUMBER:
return cellData.getNumberValue().toString().getBytes().length;
default:
return -1;
}
}
}
}
public static HorizontalCellStyleStrategy getStyleStrategy(){
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景设置为灰色
headWriteCellStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)11);
// 字体样式
headWriteFont.setFontName("Arial Unicode MS");
headWriteFont.setColor(IndexedColors.WHITE.getIndex());
headWriteCellStyle.setWriteFont(headWriteFont);
//自动换行
headWriteCellStyle.setWrapped(false);
// 水平对齐方式
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
// 垂直对齐方式
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
// contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);
// 背景白色
contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short)11);
// 字体样式
contentWriteFont.setFontName("宋体");
contentWriteCellStyle.setWriteFont(contentWriteFont);
//是否换行
contentWriteCellStyle.setWrapped(false);
// 垂直对齐方式
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
}
数据校验
java
package com.bondex.oms.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.knife.util.BeanHelper;
import com.knife.util.ValidateUtil;
public class ExcelValidateListener<T> extends AnalysisEventListener<T> {
@Override
public void invoke(T bo, AnalysisContext analysisContext) {
// 如果是空行,不处理
if (BeanHelper.allFieldAreNull(bo)) {
return;
}
int row = analysisContext.readRowHolder().getRowIndex() + 1;
try {
// 校验输入字段
ValidateUtil.validate(bo);
} catch (Exception e) {
throw new RuntimeException("第[" + row + "]行数据校验失败:" + e.getMessage());
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
Bean工具
java
package com.knife.util;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.util.CollectionUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class BeanHelper {
public static <T> List<T> convert(List<?> sources, Class<T> target) {
if (CollectionUtils.isEmpty(sources)) {
return new ArrayList<>();
}
List<T> targets = new LinkedList<>();
for (Object source : sources) {
T t = null;
try {
t = target.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
BeanUtils.copyProperties(source, t);
targets.add(t);
}
return targets;
}
public static <T> T convert(Object source, Class<T> target) {
if (source == null) {
return null;
}
T t;
try {
t = target.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
BeanUtils.copyProperties(source, t);
return t;
}
public static boolean allFieldAreNull(Object o) {
Class<?> aClass = o.getClass();
PropertyDescriptor[] beanProperties = ReflectUtils.getBeanProperties(aClass);
for (PropertyDescriptor beanProperty : beanProperties) {
Method readMethod = beanProperty.getReadMethod();
try {
Object value = readMethod.invoke(o);
if (value != null) {
return false;
}
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return true;
}
}
Excel工具类
java
package com.bondex.oms.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.knife.entity.UserDTO;
import com.knife.util.UserDtoUtils;
import com.knife.excel.helper.ExcelHandler;
import com.knife.excel.helper.ExcelValidateListener;
import com.knife.excel.helper.HeadRowListener;
import com.knife.excel.helper.StringConverter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
public class ExcelUtil {
public static <T> void exportExcel(List<T> dataList,
Class<T> tClass) {
ServletRequestAttributes servletRequestAttributes =
(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
Assert.notNull(servletRequestAttributes, "RequestAttributes不能为null");
HttpServletResponse response = servletRequestAttributes.getResponse();
Assert.notNull(response, "Response不能为null");
ServletOutputStream out = null;
try {
out = response.getOutputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
String fileName = "测试文件.xlsx";
try {
// 必须要转一下,否则中文文件名会乱码
fileName = URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// 通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
// 输出流到浏览器下载
EasyExcel.write(out)
.needHead(true)
.head(tClass)
.excelType(ExcelTypeEnum.XLSX)
.autoCloseStream(true)
.registerWriteHandler(new ExcelHandler())
.registerWriteHandler(ExcelHandler.getStyleStrategy())
.sheet(0, "Sheet1")
.doWrite(dataList);
}
public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass) {
return importExcel(file, tClass, 1, null);
}
public static <T> List<T> importExcel(MultipartFile file, Class<T> tClass, String sheet) {
return importExcel(file, tClass, 1, sheet);
}
public static <T> List<T> importExcel(MultipartFile file,
Class<T> tClass,
Integer headRowNumber,
String sheet) {
InputStream inputStream;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
List<T> list = null;
list = EasyExcel.read(inputStream)
.registerConverter(new StringConverter())
.registerReadListener(new ExcelValidateListener<T>())
.head(tClass)
// 可以指定sheet名字,不指定或null则表示第1个
.sheet(sheet)
.headRowNumber(headRowNumber)
.doReadSync();
list.removeIf(BeanHelper::allFieldAreNull);
return list;
}
}