java 利用poi根据excel模板导出数据(二)

本文是  java 利用poi根据excel模板导出数据(一) 的续篇

经常有poi的开发一定会碰到三个名词:

HSSFWorkbook 、 XSSFWorkbook、SXSSFWorkbook;

这三个都是导出excel的形式,具体区别:

HSSFworkbook,XSSFworkbook,SXSSFworkbook区别总结

我们在上篇用的是XSSFWorkbook,上篇我这边需求最多100行,所以用了XSSFworkbook,

但是由于需求不同、所导出的数据量不同,包括导出的文件大小等等,应选择不同的形式。考虑到别的需求有超过65535的,本文就以SXSSFworkbook来补充上篇

因为SXSSFworkbook在使用Excel模板下载数据时将不能直接动态改变表头,所以我们需要

去获取初始模板的行数据,并操作。

首先,我们直接把XSSFworkbook 改成SXSSFworkbook,看看会有什么效果

为什么getRow是空呢?

SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excel rows在内存里供查看,在此之前的excel rows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。

还有就是,模板数据存在于XSSFWorkbook中,你需要用sxssfWorkbook.getXSSFWorkbook()方法去获取初始模板的行数据。

为什么POI模板中的数据获取不到?

我们来试试 (只贴修改的方法代码,其他的和上篇一样)

  public static void doExportLongArrearsData() {
        // 要导出的数据
        NutMap nutMap = NutMap.NEW();
        nutMap.addv("comm","1111");
        nutMap.addv("a","1111");
        nutMap.addv("b","2222");
        nutMap.addv("c","11333311");
        nutMap.addv("d","1114441");
        nutMap.addv("e","555");
        nutMap.addv("f","6666");
        nutMap.addv("g","7777");
        nutMap.addv("h","88888");
        List<NutMap> list = Lists.newArrayList();
        list.add(nutMap);
        // 导出列  列数
        int colNum = 9;
        int[] colWidth = new int[colNum];
        for (int i = 0; i < colNum; i++) {
            colWidth[i] = 23;
        }
        // 从XX行开始为数据内容  excel 第一行为0
        int startRow = 5;
        //  2003版本的Excel (xls) ---- HSSFWorkbook
        //    2007版本以及更高版本 (xlsx)---- XSSFWorkbook
        //    2007版本以及更高版本 (xlsx)---- SXSSFWorkbook
        //SXSSF与XSSF的对比:
        //
        //a. 在一个时间点上,只可以访问一定数量的数据
        //
        //b. 不再支持Sheet.clone()
        //
        //c. 不再支持公式的求值
        //
        //d. 在使用Excel模板下载数据时将不能动态改变表头,因为这种方式已经提前把excel写到硬盘的了就不能再改了
        SXSSFWorkbook workbook = null;
        try {
            // 此处linux和windows通用   /files/cq.xlsx 在resource目录下  视情况而定
 
        /**
             *   特殊说明: this.getClass().getResourceAsStream 
             *   如果fileUrl路径前不加 / 那么会读取类文件夹下的文件。加了才会读取resource下面的文件
             *   exp: this.getClass().getResourceAsStream("/files/cq.xlsx") ==>读取resource下面的文件
             *   this.getClass().getResourceAsStream("files/cq.xlsx") ==>读取当前类下的文件
             *   源码:
             *     private String resolveName(String name) {
             *         if (name == null) {
             *             return name;
             *         }
             *         if (!name.startsWith("/")) {
             *             Class<?> c = this;
             *             while (c.isArray()) {
             *                 c = c.getComponentType();
             *             }
             *             String baseName = c.getName();
             *             int index = baseName.lastIndexOf('.');
             *             if (index != -1) {
             *                 name = baseName.substring(0, index).replace('.', '/')
             *                     +"/"+name;
             *             }
             *         } else {
             *             name = name.substring(1);
             *         }
             *         return name;
             *     }
             */
            //  InputStream inputStream = this.getClass().getResourceAsStream("/files/cq.xlsx");
            FileInputStream inputStream = new FileInputStream( new File("C:\\Users\\usaer\\Desktop\\buss.xlsx"));
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
            workbook = new SXSSFWorkbook(xssfWorkbook);
 // 获取sheet
            XSSFSheet sheetAt = xssfWorkbook.getSheetAt(0);
 
            // 动态列  修改表头名 、修改模板数据等操作
            // 自定义参数
            int k = 1;
            updateCellLoad(workbook,sheetAt ,k);
 
            // 填充数据
            fillBodyData( sheetAt ,startRow,list,colWidth);
 
          // 设置单元格宽度 (不设置就是模板宽度)
            if (null != colWidth) {
                for (int i = 0; i < colWidth.length; i++) {
                    sheetAt.setColumnWidth(i, colWidth[i] * 256 + 184);
                }
            }
 
            // 输出流
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            // excel工作空间写入流
            workbook.write(byteArrayOutputStream);
            InputStream wrap = Streams.wrap(byteArrayOutputStream.toByteArray());
            // 写到本地
            writeToLocal("C:\\Users\\usaer\\Desktop\\buss_"+k+".xlsx",wrap);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            // 关闭流
            if (null != workbook)
                try {
                    workbook.close();
// SXSSFWorkbook 
                    workbook.dispose();
                }
                catch (IOException e) {
 
                }
        }
    }

 

这样就可以修改导出的表头等信息了