直接上代码
/**
* 1.文件写入流程,调用方法 init 获取初始化对象
* 2.将调用init获取到的对象存在参数传入循环调用文件写入方法writeExcel(每一次调用该方法的数据集合不得超过65535)
* 3.调用将输出流(写入文件/http输出流)以及init对象传入writeDataToExcel方法
*/
/**
* 初始化
* @return
*/
public static SXSSFWorkbook init(){
SXSSFWorkbook workbook = new SXSSFWorkbook(10);
workbook.setCompressTempFiles(true);
return workbook;
}
/**
* excel文件写入
*/
public static <T> void writeExcel( SXSSFWorkbook workbook
, String sheetName, List<T> datas , Class<T> headers) throws Exception {
long startTime = System.currentTimeMillis();
// 分批创建sheet,避免一次性创建所有sheet占用内存
SXSSFSheet sheet = workbook.createSheet(sheetName);
// 创建表头
createHeaderRow(workbook,sheet, headers);
// 分批写入数据到当前sheet
int sheetIndex = workbook.getSheetIndex(sheet);
writeDataToSheet(sheet , sheetIndex , datas);
// 立即刷新当前sheet到磁盘,释放内存
sheet.flushRows();
// 定期清理内存
System.gc();
}
private static <T> void writeDataToSheet(SXSSFSheet sheet
, int sheetIndex , List<T> datas) throws Exception {
int size = datas.size();
long startRow = (long) sheetIndex * datas.size();
// 分批写入,每批1000行
int batchSize = 1000;
for (int batchStart = 1; batchStart <= size; batchStart += batchSize) {
int batchEnd = Math.min(batchStart + batchSize - 1, size);
writeDataBatch(sheet, startRow, batchStart, batchEnd,datas);
// 每处理10000行刷新一次
if (batchStart % 10000 == 0) {
sheet.flushRows();
}
}
}
private static <T> void writeDataBatch(SXSSFSheet sheet
, long startRow, int batchStart, int batchEnd , List<T> datas) throws IllegalAccessException {
for (int rowNum = batchStart; rowNum <= batchEnd; rowNum++) {
Row row = sheet.createRow(rowNum);
T data = datas.get(rowNum - 1);
long globalRowIndex = startRow + rowNum;
// Row数据写入
fillRowData(row, globalRowIndex,data);
// long processed = processedRows.incrementAndGet();
}
}
private static <T> void fillRowData(Row row, long globalRowIndex , T data) throws IllegalAccessException {
Class<?> aClass = data.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field declaredField = declaredFields[i];
if (declaredField.getModifiers() == 2) {
declaredField.setAccessible(true);
}
Object dataValue = declaredField.get(data);
row.createCell(i).setCellValue(String.valueOf(dataValue));
}
}
private static <T> void createHeaderRow( SXSSFWorkbook workbook
, Sheet sheet, Class<T> headers) {
Row headerRow = sheet.createRow(0);
Field[] declaredFields = headers.getDeclaredFields();
List<String> header = new ArrayList<>();
for (Field declaredField : declaredFields) {
if (declaredField.getModifiers() == 2) {
declaredField.setAccessible(true);
}
Excel declaredAnnotation = declaredField.getDeclaredAnnotation(Excel.class);
if (ObjectUtils.isEmpty(declaredAnnotation)) {
header.add(declaredField.getName());
}else {
String value = declaredAnnotation.value();
if (StringUtils.isNotEmpty(value)) {
header.add(value);
}else {
header.add(declaredField.getName());
}
}
}
for (int i = 0; i < header.size(); i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(header.get(i));
// 简单的表头样式
CellStyle headerStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerStyle.setFont(headerFont);
cell.setCellStyle(headerStyle);
}
}
public static void writeDataToExcel(OutputStream outputStream , SXSSFWorkbook workbook) throws Exception {
workbook.write(outputStream);
}
使用方式我都写在了最上面,通过泛型和反射进行解析,有需要也可以自己重新在里面改一下,写一套出来,这个功能可以导出1亿的数据都不会出现内存溢出的情况(实际测试)
9934

被折叠的 条评论
为什么被折叠?



