实现逻辑
自定义渲染策略实现逻辑:
- 找到模板中的表格标签
- render方法接收java中对应模板表格标签的所有list数据
- 执行自定义渲染逻辑
参考代码
word模板如下:
实体类:
@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;
}
自定义渲染策略类:
@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;
}
}
测试方法:
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属性。
@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
// 表格行从head头开始算,头为0 table.insertNewTableRow(startRow);