修改excel导出逻辑
parent
564d028889
commit
7e4bdbce28
|
|
@ -48,12 +48,19 @@ public class ForecastDispatchPlanController {
|
||||||
return R.ok(forecastDispatchPlanService.deleteById(id));
|
return R.ok(forecastDispatchPlanService.deleteById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Operation(summary = "导出")
|
||||||
|
// @PostMapping("/export")
|
||||||
|
// public void export(@RequestBody @Validated ForecastDispatchPlanPageSo page, HttpServletResponse response) {
|
||||||
|
// page.getPageSo().setPageSize(90000);
|
||||||
|
// Page<ForecastDispatchPlan> forecastDispatchPlanPage = forecastDispatchPlanService.pageDetail(page);
|
||||||
|
// List<ForecastDispatchPlan> records = forecastDispatchPlanPage.getRecords();
|
||||||
|
// forecastDispatchPlanService.export(records,response);
|
||||||
|
// }
|
||||||
|
|
||||||
@Operation(summary = "导出")
|
@Operation(summary = "导出")
|
||||||
@PostMapping("/export")
|
@PostMapping("/export")
|
||||||
public void export(@RequestBody @Validated ForecastDispatchPlanPageSo page, HttpServletResponse response) {
|
public void export(@RequestParam("ids") List<String> ids, HttpServletResponse response) {
|
||||||
page.getPageSo().setPageSize(90000);
|
List<ForecastDispatchPlan> records = forecastDispatchPlanService.selectByIds(ids);
|
||||||
Page<ForecastDispatchPlan> forecastDispatchPlanPage = forecastDispatchPlanService.pageDetail(page);
|
|
||||||
List<ForecastDispatchPlan> records = forecastDispatchPlanPage.getRecords();
|
|
||||||
forecastDispatchPlanService.export(records,response);
|
forecastDispatchPlanService.export(records,response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,15 @@ public class ForecastDispatchPlan implements Serializable {
|
||||||
@NotNull(message = "方案名称不能为空")
|
@NotNull(message = "方案名称不能为空")
|
||||||
private String planName;
|
private String planName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 洪水预报方案名称
|
||||||
|
*/
|
||||||
|
@TableField(value = "forecast_plan_name")
|
||||||
|
@Schema(description = "方案名称")
|
||||||
|
@Size(max = 255, message = "方案名称最大长度要小于 255")
|
||||||
|
@NotNull(message = "方案名称不能为空")
|
||||||
|
private String forecastPlanName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始时间
|
* 开始时间
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,21 @@ import com.ruoyi.common.utils.StringUtils;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 描述: 调度方案主表
|
* 描述: 调度方案主表
|
||||||
|
|
@ -58,6 +63,19 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
return forecastDispatchPlanPage;
|
return forecastDispatchPlanPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ForecastDispatchPlan> selectByIds(List<String> ids) {
|
||||||
|
LambdaQueryWrapper<ForecastDispatchPlan> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.in(ForecastDispatchPlan::getId, ids);
|
||||||
|
List<ForecastDispatchPlan> forecastDispatchPlans = this.baseMapper.selectList(queryWrapper);
|
||||||
|
for (ForecastDispatchPlan record : forecastDispatchPlans) {
|
||||||
|
List<ForecastDispatchCommand> forecastDispatchCommandList = forecastDispatchCommandService.lambdaQuery().eq(ForecastDispatchCommand::getPlanId, record.getId()).list();
|
||||||
|
record.setForecastDispatchCommands(forecastDispatchCommandList);
|
||||||
|
ForecastDispatchResult forecastDispatchResult = forecastDispatchResultService.lambdaQuery().eq(ForecastDispatchResult::getPlanId, record.getId()).one();
|
||||||
|
record.setForecastDispatchResult(forecastDispatchResult);
|
||||||
|
}
|
||||||
|
return forecastDispatchPlans;
|
||||||
|
}
|
||||||
|
|
||||||
public Boolean deleteById(Serializable id) {
|
public Boolean deleteById(Serializable id) {
|
||||||
boolean flag = removeById(id);
|
boolean flag = removeById(id);
|
||||||
if(flag){
|
if(flag){
|
||||||
|
|
@ -83,15 +101,74 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
forecastDispatchCommandService.saveBatch(forecastDispatchCommands);
|
forecastDispatchCommandService.saveBatch(forecastDispatchCommands);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void export(List<ForecastDispatchPlan> page, HttpServletResponse response) {
|
public void export(List<ForecastDispatchPlan> page, HttpServletResponse response) {
|
||||||
try {
|
// 创建临时目录
|
||||||
// 设置响应头
|
String tempDir = System.getProperty("java.io.tmpdir") + File.separator + "export_" + UUID.randomUUID();
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
File dir = new File(tempDir);
|
||||||
response.setCharacterEncoding("utf-8");
|
if (!dir.exists()) {
|
||||||
String fileName = URLEncoder.encode("调度方案数据导出", "UTF-8").replaceAll("\\+", "%20");
|
dir.mkdirs();
|
||||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
}
|
||||||
|
|
||||||
|
List<File> excelFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 为每个方案创建Excel文件
|
||||||
|
for (int i = 0; i < page.size(); i++) {
|
||||||
|
ForecastDispatchPlan plan = page.get(i);
|
||||||
|
File excelFile = createExcelForPlan(plan, tempDir, i + 1);
|
||||||
|
excelFiles.add(excelFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建ZIP压缩包
|
||||||
|
String zipFileName = "调度方案数据导出_" +
|
||||||
|
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip";
|
||||||
|
|
||||||
|
// 设置响应头
|
||||||
|
response.setContentType("application/zip");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.setHeader("Content-disposition",
|
||||||
|
"attachment;filename*=utf-8''" + URLEncoder.encode(zipFileName, "UTF-8").replaceAll("\\+", "%20"));
|
||||||
|
|
||||||
|
// 创建ZIP输出流
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
|
||||||
|
|
||||||
|
// 将Excel文件添加到ZIP
|
||||||
|
for (File excelFile : excelFiles) {
|
||||||
|
ZipEntry zipEntry = new ZipEntry(excelFile.getName());
|
||||||
|
zos.putNextEntry(zipEntry);
|
||||||
|
|
||||||
|
try (FileInputStream fis = new FileInputStream(excelFile)) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = fis.read(buffer)) > 0) {
|
||||||
|
zos.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
zos.close();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("导出Excel失败", e);
|
||||||
|
throw new RuntimeException("导出失败");
|
||||||
|
} finally {
|
||||||
|
// 清理临时文件
|
||||||
|
for (File file : excelFiles) {
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dir.exists()) {
|
||||||
|
dir.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为单个调度方案创建Excel文件
|
||||||
|
*/
|
||||||
|
private File createExcelForPlan(ForecastDispatchPlan plan, String tempDir, int index) throws IOException {
|
||||||
// 创建Excel工作簿
|
// 创建Excel工作簿
|
||||||
Workbook workbook = new XSSFWorkbook();
|
Workbook workbook = new XSSFWorkbook();
|
||||||
|
|
||||||
|
|
@ -100,27 +177,12 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
CellStyle dataStyle = createDataStyle(workbook);
|
CellStyle dataStyle = createDataStyle(workbook);
|
||||||
CellStyle titleStyle = createTitleStyle(workbook);
|
CellStyle titleStyle = createTitleStyle(workbook);
|
||||||
|
|
||||||
// 在同一个Sheet页中按方案分组导出数据
|
// 创建Sheet
|
||||||
exportGroupedData(workbook, page, headerStyle, dataStyle, titleStyle);
|
String sheetName = "调度方案";
|
||||||
|
Sheet sheet = workbook.createSheet(sheetName);
|
||||||
// 写入响应流
|
|
||||||
workbook.write(response.getOutputStream());
|
|
||||||
workbook.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("导出Excel失败", e);
|
|
||||||
throw new RuntimeException("导出失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按方案分组导出数据
|
|
||||||
*/
|
|
||||||
private void exportGroupedData(Workbook workbook, List<ForecastDispatchPlan> dataList, CellStyle headerStyle, CellStyle dataStyle, CellStyle titleStyle) {
|
|
||||||
Sheet sheet = workbook.createSheet("调度方案数据");
|
|
||||||
|
|
||||||
int currentRow = 0;
|
int currentRow = 0;
|
||||||
|
|
||||||
for (ForecastDispatchPlan plan : dataList) {
|
|
||||||
// 1. 导出调度方案基本信息
|
// 1. 导出调度方案基本信息
|
||||||
currentRow = exportPlanBasicInfo(sheet, currentRow, plan, titleStyle, dataStyle);
|
currentRow = exportPlanBasicInfo(sheet, currentRow, plan, titleStyle, dataStyle);
|
||||||
|
|
||||||
|
|
@ -130,13 +192,23 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
// 3. 导出调度指令
|
// 3. 导出调度指令
|
||||||
currentRow = exportPlanCommands(sheet, currentRow, plan, headerStyle, dataStyle);
|
currentRow = exportPlanCommands(sheet, currentRow, plan, headerStyle, dataStyle);
|
||||||
|
|
||||||
// 添加空行分隔不同方案
|
// 生成文件名
|
||||||
currentRow += 2;
|
String fileName = plan.getPlanName();
|
||||||
}
|
File excelFile = new File(tempDir, fileName + ".xlsx");
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(excelFile)) {
|
||||||
|
workbook.write(fos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workbook.close();
|
||||||
|
|
||||||
|
return excelFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出调度方案基本信息
|
* 导出调度方案基本信息(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private int exportPlanBasicInfo(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle titleStyle, CellStyle dataStyle) {
|
private int exportPlanBasicInfo(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle titleStyle, CellStyle dataStyle) {
|
||||||
// 方案标题
|
// 方案标题
|
||||||
|
|
@ -145,6 +217,9 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
titleCell.setCellValue("调度方案:" + getStringValue(plan.getPlanName()));
|
titleCell.setCellValue("调度方案:" + getStringValue(plan.getPlanName()));
|
||||||
titleCell.setCellStyle(titleStyle);
|
titleCell.setCellStyle(titleStyle);
|
||||||
|
|
||||||
|
// 合并单元格(标题跨5列)
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, 4));
|
||||||
|
|
||||||
// 基本信息表头
|
// 基本信息表头
|
||||||
Row headerRow = sheet.createRow(startRow++);
|
Row headerRow = sheet.createRow(startRow++);
|
||||||
String[] headers = {"开始时间", "结束时间", "制定时间", "制定人", "水库控制水位(m)"};
|
String[] headers = {"开始时间", "结束时间", "制定时间", "制定人", "水库控制水位(m)"};
|
||||||
|
|
@ -167,14 +242,16 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
|
|
||||||
// 设置数据行样式
|
// 设置数据行样式
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
if (dataRow.getCell(i) != null) {
|
||||||
dataRow.getCell(i).setCellStyle(dataStyle);
|
dataRow.getCell(i).setCellStyle(dataStyle);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return startRow;
|
return startRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出调度结果
|
* 导出调度结果(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private int exportPlanResult(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) {
|
private int exportPlanResult(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) {
|
||||||
ForecastDispatchResult result = plan.getForecastDispatchResult();
|
ForecastDispatchResult result = plan.getForecastDispatchResult();
|
||||||
|
|
@ -188,6 +265,9 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
resultTitleCell.setCellValue("调度结果");
|
resultTitleCell.setCellValue("调度结果");
|
||||||
resultTitleCell.setCellStyle(headerStyle);
|
resultTitleCell.setCellStyle(headerStyle);
|
||||||
|
|
||||||
|
// 合并单元格(结果标题跨7列)
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(resultTitleRow.getRowNum(), resultTitleRow.getRowNum(), 0, 6));
|
||||||
|
|
||||||
// 结果表头
|
// 结果表头
|
||||||
Row resultHeaderRow = sheet.createRow(startRow++);
|
Row resultHeaderRow = sheet.createRow(startRow++);
|
||||||
String[] resultHeaders = {
|
String[] resultHeaders = {
|
||||||
|
|
@ -219,14 +299,16 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
|
|
||||||
// 设置数据行样式
|
// 设置数据行样式
|
||||||
for (int i = 0; i < resultHeaders.length; i++) {
|
for (int i = 0; i < resultHeaders.length; i++) {
|
||||||
|
if (resultDataRow.getCell(i) != null) {
|
||||||
resultDataRow.getCell(i).setCellStyle(dataStyle);
|
resultDataRow.getCell(i).setCellStyle(dataStyle);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return startRow;
|
return startRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出调度指令
|
* 导出调度指令(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private int exportPlanCommands(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) {
|
private int exportPlanCommands(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) {
|
||||||
List<ForecastDispatchCommand> commands = plan.getForecastDispatchCommands();
|
List<ForecastDispatchCommand> commands = plan.getForecastDispatchCommands();
|
||||||
|
|
@ -240,6 +322,9 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
commandTitleCell.setCellValue("调度指令");
|
commandTitleCell.setCellValue("调度指令");
|
||||||
commandTitleCell.setCellStyle(headerStyle);
|
commandTitleCell.setCellStyle(headerStyle);
|
||||||
|
|
||||||
|
// 合并单元格(指令标题跨5列)
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(commandTitleRow.getRowNum(), commandTitleRow.getRowNum(), 0, 4));
|
||||||
|
|
||||||
// 指令表头
|
// 指令表头
|
||||||
Row commandHeaderRow = sheet.createRow(startRow++);
|
Row commandHeaderRow = sheet.createRow(startRow++);
|
||||||
String[] commandHeaders = {
|
String[] commandHeaders = {
|
||||||
|
|
@ -264,15 +349,17 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
|
|
||||||
// 设置数据行样式
|
// 设置数据行样式
|
||||||
for (int i = 0; i < commandHeaders.length; i++) {
|
for (int i = 0; i < commandHeaders.length; i++) {
|
||||||
|
if (commandDataRow.getCell(i) != null) {
|
||||||
commandDataRow.getCell(i).setCellStyle(dataStyle);
|
commandDataRow.getCell(i).setCellStyle(dataStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return startRow;
|
return startRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建标题样式
|
* 创建标题样式(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private CellStyle createTitleStyle(Workbook workbook) {
|
private CellStyle createTitleStyle(Workbook workbook) {
|
||||||
CellStyle style = workbook.createCellStyle();
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
|
@ -284,7 +371,7 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建表头样式
|
* 创建表头样式(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private CellStyle createHeaderStyle(Workbook workbook) {
|
private CellStyle createHeaderStyle(Workbook workbook) {
|
||||||
CellStyle style = workbook.createCellStyle();
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
|
@ -304,7 +391,7 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建数据样式
|
* 创建数据样式(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private CellStyle createDataStyle(Workbook workbook) {
|
private CellStyle createDataStyle(Workbook workbook) {
|
||||||
CellStyle style = workbook.createCellStyle();
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
|
@ -318,7 +405,7 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化时间
|
* 格式化时间(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private String formatDateTime(LocalDateTime dateTime) {
|
private String formatDateTime(LocalDateTime dateTime) {
|
||||||
if (dateTime == null) {
|
if (dateTime == null) {
|
||||||
|
|
@ -329,14 +416,14 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取字符串值
|
* 获取字符串值(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private String getStringValue(String value) {
|
private String getStringValue(String value) {
|
||||||
return value == null ? "" : value;
|
return value == null ? "" : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取闸门状态文字
|
* 获取闸门状态文字(保持原有逻辑)
|
||||||
*/
|
*/
|
||||||
private String getGateStatus(Integer status) {
|
private String getGateStatus(Integer status) {
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
|
|
@ -344,4 +431,6 @@ public class ForecastDispatchPlanService extends ServiceImpl<ForecastDispatchPla
|
||||||
}
|
}
|
||||||
return status == 1 ? "开" : "关";
|
return status == 1 ? "开" : "关";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue