短网址网站,asp.net 网站建设方案,wordpress做图集,东营注册公司目录 问题解决问题poi-tl介绍 功能实现引入依赖模版代码效果图 附加#xff08;插件实现#xff09;MergeColumnData 对象MergeGroupData 类ServerMergeTableData 数据信息ServerMergeTablePolicy 合并插件 问题
由于在开发功能需求中#xff0c;word文档需要垂直合并表格插件实现MergeColumnData 对象MergeGroupData 类ServerMergeTableData 数据信息ServerMergeTablePolicy 合并插件 问题
由于在开发功能需求中word文档需要垂直合并表格而word模版引擎原有的插件功能只能做行循环不满足需求
解决问题
目前选择的poi-tl的模版引擎在原有的基础上新增自定义插件来实现功能
poi-tl介绍
poi-tl 是一个基于Apache POI的Word模板引擎也是一个免费开源的Java类库你可以非常方便的加入到你的项目中
Word模板引擎功能描述文本将标签渲染为文本图片将标签渲染为图片表格将标签渲染为表格图表条形图3D条形图、柱形图3D柱形图、面积图3D面积图、折线图3D折线图、雷达图、饼图3D饼图、散点图等图表渲染If Condition判断根据条件隐藏或者显示某些文档内容包括文本、段落、图片、表格、列表、图表等Foreach Loop循环根据集合循环某些文档内容包括文本、段落、图片、表格、列表、图表等Loop表格行循环复制渲染表格的某一行Loop表格列循环复制渲染表格的某一列Loop有序列表支持有序列表的循环同时支持多级列表Highlight代码高亮word中代码块高亮展示支持26种语言和上百种着色样式Markdown将Markdown渲染为word文档Word批注完整的批注功能创建批注、修改批注等Word附件Word中插入附件SDT内容控件内容控件内标签支持Textbox文本框文本框内标签支持图片替换将原有图片替换成另一张图片书签、锚点、超链接支持设置书签文档内锚点和超链接功能Expression Language完全支持SpringEL表达式可以扩展更多的表达式OGNL, MVEL样式支持有序列表的循环同时支持多级列表模板嵌套模板包含子模板子模板再包含子模板模板嵌套模板包含子模板子模板再包含子模板合并Word合并Merge也可以在指定位置进行合并用户自定义函数(插件)插件化设计在文档任何位置执行函数
功能实现
引入依赖 dependencygroupIdcom.deepoove/groupIdartifactIdpoi-tl/artifactIdversion1.12.2/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml-full/artifactIdversion5.2.5/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi/artifactIdversion5.2.5/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion5.2.5/version/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.25/version/dependency!-- spring el表达式 --dependencygroupIdorg.springframework/groupIdartifactIdspring-expression/artifactIdversion5.3.18/version/dependency模版 代码
Testpublic void test() throws Exception {Configure config Configure.builder().bind(precipitationInfoList, new ServerMergeTablePolicy()).useSpringEL(false).build();MapString, Object dataMap new HashMapString, Object();dataMap.put(precipitationInfoList, getServerMergeTableData());ClassPathResource classPathResource new ClassPathResource(static/word/template.docx);try (InputStream resourceInputStream classPathResource.getInputStream();XWPFTemplate template XWPFTemplate.compile(resourceInputStream, config);) {template.render(dataMap);template.writeAndClose(new FileOutputStream(output.docx));} catch (Exception e) {e.printStackTrace();}}private ServerMergeTableData getServerMergeTableData() {ListMapString,Object serverDataList new ArrayList();MapString,Object serverData1 new HashMap();serverData1.put(province,广东省);serverData1.put(city,深圳市);serverData1.put(precipitation,0.3);serverDataList.add(serverData1);MapString,Object serverData2 new HashMap();serverData2.put(province,广东省);serverData2.put(city,广州市);serverData2.put(precipitation,5.1);serverDataList.add(serverData2);MapString,Object serverData3 new HashMap();serverData3.put(province,广东省);serverData3.put(city,东莞市);serverData3.put(precipitation,10);serverDataList.add(serverData3);MapString,Object serverData4 new HashMap();serverData4.put(province,湖南);serverData4.put(city,长沙);serverData4.put(precipitation,10);serverDataList.add(serverData4);MapString,Object serverData6 new HashMap();serverData6.put(province,湖南);serverData6.put(city,湘潭);serverData6.put(precipitation,4.5);serverDataList.add(serverData6);ListMergeGroupData groupDataList new ArrayList();groupDataList.add(MergeGroupData.builder().indexList(Arrays.asList(0,1,2)).build());groupDataList.add(MergeGroupData.builder().indexList(Arrays.asList(3,4)).build());ListMergeColumnData mergeColumns new ArrayList();mergeColumns.add(MergeColumnData.builder().groupDataList(groupDataList).mergeColumn(0).build());ServerMergeTableData serverMergeTableData new ServerMergeTableData();serverMergeTableData.setMergeColumns(mergeColumns);serverMergeTableData.setServerDataList(serverDataList);return serverMergeTableData;}效果图 附加插件实现
MergeColumnData 对象 import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;Builder
NoArgsConstructor
AllArgsConstructor
Data
public class MergeColumnData {/*** 携带要分组的信息*/private ListMergeGroupData groupDataList;/*** 需要合并的列从0开始*/private Integer mergeColumn;
}MergeGroupData 类 /*** 合并对象信息*/
Builder
NoArgsConstructor
AllArgsConstructor
Data
public class MergeGroupData {/*** 名称*/private ListString indexList;public Integer getListSize() {if (Objects.isNull(indexList)) {return 0;}return indexList.size();}
}ServerMergeTableData 数据信息 import lombok.Data;import java.util.List;Data
public class ServerMergeTableData {private List? serverDataList;/*** 列合并信息*/private ListMergeColumnData mergeColumns;
}ServerMergeTablePolicy 合并插件 import cn.hutool.core.collection.CollUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.render.compute.EnvModel;
import com.deepoove.poi.render.compute.RenderDataCompute;
import com.deepoove.poi.render.processor.DocumentProcessor;
import com.deepoove.poi.render.processor.EnvIterator;
import com.deepoove.poi.resolver.TemplateResolver;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.ReflectionUtils;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;import java.util.Iterator;
import java.util.List;public class ServerMergeTablePolicy extends AbstractRenderPolicyServerMergeTableData {private String prefix;private String suffix;private boolean onSameLine;public ServerMergeTablePolicy() {this(false);}public ServerMergeTablePolicy(boolean onSameLine) {this([, ], onSameLine);}public ServerMergeTablePolicy(String prefix, String suffix) {this(prefix, suffix, false);}public ServerMergeTablePolicy(String prefix, String suffix, boolean onSameLine) {this.prefix prefix;this.suffix suffix;this.onSameLine onSameLine;}Overridepublic void doRender(RenderContextServerMergeTableData context) throws Exception {XWPFTemplate template context.getTemplate();ServerMergeTableData mergeTableData context.getData();ElementTemplate eleTemplate context.getEleTemplate();this.renderTo(eleTemplate, mergeTableData, template);}public void renderTo(ElementTemplate eleTemplate, Object tableData, XWPFTemplate template) {RunTemplate runTemplate (RunTemplate) eleTemplate;XWPFRun run runTemplate.getRun();try {XWPFTableCell tagCell (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();XWPFTable table tagCell.getTableRow().getTable();run.setText(, 0);if (null tableData) {return;}ServerMergeTableData serverTableData (ServerMergeTableData) tableData;List data serverTableData.getServerDataList();if (!TableTools.isInsideTable(run)) {throw new IllegalStateException(The template tag runTemplate.getSource() must be inside a table);}int templateRowIndex getTemplateRowIndex(tagCell);int tempStartRow templateRowIndex;if (null ! data data instanceof Iterable) {Iterator? iterator ((Iterable?) data).iterator();XWPFTableRow templateRow table.getRow(templateRowIndex);int insertPosition templateRowIndex;TemplateResolver resolver new TemplateResolver(template.getConfig().copy(prefix, suffix));boolean firstFlag true;int index 0;boolean hasNext iterator.hasNext();while (hasNext) {Object root iterator.next();hasNext iterator.hasNext();insertPosition templateRowIndex;XWPFTableRow nextRow table.insertNewTableRow(insertPosition);setTableRow(table, templateRow, insertPosition);// double set rowXmlCursor newCursor templateRow.getCtRow().newCursor();newCursor.toPrevSibling();XmlObject object newCursor.getObject();nextRow new XWPFTableRow((CTRow) object, table);if (!firstFlag) {// update VMerge cells for non-first rowListXWPFTableCell tableCells nextRow.getTableCells();for (XWPFTableCell cell : tableCells) {CTTcPr tcPr TableTools.getTcPr(cell);CTVMerge vMerge tcPr.getVMerge();if (null vMerge) continue;if (STMerge.RESTART vMerge.getVal()) {vMerge.setVal(STMerge.CONTINUE);}}} else {firstFlag false;}setTableRow(table, nextRow, insertPosition);RenderDataCompute dataCompute template.getConfig().getRenderDataComputeFactory().newCompute(EnvModel.of(root, EnvIterator.makeEnv(index, hasNext)));ListXWPFTableCell cells nextRow.getTableCells();cells.forEach(cell - {ListMetaTemplate templates resolver.resolveBodyElements(cell.getBodyElements());new DocumentProcessor(template, resolver, dataCompute).process(templates);});}}table.removeRow(templateRowIndex);afterloop(table, data);//合并表格信息mergeTable(serverTableData, tempStartRow, table);} catch (Exception e) {throw new RenderException(HackLoopTable for eleTemplate error: e.getMessage(), e);}}private void mergeTable(ServerMergeTableData serverMergeTableData, int startRow, XWPFTable xwpfTable) {List serverDataList serverMergeTableData.getServerDataList();ListMergeColumnData mergeColumns serverMergeTableData.getMergeColumns();if (CollUtil.isNotEmpty(mergeColumns)) {for (int i 0; i serverDataList.size(); i) {for (MergeColumnData mergeColumnData : mergeColumns) {Integer mergeColumn mergeColumnData.getMergeColumn();ListMergeGroupData groupDataList mergeColumnData.getGroupDataList();for (int j 0; j groupDataList.size(); j) {MergeGroupData mergeGroupData groupDataList.get(j);ListString indexList mergeGroupData.getIndexList();int listSize mergeGroupData.getListSize();if (listSize 1) {continue;}// 若匹配上 就直接合并if (indexList.contains(i )) {int col i startRow;int fromRow i (startRow - 1) listSize;TableTools.mergeCellsVertically(xwpfTable, mergeColumn, col, fromRow);groupDataList.remove(j);break;}}}}}}private int getTemplateRowIndex(XWPFTableCell tagCell) {XWPFTableRow tagRow tagCell.getTableRow();return onSameLine ? getRowIndex(tagRow) : (getRowIndex(tagRow) 1);}protected void afterloop(XWPFTable table, Object data) {}SuppressWarnings(unchecked)private void setTableRow(XWPFTable table, XWPFTableRow templateRow, int pos) {ListXWPFTableRow rows (ListXWPFTableRow) ReflectionUtils.getValue(tableRows, table);rows.set(pos, templateRow);table.getCTTbl().setTrArray(pos, templateRow.getCtRow());}private int getRowIndex(XWPFTableRow row) {ListXWPFTableRow rows row.getTable().getRows();return rows.indexOf(row);}
}