什么是动态表头?
动态表头是指在运行时根据业务需求动态生成excel表格的列标题,而不是在代码中预先定义固定的表头结构。这在以下场景中非常有用:
根据用户选择的字段生成不同的报表
处理数据库中动态字段的导出
生成多级复杂表头
实现可配置的数据导出功能
基础用法
1. 简单动态表头
public class dynamicheaderexample {
public void writewithdynamicheader() {
string filename = "dynamic_header.xlsx";
// 动态构建表头
list<list<string>> head = new arraylist<>();
head.add(arrays.aslist("姓名"));
head.add(arrays.aslist("年龄"));
head.add(arrays.aslist("邮箱"));
head.add(arrays.aslist("部门"));
// 准备数据
list<list<object>> datalist = new arraylist<>();
datalist.add(arrays.aslist("张三", 25, "zhangsan@example.com", "技术部"));
datalist.add(arrays.aslist("李四", 30, "lisi@example.com", "产品部"));
datalist.add(arrays.aslist("王五", 28, "wangwu@example.com", "设计部"));
// 写入excel
easyexcel.write(filename)
.head(head)
.sheet("员工信息")
.dowrite(datalist);
}
}2. 多级表头
public void writewithmultilevelheader() {
string filename = "multi_level_header.xlsx";
// 构建多级表头
list<list<string>> head = new arraylist<>();
// 第一列:基本信息->个人信息->姓名
head.add(arrays.aslist("基本信息", "个人信息", "姓名"));
// 第二列:基本信息->个人信息->年龄
head.add(arrays.aslist("基本信息", "个人信息", "年龄"));
// 第三列:基本信息->联系方式->邮箱
head.add(arrays.aslist("基本信息", "联系方式", "邮箱"));
// 第四列:基本信息->联系方式->电话
head.add(arrays.aslist("基本信息", "联系方式", "电话"));
// 第五列:工作信息->部门
head.add(arrays.aslist("工作信息", "部门"));
// 第六列:工作信息->职位
head.add(arrays.aslist("工作信息", "职位"));
// 准备数据
list<list<object>> datalist = new arraylist<>();
datalist.add(arrays.aslist("张三", 25, "zhangsan@example.com", "13800138000", "技术部", "java工程师"));
datalist.add(arrays.aslist("李四", 30, "lisi@example.com", "13900139000", "产品部", "产品经理"));
easyexcel.write(filename)
.head(head)
.sheet("员工详细信息")
.dowrite(datalist);
}高级应用
1. 根据数据库字段动态生成表头
@service
public class dynamicexportservice {
@autowired
private fieldconfigservice fieldconfigservice;
public void exportuserdata(list<string> selectedfields) {
string filename = "user_export_" + system.currenttimemillis() + ".xlsx";
// 根据选中字段构建表头
list<list<string>> head = builddynamicheader(selectedfields);
// 获取数据
list<list<object>> datalist = builddatalist(selectedfields);
easyexcel.write(filename)
.head(head)
.sheet("用户数据")
.dowrite(datalist);
}
private list<list<string>> builddynamicheader(list<string> selectedfields) {
list<list<string>> head = new arraylist<>();
for (string fieldcode : selectedfields) {
fieldconfig config = fieldconfigservice.getbycode(fieldcode);
if (config != null) {
// 支持分组表头
if (config.getgroupname() != null) {
head.add(arrays.aslist(config.getgroupname(), config.getfieldname()));
} else {
head.add(arrays.aslist(config.getfieldname()));
}
}
}
return head;
}
private list<list<object>> builddatalist(list<string> selectedfields) {
list<user> users = userservice.getallusers();
list<list<object>> datalist = new arraylist<>();
for (user user : users) {
list<object> row = new arraylist<>();
for (string fieldcode : selectedfields) {
object value = getfieldvalue(user, fieldcode);
row.add(value);
}
datalist.add(row);
}
return datalist;
}
private object getfieldvalue(user user, string fieldcode) {
// 使用反射或map方式获取字段值
switch (fieldcode) {
case "name": return user.getname();
case "age": return user.getage();
case "email": return user.getemail();
case "department": return user.getdepartment();
case "createtime": return user.getcreatetime();
default: return "";
}
}
}
// 字段配置实体
@data
public class fieldconfig {
private string fieldcode;
private string fieldname;
private string groupname;
private integer sortorder;
}2. 配置化动态表头
@component
public class configurabledynamicheader {
public void exportwithconfig(exportconfig config) {
string filename = config.getfilename() + ".xlsx";
// 根据配置构建表头
list<list<string>> head = buildheaderfromconfig(config);
// 根据配置获取数据
list<list<object>> datalist = builddatafromconfig(config);
// 应用样式
horizontalcellstylestrategy stylestrategy = buildstylefromconfig(config);
easyexcel.write(filename)
.head(head)
.registerwritehandler(stylestrategy)
.registerwritehandler(new longestmatchcolumnwidthstylestrategy())
.sheet(config.getsheetname())
.dowrite(datalist);
}
private list<list<string>> buildheaderfromconfig(exportconfig config) {
list<list<string>> head = new arraylist<>();
for (headerconfig headerconfig : config.getheaders()) {
list<string> headerpath = new arraylist<>();
// 支持多级表头
if (headerconfig.getlevel1() != null) {
headerpath.add(headerconfig.getlevel1());
}
if (headerconfig.getlevel2() != null) {
headerpath.add(headerconfig.getlevel2());
}
if (headerconfig.getlevel3() != null) {
headerpath.add(headerconfig.getlevel3());
}
head.add(headerpath);
}
return head;
}
}
// 导出配置类
@data
public class exportconfig {
private string filename;
private string sheetname;
private list<headerconfig> headers;
private styleconfig styleconfig;
}
@data
public class headerconfig {
private string fieldcode;
private string level1;
private string level2;
private string level3;
private integer width;
}3. 动态表头与数据验证结合
public class dynamicheaderwithvalidation {
public void writewithvalidation() {
string filename = "validated_dynamic.xlsx";
// 构建表头
list<list<string>> head = arrays.aslist(
arrays.aslist("姓名"),
arrays.aslist("年龄"),
arrays.aslist("邮箱"),
arrays.aslist("手机号")
);
// 准备数据
list<list<object>> datalist = new arraylist<>();
datalist.add(arrays.aslist("张三", 25, "zhangsan@example.com", "13800138000"));
datalist.add(arrays.aslist("李四", 30, "lisi@example.com", "13900139000"));
// 创建下拉选择处理器
dropdownwritehandler dropdownhandler = new dropdownwritehandler();
easyexcel.write(filename)
.head(head)
.registerwritehandler(dropdownhandler)
.sheet("带验证的数据")
.dowrite(datalist);
}
}
// 自定义下拉选择处理器
public class dropdownwritehandler implements sheetwritehandler {
@override
public void aftersheetcreate(writeworkbookholder writeworkbookholder,
writesheetholder writesheetholder) {
sheet sheet = writesheetholder.getsheet();
workbook workbook = writeworkbookholder.getworkbook();
// 创建数据验证规则
datavalidationhelper validationhelper = sheet.getdatavalidationhelper();
// 为年龄列添加数字验证(假设年龄在b列)
cellrangeaddresslist agerange = new cellrangeaddresslist(1, 1000, 1, 1);
datavalidationconstraint ageconstraint = validationhelper
.createintegerconstraint(datavalidationconstraint.operatortype.between, "0", "150");
datavalidation agevalidation = validationhelper.createvalidation(ageconstraint, agerange);
agevalidation.seterrorstyle(datavalidation.errorstyle.stop);
agevalidation.createerrorbox("年龄错误", "年龄必须在0-150之间");
sheet.addvalidationdata(agevalidation);
}
}实际应用场景
1. 报表系统中的可配置导出
@restcontroller
@requestmapping("/api/export")
public class exportcontroller {
@autowired
private dynamicexportservice exportservice;
@postmapping("/users")
public responseentity<string> exportusers(@requestbody exportrequest request) {
try {
string filename = exportservice.exportuserdata(
request.getselectedfields(),
request.getstartdate(),
request.getenddate()
);
return responseentity.ok(filename);
} catch (exception e) {
return responseentity.badrequest().body("导出失败:" + e.getmessage());
}
}
}
@data
public class exportrequest {
private list<string> selectedfields;
private localdate startdate;
private localdate enddate;
private string groupby;
}2. 动态报表生成
public class dynamicreportgenerator {
public void generatereport(reporttemplate template, map<string, object> params) {
string filename = template.getname() + "_" +
localdatetime.now().format(datetimeformatter.ofpattern("yyyymmdd_hhmmss")) +
".xlsx";
// 根据模板构建表头
list<list<string>> head = buildheaderfromtemplate(template);
// 根据参数查询数据
list<list<object>> datalist = querydatabytemplate(template, params);
// 应用模板样式
list<writehandler> handlers = buildwritehandlers(template);
excelwriterbuilder builder = easyexcel.write(filename).head(head);
// 注册所有处理器
for (writehandler handler : handlers) {
builder.registerwritehandler(handler);
}
builder.sheet(template.getsheetname()).dowrite(datalist);
}
}最佳实践
1. 性能优化
public class optimizeddynamicexport {
public void exportlargedata(list<string> fields) {
string filename = "large_data_export.xlsx";
// 构建表头
list<list<string>> head = buildheader(fields);
// 使用excelwriter进行流式写入
try (excelwriter excelwriter = easyexcel.write(filename).head(head).build()) {
writesheet writesheet = easyexcel.writersheet("数据").build();
// 分批处理大量数据
int pagesize = 10000;
int pagenum = 1;
list<list<object>> batchdata;
do {
batchdata = querydatabypage(fields, pagenum, pagesize);
if (!batchdata.isempty()) {
excelwriter.write(batchdata, writesheet);
}
pagenum++;
} while (batchdata.size() == pagesize);
}
}
}2. 错误处理
public class safedynamicexport {
public void safeexport(list<string> fields) {
try {
validatefields(fields);
list<list<string>> head = buildheader(fields);
list<list<object>> datalist = builddata(fields);
easyexcel.write("safe_export.xlsx")
.head(head)
.sheet("数据")
.dowrite(datalist);
} catch (illegalargumentexception e) {
log.error("字段验证失败:{}", e.getmessage());
throw new businessexception("导出字段配置错误");
} catch (exception e) {
log.error("导出过程中发生错误:", e);
throw new businessexception("数据导出失败");
}
}
private void validatefields(list<string> fields) {
if (fields == null || fields.isempty()) {
throw new illegalargumentexception("导出字段不能为空");
}
list<string> validfields = getvalidfields();
for (string field : fields) {
if (!validfields.contains(field)) {
throw new illegalargumentexception("无效的字段:" + field);
}
}
}
}总结
easyexcel的动态表头功能非常强大,主要优势包括:
灵活性强:可根据运行时条件动态生成表头
支持多级:能够创建复杂的多级表头结构
易于扩展:可与其他功能(样式、验证等)结合使用
性能优良:即使处理大量数据也能保持良好性能
在实际使用中,建议:
合理设计表头结构,避免过于复杂
注意数据类型匹配,确保数据与表头对应
对用户输入进行验证,防止恶意或错误的字段配置
在处理大量数据时使用分批处理机制
通过动态表头功能,可以轻松实现灵活的数据导出需求,大大提升系统的可配置性和用户体验。
到此这篇关于easyexcel动态表头基础用法及最佳实践的文章就介绍到这了,更多相关easyexcel动态表头内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论