Commit 10c8a604 by zhangxingmin

push

parent a1d6f96f
......@@ -7,6 +7,7 @@ import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.ApiExportRequest;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import com.yd.oss.feign.result.ImportResult;
......@@ -61,6 +62,16 @@ public class ApiExcelController implements ApiExcelFeignClient {
}
/**
* 通用-多Sheet Excel导出
* @param request 多Sheet导出请求
* @return
*/
@Override
public Result<ExportResult> exportMultiSheet(MultiSheetExportRequest request) {
return apiExcelService.exportMultiSheet(request);
}
/**
* 通用Excel导入接口
* @param file Excel文件
* @param headerRow 表头行号(默认第1行,从0开始)
......
......@@ -5,6 +5,7 @@ import com.yd.oss.feign.dto.ExportParam;
import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import com.yd.oss.feign.result.ImportResult;
......@@ -20,6 +21,8 @@ public interface ApiExcelService {
Result<ExportResult> export(List<?> dataList, ExportParam exportParam, Class<?> entityClass);
Result<ExportResult> exportMultiSheet(MultiSheetExportRequest request);
Result<ImportResult> importExcel(MultipartFile file, Integer headerRow,
Integer dataStartRow, String requiredFields,Integer checkStartRow);
......
......@@ -6,6 +6,7 @@ import com.yd.common.result.Result;
import com.yd.oss.api.service.ApiExcelService;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import com.yd.oss.feign.dto.ExportParam;
......@@ -121,6 +122,17 @@ public class ApiExcelServiceImpl implements ApiExcelService {
}
/**
* 通用-多Sheet Excel导出
* @param request
* @return
*/
@Override
public Result<ExportResult> exportMultiSheet(MultiSheetExportRequest request) {
ExportResult exportResult = excelExportService.exportMultiSheetAndUploadToOss(request);
return Result.success(exportResult);
}
/**
* 通用Excel导入接口
* @param file Excel文件
* @param headerRow 表头行号(默认第1行,从0开始)
......
......@@ -6,6 +6,7 @@ import com.yd.oss.feign.fallback.ApiExcelFeignFallbackFactory;
import com.yd.oss.feign.request.ApiExportRequest;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import com.yd.oss.feign.result.ImportResult;
......@@ -50,6 +51,14 @@ public interface ApiExcelFeignClient {
Result<ExportResult> export(@Validated @RequestBody ApiExportRequest request);
/**
* 通用-多Sheet Excel导出
* @param request 多Sheet导出请求
* @return 导出结果
*/
@PostMapping("/export/multi-sheet")
Result<ExportResult> exportMultiSheet(@Validated @RequestBody MultiSheetExportRequest request);
/**
* 通用Excel导入接口
* @param file Excel文件
* @param headerRow 表头行号(默认第1行,从0开始)
......
package com.yd.oss.feign.dto;
import lombok.Data;
import java.util.List;
/**
* 多Sheet导出-单个Sheet配置
*/
@Data
public class SheetExportConfig {
/**
* Sheet名称(必填)
*/
private String sheetName;
/**
* 导出字段列表(必填)
*/
private List<String> fieldNames;
/**
* 数据列表(可选,若为空则只导出表头)
*/
private List<?> dataList;
/**
* 实体类全限定名(可选,用于读取@Excel注解获取列名,若未传则直接使用fieldNames作为列名)
*/
private String entityClassName;
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.ApiExportRequest;
import com.yd.oss.feign.request.ApiOssExcelParseRequest;
import com.yd.oss.feign.request.ApiOssExportAppointmentExcelRequest;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.feign.response.ApiOssExcelParseResponse;
import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import com.yd.oss.feign.result.ImportResult;
......@@ -40,6 +41,11 @@ public class ApiExcelFeignFallbackFactory implements FallbackFactory<ApiExcelFei
}
@Override
public Result<ExportResult> exportMultiSheet(MultiSheetExportRequest request) {
return null;
}
@Override
public Result<ImportResult> importExcel(MultipartFile file, Integer headerRow, Integer dataStartRow, String requiredFields, Integer checkStartRow) {
return null;
}
......
package com.yd.oss.feign.request;
import com.yd.oss.feign.dto.SheetExportConfig;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 多Sheet导出请求
*/
@Data
public class MultiSheetExportRequest {
/**
* Sheet配置列表(必填,至少一个)
*/
@NotEmpty(message = "Sheet配置列表不能为空")
private List<SheetExportConfig> sheets;
/**
* 导出文件名(不含扩展名,可选,默认 export_data)
*/
private String fileName;
/**
* 是否上传至OSS(默认 true)
*/
private Boolean uploadToOss = true;
}
\ No newline at end of file
......@@ -2,9 +2,12 @@ package com.yd.oss.service.service;
import com.yd.oss.feign.dto.ExportParam;
import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import java.util.List;
public interface ExcelExportService {
ExportResult exportAndUploadToOss(List<?> dataList, ExportParam exportParam, Class<?> entityClass);
ExportResult exportMultiSheetAndUploadToOss(MultiSheetExportRequest request);
}
......@@ -7,12 +7,15 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.alibaba.fastjson.JSON;
import com.yd.oss.feign.dto.ExportParam;
import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.dto.SheetExportConfig;
import com.yd.oss.feign.request.MultiSheetExportRequest;
import com.yd.oss.service.dto.OssUploadFileResDto;
import com.yd.oss.service.service.ExcelExportService;
import com.yd.oss.service.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
......@@ -36,6 +39,7 @@ public class ExcelExportServiceImpl implements ExcelExportService {
private OssService ossService;
/**
*
* 导出Excel并上传到OSS
* @param dataList 需要导出的数据列表
* @param exportParam 导出参数配置
......@@ -154,6 +158,180 @@ public class ExcelExportServiceImpl implements ExcelExportService {
}
/**
* 多Sheet导出并上传到OSS
* @param request
* @return
*/
@Override
public ExportResult exportMultiSheetAndUploadToOss(MultiSheetExportRequest request) {
log.info("导出多Sheet Excel: {}", JSON.toJSONString(request));
// 1. 参数校验
if (request == null || CollectionUtils.isEmpty(request.getSheets())) {
return ExportResult.error("Sheet配置不能为空");
}
Workbook workbook = null;
ByteArrayOutputStream outputStream = null;
try {
// 2. 创建主工作簿(XSSF格式支持.xlsx)
workbook = new XSSFWorkbook();
// 3. 遍历每个Sheet配置
for (SheetExportConfig config : request.getSheets()) {
String sheetName = config.getSheetName();
List<String> fieldNames = config.getFieldNames();
if (StringUtils.isBlank(sheetName) || CollectionUtils.isEmpty(fieldNames)) {
return ExportResult.error("Sheet名称和字段列表不能为空");
}
// 3.1 加载实体类(如果传了类名)
Class<?> entityClass = null;
if (StringUtils.isNotBlank(config.getEntityClassName())) {
try {
entityClass = Class.forName(config.getEntityClassName());
} catch (ClassNotFoundException e) {
log.warn("加载实体类失败: {}", config.getEntityClassName());
}
}
// 3.2 构建列配置
List<ExcelExportEntity> entityList = buildExportEntities(fieldNames, entityClass);
if (CollectionUtils.isEmpty(entityList)) {
return ExportResult.error("Sheet [" + sheetName + "] 列配置为空");
}
// 3.3 构建数据
List<Map<String, Object>> dataMapList = buildDataMapList(config.getDataList(), fieldNames, entityClass);
if (CollectionUtils.isEmpty(dataMapList)) {
// 空数据时创建一行空值,保证表头显示
dataMapList = new ArrayList<>();
Map<String, Object> emptyMap = new HashMap<>();
for (String fieldName : fieldNames) {
emptyMap.put(fieldName, "");
}
dataMapList.add(emptyMap);
}
// 3.4 利用EasyPOI生成单个Sheet的工作簿
ExportParams params = new ExportParams(null, sheetName, ExcelType.XSSF);
Workbook tempWb = ExcelExportUtil.exportExcel(params, entityList, dataMapList);
// 3.5 将临时工作簿中的Sheet复制到主工作簿
Sheet tempSheet = tempWb.getSheetAt(0);
Sheet newSheet = workbook.createSheet(sheetName);
copySheet(tempSheet, newSheet);
// 关闭临时工作簿释放资源
tempWb.close();
}
// 4. 将主工作簿写入字节数组
outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
byte[] excelBytes = outputStream.toByteArray();
long fileSize = excelBytes.length;
// 5. 上传至OSS(根据配置)
Boolean uploadToOss = request.getUploadToOss() != null ? request.getUploadToOss() : true;
if (uploadToOss) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(excelBytes);
String fileName = generateExcelFileName(request.getFileName());
OssUploadFileResDto uploadResult = ossService.uploadFile(
inputStream,
fileName,
"",
"",
"excel",
""
);
return ExportResult.success(uploadResult.getUrl(), fileSize);
} else {
return ExportResult.success(null, fileSize);
}
} catch (Exception e) {
log.error("多Sheet导出失败", e);
return ExportResult.error("多Sheet导出失败: " + e.getMessage());
} finally {
// 6. 资源清理
try {
if (workbook != null) {
workbook.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e) {
log.error("关闭资源异常", e);
}
}
}
/**
* 复制Sheet内容(从临时工作簿复制到主工作簿)
* 注:此处只复制值和基础格式(列宽、行高),不复制复杂样式以简化逻辑
*/
private void copySheet(Sheet srcSheet, Sheet destSheet) {
// 复制列宽
int maxCol = 0;
for (int i = 0; i <= srcSheet.getLastRowNum(); i++) {
Row row = srcSheet.getRow(i);
if (row != null && row.getLastCellNum() > maxCol) {
maxCol = row.getLastCellNum();
}
}
for (int i = 0; i < maxCol; i++) {
destSheet.setColumnWidth(i, srcSheet.getColumnWidth(i));
}
// 复制行
for (int i = 0; i <= srcSheet.getLastRowNum(); i++) {
Row srcRow = srcSheet.getRow(i);
Row destRow = destSheet.createRow(i);
if (srcRow == null) {
continue;
}
destRow.setHeight(srcRow.getHeight());
for (int j = 0; j < srcRow.getLastCellNum(); j++) {
Cell srcCell = srcRow.getCell(j);
Cell destCell = destRow.createCell(j);
if (srcCell == null) {
continue;
}
// 复制单元格值
switch (srcCell.getCellType()) {
case STRING:
destCell.setCellValue(srcCell.getStringCellValue());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(srcCell)) {
destCell.setCellValue(srcCell.getDateCellValue());
} else {
destCell.setCellValue(srcCell.getNumericCellValue());
}
break;
case BOOLEAN:
destCell.setCellValue(srcCell.getBooleanCellValue());
break;
case FORMULA:
destCell.setCellFormula(srcCell.getCellFormula());
break;
case BLANK:
break;
default:
destCell.setCellValue("");
break;
}
// 可选择性复制样式(此处忽略以提升性能)
}
}
}
/**
* 生成Excel文件名(包含时间戳)
* @param baseName 基础文件名
* @return 生成的文件名
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment