(一)HSSFworkbook,XSSFworkbook,SXSSFworkbook区别
1. HSSFworkbook
HSSFworkbook是操作版本小于等于Excel2003的版本,扩展名是.xls。该方式的局限就是导出的行数最多为65535行,超出65536条后系统 就会报错。对内存消耗比较大,容易造成内存溢出(OOM)
2. XSSFworkbook
XSSFworkbook是操作Excel2007版本以后的,扩展名是.xlsx。该方式的局限就是导出的行数最多为1048576行,超出1048576条后系统 就会报错。对内存消耗比较大,容易造成内存溢出(OOM)
3. SXSSFWorkbook
SXSSFWorkbook是操作Excel2007版本以后的,扩展名是.xlsx。从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的SXSSF方式。对于较大型的excel创建是不会造成内存溢出的。其原理就是使用硬盘空间代替内存。SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excel rows在内存里供查看,在此之前的excel rows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。
(二)代码例子
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhkj.jtb.commons.constants.CommonConstants;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.util.CollectionUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* @author lz
* @since 2020/1/2
*/
@Slf4j
public class ExportExcel {
/**
* @param sheetName 表名,页名
* @param headersName 单元格列名(中文)
* @param columns 属性名(英文)
* @param list 导出的数据
*/
public static<T> void exportExcel(String sheetName, String[] headersName, String[] columns, List<T> list, HttpServletResponse response) {
//声明一个工作簿对象
try (SXSSFWorkbook workbook = new SXSSFWorkbook(); final ServletOutputStream out = response.getOutputStream()) {
//声明一个sheet对象
SXSSFSheet sheet = workbook.createSheet(sheetName);
//设置列自动适配内容
sheet.autoSizeColumn(columns.length);
//创建单元格样式
CellStylestyle = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
//创建表头行,就是第一行
SXSSFRowrow = sheet.createRow(0);
//设置表头内容对齐方式
SXSSFCell cell;
//添加列表头内容
for (int i = 0; i < headersName.length; i++) {
cell = row.createCell(i);
//添加名字
cell.setCellValue(headersName[i]);
//设置文本对齐
cell.setCellStyle(style);
}
if (!CollectionUtils.isEmpty(list)) {
int rowIndex = 0;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Iterator<T> it = list.iterator();
while (it.hasNext()) {
rowIndex++;
row = sheet.createRow(rowIndex);
//next()方法是取出当前的元素,并指向下一个元素
T t = it.next();
JSONObject data = JSON.parseObject(JSON.toJSONString(t));
for (int i = 0; i < columns.length; i++) {
//获取getter方法
//invoke参数,参数一:调用该方法的对象,参数二:就是属性的类型
//创建单元格
cell = row.createCell(i);
//设置单元格状态
cell.setCellStyle(style);
//取值
Object fieldValue = data.get(columns[i]);
if (fieldValue instanceof Integer) {
cell.setCellValue((Integer) fieldValue);
} else if (fieldValue instanceof Long) {
cell.setCellValue((Long) fieldValue);
} else if (fieldValue instanceof Double) {
cell.setCellValue((Double) fieldValue);
} else if (fieldValue instanceof Double) {
cell.setCellValue((Double) fieldValue);
} else if (fieldValue instanceof Boolean) {
cell.setCellValue((Boolean) fieldValue);
} else if (fieldValue instanceof Date) {
Date date = (Date) fieldValue;
String dateStr = formatter.format(date);
cell.setCellValue(dateStr);
} else {
cell.setCellValue(String.valueOf(fieldValue));
}
}
String fileName = String.format("%s.xlsx", sheetName);
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(out);
out.flush();
}
}
} catch (IOException e) {
log.error("下载EXCEL出错", e);
}
}