欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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】
Java-easyexcel的导入与导出
添加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出来问题,重新写过后就可以成功导入导出了。

有任何问题都可以在下方留言,博主看到会回复!

相关标签: java java excel