cnfox

POI导出excel的几种方式及HSSFWorkbook的代码实现
由于时间问题,文中代码没有进行细致的分析讲解 POI是Apache软件基金会的开放源码函式库是Apac...
扫描右侧二维码阅读全文
21
2019/10

POI导出excel的几种方式及HSSFWorkbook的代码实现

由于时间问题,文中代码没有进行细致的分析讲解

 POI是Apache软件基金会的开放源码函式库是Apache下的顶级项目,提供API给Java程序对Microsoft Office格式档案读和写的功能。即通过简单的代码和后端流程即可实现指定数据导出Excel格式文件,便于企业进行数据分析备份等.
 POI导出Excel最常用的是第一种方式HSSFWorkbook,不过这种方式数据量大的话会产生报错问题,SXSSFWorkbook是一种大数据量导出格式,XSSFWorkbook介于两者之前大量数据伴随OOM内存溢出问题,csv是另一种excel导出的一种轻快的实现。在这里主要介绍前三种
POI

区别

 用JavaPOI导出Excel时,我们需要考虑到Excel版本及数据量的问题。针对不同的Excel版本,要采用不同的工具类,如果使用错了,会出现错误信息。
HSSFWorkbook:

  1. poi导出excel最常用的方式
  2. 操作Excel2003以前(包括2003)的版本,扩展名是.xls
  3. 导出的行数至多为65535行,超出65536条后系统就会报错。此方式因为行数不足七万行所以一般不会发生内存不足的情况(OOM)

XSSFWorkbook:

  1. 操作Excel2007的版本,扩展名是.xlsx
  2. 这种形式的出现是为了突破HSSFWorkbook的65535行局限。其对应的是excel2007(1048576行,16384列)扩展名为“.xlsx”,最多可以导出104万行,不过这样就伴随着一个问题---OOM内存溢出,原因是你所创建的book
    sheet row cell等此时是存在内存的并没有持久化。

SXSSFWorkbook

  1. 从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的SXSSF方式。对于大型excel文件的创建,一个关键问题就是,要确保不会内存溢出。其实,就算生成很小的excel(比如几Mb),它用掉的内存是远大于excel文件实际的size的。如果单元格还有各种格式(比如,加粗,背景标红之类的),那它占用的内存就更多了。对于大型excel的创建且不会内存溢出的,就只有SXSSFWorkbook了。它的原理很简单,用硬盘空间换内存(就像hashmap用空间换时间一样)。
  2. SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excelrows在内存里供查看,在此之前的excelrows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。当数据量超出65536条后,

当数据量超出65536条后,在使用HSSFWorkbook或XSSFWorkbook,程序会报OutOfMemoryError:Javaheap space;内存溢出错误。这时应该用SXSSFworkbook。

SXSSF Beta 3.8下临时文件删除方法

注意:针对 SXSSF Beta 3.8下,会有临时文件产生,比如:
poi-sxssf-sheet4654655121378979321.xml
文件位置:java.io.tmpdir这个环境变量下的位置
Windows 7下是C:UsersxxxxxAppDataLocalTemp
Linux下是 /var/tmp/
要根据实际情况,看是否删除这些临时文件

HSSFWorkbook-SXSSFWorkbook导出excel文件获取大小记录

 偶然发现HSSSFWorkbook 和SXSSFWorkbook workbook对象在执行write方法写入数据到ServletOutputStream(输出流)时 是有点区别的

 HSSFWorkbook在write方法执行完的时候并没有关闭流 ,所以我们可以对这个流统计大小来获取导出文件的大小,并且最后需要我们手动关闭
而SXSSFWorkbook的write方法流关闭,write方法执行完之后流就拿不到大小了
源码
 HSSFWorkbook可以通过拿到流写入到文件里来获取文件的大小来获取导出excel的大小
 如下面这个controller例子:

