记录封装一个excel导出工具类
因为业务需求需要支持导入导出功能,之前需要导出功能的模块比较少,可以直接调poi包的API接口,现在不行了,好几十个。。。一个一个写估计要通宵,因此写一个统一的导出模板。话不多说上代码!!
业务代码不方便贴出来,用demo演示。
jar包:
<!-- poi -->
<!--xls 03-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!--xlsx 07-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
第一步,先整个注解,把需要导出的字段给注释上,不然把id,password什么的给导出来了岂不尴尬。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author xjn
* date 2021/3/11
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAnno {
int sort();
}
第二步、给需要导出的实体类字段安排上
import com.study.config.ExcelAnno;
import lombok.Data;
/**
* @Author xjn
* date 2021/3/11
*/
@Data
public class User {
private String id;
@ExcelAnno(sort = 0)
private String name;
@ExcelAnno(sort = 1)
private Integer age;
@ExcelAnno(sort = 2)
private String createTime;
}
第三步、封装poi模板
import com.study.config.ExcelAnno;
import lombok.NonNull;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @Author xjn
* date 2021/3/11
*/
public class ExcelUtil<T> {
/**
* params包含:
* <实体类列表 objs
* 开始行索引 rowIndex
* HttpServletResponse response
* 模板路径 path
* 文件名称 fileName>
*
* @param params
*/
public void exportExcel(@NonNull Map<String, Object> params) {
XSSFWorkbook workbook = null;
try {
// 拿到需要导出的实体类(用泛型接收)
List<T> objs = (List<T>) params.get("objs");
// 从第几行开始写入
Integer rowIndex = (Integer) params.get("rowIndex");
HttpServletResponse response = (HttpServletResponse) params.get("response");
// 通过类加载器获取excel模板信息 这个path指向resources下的目录 : ./excel/demo.xlsx
InputStream inputStream = Objects.requireNonNull(ExcelUtil.class
.getClassLoader().getResourceAsStream((String) params.get("path")));
workbook = new XSSFWorkbook(inputStream);
// 获取excel的表单
XSSFSheet sheetAt = workbook.getSheetAt(0);
XSSFRow row1 = sheetAt.getRow(0);
for (int i = 0; i < objs.size(); i++) {
// 创建行
XSSFRow row = sheetAt.createRow(i + rowIndex);
// 获取实体信息
T t = objs.get(i);
Class<?> clazz = t.getClass();
// 获取字段信息
Field[] fields = clazz.getDeclaredFields();
short lastCellNum = row1.getLastCellNum();
for (int j = 0; j < lastCellNum; j++) {
XSSFCell cell = row.createCell(j);
for (Field field : fields) {
// 遍历字段信息 获取字段上的注解信息
ExcelAnno annotation = field.getAnnotation(ExcelAnno.class);
// 如果注解的sort和excel的列匹配 把值设置进去
if (annotation != null && annotation.sort() == j) {
// 暴力访问(因为字段是private),所以需要设置允许访问,或者字段设置成public也可
field.setAccessible(true);
// 这里需要判断一下,不然如果字段是空值的话会空指针。。。
cell.setCellValue(field.get(t) == null ? "" : field.get(t).toString());
break;
}
}
}
}
String fileName = URLEncoder.encode((String) params.get("fileName"), "UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
workbook.write(response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (workbook != null) {
workbook.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
封装好了,测一手
import com.study.util.ExcelUtil;
import com.study.dao.UserDao;
import com.study.entity.po.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author xjn
* date 2021/3/11
*/
@RestController
@RequestMapping("/excel")
public class ExcelDemo {
@Autowired
UserDao userDao;
@RequestMapping(value = "downLoad",method = RequestMethod.GET)
public void loadfile(HttpServletResponse response) {
List<User> all = userDao.findAll();
ExcelUtil excelUtil = new ExcelUtil();
Map<String,Object> map = new HashMap<>();
map.put("objs",all);
map.put("response",response);
map.put("path", "./excel/template.xlsx");
map.put("rowIndex",2);
map.put("fileName","人员表");
excelUtil.exportExcel(map);
}
}
模板excel:
导出后的excel:
好使,下班!