所需依赖
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.0.3</version>
</dependency>
实体类添加注解
注意实体类必须要有空参构造,否则会报错!
主要用到@Excel注解
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
name | String | null | 列名,支持name_id |
orderNum | String | "0" | 列的排序,支持name_id |
replace | String[] | {} | 值得替换 导出是{a_id,b_id} 导入反过来 |
其他相关的注解和属性有需要的可以进官网去看,在这里就不一一介绍了
public class Persion {
@Excel(name = "姓名",orderNum = "0")
private String name;
@Excel(name = "年龄",orderNum = "1")
private Integer age;
@Excel(name = "性别",orderNum = "2",replace = {"男_1", "女_2"})
private String gender;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
需要说一下的就是replace属性,坑了我一把,比如上面的性别,数据库存的是1,2。导出的Excel要显示的是男女,就应该是
replace = {"男1", "女2"},官方文档说导入则反过来,我以为是导入就应该成了replace = {"1男", "2女"},谁知
道不对,不用变换,还是跟原来的一样。
工具类
public class EasyPoiUtil {
/**
* 功能描述:复杂导出Excel,包括文件名以及表名。创建表头
* @param list 导出的实体类
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param isCreateHeader 是否创建表头
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 功能描述:复杂导出Excel,包括文件名以及表名,不创建表头
* @param list 导出的实体类
* @param title 表头名称
* @param sheetName sheet表名
* @param pojoClass 映射的实体类
* @param fileName
* @param response
* @return
*/
public static Workbook exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName,ExcelType.XSSF));
return null;
}
/**
* 功能描述:Map 集合导出
* @param list 实体集合
* @param fileName 导出的文件名称
* @param response
* @return
*/
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
defaultExport(list, fileName, response);
}
/**
* 功能描述:默认导出方法
* @param list 导出的实体集合
* @param fileName 导出的文件名
* @param pojoClass pojo实体
* @param exportParams ExportParams封装实体
* @param response
* @return
*/
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
/**
* 功能描述:Excel导出
* @param fileName 文件名称
* @param response
* @param workbook Excel对象
* @return
*/
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 功能描述:默认导出方法
* @param list 导出的实体集合
* @param fileName 导出的文件名
* @param response
* @return
*/
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null) ;
downLoadExcel(fileName, response, workbook);
}
/**
* 功能描述:根据文件路径来导入Excel
* @param filePath 文件路径
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @return
*/
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) {
e.printStackTrace();
}
return list;
}
/**
* 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类
* @param file 上传的文件
* @param titleRows 表标题的行数
* @param headerRows 表头行数
* @param pojoClass Excel实体类
* @return
*/
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;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("excel文件不能为空");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return list;
}
}
Controller
// 导入
@ResponseBody
@RequestMapping(value = "/excelBatchImport")
public String excelBatchImport(MultipartFile file) {
SimpleReturnVo returnVo = new SimpleReturnVo(ERROR, "上传失败");
try {
lock.lock();
if (file == null || StringUtils.isBlank(file.getOriginalFilename())) {
throw new Exception("文件不存在");
}
long fileSize = file.getSize();
if (fileSize > 5 * 1048576) {
throw new Exception("文件超出限制");
}
List<Persion> list = EasyPoiUtil.importExcel(file, 0, 1, Persion.class);
System.out.println("导入数据...."+list.get(0).getName()+"-"+list.get(0).getAge()+"-"+list.get(0).getGender());
returnVo = new SimpleReturnVo(SUCCESS, "上传成功");
} catch (Exception e) {
logger.error("SoftAccountController-excelBatchImport:", e);
e.printStackTrace();
returnVo.setResponseCode(ERROR);
returnVo.setResponseMsg(e.getMessage());
} finally {
lock.unlock();
}
return JsonUtils.toJson(returnVo);
}
//导出
@RequestMapping("/export")
@ResponseBody
public SimpleReturnVo export(String ids, String sessionId, HttpServletResponse response) {
SimpleReturnVo returnVo = new SimpleReturnVo(ERROR, "导出失败");
User user = this.getLoginUser(sessionId);
if (null != user && StringUtils.isNotBlank(user.getUsername())) {
try {
List<Person> list = new ArrayList<>();
Person person1 = new Person("张三",25,"1");
Person person2 = new Person("李四",21,"1");
Person person3 = new Person("王五",22,"2");
list.add(person1);
list.add(person2);
list.add(person3);
EasyPoiUtil.exportExcel(list, "人员名单", "名单", Person.class, "人员名单.xlsx", response);
returnVo = new SimpleReturnVo(SUCCESS, "导出成功");
} catch (Exception e) {
logger.error("SoftAccountController-export:", e);
e.printStackTrace();
}
}
return returnVo;
}
结果
导入
导出
注意事项:
-
导出乱码
不知道为什么,刚开始按照文章开始的链接做的导出,导出xls格式,一直不对,能导出,但是提示文件已损坏,格式不匹配,强行打开乱码,公司项目按这个方法导出,更可笑的是,数据大于等于5条,能正常导出,不然就跟上面一样。后来试了下导出xlsx格式没问题,打开不乱码,需要注意的是,xlsx格式对应的是XSSF,所以注意代码中对应的格式,如下
public static Workbook exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName,ExcelType.XSSF));
return null;
}
-
导入报错:org/apache/poi/poifs/filesystem/FileMagic
当时项目中除了easypoi的依赖,还有Apache poi的依赖,导致poi的jar包版本与其他两个的版本不一样,所以一直导入报错,后来修改至与其他两个版本一致就好了。
反射---注解属性动态替换
上面说了@Excel注解的replace属性可以很好的替换数据库中的数据,但是上面属性值是写死的,而我的项目中,很多字段都是手动添加上去的,比如品牌。所以导出的时候只能动态的去获取有关的数据,这里就需要用到反射。(其实还有更简单的方法,就是在实体类中添加成员变量,如品牌:brandStr,查询的时候就转换过来,这样就不需要反射了,这里只是就该技术进行一次说明。)
原始文章请参考:https://blog.csdn.net/u014750606/article/details/79977114
//导出
@RequestMapping("/export")
@ResponseBody
public SimpleReturnVo export(String ids, String sessionId, HttpServletResponse response) {
SimpleReturnVo returnVo = new SimpleReturnVo(ERROR, "导出失败");
User user = this.getLoginUser(sessionId);
if (null != user && StringUtils.isNotBlank(user.getUsername())) {
try {
SoftAccountExport softAccountExport = new SoftAccountExport();
Field[] fields = softAccountExport.getClass().getDeclaredFields();
//Field softwareTypeField = softAccountExport.getClass().getDeclaredField("softwareType");
for (Field field : fields) {
Excel excel = field.getAnnotation(Excel.class);
InvocationHandler h = Proxy.getInvocationHandler(excel);
Field replace = h.getClass().getDeclaredField("memberValues");
replace.setAccessible(true);
Map map = (Map) replace.get(h);
//品牌编码动态转换
if ("brand".equals(field.getName())) {
Brand brand = new Brand();
List<Brand> brands = brandService.getAll(brand);
String[] brandArr = new String[brands.size()];
for (int i = 0; i < brands.size(); i++) {
brandArr[i] = brands.get(i).getName() + "_" + brands.get(i).getCode();
}
map.put("replace", brandArr);
}
}
List<SoftAccountExport> list = this.softAccountService.getSoftAccountExportByIds(ids);
EasyPoiUtil.exportExcel(list, "测试", "测试", SoftAccountExport.class, "测试.xlsx", response);
returnVo = new SimpleReturnVo(SUCCESS, "导出成功");
} catch (Exception e) {
logger.error("SoftAccountController-export:", e);
e.printStackTrace();
}
}
return returnVo;
}