本文是 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 第一行为0int 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);// 获取sheetXSSFSheet 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) {}}}
这样就可以修改导出的表头等信息了