/**
     * 导出文件
     * @param request
     * @param response
     */
    @RequestMapping("/salesQuery/modelSalesAmountFaw/exportExcelMap")
    public void exportExcel(HttpServletRequest request,HttpServletResponse response){

        Map<String, Object> paramsMap = getPageParams(request);
        try {
            Workbook wb = modelSalesAmountFawManager.exportExcel(request, paramsMap);
            String excelName = null;
            String languageType = request.getParameter("languageType");
            System.out.println("languageType==="+languageType);
            if("EN".equals(languageType)){
                excelName = java.net.URLEncoder.encode(moduleNameEn, "UTF-8");
            } else{
                excelName = java.net.URLEncoder.encode(moduleName, "UTF-8");
            }
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            SimpleDateFormat dateFormater = new SimpleDateFormat("yyyyMMddHHmmss");
            Date date=new Date();
            response.setHeader("Content-Disposition", "attachment;filename="+excelName+dateFormater.format(date)+".xls" );  
            ServletOutputStream out = response.getOutputStream();  
            wb.write(out);
            
            //先把EXCEL写到临时目录,用来获取文件大小,最后删除
            File f = new File(request.getSession().getServletContext().getRealPath("/") + "/demoExcel/demo.xls");
            if(!f.exists())
            {
                f.createNewFile();
            }
            BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(f));
            wb.write(s);
            
            //关闭流
            s.flush();
            s.close();
            out.flush();
            out.close();
            
            //记录导出日志,并删除临时文件
            paramsMap.put("exportSize", AppFrameworkUtil.getNum(f.length()/1024, 0));
            logManager.updateModuleLog(paramsMap);
            f.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

HSSFWorkbook的代码实现

引入Maven坐标

    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.9</version>
    </dependency>

前端绑定

<a href="./cus/exportXls" class="coolbg">导出Excel</a>

后端Controller层

package cn.icnfox.crmpro.customer.controller;

import cn.icnfox.crmpro.common.controller.BaseController;
import cn.icnfox.crmpro.common.pojo.QueryObj;
import cn.icnfox.crmpro.common.pojo.Result;
import cn.icnfox.crmpro.customer.pojo.Customer;
import cn.icnfox.crmpro.customer.service.CustomerService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


@RestController
@RequestMapping("/cus")
public class CustomerController extends BaseController<Customer> {

    @Autowired
    private CustomerService customerService;
    /*分页查询*/
    @GetMapping("findByPage")
    public Result<Customer> findByPage(QueryObj queryObj,
                                       @RequestParam (value="pageNum",required = false,defaultValue = "1") int pageNum,
                                       @RequestParam(value="pageSize",required = false,defaultValue = "5") int pageSize){

        PageHelper.startPage(pageNum,pageSize);
        List<Customer> customers = customerService.findAll(queryObj);
        PageInfo<Customer> pageInfo = new PageInfo<>(customers);

        if(customers!= null && customers.size()>0){
            return getRightResult(pageInfo);
        }else{
            return getWrongResult();
        }
    }

    @GetMapping("findAll")
    public Result<Customer> findAll(){
        List<Customer> customers = customerService.findAll(null);
        return getRightResult(customers);
    }
    /*保存*/
    @PostMapping("save")
    public Result<Customer> save(Customer customer){
        customer.setAddtime(new Date());
        boolean status = customerService.save(customer);
        if(status){
            return getRightResult();
        }else{
            return getWrongResult();
        }
    }
    /*通过id查询*/
    @GetMapping("/findById/{id}")
    public Result<Customer> findById(@PathVariable Integer id){
        //健壮性判断
        if(id==0||id==null){
            return getWrongResult("the parameter(id) is not found !");
        }
        Customer customer = customerService.findById(id);
        if(customer==null){
            return getWrongResult("the result is null");
        }
        return getRightResult(customer);
    }
    /*更新操作*/
    @PostMapping("update")
    public Result<Customer> update(Customer customer){
        if(customer.getId()==0||customer.getId()==null){
            return getWrongResult("the parameter(id) is not found !");
        }
        boolean status = customerService.update(customer);
        if(!status){
            return getWrongResult("修改失败...");
        }
        return getRightResult();
    }
    /*删除指定id*/
    @PostMapping("deleteByIds")
    public Result<Customer> deleteByIds(@RequestParam("ids") List<Integer> ids){
        if(ids==null||ids.size()==0){
            return getWrongResult("please give me the ids !!");
        }
        boolean status = customerService.deleteByIds(ids);
        if(status){
            return getRightResult();
        }else{
            return getWrongResult("删除失败");
        }
    }

    @GetMapping("exportXls")
    public ResponseEntity<byte[]> exportXls() throws IOException {

        //创建工作簿
        Workbook workbook = new HSSFWorkbook();
        //创建工作表
        Sheet sheet = workbook.createSheet("new sheet");
        //标题
        Row title = sheet.createRow(0);
        title.createCell(0).setCellValue("编号");
        title.createCell(1).setCellValue("公司名称");
        title.createCell(2).setCellValue("联系人");
        title.createCell(3).setCellValue("公司地址");
        title.createCell(4).setCellValue("联系方式");
        title.createCell(5).setCellValue("座机号码");
        title.createCell(6).setCellValue("公司简介");
        title.createCell(7).setCellValue("备注");
        title.createCell(8).setCellValue("添加时间");

        //内容检索注入
        List<Customer> all = customerService.findAll(null);
        for (Customer customer : all) {
            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
            row.createCell(0).setCellValue(customer.getId());
            row.createCell(1).setCellValue(customer.getComname());
            row.createCell(2).setCellValue(customer.getCompanyperson());
            row.createCell(3).setCellValue(customer.getComaddress());
            row.createCell(4).setCellValue(customer.getComphone());
            row.createCell(5).setCellValue(customer.getCamera());
            row.createCell(6).setCellValue(customer.getPresent());
            row.createCell(7).setCellValue(customer.getRemark());
            row.createCell(8).setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(customer.getAddtime()));
        }

        //byte数组
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        workbook.write(byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();

        //header
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attchment","customer.xls");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return new ResponseEntity<byte[]>(bytes,headers, HttpStatus.OK);
    }
}

后端sercice层

package cn.icnfox.crmpro.customer.service;

import cn.icnfox.crmpro.common.pojo.QueryObj;
import cn.icnfox.crmpro.customer.pojo.Customer;

import java.util.List;


public interface CustomerService {
    List<Customer> findAll(QueryObj queryObj);

    boolean save(Customer customer);

    Customer findById(Integer id);

    boolean update(Customer customer);

    boolean deleteByIds(List<Integer> ids);
}
package cn.icnfox.crmpro.customer.service.impl;


import cn.icnfox.crmpro.common.pojo.QueryObj;
import cn.icnfox.crmpro.customer.dao.CustomerDao;
import cn.icnfox.crmpro.customer.pojo.Customer;
import cn.icnfox.crmpro.customer.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    @SuppressWarnings("all")
    private CustomerDao customerDao;

    @Override
    public List<Customer> findAll(QueryObj queryObj) {
        return customerDao.findAll(queryObj);
    }

    @Override
    public boolean save(Customer customer) {
        return customerDao.save(customer)>0;
    }

    @Override
    public Customer findById(Integer id) {
        return customerDao.findById(id);
    }

    @Override
    public boolean update(Customer customer) {
        return customerDao.update(customer)>0;
    }

    @Override
    public boolean deleteByIds(List<Integer> ids) {
        return customerDao.deleteByIds(ids)>0;
    }
}

