java实现word文档动态表格复杂操作 您所在的位置:网站首页 文档生成表格怎么操作出来 java实现word文档动态表格复杂操作

java实现word文档动态表格复杂操作

2024-06-26 15:59| 来源: 网络整理| 查看: 265

目录 一、先看效果1.1、实现前(word模板)1.2、实现后(最新版-已新增样式)额外拓展内容(代码未展示,需要的自行到项目查看) 二、测试地址三、贴出部分代码3.1、pom.xml3.2、测试类(PoiDemoApplicationTests)3.3、初始化数据3.4、初始化需要动态渲染表格3.5、定义一个类实现插件接口并重写 四、项目整体路径

一、先看效果 1.1、实现前(word模板)

在这里插入图片描述

1.2、实现后(最新版-已新增样式)

在这里插入图片描述

额外拓展内容(代码未展示,需要的自行到项目查看)

在这里插入图片描述 在这里插入图片描述

二、测试地址

目的:主要为了实现表格动态横竖合并等操作。 实现过程:定义一个类TemplateTableRenderPolicy继承DynamicTableRenderPolicy类插件重写方法实现动态渲染表格 详细记录了每一步操作,图文结合,可以更好的理解这个渲染插件的原理。 【gitee地址跳转】 【gitub地址跳转】 在这里插入图片描述

三、贴出部分代码 3.1、pom.xml

官方文档: http://deepoove.com/poi-tl/#_%E5%9B%BE%E7%89%87

