2019-08-01 15:59:18 weixin_40049583 阅读数 36
  • 基于SSM的POI导入导出Excel实战

    本课程将给大家分享如何基于SSM实现POI导入导出Excel,并讲解目前企业级JavaWeb应用mvc三层模式的开发流程,可让初学者或者职场萌新掌握如何基于SSM整合第三方框架并采用mvc三层开发模式实现自己的业务模块!

    1263 人正在学习 去看看 钟林森

百万数据POI操作(一)

概述

​ 我们都知道Excel可以分为早期的Excel2003版本(使用POI的HSSF对象操作)和Excel2007版本(使用POI的XSSF操作),两者对百万数据的支持如下:

  • Excel 2003:在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量。这时对于百万级别数据,Excel肯定容纳不了。
  • Excel 2007:当POI升级到XSSF对象时,它可以直接支持excel2007以上版本,因为它采用ooxml格式。这时excel可以支持1048576条数据,单个sheet表就支持近百万条数据。但实际运行时还可能存在问题,原因是执行POI报表所产生的行对象,单元格对象,字体对象,他们都不会销毁,这就导致OOM的风险

JDK性能监控工具

没有性能监控工具一切推论都只能停留在理论阶段,我们可以使用Java的性能监控工具来监视程序的运行情况,包括CUP,垃圾回收,内存的分配和使用情况,这让程序的运行阶段变得更加可控,也可以用来证明我们的推测。这里我们使用JDK提供的性能工具Jvisualvm来监控程序运行。

​ VisualVM 是Netbeans的profile子项目,已在JDK中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈。

​ Jvisualvm位于JAVA_HOME/bin目录下,直接双击就可以打开该程序。如果只是监控本地的java进程,是不需要配置参数的,直接打开就能够进行监控。首先我们需要在本地打开一个Java程序,例如我打开员工后台管理系统进程,这时在jvisualvm界面就可以看到与IDEA相关的Java进程了

Jvisualvm的使用

Jvisualvm使用起来比较简单,双击点击当前运行的进程即可进入到程序的监控界面:

在这里插入图片描述

  • 双击Jvisualvm.exe

在这里插入图片描述

  • 概述:可以看到进程的启动参数。
  • 监视:左上:cpu利用率,gc状态的监控,右上:堆利用率,永久内存区的利用率,左下:类的监控,右下:线程的监控
  • 线程:能够显示线程的名称和运行的状态,在调试多线程时必不可少,而且可以点进一个线程查看这个线程的详细运行情况

百万数据POI操作(二)SXSSFWorkBook处理百万数据报表打印

需求

使用Apache POI完成百万数据量的Excel报表导出。

分析

​ 基于XSSFWork导出Excel报表,是通过将所有单元格对象保存到内存中,当所有的Excel单元格全部创建完成之后一次性写入到Excel并导出。当百万数据级别的Excel导出时,随着表格的不断创建,内存中对象越来越多,直至内存溢出。ApachePoi提供了SXSSFWork对象,专门用于处理大数据量Excel报表导出。

​ 在实例化SXSSFWork这个对象时,可以指定在内存中所产生的POI导出相关对象的数量(默认100),一旦内存中的对象的个数达到这个指定值时,就将内存中的这些对象的内容写入到磁盘中(XML的文件格式),就可以将这些对象从内存中销毁,以后只要达到这个值,就会以类似的处理方式处理,直至Excel导出完成。

Api

SXSSFWorkbook

  • 处理大数据量excel报表生成的:将已经使用过的内存元素,即使删除(poi4采用)或者保存到本地磁盘(poi3)

  • 使用条件:

    (1) 不支持模板打印

    (2)不支持太多的样式对象

实现

步骤1:模拟百万数据的导出

package cn.zonhar.web.controller.cargo;

import cn.zonhar.entity.cargo.Contract;
import cn.zonhar.entity.cargo.ContractExample;
import cn.zonhar.entity.system.User;
import cn.zonhar.entity.utils.DeleteStatus;
import cn.zonhar.entity.vo.ContractProductVo;
import cn.zonhar.service.cargo.ContractProductService;
import cn.zonhar.service.cargo.ContractService;
import cn.zonhar.web.controller.BaseController;
import cn.zonhar.web.utils.DownloadUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.github.pagehelper.PageInfo;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * @author zonhar
 * @date 2019/7/27
 * 购销合同
 */
@Controller
@RequestMapping("/cargo/contract")
public class ContractController extends BaseController {

    @Reference
    private ContractService contractService;
    @Reference
    private ContractProductService contractProductService;


    @RequestMapping(value = "/print", name = "去出货表页面")
    public String toPrint() {
        return "/cargo/print/contract-print";
    }

  

