Java如何实现Excel的导入与导出?
一、核心依赖及简要介绍
1、POI是什么?
Apache POI - the Java API for Microsoft Documents,顾名思义,Apache的三方包,用来操作微软office文档的,多数时候用来操作excel,所以这里就以excel方面来说明。POI的组件列表中,针对excel的主要是HSSF和XSSF组件,前者针对97-2007的通用版excel,即后缀xls;后者针对2007或更高版的excel,即后缀xlsx。
2、POI核心类
面向对象面向对象,既然如此,自然去找找一些能表示excel中内容的类。
2.1 工作簿 Workbook
Workbook是创建或维护Excel工作簿的所有类的超接口,属于org.apache.poi.ss.usermodel包。其下有两个实现类:
-
HSSFWorkbook : 有读取.xlsx 格式和写入Microsoft Excel文件的方法。它与微软Office97-2003版本兼容
-
XSSFWorkbook : 有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容
所以在针对不同版本的excel时,需要对应以上使用不同的Workbook。构造函数中,常用的:
HSSFWorkbook
//直接创建新的
new HSSFWorkbook()
//通过输入流创建
new HSSFWorkbook(java.io.InputStream InputStream)
XSSFWorkbook
//直接创建新的
new XSSFWorkbook()
//通过File类创建
new XSSFWorkbook(java.io.File file)
//通过输入流创建
new XSSFWorkbook(java.io.InputStream is)
2.2 标签页 Sheet
HSSFSheet 和 XSSFSheet 都是Sheet接口的实现类,Sheet可以使用Workbook的两个方法获得:
workbook.createSheet();
workbook.createSheet(String sheetName);
2.3 行 Row
同理,Row是 HSSFRow 和 XSSFRow 的接口,通过Sheet获取:
// rownum为行索引下标
sheet.createRow(int rownum);
2.4 单元格 Cell
同理,Cell是 HSSFCell 和 XSSFCell 的接口,通过Row获取:
// column为行索引下标
row.createCell(int column);
row.createCell(int column, int type);
二、代码的具体实现
1、导入相关依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
2、编写相应的工具类
2.1 Excel 注解类
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* @since 2021/7/12 9:19
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Excel {
// 标题(类上注解中填写该属性,不可省略)
String title() default "";
// 列名(可省略,省略默认为属性名)
String name() default "";
// 列的宽度(默认12)
int columnWidth() default 12;
// 标题行的高度(默认24)
int titleRowHeight() default 24;
// 属性行的高度(默认20)
int attributeRowHeight() default 20;
// 内容行的高度(默认18)
int contentRowHeight() default 18;
// 单元格数据的类型(默认是String类型)
ExcelType type() default ExcelType.String;
// 单元格数据格式化的样式
// 当@Excel中指定type为ExcelType.Date或者ExcelType.Number时,可以指定格式化样式
String format() default "";
}
2.2 ExcelType 枚举类
import lombok.Data;
/**
* @since 2021/7/12 17:44
*/
public enum ExcelType {
/**
* 字符类型
*/
String("字符类型"),
/**
* 时间类型
*/
Date("时间类型"),
/**
* 数字类型
*/
Number("数字类型"),
/**
* boolean类型
*/
Boolean("boolean类型");
private String message;
ExcelType(String message){
this.message = message;
}
}
2.3 ExcelUtil 工具类
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @since 2021/7/12 9:18
*/
@Slf4j
public class ExcelUtil<T> {
Class<T> clazz;
public ExcelUtil(Class<T> clazz){
this.clazz = clazz;
}
/**
* 将List<T>对象转换成Excel表格并输出到指定流,其中<T>为对象的类型,在对象中用@Excel注解进行参数配置
* @param list 数据对象
* @param outputStream 输出的Excel文件流
*/
public void exportExcel(List<T> list, OutputStream outputStream){
// 创建空白工作簿
XSSFWorkbook workbook = new XSSFWorkbook();
try {
String sheetName = "";
String titleName = "";
// 获取该类的所有字段
Field[] fields = clazz.getDeclaredFields();
int titleRowHeight;
int attributeRowHeight;
int contentRowHeight;
// 如果这个类上有@Excel注解
if (clazz.isAnnotationPresent(Excel.class)) {
Excel excel = (Excel) clazz.getAnnotation(Excel.class);
titleName = excel.title();
sheetName = titleName;
titleRowHeight = excel.titleRowHeight();
attributeRowHeight = excel.attributeRowHeight();
contentRowHeight = excel.contentRowHeight();
}else {
throw new RuntimeException("该实体类缺少@Excel注解,不能转换");
}
// 创建sheet
Sheet sheet = workbook.createSheet(sheetName);
// 创建标题行
Row titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(titleRowHeight);
Cell titleCell = titleRow.createCell(0);
// 创建标题行的样式
XSSFCellStyle titleCellStyle = workbook.createCellStyle();
// 设置单元格格式居中对齐
titleCellStyle.setAlignment(HorizontalAlignment.CENTER);
titleCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 如果需要前景颜色或背景颜色,一定要指定填充方式,两者顺序无所谓,如果同时存在前景颜色和背景颜色,前景颜色的设置要写在前面
titleCellStyle.setFillPattern(FillPatternType.LEAST_DOTS);
titleCellStyle.setFillBackgroundColor(IndexedColors.LIGHT_YELLOW.index);
// 设置字体
XSSFFont font = workbook.createFont();
// 设置sheet默认的列宽12
sheet.setDefaultColumnWidth(12);
font.setBold(true);
font.setColor(IndexedColors.RED.index);
font.setFamily(FontFamily.ROMAN);
// 调整字体大小
font.setFontHeightInPoints((short) 14);
// 将字体样式加入到单元格样式中
titleCellStyle.setFont(font);
titleCell.setCellValue(titleName);
// 将单元格样式应用到单元格中
titleCell.setCellStyle(titleCellStyle);
int cols = 0;
// 遍历字段,统计出需要导出的字段总数
for (int j = 0; j < fields.length; j++) {
// 如果字段上有@Excel注解,则表明需要导出,否则不需要
if (fields[j].isAnnotationPresent(Excel.class)) {
cols++;
}
}
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, cols - 1));
// 创建属性列名
Row attributeRow = sheet.createRow(1);
// 创建属性行的样式
XSSFCellStyle attributeCellStyle = workbook.createCellStyle();
attributeCellStyle.setAlignment(HorizontalAlignment.CENTER);
attributeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 如果需要前景颜色或背景颜色,一定要指定填充方式,两者顺序无所谓,如果同时存在前景颜色和背景颜色,前景颜色的设置要写在前面
attributeCellStyle.setFillPattern(FillPatternType.FINE_DOTS);
attributeCellStyle.setFillBackgroundColor(IndexedColors.GREY_40_PERCENT.index);
// 记录当前单元格的索引位置
int attributeCurrent = 0;
// 设置属性行的高度
attributeRow.setHeightInPoints(attributeRowHeight);
for (int k = 0; k < fields.length; k++) {
// 如果字段上没有@Excel注解,则不导出
if (!fields[k].isAnnotationPresent(Excel.class)) {
continue;
}
// 创建单元格
Cell cell = attributeRow.createCell(attributeCurrent);
// 获取字段名
String columnName = fields[k].getName();
// 设置默认列宽为12
int columnWidth = 12;
if (fields[k].isAnnotationPresent(Excel.class)) {
Excel excel = fields[k].getAnnotation(Excel.class);
// 如果@Excel注解上的name属性不为空,则
if(!"".equals(excel.name())){
columnName = excel.name();
}
columnWidth = excel.columnWidth();
}
cell.setCellValue(columnName);
// 设置指定列的列宽,256 * 50这种写法是因为width参数单位是单个字符的256分之一
sheet.setColumnWidth(attributeCurrent, columnWidth * 256);
// 设置样式
cell.setCellStyle(attributeCellStyle);
// 设置单元格的下一个索引位置
attributeCurrent++;
}
// 写入数据
for (int i = 0; i < list.size(); i++) {
// 从第三行开始写入数据
Row contentRow = sheet.createRow(i + 2);
// 设置正文内容的行高
contentRow.setHeightInPoints(contentRowHeight);
// 记录当前单元格的索引位置
int current = 0;
for (int j = 0; j < fields.length; j++) {
// 如果字段上没有@Excel注解,则不导出
if (!fields[j].isAnnotationPresent(Excel.class)) {
continue;
}
// 创建单元格
Cell cell = contentRow.createCell(current);
// 设置单元格的下一个索引位置
current++;
// 获取字段名称
String fieldName = fields[j].getName();
// 获取字段类型
Class<?> fieldType = fields[j].getType();
// 获取字段类型的名称
String fieldTypeName = fields[j].getType().getName();
// 获取该字段的get方法名
String fieldFirstLetterUpper = fieldName.substring(0, 1).toUpperCase();
String prefix = "get";
if ("boolean".equals(fieldTypeName)) {
prefix = "is";
}
// 拼接出get方法名
String methodName = prefix + fieldFirstLetterUpper + fieldName.substring(1);
// 获取该get方法
Method method = clazz.getMethod(methodName);
// 默认类型都为String类型填充
ExcelType type = ExcelType.String;
String format = "";
if (fields[j].isAnnotationPresent(Excel.class)) {
Excel excel = fields[j].getAnnotation(Excel.class);
// 获取@Excel注解中的字段属性类型
type = excel.type();
// 获取格式
format = excel.format();
}
// 字符串类型
if(ExcelType.String.equals(type)){
// 字符串类型
XSSFCellStyle stringCellStyle = workbook.createCellStyle();
stringCellStyle.setAlignment(HorizontalAlignment.CENTER);
stringCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 填入数据
cell.setCellValue((String) method.invoke(list.get(i)));
cell.setCellStyle(stringCellStyle);
}
// 日期类型
else if(ExcelType.Date.equals(type)){
// 日期格式
XSSFCellStyle dateCellStyle = workbook.createCellStyle();
dateCellStyle.setAlignment(HorizontalAlignment.CENTER);
dateCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFDataFormat dataFormat = workbook.createDataFormat();
if("".equals(format)){
// 默认的日期格式
dateCellStyle.setDataFormat(dataFormat.getFormat("yyyy-MM-dd"));
}else {
// 指定的日期格式
dateCellStyle.setDataFormat(dataFormat.getFormat(format));
}
// 填入数据
cell.setCellValue((Date) method.invoke(list.get(i)));
cell.setCellStyle(dateCellStyle);
}
// 数字类型
else if(ExcelType.Number.equals(type)){
// 数字格式
XSSFCellStyle numberCellStyle = workbook.createCellStyle();
numberCellStyle.setAlignment(HorizontalAlignment.CENTER);
numberCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
if("".equals(format)){
// 默认的数字格式
numberCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#0"));
}else {
// 指定的数字格式
numberCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat(format));
}
// method.invoke(list.get(i))返回的有可能是Integer、Long、Float、Double、BigDecimal
if(Float.class == fieldType || Float.TYPE == fieldType){
// 将Float类型的数据转换成Double类型填入单元格,否则精度有问题
cell.setCellValue(((Float)method.invoke(list.get(i))).doubleValue());
}else if(BigDecimal.class == fieldType){
// 将BigDecimal类型的数据转换成Double类型填入单元格
cell.setCellValue(((BigDecimal)method.invoke(list.get(i))).doubleValue());
}else if(Integer.class == fieldType || Integer.TYPE == fieldType){
cell.setCellValue((Integer)method.invoke(list.get(i)));
}else if(Double.class == fieldType || Double.TYPE == fieldType){
cell.setCellValue((Double)method.invoke(list.get(i)));
}else if(Long.class == fieldType || Long.TYPE == fieldType){
// Long类型时,数值太大会出现科学计数法
cell.setCellValue((Long)method.invoke(list.get(i)));
}
cell.setCellStyle(numberCellStyle);
}else if(ExcelType.Boolean.equals(type)){
// Boolean格式
XSSFCellStyle booleanCellStyle = workbook.createCellStyle();
booleanCellStyle.setAlignment(HorizontalAlignment.CENTER);
booleanCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
Boolean result = (Boolean) method.invoke(list.get(i));
// 将true和false分别映射成是和否填入单元格
cell.setCellValue(result ? "是" : "否");
cell.setCellStyle(booleanCellStyle);
}
}
}
log.info("数据导出Excel完毕");
// 写出到输出流中
workbook.write(outputStream);
// 关闭资源
workbook.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将导入的Excel文件流转换成List<T>数据对象集合
* @param input 导入的Excel文件流
* @return List<T>数据对象集合
*/
public List<T> importExcel(InputStream input) {
// 创建List数据对象集合
List<T> list = new ArrayList<T>();
try {
// 读取Excel文件流,创建工作簿
XSSFWorkbook workbook = new XSSFWorkbook(input);
// 获取Excel中的第一个sheet
Sheet sheet = workbook.getSheetAt(0);
// 获取总行数
int rows = sheet.getPhysicalNumberOfRows();
// 有数据时才处理(前两行是标题和属性)
if (rows > 2) {
// 获取所有字段
Field[] fields = clazz.getDeclaredFields();
// 从索引为2开始创建行,即第三行开始
int firstRowNum = 2;
// 获取最后一行的索引
int lastRowNum = sheet.getLastRowNum();
// 一行一行获取数据,并填入对象中
for (int j = firstRowNum; j <= lastRowNum; j++) {
// 获取行
Row row = sheet.getRow(j);
// 记录当前单元格的索引
int current = 0;
// 创建对象
T entity = null;
// 遍历字段
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 如果字段上没有@Excel注解,表明它不需要导出,所以不填入数据
if (!field.isAnnotationPresent(Excel.class)) {
continue;
}
// 获取当前单元格
XSSFCell cell = (XSSFCell) row.getCell(current);
// 将当前单元格的数据依据类型和格式转换成对应的字符串
String cellValue = getCellValue(cell, field);
// 创建对象
entity = (entity == null ? clazz.newInstance() : entity);
// 将数据填充到对象所对应的字段中
cell2Field(entity, cellValue, field);
// 记录下一个单元格的索引位置
current++;
}
// 将填充好的对象加入到集合中
if (entity != null) {
list.add(entity);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 将数据填充到对象所对应的字段中
* @param entity 对象
* @param cell 数据
* @param field 字段
*/
private void cell2Field(T entity, String cell, Field field) throws IllegalAccessException, ParseException, NoSuchMethodException, InvocationTargetException {
// 获取字段类型
Class<?> fieldType = field.getType();
// 获取字段名称
String fieldName = field.getName();
// 获取该字段的set方法名
String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
// 获取该set方法
Method method = clazz.getMethod(methodName, fieldType);
if (String.class == fieldType) {
method.invoke(entity, cell);
}
// 处理数字特殊类型
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
// Integer的1导出到Excel中显示为1,但从Excel中读取到的cell单元格的值却为1.0,所以需要去除小数点
if(cell.contains(".")){
cell = cell.substring(0, cell.indexOf("."));
}
// 如果该字段为Integer类型,则转换为Integer类型再写入字段
method.invoke(entity, Integer.valueOf(cell));
} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
// 有时Excel表格中会误输入带小数点的数据,如124235789512.00,则需要去除小数点,否则设置字段值会出错
if(cell.contains(".")){
cell = cell.substring(0, cell.indexOf("."));
}
// 如果该字段为Long类型,则转换为Long类型再写入字段
method.invoke(entity, Long.valueOf(cell));
} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
// 如果该字段为Float类型,则转换为Float类型再写入字段
method.invoke(entity, Float.valueOf(cell));
} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
// 如果该字段为Double类型,则转换为Double类型再写入字段
method.invoke(entity, Double.valueOf(cell));
}else if ((BigDecimal.class == fieldType)) {
// 如果该字段为BigDecimal类型,则转换为BigDecimal类型再写入字段
method.invoke(entity, new BigDecimal(cell));
}
// 处理日期特殊类型(如果该字段为日期类型)
else if(Date.class == fieldType){
if (field.isAnnotationPresent(Excel.class)) {
Excel excel = field.getAnnotation(Excel.class);
// 获取@Excel上指定的日期格式
String format = excel.format();
// 如果未指定日期格式,则使用默认格式
if("".equals(format)){
format = "yyyy-MM-dd";
}
// 按照格式解析字符串为日期
Date date = new SimpleDateFormat(format).parse(cell);
// 填入字段
method.invoke(entity, date);
}
}
// 处理boolean特殊类型
else if(Boolean.class == fieldType || Boolean.TYPE == fieldType){
// 转换成true或false填入字段
Boolean result = "是".equals(cell);
method.invoke(entity, result);
}
}
/**
* 依据单元格的数据类型进行相应的处理,并返回相应的字符串数据
* @param cell 单元格
* @param field 字段(可以获取字段上的注解信息)
* @return 字符串单元格数据
*/
private String getCellValue(XSSFCell cell, Field field) {
String value = null;
// 如果单元格不为空才处理
if (cell != null) {
// 依据单元格数据的类型进行相应的处理,并返回字符串单元格数据
switch (cell.getCellType()) {
// 单元格是函数计算出来的数据
case FORMULA:
try {
value = String.valueOf(cell.getNumericCellValue());
} catch (Exception e) {
value = String.valueOf(cell.getRichStringCellValue());
}
break;
// 单元格是数字类型的(包括数字和日期)
case NUMERIC:
// 获取单元格的样式值,即获取单元格格式对应的数值
int style = cell.getCellStyle().getDataFormat();
// 判断是否是日期格式
if (HSSFDateUtil.isCellDateFormatted(cell)) {
// 获取单元格的日期
Date date = cell.getDateCellValue();
// 日期格式化样式
String format;
// 获取字段上注解中指定的格式化样式
Excel excel = field.getAnnotation(Excel.class);
format = excel.format();
// 如果为指定格式化样式,则使用默认格式化样式
if("".equals(format)){
format = "yyyy-MM-dd";
}
// 将日期格式化成对应的字符串
value = new SimpleDateFormat(format).format(date);
}
// 数字类型
else {
switch (style) {
// 单元格格式为百分比,不格式化会直接以小数输出
case 9:
value = new DecimalFormat("0.00%").format(cell.getNumericCellValue());
break;
default:
// 获取数字类型的单元格数据
value = String.valueOf(cell.getNumericCellValue());
// 处理科学计数法
if(value.contains("E")){
// value = 2.01720181436E11
BigDecimal number = new BigDecimal(value);
// 201720181436
value = number.toString();
}
// 去除excel中数字类型自带的千位分隔符(1,256.4)
value = value.replace(",", "");
break;
}
}
break;
// 单元格是字符串类型的
case STRING:
value = String.valueOf(cell.getRichStringCellValue());
break;
default:
break;
}
}
return value;
}
}
3、实体类
import cn.ecut.file.excel.util.Excel;
import cn.ecut.file.excel.util.ExcelType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
/**
* @since 2021/7/12 9:01
* 类上@Excel注解中必须指定title属性
* 类上@Excel注解中的titleRowHeight属性可指定标题的行高(默认24)
* 类上@Excel注解中的attributeRowHeight属性可指定列名的行高(默认20)
* 类上@Excel注解中的contentRowHeight属性可指定正文内容的行高(默认18)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Excel(title = "学生信息登记表")
public class Student {
/**
* ID
* name(可省略)指定生成的Excel列名,如省略name属性,则用字段名生成Excel列名
* type 默认为ExcelType.String类型,当字段为String类型时,可省略该属性,否则必须指定type
* columnWidth 指定该列的宽度,默认为12
*/
@Excel(name = "序号", type = ExcelType.Number, columnWidth = 8)
private Integer id;
/**
* 姓名
*/
@Excel(name = "姓名", columnWidth = 14)
private String name;
/**
* 性别
*/
@Excel(name = "性别")
private String sex;
/**
* 年龄
*/
@Excel(name = "年龄", type = ExcelType.Number)
private Integer age;
/**
* 出生日
* 当type为ExcelType.Date或者ExcelType.Number时,可以通过format属性指定格式化样式
* 当type=ExcelType.Date时,默认样式为yyyy-MM-dd
*/
@Excel(name = "出生日期", type = ExcelType.Date, format = "yyyy-MM-dd")
private Date birthday;
/**
* 手机号
*/
@Excel(name = "手机号", columnWidth = 15)
private String phone;
/**
* 已缴学费
* 当type为ExcelType.Date或者ExcelType.Number时,可以通过format属性指定格式化样式
* 当type=ExcelType.Number时,默认样式为#0
*/
@Excel(name = "已缴学费", type = ExcelType.Number, format = "#,##0.00")
private BigDecimal money;
/**
* 是否毕业
* 当type为ExcelType.Boolean时,true和false会转换成相应的是和否
*/
@Excel(name = "是否毕业", type = ExcelType.Boolean)
private Boolean graduate;
/**
* 通讯地址
* 若字段不声明@Excel注解,则表明该属性不需要导出到Excel中
*/
private String address;
}
4、Service层代码的实现
import cn.ecut.file.excel.entity.Student;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @since 2021/7/12 9:00
*/
public interface ExcelCustomService {
/**
* 导出Excel表格
* @param response
* @throws IOException
*/
void exportExcel(HttpServletResponse response) throws IOException;
/**
* 导入Excel表格,将Excel数据转换成List集合数据
* @param inputStream
* @return
*/
List<Student> importExcel(InputStream inputStream);
}
import cn.ecut.file.excel.entity.Student;
import cn.ecut.file.excel.service.ExcelCustomService;
import cn.ecut.file.excel.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @since 2021/7/12 9:00
*/
@Service
@Slf4j
public class ExcelCustomServiceImpl implements ExcelCustomService {
// 声明默认数据
private static List<Student> students = new ArrayList<>();
static {
Student student1 = new Student(1, "张三", "男", 23, new Date(), "18842568124", new BigDecimal("1256.4"), true, null);
Student student2 = new Student(2, "李四", "男", 21, new Date(), null, new BigDecimal("58.1"), false, null);
Student student3 = new Student(3, "王五", "女", 20, new Date(), null, new BigDecimal("1456"), true, null);
students.add(student1);
students.add(student2);
students.add(student3);
}
@Override
public void exportExcel(HttpServletResponse response) throws IOException {
String fileName = "学生信息表汇总.xlsx";
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
ServletOutputStream outputStream = response.getOutputStream();
// 将List数据集合导出到Excel中
new ExcelUtil<Student>(Student.class).exportExcel(students, outputStream);
}
@Override
public List<Student> importExcel(InputStream inputStream) {
// 将Excel中的数据转换成List数据集合
return new ExcelUtil<Student>(Student.class).importExcel(inputStream);
}
}
5、Controller层的实现
import cn.ecut.file.excel.entity.Student;
import cn.ecut.file.excel.service.ExcelCustomService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @since 2021/7/12 8:59
*/
@RestController
@RequestMapping("/excel")
@Api(value = "EXCEL相关操作接口", tags = "EXCEL相关操作接口")
public class ExcelController {
@Autowired
private ExcelCustomService excelCustomService;
@GetMapping("/exportExcel")
@ApiOperation(value = "导出Excel")
public void exportExcel(HttpServletResponse response){
try {
excelCustomService.exportExcel(response);
} catch (IOException e) {
e.printStackTrace();
}
}
@PostMapping("/importExcel")
@ApiOperation(value = "导入Excel")
public List<Student> importExcel(MultipartFile file){
List<Student> list = new ArrayList<>();
try {
InputStream inputStream = file.getInputStream();
list = excelCustomService.importExcel(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
三、测试效果
1、Excel的导出测试
请求接口,下载导出的Excel文件
打开Excel表格
2、Excel的导入测试
请求接口,上传Excel表格
响应结果正确,完美导入