poi-tl自定义渲染策略学习

实现逻辑

自定义渲染策略实现逻辑:

  • 找到模板中的表格标签
  • render方法接收java中对应模板表格标签的所有list数据
  • 执行自定义渲染逻辑

参考代码

word模板如下:
在这里插入图片描述

实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Data
public class GksxRowData {
/**
* problemType 问题类型
*/
private String problemTypeDesc;
/**
* 序号
*/
private String num;

/**
* problemContent 问题描述
*/
private String problemContent;

/**
* problemScore 扣除分值
*/
private BigDecimal problemScore;

/**
* 1集团巡视审计专项检查的长度
*/
private Integer typeOneSize;

/**
* 2集团研发专项检查的长度
*/
private Integer typeTwoSize;
}

@Data
public class GksxTableData {
/**
* 待渲染的数据 (扣分详细+合计)
*/
private List<GksxRowData> gksxRowDataList;

}

@Data
public class JxWordExport {
/**
* 管控事项table表格
*/
private GksxTableData gksxTable;
}

自定义渲染策略类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@Slf4j
public class TemplateGksxTablePolicy extends DynamicTableRenderPolicy {

@Override
public void render(XWPFTable table, Object data) throws Exception {
if(data == null){
log.error("待渲染管控事项数据为空。");
return;
}
GksxTableData gksxTableData = (GksxTableData) data;
List<GksxRowData> problemList = gksxTableData.getGksxRowDataList();

// 设置样式
Style style = getStyle();
// 循环插入行
int startRow = 2;
for (int i = 0; i < problemList.size(); i++) {
// 先生成一行
XWPFTableRow insertNewTableRow = table.insertNewTableRow(startRow+i);
// 每一行有4列
for (int j = 0; j < 4; j++) insertNewTableRow.createCell();

// 封装数据
GksxRowData gksxRowData = problemList.get(i);
RowRenderData templateGksxRow = Rows.of(
new TextRenderData(gksxRowData.getProblemTypeDesc(),style)
,new TextRenderData(gksxRowData.getNum(),style),
new TextRenderData(gksxRowData.getProblemContent(),style),
new TextRenderData(String.valueOf(gksxRowData.getProblemScore()),style))
.center()
.create();
// 渲染数据
TableRenderPolicy.Helper.renderRow(table.getRow(startRow+i), templateGksxRow);
}

GksxRowData firstRowData = problemList.get(0);
// 合并单元格
if(firstRowData.getTypeOneSize() > 1){
TableTools.mergeCellsVertically(table, 0, startRow, startRow+firstRowData.getTypeOneSize()-1);
}
if(firstRowData.getTypeTwoSize() > 1){
TableTools.mergeCellsVertically(table, 0, startRow+firstRowData.getTypeOneSize(), startRow+firstRowData.getTypeOneSize()+firstRowData.getTypeTwoSize()-1);
}
TableTools.mergeCellsHorizonal(table, startRow+firstRowData.getTypeOneSize()+firstRowData.getTypeTwoSize(), 0, 2);
}

private Style getStyle(){
final Style style = new Style();
style.setFontFamily("FangSong");
style.setFontSize(12);
style.setBold(false);
return style;
}
}

测试方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
String filePath = "E:\\Documents\\CompanyProjects\\cxhl-services\\src\\test\\java\\word\\template\\gksx_problem.docx";
String targetPath = "C:\\Users\\Desktop\\output_gksx_problem.docx";
// 初始化数据
GksxRowData problem1 = new GksxRowData();
problem1.setProblemTypeDesc("集团巡视审计专项检查");
problem1.setNum("1");
problem1.setProblemContent("测试问题描述1");
problem1.setProblemScore(BigDecimal.ONE);
problem1.setTypeOneSize(4);
problem1.setTypeTwoSize(2);

GksxRowData problem2 = new GksxRowData();
problem2.setProblemTypeDesc("集团巡视审计专项检查");
problem2.setNum("2");
problem2.setProblemContent("测试问题描述2");
problem2.setProblemScore(BigDecimal.ONE);
problem2.setTypeOneSize(1);
problem2.setTypeTwoSize(1);

GksxRowData problem3 = new GksxRowData();
problem3.setProblemTypeDesc("集团巡视审计专项检查");
problem3.setNum("3");
problem3.setProblemContent("测试问题描述3");
problem3.setProblemScore(BigDecimal.ONE);

GksxRowData problem4 = new GksxRowData();
problem4.setProblemTypeDesc("集团巡视审计专项检查");
problem4.setNum("4");
problem4.setProblemContent("测试问题描述4");
problem4.setProblemScore(BigDecimal.ONE);

GksxRowData problem5 = new GksxRowData();
problem5.setProblemTypeDesc("集团研发专项检查");
problem5.setNum("5");
problem5.setProblemContent("测试问题描述5");
problem5.setProblemScore(BigDecimal.ONE);

GksxRowData problem6 = new GksxRowData();
problem6.setProblemTypeDesc("集团研发专项检查");
problem6.setNum("6");
problem6.setProblemContent("测试问题描述6");
problem6.setProblemScore(BigDecimal.ONE);

GksxRowData problem7 = new GksxRowData();
problem7.setProblemTypeDesc("合计");
//problem7.setNum("合计");
problem7.setProblemContent("合计");
problem7.setProblemScore(BigDecimal.valueOf(8.8));

List<GksxRowData> problemList = Arrays.asList(problem1, problem2, problem3,problem4,
problem5, problem6, problem7);

GksxTableData gksxTableData = new GksxTableData();
gksxTableData.setGksxRowDataList(problemList);

JxWordExport jxWordExport = new JxWordExport();
jxWordExport.setGksxTable(gksxTableData);
//HashMap<String,Object> hashMap = new HashMap<>();
//hashMap.put("gksxTable",gksxTableData);

// 开始渲染
Configure config = Configure.builder().bind("gksxTable", new TemplateGksxTablePolicy()).build();
XWPFTemplate template = XWPFTemplate.compile(filePath, config).render(jxWordExport);
//XWPFTemplate template = XWPFTemplate.compile(filePath, config).render(hashMap);
template.writeToFile(targetPath);

生成效果如下:
在这里插入图片描述

注意点

  • 1、上面例子中,实体类GksxTableData对应整个表格数据,里面也可以有多个list,且render方法只会处理里面的list属性。
1
2
3
4
5
6
7
8
9
10
@Data
public class GksxTableData {
/**
* 待渲染的数据 (扣分详细+合计)
*/
private List<GksxRowData> gksxRowDataList;

private List<GksxRowData> testList;

}

在这里插入图片描述
testList也可以接收到,官方文档中的收费单案例就是这样实现的。

  • 2、JxWordExport(也可以不用实体类,使用HashMap替代)中的表格属性名必须和模板中的属性值相同。若行数据实体类属性添加@Name注解,则取注解的名字。

  • 3、1.10.X版本中,RowRenderData获取不到文本数据了。
    可以参考上面的案例,根据实际数据生成RowRenderData,这样代码扩展性也更强。

  • 4、表格行从head头开始算,头为0

    1
    2
    // 表格行从head头开始算,头为0
    table.insertNewTableRow(startRow);

官方文档poi-tl导出word复杂表格