    /**
     * 处理百万级导出
     *
     * @param inputDate 出货时间
     * @return
     */
    @RequestMapping(value = "/printExcel", name = "打印出货表")
    public void printExcel(String inputDate) throws IOException {
        Workbook workbook = new SXSSFWorkbook();

        Sheet sheet = workbook.createSheet("出货表");


        //出货表.xls ,设置每列列宽
        sheet.setColumnWidth(0, 0 * 256);
        sheet.setColumnWidth(1, 26 * 256);
        sheet.setColumnWidth(2, 12 * 256);
        sheet.setColumnWidth(3, 30 * 256);
        sheet.setColumnWidth(4, 12 * 256);
        sheet.setColumnWidth(5, 15 * 256);
        sheet.setColumnWidth(6, 10 * 256);
        sheet.setColumnWidth(7, 10 * 256);
        sheet.setColumnWidth(8, 8 * 256);

        //合并单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 1, 8));
        /**
         * 创建第一行
         */
        Row row = sheet.createRow(0);
        row.setHeightInPoints(36);
        Cell cell = row.createCell(1);
        cell.setCellStyle(this.bigTitle(workbook));
        String value = inputDate.replace("-0", "-").replace("-", "年") + "月份出货表";
        cell.setCellValue(value);
        /**
         * 创建第二行
         */
        row = sheet.createRow(1);
        row.setHeightInPoints(26);
        String titles[] = new String[]{"客户", "订单号", "货号", "数量", "工厂",
                "工厂交期", "船期", "贸易条款"};
        for (int i = 0; i < titles.length; i++) {
            cell = row.createCell(i + 1);
            cell.setCellValue(titles[i]);
            cell.setCellStyle(this.title(workbook));
        }

        /**
         * 导出数据行
         */
        String companyId = getLoginCompanyId();
        List<ContractProductVo> list =
                contractProductService.findByShipTime(companyId, inputDate);

        if (list != null && list.size() > 0) {
            int index = 2;
            for (ContractProductVo cp : list) {
                for (int i = 0; i < 6000; i++) {


                    row = sheet.createRow(index++);
                    row.setHeightInPoints(24);

                    cell = row.createCell(1);
                    cell.setCellValue(cp.getCustomName());
                    //  cell.setCellStyle(this.text((workbook)));

                    cell = row.createCell(2);
                    cell.setCellValue(cp.getContractNo());
                    //  cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(3);
                    cell.setCellValue(cp.getProductNo());
                    //  cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(4);
                    cell.setCellValue(cp.getCnumber());
                    // cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(5);
                    cell.setCellValue(cp.getFactoryName());
                    //  cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(6);
                    cell.setCellValue(cp.getDeliveryPeriod());
                    //  cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(7);
                    cell.setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(cp.getShipTime()));
                    // cell.setCellStyle(this.text(workbook));

                    cell = row.createCell(8);
                    cell.setCellValue(cp.getTradeTerms());
                    //  cell.setCellStyle(this.text(workbook));
                }
            }
        }

        //导出下载
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        workbook.write(bos);
        new DownloadUtil().download(bos, response, "出货表.xlsx");


    }
  
}

堆内存的消耗:

在这里插入图片描述

导出后的大小:

在这里插入图片描述

在这里插入图片描述

2018-01-22 09:29:41 huangchunxia_1 阅读数 4139
  • 基于SSM的POI导入导出Excel实战

    本课程将给大家分享如何基于SSM实现POI导入导出Excel,并讲解目前企业级JavaWeb应用mvc三层模式的开发流程,可让初学者或者职场萌新掌握如何基于SSM整合第三方框架并采用mvc三层开发模式实现自己的业务模块!

    1263 人正在学习 去看看 钟林森

转载自:http://bbs.chinaunix.net/thread-3620272-1-1.html

说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M
我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出。由于Excel 一个sheet允许的最大行数是65536这时我们想到分sheet进行导出;但是这种情况也不能解决内存溢出的问题。毕竟数据还是一次性在内存中进行保存的。这时我们想是不是可以导出多个excel呢?下面我就尝试着按照导出多个excel
首先:我们要确定数据量有多大,然后确定一个excel导出多少条数据,这样就可以确定导出的Excel的数量,于是我们就可以循环的导出excel并保存在任意的临时目录中。去这样如果内存不够的话虚拟机就会去进行回收已经保存的excel在内存中的空间。
假设我们我们已经成功的生成了多个excel,这时我们怎么把这N个excel文档传到客户端呢?其实一个一个的传也未尝不可,但是考虑那样对用户来说体验不够好,再次多个文件在网络上传输也比较慢。我们可以考虑对生成的几个文件进行压缩,然后传到客户端。
总结一下第一、分批次生成excel第二、压缩后到客户端