com.deepoove poi-tl 1.12.1 3.2、测试类(PoiDemoApplicationTests) @Test void contextLoads() { try { // 一、初始化数据 // 1)初始化模板数据-实际是去数据库查询-自行整合 Templates templates = initTemplates(); // 2)初始化家庭成员信息-实际是去数据库查询-自行整合 List familyMemberList = initFamilyMember(); // 3)初始化工作情况-实际是去数据库查询-自行整合 List goingList = initGoing(); // 二、初始化动态数据-并整合一个完整的对象 // 1)处理动态数据->转为RowRenderData类型即List->List TemplateRowRenderData templateRowRenderData = new TemplateRowRenderData(familyMemberList,goingList); // 2)完整数据 TemplateData templateData = new TemplateData(templates,templateRowRenderData); // 三、绑定插件 // 1)插件绑定-【TemplateTableRenderPolicy】插件中data能获取到【TemplateRowRenderData】动态数据的关键 // 注意:模板中也是根据该字段进行渲染:templateRowRenderData 如图resources/pictures/images1.jpg 特别注意不要用到了中文画框花,鼠鼠我郁闷了一早上也想不明道插件为什么不生效 Configure config = Configure.builder().bind("templateRowRenderData", new TemplateTableRenderPolicy()).build(); // 四、导出 ClassPathResource classPathResource = new ClassPathResource("templates" + File.separator + "template.docx"); XWPFTemplate template = XWPFTemplate.compile(classPathResource.getInputStream(),config).render( templateData); Assertions.assertNotNull(template); // 通过浏览器下载自行整合下即可 // controller获取HttpServerResponse template.writeAndClose(Files.newOutputStream(Paths.get("C:\\Users\\WUDI\\Desktop\\export-word.docx"))); } catch (IOException e) { throw new RuntimeException(e); } } 3.3、初始化数据 private Templates initTemplates() { // 填充一些基本信息 Templates templates = new Templates(); templates.setName("牧羊人OVO"); templates.setAliases("牧羊人OVo"); templates.setDeptName("青龙小组"); templates.setSexName("未知"); templates.setPeoples("汉族"); templates.setBirth("2000"); templates.setCulture("小学"); return templates; } /** * 测试数据、实际是需要查询数据库的 * @return */ private List initFamilyMember() { List familyMemberList = new ArrayList(); for (int i = 0; i < 3; i++) { FamilyMember familyMember = new FamilyMember(); familyMember.setRelationship("关系" + i); familyMember.setName("姓名" + i); familyMember.setPosition("职位" + i); familyMemberList.add(familyMember); } return familyMemberList; } /** * 测试数据 * * @return */ private List initGoing() { List goingList = new ArrayList(); for (int i = 0; i < 3; i++) { Going going = new Going(); going.setCompany("工作单位" + i); going.setAddress("地址" + i); going.setPhone("程联系电话" + i); goingList.add(going); } return goingList; } 3.4、初始化需要动态渲染表格 import com.deepoove.poi.data.*; import com.deepoove.poi.data.style.*; import com.deepoove.poi.policy.TableRenderPolicy; import com.muyangren.poidemo.entity.FamilyMember; import com.muyangren.poidemo.entity.Going; import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import java.util.ArrayList; import java.util.Collections; import java.util.List; @Data public class TemplateRowRenderData { /** * 家庭人员 */ private List familyRowRenderDataList; /** * 工作情况 */ private List goingRowRenderDataList; private RowStyle rowStyle; public TemplateRowRenderData(List familyMemberList, List goingList) { // 初始化样式 initStyle(); // 初始化动态数据 initData(familyMemberList, goingList); } private void initStyle() { // 此处定义样式的优先级高:想看样式获取顺序可以看【TemplateTableRenderPolicy】中的【TableRenderPolicy.Helper.renderRow(xwpfTable.getRow(familyMemberRow), familyRowRenderDataList.get(i))】 谢谢你作者 很规范 nmd // 字体样式 Style style = new Style("宋体", 10); // 段落样式 ParagraphStyle paragraphStyle = new ParagraphStyle(); paragraphStyle.setDefaultTextStyle(style); // ps:这里才是字体居中对齐 paragraphStyle.setAlign(ParagraphAlignment.CENTER); // 表格样式 CellStyle cellStyle = new CellStyle(); // ps:表格也需要居中,否则字体不在正中间,会偏上 cellStyle.setVertAlign(XWPFTableCell.XWPFVertAlign.CENTER); cellStyle.setDefaultParagraphStyle(paragraphStyle); // 行样式 this.rowStyle = new RowStyle(); rowStyle.setDefaultCellStyle(cellStyle); } private void initData(List familyMemberList, List goingList) { List newFamilyRowRenderDataList = new ArrayList(); List newGoingRowRenderDataList = new ArrayList(); // 判空-家庭人员 if (CollectionUtils.isNotEmpty(familyMemberList)) { for (FamilyMember familyMember : familyMemberList) { // 创建一行五表格(根据实际情况来哈) List cellDataList = new ArrayList(); // 留两个空格(为什么要留两个空白格,大家可以试试自己去添加下行就知道了) 如图:resources/pictures/images3.jpg|images2.jpg cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(""))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(""))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(familyMember.getRelationship()))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(familyMember.getName()))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(familyMember.getPosition()))); RowRenderData rowRenderData = new RowRenderData(); // 样式 rowRenderData.setRowStyle(rowStyle); rowRenderData.setCells(cellDataList); newFamilyRowRenderDataList.add(rowRenderData); } this.familyRowRenderDataList = newFamilyRowRenderDataList; }else { // 要是不存在传null值的话,插件里就要多一层判断了 this.familyRowRenderDataList= Collections.emptyList(); } // 判空-工作情况 if (CollectionUtils.isNotEmpty(goingList)) { for (Going going : goingList) { // 创建一行四表格(根据实际情况来哈) List cellDataList = new ArrayList(); // 保留一个空格(如【家庭成员所示】) cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(""))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(going.getCompany()))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(going.getAddress()))); cellDataList.add(new CellRenderData().addParagraph(new ParagraphRenderData().addText(going.getPhone()))); RowRenderData rowRenderData = new RowRenderData(); // 样式 rowRenderData.setRowStyle(rowStyle); rowRenderData.setCells(cellDataList); newGoingRowRenderDataList.add(rowRenderData); } this.goingRowRenderDataList = newGoingRowRenderDataList; }else { this.goingRowRenderDataList= Collections.emptyList(); } } } 3.5、定义一个类实现插件接口并重写 import com.deepoove.poi.data.RowRenderData; import com.deepoove.poi.policy.DynamicTableRenderPolicy; import com.deepoove.poi.policy.TableRenderPolicy; import com.deepoove.poi.util.TableTools; import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import java.util.List; @NoArgsConstructor public class TemplateTableRenderPolicy extends DynamicTableRenderPolicy { @Override public void render(XWPFTable xwpfTable, Object data) throws Exception { if (null == data) { return; } //-----------------------------------先别急,一行一行看下去------------------------------------------------------- // 因为我们前面用Config绑定了【List】渲染规则 TemplateRowRenderData templateRowRenderData = (TemplateRowRenderData) data; // 一、处理家庭成员数据 List familyRowRenderDataList = templateRowRenderData.getFamilyRowRenderDataList(); if (CollectionUtils.isNotEmpty(familyRowRenderDataList)) { // 1)计算家庭成员表头所在行数 如图:resource/pictures/images4.jpg int familyMemberRow = 9; // 2)删掉空白内容:xwpfTable.removeRow是从下标0开始计算的,所以这里删除的是空白内容如图:resource/pictures/images5.jpg xwpfTable.removeRow(familyMemberRow); // 3)获取该表家庭成员表头高度 【familyMemberRow-1】即家庭成员表头的下标 作用:统一高度 XWPFTableRow xwpfTableRow = xwpfTable.getRow(familyMemberRow-1); // 4)循环插入行 (倒序插入)ps:这里是一直在第9行插入表格。 for (int i = familyRowRenderDataList.size() - 1; i > -1; i--) { // 4.1)插入表格 XWPFTableRow insertNewTableRow = xwpfTable.insertNewTableRow(familyMemberRow); // 4.1.1)控制表格高度 insertNewTableRow.setHeight(xwpfTableRow.getHeight()); // 4.2)每行添加11个表格,这里需要根据实际情况填充。秉持多则退少补原则 // 如图:假如我添加12个 resource/pictures/images6.jpg // 如图:假如我添加10个 resource/pictures/images7.jpg // 注:想看效果时记得注释下面的代码 【TableTools.mergeCellsHorizonal】,【TableTools.mergeCellsVertically】 for (int j = 0; j < 11; j++) { insertNewTableRow.createCell(); } // 基本信息占1格,家庭成员占1个,关系、姓名、职位各占3 刚好11格 // 5)合并上面创建的11个单元格 fromCol-toCol 且 fromCol(起始) < toCol(结束) // 5.1)【关系】下标为2,所以2(fromCol)合并至4(toCol)的单元格 TableTools.mergeCellsHorizonal(xwpfTable, familyMemberRow, 2, 4); // 5.2)【姓名】下标为3,所以3(fromCol)合并至5(toCol)的单元格:注意:按上一个合并后的结果再数格子并合并 TableTools.mergeCellsHorizonal(xwpfTable, familyMemberRow, 3, 5); // 5.3)【职位】下标为4,所以4(fromCol)合并至6(toCol)的单元格:注意:按上一个合并后的结果再数格子并合并 TableTools.mergeCellsHorizonal(xwpfTable, familyMemberRow, 4, 6); // 6) 渲染数据(表格对齐后在进行渲染数据) TableRenderPolicy.Helper.renderRow(xwpfTable.getRow(familyMemberRow), familyRowRenderDataList.get(i)); } // 7)跨行合并行 参数说明: 1-操作表格方法 2-需要合并行 3-开始合并列 4-结束合并列 // 7.1) 合并前:resource/pictures/images8.jpg // 7.2) 合并后:resource/pictures/images9.jpg int fromRow = familyMemberRow - 1; // 7.3)合并下标为1的行 合并列为fromRow->familyRowRenderDataList.size() + fromRow // 7.4)合并下标为0的行 合并列为0->familyRowRenderDataList.size() + fromRow TableTools.mergeCellsVertically(xwpfTable, 1, fromRow, familyRowRenderDataList.size() + fromRow); TableTools.mergeCellsVertically(xwpfTable, 0, 0, familyRowRenderDataList.size() + fromRow); } //---------------------------------------以上为家庭成员的数据渲染------------------------------------------------------------ // 二、处理工作情况数据-关键处此篇不给出解析,大家根据【家庭成员】 自行填写 List goingRowRenderDataList = templateRowRenderData.getGoingRowRenderDataList(); // 1)判空 if (CollectionUtils.isNotEmpty(goingRowRenderDataList)) { // 2)工作情况所在行数 ps:其实我们从0开始数的话、可以省很多事 int goingMemberRow = 11; if (!CollectionUtils.isEmpty(familyRowRenderDataList)) { goingMemberRow = 11 + familyRowRenderDataList.size() - 1; } // 3) xwpfTable.removeRow(goingMemberRow); // 4) XWPFTableRow xwpfTableRow = xwpfTable.getRow(goingMemberRow-1); // 5)循环插入行(倒序插入) for (int i = goingRowRenderDataList.size() - 1; i > -1; i--) { XWPFTableRow insertNewTableRow = xwpfTable.insertNewTableRow(goingMemberRow); insertNewTableRow.setHeight(xwpfTableRow.getHeight()); // 6) for (int j = 0; j < 11; j++) { insertNewTableRow.createCell(); } // 7) // 7.1)合并表格 TableTools.mergeCellsHorizonal(xwpfTable, goingMemberRow, 1, 2); // 7.2)合并表格 TableTools.mergeCellsHorizonal(xwpfTable, goingMemberRow, 2, 7); // 7.3)合并表格 TableTools.mergeCellsHorizonal(xwpfTable, goingMemberRow, 3, 4); // 8)渲染数据 TableRenderPolicy.Helper.renderRow(xwpfTable.getRow(goingMemberRow), goingRowRenderDataList.get(i)); } // 9)合并行 TableTools.mergeCellsVertically(xwpfTable,0,goingMemberRow-1,goingMemberRow +goingRowRenderDataList.size()-1); } } } 四、项目整体路径

在这里插入图片描述

如果该篇文章对您有帮助 麻烦点个赞以及star支持下哈


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有