Java如何实现Excel的导入与导出?

admin 4357

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、导入相关依赖

org.apache.poi

poi

4.0.1

org.apache.poi

poi-ooxml

4.0.1

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 {

Class clazz;

public ExcelUtil(Class clazz){

this.clazz = clazz;

}

/**

* 将List对象转换成Excel表格并输出到指定流,其中为对象的类型,在对象中用@Excel注解进行参数配置

* @param list 数据对象

* @param outputStream 输出的Excel文件流

*/

public void exportExcel(List 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数据对象集合

* @param input 导入的Excel文件流

* @return List数据对象集合

*/

public List importExcel(InputStream input) {

// 创建List数据对象集合

List list = new ArrayList();

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 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 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.class).exportExcel(students, outputStream);

}

@Override

public List importExcel(InputStream inputStream) {

// 将Excel中的数据转换成List数据集合

return new ExcelUtil(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 importExcel(MultipartFile file){

List 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表格

响应结果正确,完美导入