下面我把我的一个小实例贴上供大家参考

第一、Person.java 普通javabean

Javabean代码

  1. package bean;  
  2. /**  
  3. *   
  4. * @author QQ:三二8二4七6七六  
  5. *  
  6. */  
  7. public class Person {  
  8.   
  9.     private Integer id;  
  10.     private String name;  
  11.     private String address;  
  12.     private String tel;  
  13.     private Double money=0.0;  
  14.     public Double getMoney() {  
  15.         return money;  
  16.     }  
  17.     public void setMoney(Double money) {  
  18.         this.money = money;  
  19.     }  
  20.     public Person(Integer id, String name, String address, String tel,Double money) {  
  21.         super();  
  22.         this.id = id;  
  23.         this.name = name;  
  24.         this.address = address;  
  25.         this.tel = tel;  
  26.         this.money=money;  
  27.     }  
  28.     public Integer getId() {  
  29.         return id;  
  30.     }  
  31.     public void setId(Integer id) {  
  32.         this.id = id;  
  33.     }  
  34.     public String getName() {  
  35.         return name;  
  36.     }  
  37.     public void setName(String name) {  
  38.         this.name = name;  
  39.     }  
  40.     public String getAddress() {  
  41.         return address;  
  42.     }  
  43.     public void setAddress(String address) {  
  44.         this.address = address;  
  45.     }  
  46.     public String getTel() {  
  47.         return tel;  
  48.     }  
  49.     public void setTel(String tel) {  
  50.         this.tel = tel;  
  51.     }  
  52. }  
复制代码
第二、PersonService模拟业务逻辑循环生成100023个Person对象

模拟业务逻辑代码
  1. package service;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import bean.Person;  
  7. /**  
  8. *   
  9. * @author QQ:三二8二4七6七六  
  10. *  
  11. */  
  12. public class PersonService {  
  13.     public static List getPerson(){  
  14.         List<Person> list =new ArrayList<Person>();  
  15.         for(int i=0;i<100320;i++){  
  16.             list.add(new Person(i,"zhangsan"+i,"北京"+i,"13214587632",123123.12+i));   
  17.         }  
  18.         return list;  
  19.     }  
  20.   
  21. }  
复制代码
第三、业务处理Servlet

操作servlet代码
  1. package servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.OutputStream;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.ArrayList;  
  10. import java.util.Date;  
  11. import java.util.List;  
  12.   
  13. import javax.servlet.ServletException;  
  14. import javax.servlet.http.HttpServlet;  
  15. import javax.servlet.http.HttpServletRequest;  
  16. import javax.servlet.http.HttpServletResponse;  
  17.   
  18. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  19. import org.apache.poi.hssf.util.CellRangeAddress;  
  20. import org.apache.poi.ss.usermodel.Cell;  
  21. import org.apache.poi.ss.usermodel.CellStyle;  
  22. import org.apache.poi.ss.usermodel.Row;  
  23. import org.apache.poi.ss.usermodel.Sheet;  
  24. import org.apache.poi.ss.usermodel.Workbook;  
  25.   
  26. import bean.Person;  
  27.   
  28. import service.PersonService;  
  29.   
  30. /**  
  31. *   
  32. * @author QQ:三二8二4七6七六  
  33. *   
  34. */  
  35. public class PersonServlet extends HttpServlet {  
  36.     private String fileName;  
  37.   
  38.     public PersonServlet() {  
  39.         super();  
  40.     }  
  41.   
  42.     public void destroy() {  
  43.         super.destroy(); // Just puts "destroy" string in log  
  44.         // Put your code here  
  45.     }  
  46.   
  47.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  48.             throws ServletException, IOException {  
  49.         // 文件名获取  
  50.         Date date = new Date();  
  51.         SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");  
  52.         String f = "Person-" + format.format(date);  
  53.         this.fileName = f;  
  54.         setResponseHeader(response);  
  55.         OutputStream out = null;  
  56.         try {  
  57.             out = response.getOutputStream();  
  58.             List<Person> list = PersonService.getPerson();  
  59.             toExcel(list,request,10000,f,out);  
  60.         } catch (IOException e1) {  
  61.             e1.printStackTrace();  
  62.         } finally {  
  63.             try {  
  64.                 out.flush();  
  65.                 out.close();  
  66.             } catch (IOException e) {  
  67.                 e.printStackTrace();  
  68.             }  
  69.         }  
  70.     }  
  71.   
  72.     /** 设置响应头 */  
  73.     public void setResponseHeader(HttpServletResponse response) {  
  74.         try {  
  75.             response.setContentType("application/octet-stream;charset=UTF-8");  
  76.             response.setHeader("Content-Disposition", "attachment;filename="  
  77.                     + java.net.URLEncoder.encode(this.fileName, "UTF-8")  
  78.                     + ".zip");  
  79.             response.addHeader("Pargam", "no-cache");  
  80.             response.addHeader("Cache-Control", "no-cache");  
  81.         } catch (Exception ex) {  
  82.             ex.printStackTrace();  
  83.         }  
  84.     }  
  85.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  86.             throws ServletException, IOException {  
  87.   
  88.         doGet(request, response);  
  89.     }  
  90.     public void init() throws ServletException {  
  91.         // Put your code here  
  92.     }  
  93.   
  94.     public void toExcel(List<Person> list, HttpServletRequest request,  
  95.             int length, String f, OutputStream out) throws IOException {  
  96.         List<String> fileNames = new ArrayList();// 用于存放生成的文件名称s  
  97.         File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");// 压缩文件  
  98.         // 生成excel  
  99.         for (int j = 0, n = list.size() / length + 1; j < n; j++) {  
  100.             Workbook book = new HSSFWorkbook();  
  101.             Sheet sheet = book.createSheet("person");  
  102.   
  103.             double d = 0;// 用来统计  
  104.             String file = request.getRealPath("/files") + "/" + f + "-" + j  
  105.                     + ".xls";  
  106.   
  107.             fileNames.add(file);  
  108.             FileOutputStream o = null;  
  109.             try {  
  110.                 o = new FileOutputStream(file);  
  111.   
  112.                 // sheet.addMergedRegion(new  
  113.                 // CellRangeAddress(list.size()+1,0,list.size()+5,6));  
  114.                 Row row = sheet.createRow(0);  
  115.                 row.createCell(0).setCellValue("ID");  
  116.                 row.createCell(1).setCellValue("NAME");  
  117.                 row.createCell(2).setCellValue("ADDRESS");  
  118.                 row.createCell(3).setCellValue("TEL");  
  119.                 row.createCell(4).setCellValue("Money");  
  120.   
  121.                 int m = 1;  
  122.   
  123.                 for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)  
  124.                         : (list.size() - j * length + 1); i < min; i++) {  
  125.                     m++;  
  126.                     Person user = list.get(length * (j) + i - 1);  
  127.                     Double dd = user.getMoney();  
  128.                     if (dd == null) {  
  129.                         dd = 0.0;  
  130.                     }  
  131.                     d += dd;  
  132.                     row = sheet.createRow(i);  
  133.                     row.createCell(0).setCellValue(user.getId());  
  134.                     row.createCell(1).setCellValue(user.getName());  
  135.                     row.createCell(2).setCellValue(user.getAddress());  
  136.                     row.createCell(3).setCellValue(user.getTel());  
  137.                     row.createCell(4).setCellValue(dd);  
  138.   
  139.                 }  
  140.                 CellStyle cellStyle2 = book.createCellStyle();  
  141.                 cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);  
  142.                 row = sheet.createRow(m);  
  143.                 Cell cell0 = row.createCell(0);  
  144.                 cell0.setCellValue("Total");  
  145.                 cell0.setCellStyle(cellStyle2);  
  146.                 Cell cell4 = row.createCell(4);  
  147.                 cell4.setCellValue(d);  
  148.                 cell4.setCellStyle(cellStyle2);  
  149.                 sheet.addMergedRegion(new CellRangeAddress(m, m, 0, 3));  
  150.             } catch (Exception e) {  
  151.                 e.printStackTrace();  
  152.             }  
  153.             try {  
  154.                 book.write(o);  
  155.             } catch (Exception ex) {  
  156.                 ex.printStackTrace();  
  157.             } finally {  
  158.                 o.flush();  
  159.                 o.close();  
  160.             }  
  161.         }  
  162.         File srcfile[] = new File[fileNames.size()];  
  163.         for (int i = 0, n = fileNames.size(); i < n; i++) {  
  164.             srcfile[i] = new File(fileNames.get(i));  
  165.         }  
  166.         util.FileZip.ZipFiles(srcfile, zip);  
  167.         FileInputStream inStream = new FileInputStream(zip);  
  168.         byte[] buf = new byte[4096];  
  169.         int readLength;  
  170.         while (((readLength = inStream.read(buf)) != -1)) {  
  171.             out.write(buf, 0, readLength);  
  172.         }  
  173.         inStream.close();  
  174.     }  
  175. }  
  176. 最后还有个工具类package util;
  177. 压缩工具类代码  
  178. import java.io.FileInputStream;  
  179. import java.io.FileOutputStream;  
  180. import java.io.IOException;  
  181. import java.util.zip.ZipEntry;  
  182. import java.util.zip.ZipOutputStream;  
  183. /**  
  184. *   
  185. * @author QQ:三二8二4七6七六  
  186. *  
  187. */  
  188. public class FileZip {  
  189.     /**  
  190.      *   
  191.      * @param srcfile 文件名数组  
  192.      * @param zipfile 压缩后文件  
  193.      */  
  194.     public static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) {  
  195.         byte[] buf = new byte[1024];  
  196.         try {  
  197.             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(  
  198.                     zipfile));  
  199.             for (int i = 0; i < srcfile.length; i++) {  
  200.                 FileInputStream in = new FileInputStream(srcfile[i]);  
  201.                 out.putNextEntry(new ZipEntry(srcfile[i].getName()));  
  202.                 int len;  
  203.                 while ((len = in.read(buf)) > 0) {  
  204.                     out.write(buf, 0, len);  
  205.                 }  
  206.                 out.closeEntry();  
  207.                 in.close();  
  208.             }  
  209.             out.close();  
  210.         } catch (IOException e) {  
  211.             e.printStackTrace();  
  212.         }  
  213.     }  
  214. }  

2019-05-25 10:51:28 y506798278 阅读数 655
  • 基于SSM的POI导入导出Excel实战

    本课程将给大家分享如何基于SSM实现POI导入导出Excel,并讲解目前企业级JavaWeb应用mvc三层模式的开发流程,可让初学者或者职场萌新掌握如何基于SSM整合第三方框架并采用mvc三层开发模式实现自己的业务模块!

    1263 人正在学习 去看看 钟林森

一、适用场景

       使用poi所供的api可以实现excel文件的导入导出,其中org.apache.poi.ss.usermodel.Workbook对象可以满足工作簿的创建以及通过excel模板创建工作簿。但是这个对象及相关api的实现原理是一次性将数据读取到内存中,然后写入excel文件,这样当数据量大时,会出现内存溢出。在这种情况下可以使用org.apache.poi.xssf.streaming.SXSSFWorkbook对象来完成工作簿的创建。

 

二、实现原理

       使用SXSSFWorkbook wb = new SXSSFWorkbook(100)创建的工作簿在读取数据时,会根据所传入的阈值(此处是100)。当内存中的对象达到这个阈值时,生成一个临时文件,以临时文件进行存储,来实现分段读取与写入。

 

三、代码

       以下两部分代码分别从控制层和业务层提取,在业务层完成了SXSSFWorkbook对象的创建,并读取通过for循环构造的测试数据完成了sheet和cell部分的赋值,最后在控制层调用业务层的方法,获取返回的对象SXSSFWorkbook,并通过io流完成excel文件的导出。