后端dao层

package cn.icnfox.crmpro.customer.dao;

import cn.icnfox.crmpro.common.pojo.QueryObj;
import cn.icnfox.crmpro.customer.pojo.Customer;

import java.util.List;

public interface CustomerDao {

    List<Customer> findAll(QueryObj queryObj);

    int save(Customer customer);

    Customer findById(Integer id);

    int update(Customer customer);

    int deleteByIds(List<Integer> ids);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.icnfox.crmpro.customer.dao.CustomerDao">


    <select id="findAll" parameterType="queryObj" resultType="customer">
        select * from customer
        <where>
            <if test="cid==1">
               comname like '%${keyword}%'
            </if>
            <if test="cid==2">
                companyperson like '%${keyword}%'
            </if>
        </where>
        <if test="orderby==1">
            order by id desc
        </if>
    </select>

    <insert id="save" parameterType="customer">
        insert into customer values (null,#{comname},#{companyperson},#{comaddress},#{comphone},#{camera},#{present},#{remark},#{addtime})
    </insert>

    <select id="findById" parameterType="int" resultType="customer">
        select * from customer where id = #{id}
    </select>

    <update id="update" parameterType="customer">
        update customer
        <set>
            <if test="comname!=null">
                comname=#{comname},
            </if>
            <if test="companyperson!=null">
                companyperson=#{companyperson},
            </if>
            <if test="comaddress!=null">
                comaddress=#{comaddress},
            </if>
            <if test="comphone!=null">
                comphone=#{comphone},
            </if>
            <if test="camera!=null">
                camera=#{camera},
            </if>
            <if test="present!=null">
                present=#{present},
            </if>
            <if test="remark!=null">
                remark=#{remark},
            </if>
            <if test="addtime!=null">
                addtime=#{addtime},
            </if>
        </set>
        where id = #{id}
    </update>

    <delete id="deleteByIds" parameterType="int">
        delete from customer where
        <foreach collection="list" item="id" open="id in (" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
</mapper>

Photo by eberhard grossgasteiger from Pexels

Last modification:October 21st, 2019 at 11:22 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment