赞
踩
无非就是下面两种逻辑:
1.for循环查询数据,将数据写入缓存,最后一次性写入excel。
2.将已有的excel通过FIleInputStream流读出来,加载到内存当中,然后获取对应sheet页的行数,进行追加操作。
PS:建议使用CSV文件格式,直接使用Java原生的FileUtils追加写入
FileUtils.writeStringToFile(file, sb.toString(), "GBK", true);
下面来讲讲easyExcel、POI、csv相关的代码写法:
要求:
1.对表头进行排序过滤
2.对列进行排序过滤
官网地址:EasyExcel官网
我们使用新版本的,旧的对于字段排序/过滤都不支持 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency> //此为线程池异步导出 commonExecutor.execute(() -> { File file = null; ExcelWriter excelWriter = null; try { file = File.createTempFile("a", ".xlsx"); file.deleteOnExit(); excelWriter = EasyExcel.write(file, UserVO.class) .head(headlist) // 表头,传入一个list集合 .includeColumnFieldNames(showColumnList) // 对于UserVO要展示的列集合 .orderByIncludeColumn(true) // 是否根据showColumnList集合的顺序排序 .autoCloseStream(true) // 自动关闭流 .build(); WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); // 循环 200/页查询数据 int pageNum = 1; int pageSize = 200; while (true) { List<UserVO> voList = getData(pageNum, pageSize); // getData根据业务实现 // 将数据写入临时文件 此处循环追加就是写到内存里面 excelWriter.write(voList , writeSheet); if (pageNum * pageSize >= count) { break; } pageNum++; } // 数据处理完毕后,刷盘写入物理文件 excelWriter.finish(); } catch (Exception e) { log.error("导出 异常:" + e.getMessage(), e); } finally { // 删除临时文件 if (!Objects.isNull(file)) { file.delete(); } } });
网传SXSSFWorkbook可以实现追加写入,然后实操后,其实是覆盖写入。
//SXSSFWorkbook 和 XSSFWorkbook 都差不多,只是定义不同,写法都差不多 import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; public class ExcelAppender { public static void main(String[] args) { String filePath = "C:\\Local\\Temp\\11.xlsx"; // 构造一个查询数据的列表 List<String> queryDataList = List.of("query4", "query5", "query6"); // 加载已存在的 Excel 文件 try (Workbook workbook = new SXSSFWorkbook(new FileInputStream(new File(filePath)))) { Sheet sheet = workbook.getSheetAt(0); // 获取已存在数据的最后一行索引 int lastRowNum = sheet.getLastRowNum(); // 在最后一行索引的下一行开始追加写入查询数据 int rowNum = lastRowNum + 1; for (String queryData : queryDataList) { Row row = sheet.createRow(rowNum++); Cell cell = row.createCell(0); cell.setCellValue(queryData); } // 保存修改后的工作簿到文件 try (FileOutputStream outputStream = new FileOutputStream(new File(filePath))) { workbook.write(outputStream); System.out.println("查询数据已覆盖写入到 Excel 文件:" + filePath); } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } }
来写我最终选择的写法CSV,就是追加物理文件数据。很不错。
commonExecutor.execute(() -> { File temp = null; try { temp = File.createTempFile("aaa", ".csv"); temp.deleteOnExit(); List<List<String>> fillData = new ArrayList<>(); // 1.初始化表头,showNameList是表头集合,有顺序的哈~ fillData.add(ImmutableList.of(showNameList.toString())); // 2.循环 200/页查询数据 int pageNum = 1; int pageSize = 200; while (true) { List<UserVO> recordVOList = getData(pageNum, pageSize); // 3.填充业务数据 我用的反射 fillData.addAll(ExcelUtil.convertSortEntityListToDataList(showColumnList, recordVOList)); StringBuilder sb = new StringBuilder(); for (List<String> rowData : fillData) { sb.append(String.join(",", rowData)); sb.append(System.lineSeparator()); } try { FileUtils.writeStringToFile(temp, outPutStr, "GBK", true); } catch (IOException e) { log.error("写入CSV 异常:{}", e.getMessage(), e); return; } if (pageNum * pageSize >= count) { break; } pageNum++; fillData.clear(); } } catch (Exception e) { log.error("导出 异常:{}", e.getMessage(), e); } finally { // 4.删除临时文件 if (!Objects.isNull(temp)) { temp.delete(); } } });
当然,会存在一定的问题,比如csv文件打开时,office全家桶会把日期格式转换,比如:
“2024-01-04 14:28:29” -> “2024/1/4 14:28:29”
就看大家能不能接受了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。