73 lines
3.3 KiB
Markdown
73 lines
3.3 KiB
Markdown
# 通用 Excel 模块
|
|
|
|
`pjcloud-common-excel` 提供 Excel 导入、普通导出以及大数据量 XLSX 分批流式导出能力。
|
|
|
|
## 分批流式导出
|
|
|
|
`BatchExcelExportTemplate` 适用于单次导出不能把全部查询结果和全部工作表行同时保留在 JVM 堆中的场景。它统一负责:
|
|
|
|
- 根据预统计数量循环分页查询;
|
|
- 使用 `SXSSFWorkbook` 把超出内存窗口的工作表行刷新到磁盘;
|
|
- 校验分页实际数量与预统计数量一致;
|
|
- 校验 Excel 2007 单工作表行数上限;
|
|
- 释放模板流、工作簿、SXSSF 临时 XML 和最终 XLSX 临时文件;
|
|
- 通过回调接入业务进度、汇总行和文件上传逻辑。
|
|
|
|
业务模块先增加公共 Excel 依赖:
|
|
|
|
```xml
|
|
<dependency>
|
|
<groupId>com.bsd</groupId>
|
|
<artifactId>pjcloud-common-excel</artifactId>
|
|
</dependency>
|
|
```
|
|
|
|
典型调用方式:
|
|
|
|
```java
|
|
String fileUrl = BatchExcelExportTemplate.<ExportRow, ExportContext, String>builder(total)
|
|
.batchSize(1000)
|
|
.dataStartRowIndex(2)
|
|
.reservedTailRowCount(1)
|
|
.temporaryFilePrefix("user-export-")
|
|
.templateSupplier(() -> ResourceUtil.getStream("file/user.xlsx"))
|
|
.templateInitializer(workbook -> prepareTemplate(workbook))
|
|
.pageFetcher((pageNumber, batchSize) -> {
|
|
Page<ExportRow> page = new Page<>(pageNumber, batchSize, false);
|
|
return userService.pageForExport(page, query).getRecords();
|
|
})
|
|
.rowWriter((sheet, rowIndex, dataIndex, item, context) ->
|
|
writeRow(sheet, rowIndex, dataIndex, item, context))
|
|
.footerWriter((sheet, rowIndex, processedTotal, context) ->
|
|
writeSummary(sheet, rowIndex, context))
|
|
.progressListener((processedTotal, expectedTotal) ->
|
|
reporter.advance("已整理 " + processedTotal + " / " + expectedTotal + " 条"))
|
|
.fileConsumer(path -> upload(Files.readAllBytes(path), fileName))
|
|
.execute();
|
|
```
|
|
|
|
## 与异步任务组合
|
|
|
|
公共 Excel 模块不依赖 `pjcloud-common-async-task`。业务层通过 `progressListener` 把每批完成事件转给
|
|
`AsyncTaskProgressReporter`,通过 `fileConsumer` 上传完整文件并返回 `AsyncTaskResult` 所需的地址。
|
|
|
|
异步任务总步数可统一计算:
|
|
|
|
```java
|
|
int progressTotal = BatchExcelExportTemplate.calculateProgressTotal(total, batchSize, 2);
|
|
reporter.updateTotal(progressTotal, "已查询 " + total + " 条数据,将分批生成文件");
|
|
```
|
|
|
|
额外的 `2` 由业务流程定义,例如文件上传一步和异步任务成功收尾一步。公共模板每完成一个查询批次只通知一次,
|
|
不会按明细行高频写 Redis。
|
|
|
|
## 调用约束
|
|
|
|
- 预统计和分页查询必须使用完全相同的筛选条件、租户上下文和数据权限。
|
|
- 分页 SQL 必须有稳定排序;排序字段存在重复值时,需要追加唯一字段,避免翻页时漏行或重复。
|
|
- 导出期间数据发生增删会触发数量不一致异常,业务方应提示用户重新导出。
|
|
- `dataStartRowIndex` 和 `reservedTailRowCount` 都按 Excel 零基行号语义配置。
|
|
- `fileConsumer` 收到的路径只在回调期间有效,不得交给其他线程延迟读取。
|
|
- 默认关闭共享字符串表以控制内存;只有确认重复文本占比高且内存可控时才启用。
|
|
- 单个工作表仍受 XLSX 的 1,048,576 行上限约束;超过上限时应按业务条件拆分文件或扩展为多工作表导出。
|