word 模板内容的替换和生成word 表格(使用poi)
1. maven 相关依赖 和模板
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.15-beta2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/ooxml-schemas --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.1</version> </dependency>
2. 工具类中的方法
// 给生成的表格设置样式 public static void setCellWitchAndAlign(XWPFTableCell cell,String width,STVerticalJc.Enum typeEnum,STJc.Enum align){ CTTc cttc = cell.getCTTc(); CTTcPr ctPr = cttc.addNewTcPr(); ctPr.addNewVAlign().setVal(typeEnum); cttc.getPList().get(0).addNewPPr().addNewJc().setVal(align); CTTblWidth ctTblWidth = (ctPr != null && ctPr.isSetTcW() && ctPr.getTcW()!=null &&ctPr.getTcW().getW()!=null) ? ctPr.getTcW(): ctPr.addNewTcW(); if(StringUtils.isNotBlank(width)){ ctTblWidth.setW(new BigInteger(width)); ctTblWidth.setType(STTblWidth.DXA); } }
/** * 生成word文档下载 */ public static void DownloadWord(HttpServletResponse response,List<DisUser> list, Map<String, Object> map,String file){ XWPFDocument document = null; ServletOutputStream servletOS = null; ByteArrayOutputStream ostream = null; //添加表格 try { servletOS = response.getOutputStream(); ostream = new ByteArrayOutputStream(); document = new XWPFDocument(POIXMLDocument.openPackage(file));// 生成word文档并读取模板 /* ***********************比赛报名表基本信息******************************begin */ Iterator<XWPFTable> it = document.getTablesIterator(); //表格内容替换添加 while(it.hasNext()){ XWPFTable table = it.next(); int rcount = table.getNumberOfRows(); for(int i =0 ;i < rcount;i++){ XWPFTableRow row = table.getRow(i); List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells){ for(Entry<String, Object> e : map.entrySet()){ if (cell.getText().equals(e.getKey())){ //删除原来内容 cell.removeParagraph(0); //写入新内容 cell.setText((String) e.getValue()); } } } } } //换行 XWPFParagraph paragraph2 = document.createParagraph(); XWPFRun paragraphRun2 = paragraph2.createRun(); paragraphRun2.setText("\r"); /* ***********************比赛报名表基本信息******************************end */ //添加标题 XWPFParagraph titleParagraph2 = document.createParagraph(); //设置段落靠左 titleParagraph2.setAlignment(ParagraphAlignment.LEFT); XWPFRun titleParagraphRun2 = titleParagraph2.createRun(); titleParagraphRun2.setText("附: 作品清单"); titleParagraphRun2.setColor("000000"); titleParagraphRun2.setFontSize(10); //附表格 XWPFTable ComTable = document.createTable(); //列宽自动分割 /*CTTblWidth comTableWidth = ComTable.getCTTbl().addNewTblPr().addNewTblW(); comTableWidth.setType(STTblWidth.DXA); comTableWidth.setW(BigInteger.valueOf(9072));*/ //表格第一行 XWPFTableRow comTableRowOne = ComTable.getRow(0); // 表格标题内容的填充 // 因为document.createTable() 创建表格后默认是一行一列,所以第一行第一列是直接comTableRowOne.getCell(0).setText("序号"); 赋值的。 // 第一行的其他列需要创建后才能赋值 comTableRowOne.addNewTableCell().setText("作品类型"); comTableRowOne.getCell(0).setText("序号"); comTableRowOne.addNewTableCell().setText("作品类型"); comTableRowOne.addNewTableCell().setText("作品名称"); comTableRowOne.addNewTableCell().setText("作品署名"); // 表格标题剧中+单元格大小设置 setCellWitchAndAlign(comTableRowOne.getCell(0),"700",STVerticalJc.CENTER,STJc.CENTER); setCellWitchAndAlign(comTableRowOne.getCell(1),"1500",STVerticalJc.CENTER,STJc.CENTER); setCellWitchAndAlign(comTableRowOne.getCell(2),"3200",STVerticalJc.CENTER,STJc.CENTER); setCellWitchAndAlign(comTableRowOne.getCell(3),"3200",STVerticalJc.CENTER,STJc.CENTER); XWPFTableRow comTableRow = null; // 生成表格内容 // 根据上面的表格标题 确定列数,所以下面创建的是行数。 // comTableRow.getCell(1).setText(user.getName()); 确定第几列 然后创建赋值 // 注意:我这边是列数较少固定的,如果列数不固定可循环创建上面的列数 for (int i=0;i < list.size();i++) { comTableRow = ComTable.createRow(); // 表格内容的填充 DisUser user = list.get(i); comTableRow.getCell(0).setText(((Integer)(i+1)).toString()); comTableRow.getCell(1).setText(user.getName()); comTableRow.getCell(2).setText(user.getCname()); comTableRow.getCell(3).setText(user.getCnreason()); // 表格内容剧中+单元格大小设置 setCellWitchAndAlign(comTableRow.getCell(0),"700",STVerticalJc.CENTER,STJc.CENTER); setCellWitchAndAlign(comTableRow.getCell(1),"1500",STVerticalJc.CENTER,STJc.CENTER); setCellWitchAndAlign(comTableRow.getCell(2),"3200",STVerticalJc.CENTER,STJc.LEFT); setCellWitchAndAlign(comTableRow.getCell(3),"3200",STVerticalJc.CENTER,STJc.LEFT); } //换行 XWPFParagraph paragraph3 = document.createParagraph(); XWPFRun paragraphRun3 = paragraph3.createRun(); paragraphRun3.setText("\r"); //添加标题 XWPFParagraph titleParagraph3 = document.createParagraph(); //设置段落靠左 titleParagraph3.setAlignment(ParagraphAlignment.RIGHT); XWPFRun titleParagraphRun3 = titleParagraph3.createRun(); titleParagraphRun3.setText("单位(盖 章)"+"\t"); titleParagraphRun3.setColor("000000"); titleParagraphRun3.setFontSize(10); document.createParagraph();// 换行 //添加标题 XWPFParagraph titleParagraph4 = document.createParagraph(); //设置段落靠左 titleParagraph4.setAlignment(ParagraphAlignment.RIGHT); XWPFRun titleParagraphRun4 = titleParagraph4.createRun(); titleParagraphRun4.setText("年 月 日"); titleParagraphRun4.setColor("000000"); titleParagraphRun4.setFontSize(10); //输出word内容文件流,提供下载 response.setContentType("application/x-msdownload"); String name = java.net.URLEncoder.encode("生成word.docx", "UTF8"); name = new String((name).getBytes("UTF-8"), "ISO-8859-1"); response.addHeader("Content-Disposition", "attachment; filename*=utf-8'zh_cn'"+name); document.write(ostream); servletOS.write(ostream.toByteArray()); } catch (Exception e1) { e1.printStackTrace(); }finally{ try{ if(ostream != null){ ostream.close(); } if(servletOS != null){ servletOS.close(); } } catch(IOException e){ e.printStackTrace(); } } }
* 其中的list 是生成表格填充的内容,map是模板word表格内容替换的集合,file是模板word表格的地址
3. controller 控制台的部分
/** * 功能描述:动态替换docx 表格内容 并下载 * @param id * @return * @Date 2019年3月8日 */ @RequestMapping(value = "/shengWord", produces = "application/json;charset=UTF-8") @ResponseBody public void shengWord(HttpServletRequest request, HttpServletResponse response){ String file = "D:\\报名表模板.docx";// 文件路径 Map<String, Object> map = new HashMap<String, Object>();// 动态上传数据 map.put("$(“name”)", "张三"); map.put("$(“sex”)", "男"); map.put("$(“age”)", "24岁"); map.put("$(“addess”)", "北京瑞德凯勒科技有限公司"); map.put("$(“type”)", "内蒙古医科大学附属医院"); map.put("$(“zhi”)", "教师"); map.put("$(“xing”)", "人事管理员"); map.put("$(“dizhi”)", "北京市朝阳区潘家园弘善家园415号楼北京人卫设电子音像出版社"); map.put("$(“phone”)", "0471-060605"); map.put("$(“telephone”)", "12345678909"); map.put("$(“email”)", "355365476@qq.com"); map.put("$(“chargeName”)", "记叙文一般可分为记人、叙事、写景、咏物等几种。记人,要表现人物的思想感情和性格;叙事,要写出事件所蕴涵的意义,这些意义可以是政治思想方面的,也可以表达某种哲理,或某种情趣;写景,要通过景物描写表现出个人某种感情或深刻的感悟;咏物,或透露出世间人生的某种乐趣,或托物言志,表现对社会上某种人某种现象的情感。因此,我们写记叙文总会有一定的目的,总要表达一定的思想和感情,实际上就是我们平常所讲的“文章的主题”,主题是文章的灵魂,它像一根红线贯串于文章的始终。没有明确主题的记叙文,只能是一篇流水帐,所以要写好记叙文,就必须要明确“为何叙”,即主题要明确。要主题明确可注意三点:第一,要有积极意义,即确定的主题思想感情必须是健康的,有意义的。"); map.put("$(“jian”)", "先说文章的结构,即所要写的这篇记叙文用什么结构来表现出来。它包括这篇文章分几层写,哪些材料先写,哪些后写,哪些详写,哪些略写,如何安排过渡,于何处伏笔,在哪里呼应,如何开头,怎样结尾,等等。从整篇记叙文来看、常见的结构有顺序、倒叙、插叙。顺叙,就是按照事情发生、发展的,过程进行叙述。包括以下几种情况:其一,按时间的推移来叙述;其二,按事情的发展来叙述;其三,按认识发展的过程来叙述;其四,按作者的行踪来叙述。倒叙,就是把事情的结局,或某个突出的精彩片断提到前边写,然后再按事件发生、发展的顺序叙述。倒叙的运用有四种类型:一种是把事件的结局提前,造成悬念,然后再按时间顺序叙述事情的发生与发展;一种是把事件中最精彩的或最紧张的片断截取下来,写在前面,震动和吸引读者,然后按时间的顺序叙述事件的起因、发展与结局;一种是先写眼前的事物,由此及彼,引起回忆,再追叙往事,形成倒叙,一种是先写当前情况,再回忆过去的情况,以形成鲜明的对比,给读者留下深刻印象。插叙,是在文章的叙述中,暂时中断叙述的线索,插入一些与中心事件有关的内容,然后再继续进行原来的叙述。插叙的具体内容和形式有种种不同:有的是追叙,对过去事件片断进行回忆,有的是补叙,对有关人和事作必要的补充、解释;有的是逆叙,对有关内容由近及远、由今及古地回溯,灵活多样的插叙,可以使主题开掘得更深刻,情节展开得更充分,内容表现得更充实,人物形象刻画得更丰满,避免了平辅直叙。"); map.put("$(“yijian”)", "无"); List<DisUser> list = new ArrayList<DisUser>(); DisUser user1 = new DisUser(); user1.setUserid(1l); user1.setName("张三"); user1.setCname("文档"); user1.setCnreason("fjsdn"); DisUser user2 = new DisUser(); user2.setUserid(2l); user2.setName("赵四"); user2.setCname("文档"); user2.setCnreason("放手发动"); DisUser user3 = new DisUser(); user3.setUserid(3l); user3.setName("吕五"); user3.setCname("文档"); user3.setCnreason("居然敢"); list.add(user1); list.add(user2); list.add(user3); ResolutionWord.DownloadWord(response,list,map,file); }
4. 运行结果
5. 第一个表格是 按照模板替换的内容 第二个表格是纯 java 生成的表格
* :注意:代码只适合 使用 poi 操作word 2007 以上版本(docx) 不适合 word 2003(doc)