在企业级应用开发中,数据导出是高频需求。本文介绍一种支持动态列选择、灵活配置的通用 Excel 导出方案,通过前后端协同设计,实现导出字段、列顺序、数据格式的自定义,满足多样化业务场景。
入参结构(ExcelExportRequest)
@Data
public class UserExportRequest extends ExcelExportRequest {
private List userIdList; // 待导出的用户ID列表(可选)
}
@Data
public class ExcelExportRequest {
private String excelName; // Excel文件名
private String sheetName; // Sheet页名称
private List fieldList; // 导出字段列表(有序)
}
@Data
public class ExcelExportField {
private String fieldName; // 实体类字段名(如"userId")
private String fieldDesc; // 表格显示名称(如"用户ID")
}
出参结构(ExcelExportResponse)
@Data
public class ExcelExportResponse {
private String excelName; // 导出文件名
private List sheetList; // Sheet数据集合
@Data
public static class ExcelSheet {
private String sheetName; // Sheet名称
private List headList; // 表头信息
private List
案例1:勾选需要导出的列
案例2:勾选需要导出的列 & 行
选择记录
function download(data, url) {
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.responseType = 'blob';
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
xhr.onload = function() {
if (this.status === 200) {
const blob = this.response;
if (blob.size > 0) {
// 从响应头解析文件名
const fileName = getFileNameFromResponse(this.getResponseHeader("content-disposition"));
// 创建临时链接下载
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName;
a.click();
}
}
};
xhr.send(JSON.stringify(data));
}
// 文件名解析工具
function getFileNameFromResponse(disposition) {
const match = /filename=(.*)/.exec(disposition);
return decodeURIComponent(match[1].replace(/['"]/g, ''));
}
@Controller
@CrossOrigin
public class UserController {
@Resource private UserService userService;
// 页面跳转
@GetMapping("/userList")
public String userList(Model model) {
model.addAttribute("userList", userService.getUserList());
return "userList";
}
// 导出接口
@PostMapping("/userExport")
public void userExport(@RequestBody UserExportRequest request) throws IOException {
ExcelExportResponse response = userService.userExport(request);
ExcelExportUtils.writeExcelToResponse(response);
}
}
@Service
public class UserServiceImpl implements UserService {
@Override
public ExcelExportResponse userExport(UserExportRequest request) {
List dataList;
// 处理行筛选逻辑
if (CollectionUtil.isEmpty(request.getUserIdList())) {
dataList = getUserList(); // 导出全部数据
} else {
dataList = getUserList(request.getUserIdList()); // 按ID筛选
}
// 构建导出数据
return ExcelExportUtils.build(dataList, request);
}
// 模拟数据获取
private List getUserList() {
List list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(new User(i, "用户名-" + i, 20 + i, "地址-" + i));
}
return list;
}
}
public class ExcelExportUtils {
public static ExcelExportResponse build(List> dataList, ExcelExportRequest request) {
ExcelExportResponse result = new ExcelExportResponse();
result.setExcelName(request.getExcelName());
List sheetList = new ArrayList<>();
ExcelSheet sheet = new ExcelSheet();
sheet.setSheetName(request.getSheetName());
// 构建表头(保持字段顺序)
sheet.setHeadList(buildSheetHeadList(request.getFieldList()));
// 构建数据行(通过反射获取字段值)
sheet.setDataList(buildSheetDataList(dataList, request.getFieldList()));
sheetList.add(sheet);
result.setSheetList(sheetList);
return result;
}
private static List buildSheetHeadList(List fields) {
return fields.stream()
.map(field -> new ExcelSheet.ExcelHead(field.getFieldName(), field.getFieldDesc()))
.collect(Collectors.toList());
}
// 反射获取对象字段值
private static List
通过该方案,开发者可快速实现具备灵活配置能力的 Excel 导出功能,同时保持代码的可维护性与扩展性。实际应用中可根据业务需求,进一步扩展数据格式化、单元格样式、多语言支持等高级功能。