controller:

    /**
     * 导出大批量数据的excel
     * @param response HttpServletResponse
     */
    @RequestMapping(value = {"/exportBigDataFile.action"}, method = RequestMethod.GET)
    public void exportBigDataFile(HttpServletResponse response) {
        try {
            // 獲取工作表
            Workbook workbook = exportExcelService.exportBigDataExcel();
            // 完成下載
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);

            downFile(os, response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 抽取下载部分的公共代码
     * @param os ByteArrayOutputStream
     * @param response HttpServletResponse
     * @throws IOException
     */
    public void downFile(ByteArrayOutputStream os, HttpServletResponse response) throws IOException {
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + "test.xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        os.writeTo(outputStream);
        os.close();
        outputStream.flush();
    }

service:

    /**
     * 导出大数据量excel文件(该方式不能使用模板进行excel导出)
     * @return SXSSFWorkbook
     */
    @Override
    public SXSSFWorkbook exportBigDataExcel() {
        // 1.获取数据
        List<Employee> employeeList = getEmployeeList(999999);
        // 2.创建工作簿
        // 阈值,内存中的对象数量最大值,超过这个值会生成一个临时文件存放到硬盘中
        SXSSFWorkbook wb = new SXSSFWorkbook(100);
        Sheet sheet = wb.createSheet();
        // 标题
        String[] titles = {"编号", "名字", "性别", "部门", "职位", "直系领导", "月薪", "入职日期", "年假天数"};
        Row titleRow = sheet.createRow(0);
        for (int i = 0; i < titles.length; i++) {
            Cell cell = titleRow.createCell(i);
            cell.setCellValue(titles[i]);
        }
        // 3.从集合中取数据并赋值
        for (int i = 0; i < employeeList.size(); i++) {
            Employee employee = employeeList.get(i);
            Row row = sheet.createRow(i+1);
            row.createCell(0).setCellValue(employee.getCode());
            row.createCell(1).setCellValue(employee.getName());
            row.createCell(2).setCellValue(employee.getSex());
            row.createCell(3).setCellValue(employee.getDept());
            row.createCell(4).setCellValue(employee.getPosition());
            row.createCell(5).setCellValue(employee.getLeaderName());
            row.createCell(6).setCellValue(employee.getSalary());
            row.createCell(7).setCellValue(employee.getInDateStr());
            row.createCell(8).setCellValue(employee.getHolidayCount());
        }
        return wb;
    }

    /**
     * 获取模板数据
     * @return List
     * @param row 生成多少行数据
     */
    public List<Employee> getEmployeeList(int row) {
        List<Employee> employeeList = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            Employee employee = new Employee();
            employee.setCode(100 + i);
            employee.setName("名字" + i);
            employee.setDept("牛棚");
            employee.setHolidayCount(2 + i);
            employee.setInDateStr("2018-01-02");
            employee.setLeaderName("张四");
            employee.setPosition("工程师");
            employee.setSalary(3000.0);
            employee.setSex("男");
            employeeList.add(employee);
        }
        return employeeList;
    }

实体类:

public class Employee {
    /**
     * 编号
     */
    private Integer code;

    /**
     * 姓名
     */
    private String name;

    /**
     * 性别
     */
    private String sex;

    /**
     * 部门
     */
    private String dept;

    /**
     * 职位
     */
    private String position;

    /**
     * 直系领导姓名
     */
    private String leaderName;

    /**
     * 月薪
     */
    private Double salary;

    /**
     * 入职日期
     */
    private String inDateStr;

    /**
     * 年假天数
     */
    private Integer holidayCount;
}

 

2011-11-17 14:42:05 hopestar2008 阅读数 648
  • 基于SSM的POI导入导出Excel实战

    本课程将给大家分享如何基于SSM实现POI导入导出Excel,并讲解目前企业级JavaWeb应用mvc三层模式的开发流程,可让初学者或者职场萌新掌握如何基于SSM整合第三方框架并采用mvc三层开发模式实现自己的业务模块!

    1263 人正在学习 去看看 钟林森

说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M

我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出。由于Excel 一个sheet允许的最大行数是65536这时我们想到分sheet进行导出;但是这种情况也不能解决内存溢出的问题。毕竟数据还是一次性在内存中进行保存的。这时我们想是不是可以导出多个excel呢?下面我就尝试着按照导出多个excel

首先:我们要确定数据量有多大,然后确定一个excel导出多少条数据,这样就可以确定导出的Excel的数量,于是我们就可以循环的导出excel并保存在任意的临时目录中。去这样如果内存不够的话虚拟机就会去进行回收已经保存的excel在内存中的空间。

假设我们我们已经成功的生成了多个excel,这时我们怎么把这N个excel文档传到客户端呢?其实一个一个的传也未尝不可,但是考虑那样对用户来说体验不够好,再次多个文件在网络上传输也比较慢。我们可以考虑对生成的几个文件进行压缩,然后传到客户端。

总结一下第一、分批次生成excel第二、压缩后到客户端

 

下面我把我的一个小实例贴上供大家参考

 

第一、Person.java 普通javabean

 

package bean;
/**
 * 
 * @author http://javaflex.iteye.com/
 *
 */
public class Person {

	private Integer id;
	private String name;
	private String address;
	private String tel;
	private Double money=0.0;
	public Double getMoney() {
		return money;
	}
	public void setMoney(Double money) {
		this.money = money;
	}
	public Person(Integer id, String name, String address, String tel,Double money) {
		super();
		this.id = id;
		this.name = name;
		this.address = address;
		this.tel = tel;
		this.money=money;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
}

 

第二、PersonService模拟业务逻辑循环生成100023个Person对象

 

package service;

import java.util.ArrayList;
import java.util.List;

import bean.Person;
/**
 * 
 * @author http://javaflex.iteye.com/
 *
 */
public class PersonService {
	public static List getPerson(){
		List<Person> list =new ArrayList<Person>();
		for(int i=0;i<100320;i++){
			list.add(new Person(i,"zhangsan"+i,"北京"+i,"13214587632",123123.12+i));	
		}
		return list;
	}

}

 

 第三、业务处理Servlet

 

package servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import bean.Person;

import service.PersonService;

/**
 * 
 * @author http://javaflex.iteye.com/
 *
 */
public class PersonServlet extends HttpServlet {
	private String fileName;

	public PersonServlet() {
		super();
	}

	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 文件名获取
		Date date = new Date();
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		String f = "Person-" + format.format(date);
		this.fileName = f;
		setResponseHeader(response);
		OutputStream out = null;
		try {
			out = response.getOutputStream();
			List<Person> list = PersonService.getPerson();
			toExcel(list,request,10000,f,out);
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			try {
				out.flush();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/** 设置响应头 */
	public void setResponseHeader(HttpServletResponse response) {
		try {
			response.setContentType("application/octet-stream;charset=UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ java.net.URLEncoder.encode(this.fileName, "UTF-8")
					+ ".zip");
			response.addHeader("Pargam", "no-cache");
			response.addHeader("Cache-Control", "no-cache");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}
	public void init() throws ServletException {
		// Put your code here
	}

	public void toExcel(List<Person> list, HttpServletRequest request,
			int length, String f, OutputStream out) throws IOException {
		List<String> fileNames = new ArrayList();// 用于存放生成的文件名称s
		File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");// 压缩文件
		// 生成excel
		for (int j = 0, n = list.size() / length + 1; j < n; j++) {
			Workbook book = new HSSFWorkbook();
			Sheet sheet = book.createSheet("person");

			double d = 0;// 用来统计
			String file = request.getRealPath("/files") + "/" + f + "-" + j
					+ ".xls";

			fileNames.add(file);
			FileOutputStream o = null;
			try {
				o = new FileOutputStream(file);

				// sheet.addMergedRegion(new
				// CellRangeAddress(list.size()+1,0,list.size()+5,6));
				Row row = sheet.createRow(0);
				row.createCell(0).setCellValue("ID");
				row.createCell(1).setCellValue("NAME");
				row.createCell(2).setCellValue("ADDRESS");
				row.createCell(3).setCellValue("TEL");
				row.createCell(4).setCellValue("Money");

				int m = 1;

				for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)
						: (list.size() - j * length + 1); i < min; i++) {
					m++;
					Person user = list.get(length * (j) + i - 1);
					Double dd = user.getMoney();
					if (dd == null) {
						dd = 0.0;
					}
					d += dd;
					row = sheet.createRow(i);
					row.createCell(0).setCellValue(user.getId());
					row.createCell(1).setCellValue(user.getName());
					row.createCell(2).setCellValue(user.getAddress());
					row.createCell(3).setCellValue(user.getTel());
					row.createCell(4).setCellValue(dd);

				}
				CellStyle cellStyle2 = book.createCellStyle();
				cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);
				row = sheet.createRow(m);
				Cell cell0 = row.createCell(0);
				cell0.setCellValue("Total");
				cell0.setCellStyle(cellStyle2);
				Cell cell4 = row.createCell(4);
				cell4.setCellValue(d);
				cell4.setCellStyle(cellStyle2);
				sheet.addMergedRegion(new CellRangeAddress(m, m, 0, 3));
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				book.write(o);
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				o.flush();
				o.close();
			}
		}
		File srcfile[] = new File[fileNames.size()];
		for (int i = 0, n = fileNames.size(); i < n; i++) {
			srcfile[i] = new File(fileNames.get(i));
		}
		util.FileZip.ZipFiles(srcfile, zip);
		FileInputStream inStream = new FileInputStream(zip);
		byte[] buf = new byte[4096];
		int readLength;
		while (((readLength = inStream.read(buf)) != -1)) {
			out.write(buf, 0, readLength);
		}
		inStream.close();
	}
}

最后还有个工具类package util;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
 * 
 * @author http://javaflex.iteye.com/
 *
 */
public class FileZip {
	/**
	 * 
	 * @param srcfile 文件名数组
	 * @param zipfile 压缩后文件
	 */
	public static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) {
		byte[] buf = new byte[1024];
		try {
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
					zipfile));
			for (int i = 0; i < srcfile.length; i++) {
				FileInputStream in = new FileInputStream(srcfile[i]);
				out.putNextEntry(new ZipEntry(srcfile[i].getName()));
				int len;
				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}
				out.closeEntry();
				in.close();
			}
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

OK全部内容完成



 

12.8M的excel内容压缩后2.68M,给力吧

以后记得代码加注释

 

亲,记得给个评论哦

2018-02-27 16:50:33 qq_34087560 阅读数 5486
  • 基于SSM的POI导入导出Excel实战

    本课程将给大家分享如何基于SSM实现POI导入导出Excel,并讲解目前企业级JavaWeb应用mvc三层模式的开发流程,可让初学者或者职场萌新掌握如何基于SSM整合第三方框架并采用mvc三层开发模式实现自己的业务模块!

    1263 人正在学习 去看看 钟林森

maven 依赖 (版本必须一致

,否则使用SXSSFworkbook 时程序会报错)

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

HSSFworkbook,XSSFworkbook,SXSSFworkbook 三者 区别

HSSFworkbook:操作Excel2003版本,扩展名为xls

XSSFworkbook:操作Excel2007版本,扩展名为xlsx

SXSSFworkbook :用于大数据量导出,当数据量超过 65536后 程序 会报错:Invalid row number (65536) outside allowable range (0..65535)


例子1:简单导出Excel

@Test
    public void test1() throws IOException {
        // 读取文件
        POIFSFileSystem fs = new POIFSFileSystem(Thread.currentThread().getContextClassLoader().getResourceAsStream("test.xls"));
        // 创建一个工作簿
        HSSFWorkbook workbook = new HSSFWorkbook(fs);
        // 获取第一个sheet
        HSSFSheet sheet = workbook.getSheetAt(0);
        System.out.println(sheet.getSheetName());
        // 获取第一行
        HSSFRow row = sheet.getRow(0);
        // 获取第一行第一列
        HSSFCell cell = row.getCell(0);
        System.out.println(cell.getStringCellValue());

        // 创建一行
        HSSFRow row1 = sheet.createRow(1);
        // 创建单元格
        HSSFCell cell1 = row1.createCell(0);
        // 单元格赋值
        cell1.setCellValue("我是程序创建的内容");
        System.out.println(cell1.getStringCellValue());

        // 创建输出流
        FileOutputStream os = new FileOutputStream(new File("D:\\8888.xls"));
        // 输出文件
        workbook.write(os);
    }

例子2:导出查询数据

@Test
    public void test2() {
        // 模拟导出数据
        Object[] obj = new Object[]{"哈哈", "呵呵", "哼哼"};
        List<Object[]> list = new ArrayList<Object[]>();
        // HSSFWorkbook 只支持2003版本及以下版本Excel 且容量最大为65536
        for (int i = 0; i < 65536; i++) {
            list.add(obj);
        }

        export("test.xls", list, 2);
    }

    /**
     * poi 导出
     * @param fileName
     * @param objs
     * @param rowIndex
     */
    private void export(String fileName, List<Object[]> objs, int rowIndex) {
        POIFSFileSystem fs = null;
        FileOutputStream os = null;
        try {
            fs = new POIFSFileSystem(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建一个工作簿
        try {
            HSSFWorkbook workbook = new HSSFWorkbook(fs);
            HSSFCellStyle style = setCellStyle(workbook);
            // 获取一个sheet页
            HSSFSheet sheet = workbook.getSheetAt(0);

            for (int i = rowIndex - 1; i < objs.size(); i++) {
                // 创建行
                HSSFRow row = sheet.createRow(i);

                // 创建列
                for (int j = 0; j < objs.get(i).length; j++) {
                    HSSFCell cell = row.createCell(j);
                    // 设置单元格样式
                    cell.setCellStyle(style);
                    cell.setCellValue(objs.get(i)[j].toString());
                }
            }
            // 创建输出流
             os = new FileOutputStream(new File("D:\\8888.xls"));
            // 输出文件
            workbook.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 设置样式
     * @param workbook
     */
    private HSSFCellStyle setCellStyle(HSSFWorkbook workbook) {
        HSSFCellStyle style = workbook.createCellStyle();
        HSSFFont font = workbook.createFont();
        // 字号
        font.setFontHeightInPoints((short) 12);
        style.setFont(font);
        // 左右居中 上下居中
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        return style;
    }

例子3:大数据量导出

/**
     * 大数据量导出
     * @throws IOException
     */
    @Test
    public void text2() throws IOException {

        XSSFWorkbook xssfWorkbook = new   XSSFWorkbook(Thread.currentThread().getContextClassLoader().getResourceAsStream("bigdata.xlsx"));
        SXSSFWorkbook wb = new SXSSFWorkbook(xssfWorkbook, 100);

        Sheet sh = wb.getSheetAt(0);
        for(int rownum = 1; rownum < 75537; rownum++){
            Row row = sh.createRow(rownum);
            for(int cellnum = 0; cellnum < 10; cellnum++){
                Cell cell = row.createCell(cellnum);
                String address = new CellReference(cell).formatAsString();
                cell.setCellValue(address);
            }

        }

//        // Rows with rownum < 900 are flushed and not accessible
//        for(int rownum = 0; rownum < 900; rownum++){
//            Assert.assertNull(sh.getRow(rownum));
//        }
//
//        // ther last 100 rows are still in memory
//        for(int rownum = 900; rownum < 1000; rownum++){
//            Assert.assertNotNull(sh.getRow(rownum));
//        }

        FileOutputStream out = new FileOutputStream("D:\\sxssf.xlsx");
        wb.write(out);
        out.close();

        // dispose of temporary files backing this workbook on disk
        wb.dispose();
    }

poi之大数据量导出

阅读数 1673

POI 大数据导出

阅读数 240

没有更多推荐了,返回首页