本文是 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 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) {
}
}
}
这样就可以修改导出的表头等信息了
没来得及全测,如有错误,欢迎各位大佬指出