poi-tl-ext扩展,实现多行表格模板替换
前言
目前poi-tl
只提供了word表格的单行模板渲染能力,但是在实际的开发中,业务需求涉及多行,这里就需要自己编写一个渲染策略。
正文
因为poi-tl
使用指定策略的方式为通过ConfigureBuilder
的bind方式指定处理某个参数的变量,比如这样:
ConfigureBuilder builder = Configure.builder();
builder.bind("reports", new MultipleRowTableRenderPolicy());
所以第一步需要获取reports
所在的行位置。
protected int getRowIndex(XWPFTableRow row) {List<XWPFTableRow> rows = row.getTable().getRows();return rows.indexOf(row);
}
由于是多行渲染,因此需要知道定义的模板行数。
protected int getMultipleRowNum(XWPFTemplate template) throws CloneNotSupportedException {TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(multiplePrefix, multipleSuffix));List<MetaTemplate> metaTemplates = resolver.resolveDocument(template.getXWPFDocument());if (!metaTemplates.isEmpty()) {RunTemplate run = cast2runTemplate(metaTemplates.get(0));String tagName = run.getTagName();int num = Integer.parseInt(tagName);run.getRun().setText("", 0);return num < 1 ? DEFAULT_MULTIPLE_ROW_NUM : num;}return DEFAULT_MULTIPLE_ROW_NUM;
}
拿到基本信息后就可以遍历数据,进而遍历渲染表格了。
run.setText("", 0);
TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(prefix, suffix));
// 获取模板所在的起始行
int position = getRowIndex(tagCell.getTableRow());
List<XWPFTableRow> tempRows = getAllTemplateRow(table, template, position);
// 保存第行模板,以便在后续操作中获取光标
final XWPFTableRow firstTempRow = tempRows.get(0);
Iterator<?> dataIt = ((Iterable<?>) data).iterator();
boolean hasNextData = dataIt.hasNext();
int index = 0;while (hasNextData) {Object dt = dataIt.next();hasNextData = dataIt.hasNext();Iterator<XWPFTableRow> rowTempIt = tempRows.iterator();boolean hasNextTempRow = rowTempIt.hasNext();while (hasNextTempRow) {XWPFTableRow tempRow = rowTempIt.next();hasNextTempRow = rowTempIt.hasNext();if (!table.addRow(tempRow, position)) {throw new RenderException("创建新的表格行失败");}// 光标操作,移动光标到目标行,以便后续的模板渲染XmlCursor newCursor = firstTempRow.getCtRow().newCursor();newCursor.toPrevSibling();XmlObject object = newCursor.getObject();XWPFTableRow newRow = new XWPFTableRow((CTRow) object, table);newRow.getCtRow().set(object);setTableRow(table, newRow, position);List<XWPFTableCell> cells = newRow.getTableCells();RenderDataCompute dataCompute = template.getConfig().getRenderDataComputeFactory().newCompute(EnvModel.of(dt, EnvIterator.makeEnv(index++, hasNextData || hasNextTempRow)));cells.forEach(tableCell -> {List<MetaTemplate> metaTemplates = resolver.resolveBodyElements(tableCell.getBodyElements());new DocumentProcessor(template, resolver, dataCompute).process(metaTemplates);});++position;}
}removeTableRow(table, position, tempRows.size());
值得一提就是光标的移动操作,相当于操作所有行的确定。取模板的第一行作为基位置,然后每次插入的渲染的行后,就把光标向上移一行,进而指向刚插入的行,最后渲染即可。
EnvIterator.makeEnv
只是为了生成一些遍历现在时参数,可以用在渲染参数的表达式中,具体可以参数poi-tl
的文档。
附上removeTableRow
函数的实现,注意:使用下标移出行时,下标千万不要作自增操作。
protected void removeTableRow(XWPFTable table, int startIndex, int size) {for (int i = 0; i < size; ++i) {table.removeRow(startIndex);}
}
测试
模板
代码
public class MultipleRowTableRenderPolicyTest {public static void main(String[] args) throws IOException {Map<String, Object> params = new HashMap<>();params.put("title", "某某某会议");params.put("date", new Date());params.put("address", "某某会议室");List<Report> reports = new ArrayList<>();reports.add(new Report("王五", new Date(), "汇报内容1"));reports.add(new Report("张三", new Date(), "汇报内容2"));reports.add(new Report("李四", new Date(), "汇报内容3"));params.put("reports", reports);ConfigureBuilder builder = Configure.builder();builder.bind("reports", new MultipleRowTableRenderPolicy());XWPFTemplate xt = XWPFTemplate.compile("src/test/resources/template/render-multiple-row.docx", builder.build()).render(params);xt.writeToFile("render-multiple-row.docx");}static class Report {private String author;private Date time;private String content;public Report(String author, Date time, String content) {this.author = author;this.time = time;this.content = content;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public Date getTime() {return time;}public void setTime(Date time) {this.time = time;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}}
}
结语
相关代码已经上传至github,地址:https://github.com/llzero54/poi-tl-ext
poi-tl-ext扩展,实现多行表格模板替换相关推荐
- POI渲染Excel表格模板替换其中指定表格参数,以及Microsoft联机文档查看器遇到的坑
POI渲染表格替换指定address参数 pom.xml Util工具类 划重点excel文件渲染数据核心方法 POJO 下边介绍下小编这里对线上office展示采用的方式 坑! 缺点 pom.xml ...
- 扩展jquery实现客户端表格的分页、排序
下面链接中是我用jQuery的扩展来实现的表格分页和排序,使用这个扩展必须加上表头<thead>和<tbody>标签,因为我是 通过<tbody>来进行分页的,要是 ...
- java使用poi操作excel删除一整行
java使用poi操作excel删除一整行 需求1:删除excel表格第4行 代码示例: sheet.shiftRows(4, sheet.getLastRowNum(),-1); 第一个参数为行数( ...
- Java使用Poi填充Word表格模板(图片和文字)
Java使用Poi填充Word表格模板(图片和文字) **** 由于个人需求需要对表格模板进行操作,所以本文章只对表格进行替换数据操作,没有段落,没有循环遍历,没有延伸!!!!!(后续补充!!!) * ...
- java poi 模板填数据库,java使用POI读取excel模版并向固定表格里填写数据详解
java使用POI读取excel模版并向固定表格里填写数据详解:public class ExportExcelDemo { private HSSFWorkbook workbook = null; ...
- java excel 删除行_使用Apache POI在Excel中删除多行
我有一张包含75行表格的Excel表格 . 在第76行我有各列的总功能 =SUM(A1:A75) 和 =SUM(B1:B75) 在第77到第92位的行我有一个Excel图表这需要A1:A75和B1:为 ...
- SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格、合并单元格)
本编文章继SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格)文章之后 介绍Poi-tl导出word的延伸功能: 所需依赖以及word模板所属位置 见 SpringBoo ...
- 使用jquery进行多行表格数据验证
使用jquery进行多行表格数据验证 <!DOCTYPE html> <html lang="en"> <head><meta chars ...
- JeecgBoot轻松解决ERP项目复杂布局需求,JVXETable高性能行表格效果和项目案例
ERP项目表格布局一般都很复杂,要求大数据.高操作.高性能 ,这个用JeecgBoot如何解决呢? 行编辑无痕刷新,实现鼠标移开即时保存,其他用户数据实时更新并有日历翻牌效果和无痕刷新效果: 行编辑实 ...
最新文章
- 和qc哪个发展更好_一图一表让你秒懂什么叫QC/QA/QM
- modelandview跳转页面404_Thinkphp制作404跳转页
- javamail command not implemented
- WSUS使用网络共享存储补丁
- 快速安装第三方库的指令——解决第三方库安装超时问题
- java 带参数的构造函数_java – mockito模拟一个带参数的构造函数
- JavaScript 函数循环、延时、节流、防抖
- mysql 移植ucos_基于STM32F767的UCOSIII移植学习
- numpy求逆矩阵_线性代数精华2——逆矩阵的推导过程
- php 合并 js css,PHP实现合并多个JS和CSS文件示例
- linux修改mdc时钟,Linux下用xsupplicant或mdc拨号上网
- InVEST实践及在生态系统服务供需、固碳、城市热岛、论文写作等实际项目中的具体应用
- 前端面试常问的问题(必须掌握)
- 全栈式python工程师培训课程
- 各公司用户画像技术案例分享
- 裂变海报设计的落地干货,为什么海报在裂变活动中这么重要?
- “Win7内部版本7600此Windows副本不是正版”解决方法
- Ad Mucher最新有效注册,升级方式
- 初识Android 制作一个简单的记账本
- 2021年最新ABAQUS复合材料建模仿真与应用专题培训