Java-easyexcel的导入与导出
程序员文章站
2024-03-20 14:29:16
...
最近公司要求在项目中新增一个导入导出Excel的功能,在对比Apache poi、jxl和easyexcel后,最终选择了easyexcel。
alibaba.easyExcel
easyexcel重写了POI对07版的Excel的解析,能够原本一个3M的Excel的用POI sax依然需要100M左右内存降低到KB级别,并且再大的Excel中不会出现内存溢出,03版依赖POI的萨克斯模式。在上层做了模型转换的封装,让使用者更加简单方便。
Excel文件导入、导出
下面是我写的阿里easyexcel实现Excel导入、导出示例,使用网络下载的方法导出数据。
准备工作
先准备一个测试导入的Excel文档,后缀名必须是【.xlsx】
添加maven
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.2-beta4</version>
</dependency>
添加Excel的映射实体类
/**
* 员工表 atest
*
* @author SJH
* @date 2020-03-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class Atest extends BaseRowModel
{
private static final long serialVersionUID = 1L;
/**
* value: 表头名称
* index: 列的号, 0表示第一列
*/
/** 编号 */
private Integer id;
/** 姓名 */
@ExcelProperty(value ="姓名", index = 0)
private String aname;
/** 年龄 */
@ExcelProperty(value ="年龄", index = 1)
private Integer aage;
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setAname(String aname)
{
this.aname = aname;
}
public String getAname()
{
return aname;
}
public void setAage(Integer aage)
{
this.aage = aage;
}
public Integer getAage()
{
return aage;
}
@Override
public String toString() {
return "Atest{" +
"id=" + id +
", aname='" + aname + '\'' +
", aage=" + aage +
'}';
}
}
controller层方法
/*
* 导入Excel数据
*/
@ApiOperation(value="接口说明",httpMethod="POST",notes="导入Excel数据")
@RequestMapping("/insert")
@ResponseBody
public Map<String,Object> insert(@RequestParam("file") MultipartFile file){
Map<String,Object> map=new HashMap<>();
try {
if (file.isEmpty()) {
map.put("msg","文件为空");
map.put("code","0");
return map;
}
// 获取文件名
String fileName = file.getOriginalFilename();
// 获取文件的后缀名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
//创建一个临时文件,用于暂时存放
File tmpFile = File.createTempFile("tmp", null);
//将MultipartFile 转换为 File 临时文件
file.transferTo(tmpFile);
//将临时文件转为输入流
InputStream inputStream = new FileInputStream(tmpFile);
boolean result=atestService.readExcel(inputStream, Atest.class);
if (result){
map.put("code",1);
}
//上传完成 删除临时文件
tmpFile.delete();
return map;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
map.put("code",0);
return map;
}
/**
* 下载模板,用于填写导入数据
* @param request
* @param response
*/
@ApiOperation(value="接口说明",httpMethod="POST",notes="下载模板,用于填写导入数据")
@RequestMapping("/downloadExcel")
public void cooperation(HttpServletRequest request, HttpServletResponse response) {
ServletOutputStream out = null;
try {
out = response.getOutputStream();
response.setContentType("multipart/form-data");
response.setCharacterEncoding("utf-8");
String fileName = "数据模板";
response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")+".xlsx");
atestService.writeExcel(out,Atest.class,null);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 导出全表数据文件
* @param request
* @param response
*/
@ApiOperation(value="导出全表数据文件")
@RequestMapping("/downloadExcelData")
@ResponseBody
public void cooperationData(HttpServletRequest request, HttpServletResponse response) {
ServletOutputStream out = null;
try {
//清除空白行
response.reset();
//设置下载类型
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//设置不缓存
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
//在代理服务器端防止缓冲
response.setDateHeader("Expires", 0);
//设置当前时间作为下载名称
String nowtimes=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
// 设置头消息
response.setHeader("Content-Disposition", "attachment;filename=" + nowtimes +".xlsx");
//下载到浏览器默认地址
out= response.getOutputStream();
Atest atest=new Atest();
//查询全表,把数据明细放在list中
List<Atest> list =atestService.selectAtestList(atest);
//将数据写入excel表中
Boolean flag = atestService.writeExcel(out,Atest.class,list);
if(flag){
log.info("导出数据表成功:" + flag);
}else {
log.error("导出数据表失败:" + flag);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null){
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
service层
这里没有使用批量导入数据库,单纯循环插入数据库,如果需要可在下面 readExcel 方法中修改。
/**
* @param is 导入文件输入流
* @param clazz Excel实体映射类
* @return
*/
@Transactional
@Override
public boolean readExcel(InputStream is, Class clazz){
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(is);
// 解析每行结果在listener中处理
AnalysisEventListener listener = new AtestListener();
ExcelReader excelReader = EasyExcelFactory.getReader(bis, listener);
excelReader.read(new Sheet(1, 1, clazz));
int count=0;
if(((AtestListener) listener).getCount()==((AtestListener) listener).getDatas().size()){
for (Atest a:((AtestListener) listener).getDatas()){
if(insertAtest(a)>0){
count+=1;
}
}
if (count==((AtestListener) listener).getDatas().size()){
log.info("导入文件数据,成功插入数据库!");
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("文件IO异常:{}", e.getMessage());
return false;
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
*
* @param os 文件输出流
* @param clazz Excel实体映射类
* @param data 导出数据
* @return
*/
@Override
public boolean writeExcel(OutputStream os, Class clazz, List<? extends BaseRowModel> data){
BufferedOutputStream bos= null;
try {
bos = new BufferedOutputStream(os);
ExcelWriter writer = new ExcelWriter(bos, ExcelTypeEnum.XLSX);
//写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
Sheet sheet1 = new Sheet(1, 0,clazz);
writer.write(data, sheet1);
writer.finish();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
添加导入数据监听类
import com.aaa.project.system.atest.domain.Atest;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* @author SJH
* @create 2020/3/30
*/
public class AtestListener extends AnalysisEventListener{
private static final Logger log = LoggerFactory.getLogger(AtestListener.class);
private int count = 0;
//自定义用于暂时存储data。
//可以通过实例获取该值
private List<Atest> datas = new ArrayList<Atest>();
@Override
public void invoke(Object object, AnalysisContext context) {
log.info("当前行:"+context.getCurrentRowNum());
log.info("object:"+object);
doSomething(object);//根据自己业务做处理
}
private void doSomething(Object object) {
try {
/**
*@desc 总数增加
*/
count++;
datas.add((Atest) object);
} catch (Exception e) {
log.error("批量获取用户数据异常:{}", e.getMessage());
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// datas.clear();//解析结束销毁不用的资源
}
public List<Atest> getDatas() {
return datas;
}
public void setDatas(List<Atest> datas) {
this.datas = datas;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
关于mybatis的我就不写出来的,无非就是对mysql的操作。
最后
在编写过程中出现了一个小问题:导入Excel时能获取到Excel的数据,但却插入不了数据库。后面发现是mybatis出来问题,重新写过后就可以成功导入导出了。
有任何问题都可以在下方留言,博主看到会回复!