多场景对练材料的 Excel 横向导出方案(EasyExcel 动态表头实践)

一、背景

在日常开发中,我们经常需要将复杂的场景数据导出成 Excel 文件,方便运营或培训人员查看。

比如“客户与学员对练场景”这种数据,原始结构大致如下:

  • 多个场景(List<LearnHouseScene2Vo>)

  • 每个场景里有 若干轮对话(List<SceneItem>)

一个 SceneItem 就是一轮对话:

  • 客户节点

  • 客户话术

  • 学员节点

  • 学员标准话术

  • 关键词

需求:
希望在 Excel 中导出成:

  • 每个场景占 5 列(客户节点、客户话术、学员节点、学员标准话术、关键词)

  • 多个场景横向拼接

  • 每行对应第几轮对话,不足的用空白填充

二、需求分析

举个例子:

  • 场景1 有 2 轮

  • 场景2 有 3 轮

期望的 Excel:

场景1-客户节点场景1-客户话术场景1-学员节点场景1-学员标准话术场景1-关键词场景2-客户节点场景2-客户话术场景2-学员节点场景2-学员标准话术场景2-关键词
A1A1话术S1S1话术K1B1B1话术S2S2话术K2
A2A2话术S2S2话术K2B2B2话术S2S2话术K2
B3B3话术S3S3话术K3

三、解决方案

  1. 动态表头
    每个场景占 5 列,表头通过循环生成,使用 EasyExcel 的多级表头功能。

  2. 数据行构造

    • 先计算所有场景的最大对话轮数 maxRow

    • 遍历 0 ~ maxRow-1,每一行拼接所有场景的对应对话

    • 不足的补空字符串

四、实体类

@Data
public class SceneItem {
@ExcelProperty("客户节点")
private String customerNode;
@ExcelProperty("客户话术")
private String customerScript;
@ExcelProperty("学员节点")
private String studentNode;
@ExcelProperty("学员标准话术")
private String studentScript;
@ExcelProperty("关键词")
private String keyword;
}

@Data
public class LearnHouseScene2Vo {
// 存储动态数量的场景组
private List sceneItems = new ArrayList<>();
/**
* 向当前场景组中追加一个对话节点
*/
public void addSceneItem(SceneItem item) {
sceneItems.add(item);
}
}

五、工具类实现

import com.alibaba.excel.EasyExcel;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SceneExcelExporter {
/**
* 导出场景对练数据到 Excel
*
* @param scenes 多个场景
* @param out    输出流
*/
public static void export(List scenes, OutputStream out) {
List> head = buildHead(scenes);
List> data = buildData(scenes);
EasyExcel.write(out)
.head(head)
.sheet("场景对练")
.doWrite(data);
}
/**
* 构造动态表头
*/
private static List> buildHead(List scenes) {
List> head = new ArrayList<>();
for (int i = 0; i > buildData(List scenes) {
int maxRow = scenes.stream()
.mapToInt(vo -> vo.getSceneItems().size())
.max().orElse(0);
List> rows = new ArrayList<>();
for (int r = 0; r  row = new ArrayList<>();
for (LearnHouseScene2Vo vo : scenes) {
if (r < vo.getSceneItems().size()) {
SceneItem item = vo.getSceneItems().get(r);
row.add(item.getCustomerNode());
row.add(item.getCustomerScript());
row.add(item.getStudentNode());
row.add(item.getStudentScript());
row.add(item.getKeyword());
} else {
// 补空白
row.add(""); row.add(""); row.add(""); row.add(""); row.add("");
}
}
rows.add(row);
}
return rows;
}
}

六、使用方式

List scenes = findUrlGetSPBlockingData3(url); // 解析后的场景数据
try (OutputStream out = new FileOutputStream("场景对练.xlsx")) {
SceneExcelExporter.export(scenes, out);
}

七、总结

  • 核心点:多场景横向导出,本质是动态生成表头 + 按行拼接数据。

  • 通用性:这个 SceneExcelExporter 工具类可以复用在任何类似的“多组相同字段横向导出”需求中。

  • 扩展点:如果需要在 Excel 顶部加一行大标题,可以在 EasyExcel 写出前用 POI 或者在 head 中加额外层级。

posted @ 2025-09-08 20:43  yjbjingcha  阅读(13)  评论(0)    收藏  举报