使用EasyExcel完成导出导入功能
前言
最近的项目中模块需要用到Excel的导入,在同事的建议下选择了EasyExcel。看了一下EasyExcel的介绍,其是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。那废话不多说,直接上手试试,用代码试试EasyExcel是否真的那么好用。
一.主要实现步骤
1.@ExcelProperty注解
我们需要导入的类的字段需要用到注解@ExcelProperty("列名"),这里特别注意的是一定得跟对应的导入模板里的表头保持一致,不然导入的时候匹配不上。
//导出导入类使用注解
@ExcelProperty("表头对应的中文列名")
private String data;
复制代码
2.导入模板
public void exportTemplate(HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String fileName="数据模板";
fileName = URLEncoder.encode(fileName, "UTF-8");
fileName = new String(fileName.getBytes("utf-8"),"ISO-8859-1");
String filePath = new ClassPathResource("docs/other/".concat(fileName).concat(dateFormat.format(new Date())).concat(".xlsx")).getPath();
//导出模板表头
List<String> headers = Arrays.asList("列名");
List list = new ArrayList();
PoiUtil.exportTemplateData(filePath,headers,list);
//获取文件流返回给客户端
DownloadFileUtil.downloadFile(response, request, filePath);
}
复制代码
//构造模板基础数据,比如下拉列表及其校验规则
public static void exportTemplateData(String filePath, List<String> headers, List list) {
//证件类型 下拉
List<String> certificationTypeAttributeList = new ArrayList<String>();
certificationTypeAttributeList.add("身份证");
certificationTypeAttributeList.add("户口簿");
certificationTypeAttributeList.add("护照");
certificationTypeAttributeList.add("其他");
// 2.创建Excel
// 1)创建workbook
HSSFWorkbook hssfWorkBook = new HSSFWorkbook();
// 2)创建sheet
HSSFSheet mainSheet = hssfWorkBook.createSheet(MAIN_SHEET);// 主sheet
// 用于展示
//2.1 创建表头,供用户输入
initHeaders(hssfWorkBook, mainSheet, headers);
//导出数据到主sheet
setMainSheet(mainSheet, list);
// attribute 下拉框 sheet
HSSFSheet certificationTypeAttributeSheet= hssfWorkBook.createSheet(CERTIFICATIONTYPE_ATTRIBUTE_STATUS);
hssfWorkBook.setSheetHidden(hssfWorkBook.getSheetIndex(certificationTypeAttributeSheet), true);// 设置sheet是否隐藏
// 3.写入数据
writeData(hssfWorkBook, mapSheet, mapOneList, map);
//证件类型位
writeDropDownData(hssfWorkBook, certificationTypeAttributeSheet, certificationTypeAttributeList, CERTIFICATIONTYPE_ATTRIBUTE_STATUS);
// 4.设置数据有效性
setDataValid(hssfWorkBook, mainSheet,"boundaryMarking");
FileOutputStream os = null;
try {
String exisname = filePath.substring(0, filePath.lastIndexOf("/"));
File f = new File(exisname);
if (!f.exists()) {
f.mkdirs();//创建目录
}
// 创建可写入的Excel工作簿
File file = new File(filePath);
if (!file.exists()) {
boolean bool = file.createNewFile();
System.out.println(bool);
} else {
file.delete();
file.createNewFile();
}
os = new FileOutputStream(filePath);
hssfWorkBook.write(os);
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(os);
}
}
复制代码
2.创建导入模板下载类
用于下载后填充数据进行导入操作
public static void downloadFile(HttpServletResponse response, HttpServletRequest request, String filePath) {
try {
//获取文件
File file = new File(filePath);
String fileName = file.getName();
response.reset();
ServletOutputStream out = response.getOutputStream();
request.setCharacterEncoding("UTF-8");
int BUFFER = 1024 * 10;
byte data[] = new byte[BUFFER];
BufferedInputStream bis = null;
//获取文件输入流
InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath));
// 以流的形式下载文件。
DataInputStream fis = new DataInputStream(inputStream);
int read;
bis = new BufferedInputStream(fis, BUFFER);
response.setContentType("application/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
while ((read = bis.read(data)) != -1) {
out.write(data, 0, read);
}
fis.close();
bis.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
File file = new File(filePath);
//删除临时文件
if (file.exists()) {
file.delete();
}
}
}
复制代码
3.创建导入监听器,监听器负责处理数据
比如数据的校验、转换、业务逻辑处理、数据入库操作。我感觉用监听器比较麻烦直接使用了另外一种做法,对监听器感兴趣的小伙伴可以去看看
//从前端接收传过来的文件
InputStream inputStream = file.getInputStream();
List<DataModel> list = EasyExcel.read(inputStream).head(DataModel.class).sheet().doReadSync();
//对解析到数据进行逻辑操作......
复制代码
二.值得注意的地方
1.下拉列表及单选框
如果需要导入的列名需要用到大量的下拉列表,单选框,在创建导入模板里就需要提前将其需要填充的数据从数据库或者接口里获取到先进行下拉列表或者单选框的数据填充。而且填充的只能是中文,这就涉及到一个问题,在进行导入处理数据时还需要将中文的转换为其对应的编码入库,这时就比较麻烦了。
2.级联操作
遇到到省市区三级联或者四级联时,同样需要提前进行数据填充,还要维护好级联关系。另外就是虽然省市区的变化不会太大,但是出于数据的严谨性需要定期同步最新的省市区数据,废弃掉在此之前的数据模板(模板导出时文件名带当前日期,用日期进行判断),如果业务不需要这么严谨这点可以不用考虑。
三.总结
按业务场景用了一下,感觉挺不错,比之前一步步的操作方便多了,导出导入都很快,而且都是流操作,不会产生额外的临时文件。不过也由于Excel本身的一些限制,在一些业务场景下使用起来就很费劲,比如有大量下拉列表的这种业务场景就不太适用。对这块感兴趣的小伙伴可以一起交流交流。