类似于生成此动态,需要根据业务去合并不同数量的单元格的table表格。
思路便是:先创建一个模板单元格,然后通过其属性去动态更改table中的元素标签。
利用模版:
<table style="border-collapse: collapse; width: 100%;" border="1">
<tbody>
<tr>
<td style="width: 23.2763%;"> </td>
<td style="width: 23.2763%;"> </td>
<td style="width: 23.2763%;"> </td>
<td style="width: 23.2763%;"> </td>
</tr>
</tbody>
</table>
按照实体类中的一个集合属性去判断合并多少单元格,遍历集合中的数据获得需合并单元格多少单元格的数据
实体类:
@Data
public class ICBmEvaluationDocumentDTO {
//标题
private String a;
//细则集合
private List<ICBmEvaluationDetailDTO> icBmEvaluationDetailDTOS;
}
List<ICBmEvaluationDetailDTO>中有多少元素,就合并多少单元格。一个标题a为一个整的单元格。
@Data
public class ICBmEvaluationDetailDTO {
//编号
private String number;
//评审指标
private String reviewIndicators;
//等级要求
private String grade;
//评审内容
private String reviewContent;
}
工具类:
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ICEdTemplateUtils {
private static Logger logger = LoggerFactory.getLogger(ICEdTemplateUtils.class);
/**
* 填充表格
* @param <T>
* @param table 表格对象
* @param icBmEvaluationDocumentDTOS 数据
* @param consumer 具体填充方式
* @param placeHolder 定位数据行tr的占位符
* @param removeLast
* @return
*/
public static <T> Element fillTable(Element table, List<ICBmEvaluationDocumentDTO> icBmEvaluationDocumentDTOS, BiConsumer<Element, ICBmEvaluationDetailDTO> consumer, String placeHolder, boolean removeLast){
if (table == null){
return null;
}
Element td = getPlaceholderParentFilterByTag(table, placeHolder, "tr");
if (td == null){
throw new CustomException("找不到表格中的行元素");
}
Element emptyTd = td.clone();
Element nextRow;
for (ICBmEvaluationDocumentDTO item : icBmEvaluationDocumentDTOS) {
List<ICBmEvaluationDetailDTO> child = item.getIcBmEvaluationDetailDTOS();
Integer size = child.size();
if (size == 1) {
//将数据拆分出来
ICBmEvaluationDetailDTO icBmEvaluationDetailDTO = child.get(0);
icBmEvaluationDetailDTO.setReviewContent(item.getReviewContent());
consumer.accept(td, icBmEvaluationDetailDTO);
nextRow = emptyTd.clone();
td.after(nextRow);
td = nextRow;
} else {
//获取第一个tr列的对象
Element esTr = td.select("tr").first();
//获取第一个tr列对象中的height
String heightTr = esTr.attr("style");
//获取字符串中的所有数字
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(heightTr);
int s = Integer.parseInt(m.replaceAll("").trim());
//将height根据合并单元格数量扩大
Integer heightMax = s * size;
//获取第一个td列的对象
Element esTd = td.select("td").first();
//修改style
String heightTd = esTd.attr("style");
String[] he = heightTd.split(";");
String widthS = null;
for (int i = 0; i < he.length; i++) {
if (he[i].contains("width")) {
widthS = he[i];
}
}
//style的值
String style = widthS + ";" + "height: " + heightMax + "px;";
//修改其中height的值
for (int i = 0; i < size; i++) {
//
if (i == 0) {
ICBmEvaluationDetailDTO child1 = child.get(i);
//修改style属性的值
td.select("td").first().attr("style", style);
//新增rowspan的值
td.select("td").first().attr("rowspan", String.valueOf(size));
child1.setReviewContent(item.getReviewContent());
consumer.accept(td, child1);
nextRow = emptyTd.clone();
td.after(nextRow);
td = nextRow;
} else {
ICBmEvaluationDetailDTO child2 = child.get(i);
//删除一个td列
td.select("td").first().remove();
consumer.accept(td, child2);
nextRow = emptyTd.clone();
td.after(nextRow);
td = nextRow;
}
}
}
}
if (removeLast){
td.remove();
}
return td;
}
/**
* 医疗机构情况 -- 医疗情况
* @param condition
* @param icEdCondition
* @param consumer
* @param placeHolder
* @param removeLast
* @param <T>
* @return
*/
public static <T> Element fillCondition(Element condition, ICEdCondition icEdCondition, BiConsumer<Element, ICEdCondition> consumer, String placeHolder, boolean removeLast){
if(condition == null){
return null;
}
Element trCondition = getPlaceholderParentFilterByTag(condition, placeHolder, "tr");
if (trCondition == null){
throw new CustomException("找不到表格中的行元素!");
}
consumer.accept(trCondition, icEdCondition);
return trCondition;
}
/**
* 获取指定标签的占位符的父级元素
* @param element html对象
* @param placeholder 占位符
* @param tag html标签
* @return
*/
public static Element getPlaceholderParentFilterByTag(Element element, String placeholder, String tag){
Element index = element.getElementsContainingOwnText(placeholder).first();
while (true){
if (index == null){
logger.warn("找不到占位符" + placeholder);
return null;
}
if (index.is(tag)){
return index;
}
index = index.parent();
if (index.is("body")){
logger.warn("找不到占位符" + placeholder);
return null;
}
}
}
/**
* 填充占位符(填充所有匹配到的)
* @param element html对象
* @param placeholder 占位符
* @param value 填充值
*/
public static void replace(Element element, String placeholder, String value){
if (placeholder == null){
return;
}
if (value == null){
value = "";
}
for (Element target : element.getElementsContainingOwnText(placeholder)) {
target.removeAttr("contenteditable");
target.parent().removeClass("mymention");
String html = target.html();
target.html(html.replace(placeholder, value));
}
}
}
实现类:
/**
* 文档模板编写实现类
*/
public class DocumentOperation {
/**
* 填充医疗机构情况-医疗情况
* @param templateDetailContent
* @param icBmEvaluationDocumentDTOS
* @return
* @throws Exception
*/
@Override
protected String fillTemplate2(String templateDetailContent, List<ICBmEvaluationDocumentDTO> icBmEvaluationDocumentDTOS) throws Exception {
Document document = Jsoup.parse(templateDetailContent);
Element body = document.body();
//填充表格模板
fillTable(body,icBmEvaluationDocumentDTOS);
return body.html();
}
/**
* 填充表格模板
* @param body
* @param icBmEvaluationDocumentDTOS
*/
private void fillTable(Element body, List<ICBmEvaluationDocumentDTO> icBmEvaluationDocumentDTOS){
ICEdTemplateUtils.fillTable(
getPlaceholderParentFilterByTag(body, "{评审内容}","table"),
icBmEvaluationDocumentDTOS,
(row, lysjjlb) -> {
replace(row, "{评审内容}", lysjjlb.getReviewContent());
replace(row, "{编号}", lysjjlb.getNumber());
replace(row, "{评审指标}", lysjjlb.getReviewIndicators());
replace(row, "{等级要求}", lysjjlb.getGrade());
}, "{评审内容}", true);
}
}
用法:
//填充评审内容表格
List<ICBmEvaluationDocumentDTO> list = new ArrayList<>();
//表格
String table = "<table style=\"border-collapse: collapse; width: 100%; height: 30px;\" border=\"1\"><tbody><tr style=\"height: 30px;\"><td style=\"width: 23.2763%; height: 30px;\">{评审内容}</td><td style=\"width: 23.2763%; height: 30px;\">{编号}</td><td style=\"width: 23.2763%; height: 30px;\">{评审指标}</td><td style=\"width: 23.2763%; height: 30px;\">{等级要求}</td></tr></tbody></table>";
//填充内容生成表单
String matter = projectTextOperation.fillTemplate2(table, list);