1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格 合并单元格)

SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格 合并单元格)

时间:2023-11-06 05:43:25

相关推荐

SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格 合并单元格)

本编文章继SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格)文章之后

介绍Poi-tl导出word的延伸功能:

所需依赖以及word模板所属位置 见 SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格),这里不再累赘。

直接介绍延伸功能的实现。

一、延伸功能

功能1:导出多个动态行表格(固定个数)

功能2:导出循环列表下的动态行表格(个数不固定)

功能3:导出合并单元格

功能4:导出循环列表下合并单元格

功能5:导出循环列表下合并单元格、外加一个动态行表格

二、功能实现

功能1:导出多个动态行表格(固定个数)

(1)新建一个word(orderD2.docx),编写word模板:

(2)在ExportWordController类中,编写相应的导出方法,供页面请求

/*** 销售订单信息导出word --- poi-tl(包含两个动态行表格)* @throws IOException */@RequestMapping("/exportDataWordD4")public void exportDataWordD4(HttpServletRequest request,HttpServletResponse response) throws IOException{try {Map<String, Object> params = new HashMap<>();// TODO 渲染其他类型的数据请参考官方文档DecimalFormat df = new DecimalFormat("######0.00"); Calendar now = Calendar.getInstance(); double money = 0;//总金额//组装表格列表数据List<Map<String,Object>> typeList=new ArrayList<Map<String,Object>>();for (int i = 0; i < 2; i++) {Map<String,Object> detailMap = new HashMap<String, Object>();detailMap.put("index", i+1);//序号if(i == 0){detailMap.put("sub_type", "监督技术装备");//商品所属大类名称}else if(i == 1){detailMap.put("sub_type", "火灾调查装备");//商品所属大类名称}else if(i == 2){detailMap.put("sub_type", "工程验收装备");//商品所属大类名称}double saleprice=Double.valueOf(String.valueOf(100+i));Integer buy_num=Integer.valueOf(String.valueOf(3+i));String buy_price=df.format(saleprice*buy_num);detailMap.put("buy_price", buy_price);//所属大类总价格money=money+Double.valueOf(buy_price);typeList.add(detailMap);}//组装表格列表数据List<Map<String,Object>> detailList=new ArrayList<Map<String,Object>>();for (int i = 0; i < 3; i++) {Map<String,Object> detailMap = new HashMap<String, Object>();detailMap.put("index", i+1);//序号if(i == 0 || i == 1){detailMap.put("product_type", "二级分类1");//商品二级分类}else{detailMap.put("product_type", "二级分类2");//商品二级分类}detailMap.put("title", "商品"+i);//商品名称detailMap.put("product_description", "套");//商品规格detailMap.put("buy_num", 3+i);//销售数量detailMap.put("saleprice", 100+i);//销售价格detailMap.put("technical_parameter", "技术参数"+i);//技术参数detailList.add(detailMap);}//总金额String order_money=String.valueOf(money);//金额中文大写String money_total = MoneyUtils.change(money);//word模板地址获取方式一:缺点---打jar包获取不到该路径//String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//String resource =basePath+"orderD2.docx";//word模板地址//word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效ClassPathResource classPathResource = new ClassPathResource("static/template/orderD2.docx");String resource = classPathResource.getURL().getPath();//渲染表格 动态行HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();Configure config = Configure.newBuilder().bind("typeList", policy).bind("detailList", policy).build();XWPFTemplate template = pile(resource, config).render(new HashMap<String, Object>() {{put("typeList", typeList);put("detailList",detailList);put("order_number", "2356346346645");put("y", now.get(Calendar.YEAR));//当前年put("m", (now.get(Calendar.MONTH) + 1));//当前月put("d", now.get(Calendar.DAY_OF_MONTH));//当前日put("order_money",order_money);//总金额put("money_total",money_total);//金额中文大写}});//=================生成文件保存在本地D盘某目录下=================String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址//生成文件名Long time = new Date().getTime();// 生成的word格式String formatSuffix = ".docx";// 拼接后的文件名String fileName = time + formatSuffix;//文件名 带后缀FileOutputStream fos = new FileOutputStream(temDir+fileName);template.write(fos);//=================生成word到设置浏览默认下载地址=================// 设置强制下载不打开response.setContentType("application/force-download");// 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();template.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}

(3)页面编写调用方法

<div class="m2" style="margin-top: 30px;">使用<span class="s1">POI-tl</span>根据word模板动态生成word(包含两个动态行表格)</div><a href="#" class="easyui-linkbutton" onclick="doExportWordD4();" data-options="iconCls:'icon-save'">导出word(包含两个动态行表格)</a>

//方式一导出word(包含两个动态行表格)function doExportWordD4(){window.location.href="<%=basePath%>/auth/exportWord/exportDataWordD4";}

(4)导出结果:

功能2:导出循环列表下的动态行表格(个数不固定)

如果列表的每一项不是简单的文本,而是包含很多文档内容,或者多级列表该怎么生成?区块对的循环功能可以很好的循环列表,并且支持编号有序。

(1)新建一个word(order2.docx),编写word模板:

(2)在ExportWordController类中,编写相应的导出方法,供页面请求

/*** 销售订单信息导出word --- poi-tl(包含动态行表格、循环列表中的动态行表格)* @throws IOException */@RequestMapping("/exportDataWord4")public void exportDataWord4(HttpServletRequest request,HttpServletResponse response) throws IOException{try {Map<String, Object> params = new HashMap<>();// TODO 渲染其他类型的数据请参考官方文档DecimalFormat df = new DecimalFormat("######0.00"); Calendar now = Calendar.getInstance(); double money = 0;//总金额//组装表格列表数据List<Map<String,Object>> typeList=new ArrayList<Map<String,Object>>();for (int i = 0; i < 2; i++) {Map<String,Object> detailMap = new HashMap<String, Object>();detailMap.put("index", i+1);//序号if(i == 0){detailMap.put("sub_type", "监督技术装备");//商品所属大类名称}else if(i == 1){detailMap.put("sub_type", "火灾调查装备");//商品所属大类名称}else if(i == 2){detailMap.put("sub_type", "工程验收装备");//商品所属大类名称}double saleprice=Double.valueOf(String.valueOf(100+i));Integer buy_num=Integer.valueOf(String.valueOf(3+i));String buy_price=df.format(saleprice*buy_num);detailMap.put("buy_price", buy_price);//所属大类总价格money=money+Double.valueOf(buy_price);typeList.add(detailMap);}//组装表格列表数据List<Map<String,Object>> detailList=new ArrayList<Map<String,Object>>();for (int i = 0; i < 3; i++) {Map<String,Object> detailMap = new HashMap<String, Object>();detailMap.put("index", i+1);//序号if(i == 0 || i == 1){detailMap.put("product_type", "二级分类1");//商品二级分类}else{detailMap.put("product_type", "二级分类2");//商品二级分类}detailMap.put("title", "商品"+i);//商品名称detailMap.put("product_description", "套");//商品规格detailMap.put("buy_num", 3+i);//销售数量detailMap.put("saleprice", 100+i);//销售价格detailMap.put("technical_parameter", "技术参数"+i);//技术参数detailList.add(detailMap);}List<Map<String,Object>> tList=new ArrayList<Map<String,Object>>();Map<String,Object> tMap = new HashMap<String, Object>();tMap.put("index", 1);tMap.put("sub_type", "监督技术装备");tMap.put("detailList", detailList);tMap.put("buy_price", 100);tList.add(tMap);tMap = new HashMap<String, Object>();tMap.put("index", 2);tMap.put("sub_type", "火灾调查装备");tMap.put("detailList", detailList);tMap.put("buy_price", 200);tList.add(tMap);tMap = new HashMap<String, Object>();tMap.put("index", 3);tMap.put("sub_type", "工程验收装备");tMap.put("detailList", detailList);tMap.put("buy_price", 300);tList.add(tMap);//总金额String order_money=String.valueOf(money);//金额中文大写String money_total = MoneyUtils.change(money);//word模板地址获取方式一:缺点---打jar包获取不到该路径//String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//String resource =basePath+"order2.docx";//word模板地址//word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效ClassPathResource classPathResource = new ClassPathResource("static/template/order2.docx");String resource = classPathResource.getURL().getPath();//渲染表格 动态行HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();Configure config = Configure.newBuilder().bind("typeList", policy).bind("detailList", policy).build();XWPFTemplate template = pile(resource, config).render(new HashMap<String, Object>() {{put("typeList", typeList);put("typeProducts",tList);put("order_number", "2356346346645");put("y", now.get(Calendar.YEAR));//当前年put("m", (now.get(Calendar.MONTH) + 1));//当前月put("d", now.get(Calendar.DAY_OF_MONTH));//当前日put("order_money",order_money);//总金额put("money_total",money_total);//金额中文大写}});//=================生成文件保存在本地D盘某目录下=================String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址//生成文件名Long time = new Date().getTime();// 生成的word格式String formatSuffix = ".docx";// 拼接后的文件名String fileName = time + formatSuffix;//文件名 带后缀FileOutputStream fos = new FileOutputStream(temDir+fileName);template.write(fos);//=================生成word到设置浏览默认下载地址=================// 设置强制下载不打开response.setContentType("application/force-download");// 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();template.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}

(3)页面编写调用方法

<div class="m2" style="margin-top: 30px;">使用<span class="s1">POI-tl</span>根据word模板动态生成word(包含动态行表格、循环列表下动态行表格)</div><a href="#" class="easyui-linkbutton" onclick="doExportWord4();" data-options="iconCls:'icon-save'">导出word(包含动态行表格、循环列表下动态行表格)</a>

//方式一导出word(包含动态行表格、循环列表中的动态行表格)function doExportWord4(){window.location.href="<%=basePath%>/auth/exportWord/exportDataWord4";}

(4)导出结果:

功能3:导出合并单元格(一个列表下的合并行)

示例中:

比较复杂的表格,一个二级分类下,有多个商品。由7列组成,行数不定。

默认表格数据模型(MiniTableRenderData)实现了最基本的样式,当需求中的表格更加复杂的时候,我们完全可以设计好那些固定的部分,将需要动态渲染的部分单元格交给自定义模板渲染策略。

poi-tl提供了抽象表格策略DynamicTableRenderPolicy来实现这样的功能,{{detail_table}}标签可以在表格内的任意单元格内,DynamicTableRenderPolicy会获取XWPFTable对象进而获得操作整个表格的能力。

(1)新建一个word(order4.docx),编写word模板:

设置{{detail_table}}为自定义模板渲染策略(继承抽象表格策略DynamicTableRenderPolicy),自定义已有表格中部分单元格的渲染。

(2)代码实现:

新建渲染策略DetailTablePolicy2,继承于抽象表格策略:

package com.mon.mergeCell2;import java.util.List;import java.util.Map;import org.apache.poi.xwpf.usermodel.XWPFTable;import org.apache.poi.xwpf.usermodel.XWPFTableCell;import org.apache.poi.xwpf.usermodel.XWPFTableRow;import com.deepoove.poi.data.RowRenderData;import com.deepoove.poi.policy.DynamicTableRenderPolicy;import com.deepoove.poi.policy.MiniTableRenderPolicy;import com.deepoove.poi.util.TableTools;public class DetailTablePolicy2 extends DynamicTableRenderPolicy {// 填充数据所在行数int listsStartRow = 1;@Overridepublic void render(XWPFTable table, Object data) {if (null == data) return;DetailData2 detailData = (DetailData2) data;// 商品订单详情列表数据 循环渲染List<RowRenderData> lists = detailData.getPlists();// 二级分类分组统计商品个数数据List<Map<String,Object>> tlists = detailData.getTlists();if (null != lists) {table.removeRow(listsStartRow);// 循环插入行for (int i = lists.size()-1; i >=0; i--) {XWPFTableRow insertNewTableRow = table.insertNewTableRow(listsStartRow);for (int j = 0; j < 7; j++)insertNewTableRow.createCell();// 渲染单行商品订单详情数据MiniTableRenderPolicy.Helper.renderRow(table, listsStartRow, lists.get(i));}//处理合并for (int i=0;i<lists.size();i++) {Object v =lists.get(i).getCells().get(1).getCellText();String type_name=String.valueOf(v);for(int j=0;j<tlists.size();j++){String typeName = String.valueOf(tlists.get(j).get("typeName"));Integer listSize = Integer.parseInt(String.valueOf(tlists.get(j).get("listSize")));if(type_name.equals(typeName)){// 合并第1列的第i+1行到第i+listSize行的单元格TableTools.mergeCellsVertically(table, 1, i+1, i+listSize);//处理垂直居中for (int y = 1; y < 7; y++){XWPFTableCell cell = table.getRow(i+1).getCell(y);cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); //垂直居中}tlists.remove(j);break;}}System.out.println(v);}}}}

DetailData2:

package com.mon.mergeCell2;import java.util.List;import java.util.Map;import com.deepoove.poi.data.RowRenderData;public class DetailData2 {// 商品订单详情列表数据private List<RowRenderData> plists;// 二级分类分组统计商品个数数据private List<Map<String,Object>> tlists;public List<RowRenderData> getPlists() {return plists;}public void setPlists(List<RowRenderData> plists) {this.plists = plists;}public List<Map<String,Object>> getTlists() {return tlists;}public void setTlists(List<Map<String,Object>> tlists) {this.tlists = tlists;}}

PaymentData2:

package com.mon.mergeCell2;import com.deepoove.poi.el.Name;public class PaymentData2 {@Name("detail_table")private DetailData2 detailTable;private String total;public void setDetailTable(DetailData2 detailTable) {this.detailTable = detailTable;}public DetailData2 getDetailTable() {return this.detailTable;}public String getTotal() {return total;}public void setTotal(String total) {this.total = total;}}

在ExportWordController类中,编写相应的导出方法,供页面请求:

/*** 销售订单信息导出word --- poi-tl(合并单元格(一个列表下的合并行)--商品订单明细)* @throws IOException */@RequestMapping("/exportDataWord6")public void exportDataWord6(HttpServletRequest request,HttpServletResponse response) throws IOException{try {Map<String, Object> params = new HashMap<>();// TODO 渲染其他类型的数据请参考官方文档//word模板地址获取方式一:缺点---打jar包获取不到该路径//String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//String resource =basePath+"order4.docx";//word模板地址//word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效ClassPathResource classPathResource = new ClassPathResource("static/template/order4.docx");String resource = classPathResource.getURL().getPath();PaymentData2 datas = new PaymentData2();TableStyle rowStyle = new TableStyle();rowStyle = new TableStyle();rowStyle.setAlign(STJc.CENTER);DetailData2 detailTable = new DetailData2();List<RowRenderData> plists =new ArrayList<RowRenderData>();for(int i=0;i<6;i++){String typeName="二级分类1";if(i == 3 || i == 4){typeName="二级分类2";}else if(i == 5){typeName="二级分类3";}String index = String.valueOf(i+1);RowRenderData plist = RowRenderData.build(index, typeName, "商品"+i, "套", "2","100","技术参数"+i);plist.setRowStyle(rowStyle);plists.add(plist);}//二级分类 分组统计 商品个数List<Map<String,Object>> tlists = new ArrayList<Map<String,Object>>();Map<String,Object> map = new HashMap<String, Object>();map.put("typeName", "二级分类1");map.put("listSize", "3");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类2");map.put("listSize", "2");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类3");map.put("listSize", "1");tlists.add(map);detailTable.setPlists(plists);detailTable.setTlists(tlists);datas.setDetailTable(detailTable);datas.setTotal("1000");Configure config = Configure.newBuilder().bind("detail_table", new DetailTablePolicy2()).build();XWPFTemplate template = pile(resource, config).render(datas);//=================生成文件保存在本地D盘某目录下=================String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址//生成文件名Long time = new Date().getTime();// 生成的word格式String formatSuffix = ".docx";// 拼接后的文件名String fileName = time + formatSuffix;//文件名 带后缀FileOutputStream fos = new FileOutputStream(temDir+fileName);template.write(fos);//=================生成word到设置浏览默认下载地址=================// 设置强制下载不打开response.setContentType("application/force-download");// 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();template.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}

注意: @Name(“detail_table”) 是必须的,不然word表格无法渲染, name可以自定义,要和 模板的一致

(3)页面编写调用方法

<div class="m2" style="margin-top: 30px;">使用<span class="s1">POI-tl</span>根据word模板动态生成word(合并单元格2)</div><a href="#" class="easyui-linkbutton" onclick="doExportWord6();" data-options="iconCls:'icon-save'">导出word(合并单元格(一个列表下的合并行)--商品订单明细)</a><div style="font-size: 13px;color:#cccccc">如:合并第1列的第1行到第3行的单元格</div>

//方式一导出word(合并单元格(一个列表下的合并行)--商品订单明细))function doExportWord6(){window.location.href="<%=basePath%>/auth/exportWord/exportDataWord6";}

(4)导出结果:

功能4:导出循环列表下合并单元格(循环列表下的合并行)

在功能3的基础上做修改:

(1)新建一个word(order5.docx),编写word模板:

(2)代码实现:

复用 功能3中的合并处理类,修改PaymentData2.java类,添加 typeLists变量存储循环列表(@Name(“typeLists”)用于表格渲染,不能省略):

package com.mon.mergeCell2;import java.util.List;import java.util.Map;import com.deepoove.poi.el.Name;public class PaymentData2 {@Name("detail_table")private DetailData2 detailTable;@Name("typeLists")private List<Map<String,Object>> typeLists;//所属大类统计列表private String total;public void setDetailTable(DetailData2 detailTable) {this.detailTable = detailTable;}public DetailData2 getDetailTable() {return this.detailTable;}public String getTotal() {return total;}public void setTotal(String total) {this.total = total;}public List<Map<String, Object>> getTypeLists() {return typeLists;}public void setTypeLists(List<Map<String, Object>> typeLists) {this.typeLists = typeLists;}}

在ExportWordController类中,编写相应的导出方法,供页面请求:

/*** 销售订单信息导出word --- poi-tl(合并单元格(循环列表下的合并行)--商品订单明细)* @throws IOException */@RequestMapping("/exportDataWord7")public void exportDataWord7(HttpServletRequest request,HttpServletResponse response) throws IOException{try {Map<String, Object> params = new HashMap<>();// TODO 渲染其他类型的数据请参考官方文档//word模板地址获取方式一:缺点---打jar包获取不到该路径//String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//String resource =basePath+"order5.docx";//word模板地址//word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效ClassPathResource classPathResource = new ClassPathResource("static/template/order5.docx");String resource = classPathResource.getURL().getPath();PaymentData2 datas = new PaymentData2();TableStyle rowStyle = new TableStyle();rowStyle = new TableStyle();rowStyle.setAlign(STJc.CENTER);//组装循环体List<Map<String,Object>> typeLists = new ArrayList<Map<String,Object>>();for(int x=0;x<3;x++){DetailData2 detailTable = new DetailData2();List<RowRenderData> plists =new ArrayList<RowRenderData>();for(int i=0;i<6;i++){String typeName="二级分类1"+x;if(i == 3 || i == 4){typeName="二级分类2"+x;}else if(i == 5){typeName="二级分类3"+x;}String index = String.valueOf(i+1);RowRenderData plist = RowRenderData.build(index, typeName, "商品"+i, "套", "2","100","技术参数"+i);plist.setRowStyle(rowStyle);plists.add(plist);}//二级分类 分组统计 商品个数List<Map<String,Object>> tlists = new ArrayList<Map<String,Object>>();Map<String,Object> map = new HashMap<String, Object>();map.put("typeName", "二级分类1"+x);map.put("listSize", "3");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类2"+x);map.put("listSize", "2");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类3"+x);map.put("listSize", "1");tlists.add(map);detailTable.setPlists(plists);detailTable.setTlists(tlists);Map<String,Object> data= new HashMap<String, Object>();data.put("detail_table", detailTable);data.put("sub_type", "大类"+x);data.put("total_price", 100+x);typeLists.add(data);}datas.setTypeLists(typeLists);Configure config = Configure.newBuilder().bind("detail_table", new DetailTablePolicy2()).build();XWPFTemplate template = pile(resource, config).render(datas);//=================生成文件保存在本地D盘某目录下=================String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址//生成文件名Long time = new Date().getTime();// 生成的word格式String formatSuffix = ".docx";// 拼接后的文件名String fileName = time + formatSuffix;//文件名 带后缀FileOutputStream fos = new FileOutputStream(temDir+fileName);template.write(fos);//=================生成word到设置浏览默认下载地址=================// 设置强制下载不打开response.setContentType("application/force-download");// 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();template.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}

(3)页面编写调用方法

<div class="m2" style="margin-top: 30px;">使用<span class="s1">POI-tl</span>根据word模板动态生成word(循环列表下的动态行表格以及合并单元格)</div><a href="#" class="easyui-linkbutton" onclick="doExportWord7();" data-options="iconCls:'icon-save'">导出word(合并单元格(循环列表下的合并行)--商品订单明细)</a>

//方式一导出word(合并单元格(循环列表下的合并行)--商品订单明细)function doExportWord7(){window.location.href="<%=basePath%>/auth/exportWord/exportDataWord7";}

(4)导出结果:

功能5:导出循环列表下合并单元格、外加一个动态行表格

(1)新建一个word(order6.docx),编写word模板:

(2)代码实现:

功能4中已经编写了循环列表合并处理,见上述。 讲解下如何在循环列表合并的基础上,再加上一个动态行表格:

①新增DetailTablePolicy4用于 另加的动态行表格的插入与渲染:

package com.mon.mergeCell3;import java.util.ArrayList;import java.util.List;import java.util.Map;import org.apache.poi.xwpf.usermodel.XWPFTable;import org.apache.poi.xwpf.usermodel.XWPFTableCell;import org.apache.poi.xwpf.usermodel.XWPFTableRow;import org.openxmlformats.schemas.wordprocessingml.x.main.STJc;import com.deepoove.poi.data.RowRenderData;import com.deepoove.poi.data.style.TableStyle;import com.deepoove.poi.policy.DynamicTableRenderPolicy;import com.deepoove.poi.policy.MiniTableRenderPolicy;import com.deepoove.poi.util.TableTools;/*** 商品所属大类统计 表格动态行插入、渲染、合并单元格处理* @author Administrator**/public class DetailTablePolicy4 extends DynamicTableRenderPolicy {// 填充数据所在行数int listsStartRow = 1;@Overridepublic void render(XWPFTable table, Object data) {if (null == data) return;//文本居中TableStyle rowStyle = new TableStyle();rowStyle = new TableStyle();rowStyle.setAlign(STJc.CENTER);List<RowRenderData> lists = new ArrayList<RowRenderData>();//所属大类列表数据List<Map<String,Object>> typeLists = (List<Map<String, Object>>) data;for(Map<String,Object> map:typeLists){String index =String.valueOf(map.get("index")); String sub_type =String.valueOf(map.get("sub_type")); String total_price =String.valueOf(map.get("total_price")); RowRenderData tlist = RowRenderData.build(index, sub_type, total_price,total_price);tlist.setRowStyle(rowStyle);lists.add(tlist);}if (null != lists) {table.removeRow(listsStartRow);// 循环插入行for (int i = lists.size()-1; i >=0; i--) {XWPFTableRow insertNewTableRow = table.insertNewTableRow(listsStartRow);for (int j = 0; j < 4; j++)insertNewTableRow.createCell();// 渲染单行所属大类数据MiniTableRenderPolicy.Helper.renderRow(table, listsStartRow, lists.get(i));}}}}

②PaymentData2类新增两个变量:

private String order_money;//订单总金额private String money_total;//订单总金额的中文大写

③导出方法修改

在功能4的导出方法做如下修改:

导出方法完整代码:

/*** 销售订单信息导出word --- poi-tl(合并单元格(循环列表下的合并行)--商品订单明细、另加一个动态行表格)* @throws IOException */@RequestMapping("/exportDataWord8")public void exportDataWord8(HttpServletRequest request,HttpServletResponse response) throws IOException{try {Map<String, Object> params = new HashMap<>();// TODO 渲染其他类型的数据请参考官方文档//word模板地址获取方式一:缺点---打jar包获取不到该路径//String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//String resource =basePath+"order6.docx";//word模板地址//word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效ClassPathResource classPathResource = new ClassPathResource("static/template/order6.docx");String resource = classPathResource.getURL().getPath();PaymentData2 datas = new PaymentData2();TableStyle rowStyle = new TableStyle();rowStyle = new TableStyle();rowStyle.setAlign(STJc.CENTER);//组装循环体List<Map<String,Object>> typeLists = new ArrayList<Map<String,Object>>();List<Map<String,Object>> typeTotalList = new ArrayList<Map<String,Object>>();for(int x=0;x<3;x++){DetailData2 detailTable = new DetailData2();List<RowRenderData> plists =new ArrayList<RowRenderData>();for(int i=0;i<6;i++){String typeName="二级分类1"+x;if(i == 3 || i == 4){typeName="二级分类2"+x;}else if(i == 5){typeName="二级分类3"+x;}String index = String.valueOf(i+1);RowRenderData plist = RowRenderData.build(index, typeName, "商品"+i, "套", "2","100","技术参数"+i);plist.setRowStyle(rowStyle);plists.add(plist);}//二级分类 分组统计 商品个数List<Map<String,Object>> tlists = new ArrayList<Map<String,Object>>();Map<String,Object> map = new HashMap<String, Object>();map.put("typeName", "二级分类1"+x);map.put("listSize", "3");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类2"+x);map.put("listSize", "2");tlists.add(map);map = new HashMap<String, Object>();map.put("typeName", "二级分类3"+x);map.put("listSize", "1");tlists.add(map);detailTable.setPlists(plists);detailTable.setTlists(tlists);Map<String,Object> data= new HashMap<String, Object>();data.put("detail_table", detailTable);data.put("index", x+1);data.put("sub_type", "大类"+x);data.put("total_price", 100+x);typeLists.add(data);}datas.setTypeLists(typeLists);datas.setOrder_money("100");datas.setMoney_total("壹佰元整");Configure config = Configure.newBuilder().bind("detail_table", new DetailTablePolicy2()).bind("typeLists", new DetailTablePolicy4()).build();XWPFTemplate template = pile(resource, config).render(datas);//=================生成文件保存在本地D盘某目录下=================String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址//生成文件名Long time = new Date().getTime();// 生成的word格式String formatSuffix = ".docx";// 拼接后的文件名String fileName = time + formatSuffix;//文件名 带后缀FileOutputStream fos = new FileOutputStream(temDir+fileName);template.write(fos);//=================生成word到设置浏览默认下载地址=================// 设置强制下载不打开response.setContentType("application/force-download");// 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();template.write(out);out.flush();out.close();template.close();} catch (Exception e) {e.printStackTrace();}}

(3)页面编写调用方法

<div class="m2" style="margin-top: 30px;">使用<span class="s1">POI-tl</span>根据word模板动态生成word(循环列表下的动态行表格以及合并单元格)</div><a href="#" class="easyui-linkbutton" onclick="doExportWord8();" data-options="iconCls:'icon-save'">导出word(合并单元格(循环列表下的合并行)--商品订单明细、另加一个动态行表格)</a>

//方式一导出word(合并单元格(循环列表下的合并行)--商品订单明细、另加一个动态行表格)function doExportWord8(){window.location.href="<%=basePath%>/auth/exportWord/exportDataWord8";}

(4)导出结果:

三、完整代码

点击此处获取

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。