使用poi操作word文档实现套打功能

本文目的是为了分享一个实现套打功能,但是不同于简单的word的文本替换而是采用poi对word的文本框就行操作实现的功能:

  • poi中各种jar的说明
  • 套打的实现思路
  • poi操作word文本框中的数据
  • *代码实现

POI各个jar的说明以及本文使用jar包

这里引用一个表格,只要看一下这个表格就知道自己需要哪个jar包了,本文中需要引入的是如下几个jar包(maven项目导入方式)。

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.11</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.11</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.1</version></dependency><!-- word poi--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.9</version></dependency>
项目 价格
Computer $1600
Phone $12
Pipe $1

可以使用冒号来定义对齐方式:

Component Application type Maven artifactId Notes
POIFS OLE2 Filesystem poi Required to work with OLE2 / POIFS based files
HPSF OLE2 Property Sets poi
HSSF Excel XLS poi For HSSF only, if common SS is needed see below
HSLF PowerPoint PPT poi-scratchpad
HWPF Word DOC poi-scratchpad
HDGF Visio VSD poi-scratchpad
HPBF Publisher PUB poi-scratchpad
HSMF Outlook MSG poi-scratchpad
OpenXML4J OOXML poi-ooxml plus one of
poi-ooxml-schemas ooxml-schemas Only one schemas jar is needed, see below for differences
XSSF Excel XLSX poi-ooxml
XSLF PowerPoint PPTX poi-ooxml
XWPF Word DOCX poi-ooxml
Common SS Excel XLS and XLSX poi-ooxml WorkbookFactory and friends all require poi-ooxml, not just core poi

套打实现思路

既然是套打,那么打印的文本一定有一个固定的格式,如果通过前端的html的css去控制,那么有个问题就是可能出现预留长度不够那么打印出来的排版就会出现问题,如果使用word文档的空格和tab去实现格式,然后用打印的文本去替换模板文件中的内容也同样会出现css一样的问题,那现在有一个方法就是将需要打印的内容放到word文档的文本框中,不管预留的长度是否足够,都不会出现整个布局乱套的问题,因为word文档中的文本框的布局是固定的。有可能有人会问,这么简单不就直接使用replaceText就可以替换了么?那就很可能是因为你小看了word的文本框。
这篇博客讲解了poi操作word,我认为讲的已经很详细了(但是没有对文本框的操作),再加上本文,那么你就掌握了poi对word操作的大部分技能。

POI操作word文本框

word文档其实也是一种特殊的xml文件,有其他的方法操作word文档的时候是先要将word转换成xml文档,然后在对xml文档进行操作。同样的,poi操作word文档内部实现其实也是讲word文档转换成了xml文档(只不过该步骤不需要我们手动去完成,poi帮助我们自动完成了)。既然要解析xml,所以本文中的代码就需要用到poi的解析xml的jar包了(ooxml-schemas)。既然poi是对xml文件操作,那文本框也一定是解析成了xml的一部分,我们只要找到文本框对应的xml标签,然后找到文本在使用替换文本的方式,是不是就可以实现文本框的套打功能了。那如何才能找到文本框的标签呢,那就是游标,poi操作word文档的游标便可实现。

代码如下 

File file = new File(filePath + File.separator + fileName);InputStream is = new FileInputStream(file);XWPFDocument doc = new XWPFDocument(is);List<XWPFParagraph> paragraphList = doc.getParagraphs();String startTime = home.getIntBd();String endTime = home.getIntDl();String apprTime = home.getApprDt();//开始日期Calendar calendar = Calendar.getInstance();Date bdDt = DateUtil.string2Date(startTime, DateUtil.FORMAT0);calendar.setTime(bdDt);String y1 = String.valueOf(calendar.get(Calendar.YEAR));String m1 = String.valueOf(calendar.get(Calendar.MONTH));String d1 = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));//结束日期Date dlDt = DateUtil.string2Date(endTime, DateUtil.FORMAT0);calendar.setTime(dlDt);String y2 = String.valueOf(calendar.get(Calendar.YEAR));String m2 = String.valueOf(calendar.get(Calendar.MONTH));String d2 = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));//提交日期Date apprDt = DateUtil.string2Date(apprTime, DateUtil.FORMAT0);calendar.setTime(apprDt);String y3 = String.valueOf(calendar.get(Calendar.YEAR));String m3 = String.valueOf(calendar.get(Calendar.MONTH));String d3 = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));String sb = “测试数据”;Field[] fields = home.getClass().getDeclaredFields();for (XWPFParagraph paragraph : paragraphList) {CTP ctp = paragraph.getCTP();List<CTR> object = ctp.getRList();for (int i = 0; i < object.size(); i++) {XmlObject xo = object.get(i);//在此处数据xo的字符串文本(xml文本),借助xml格式化工具格式化xml文本,然后通过标签移动游标找到需要替换的值XmlCursor cursor = xo.newCursor();if (cursor.isStart() || cursor.isAttr() || cursor.isProcinst()) {cursor.toChild(1);cursor.toChild(0);cursor.toChild(0);cursor.toChild(0);cursor.toChild(8);cursor.toChild(0);cursor.toChild(0);cursor.toChild(2);cursor.toChild(0);cursor.toChild(0);cursor.toChild(1);cursor.toChild(1);String textValue = cursor.getTextValue();switch (textValue) {case "y1":cursor.setTextValue(y1);break;case "m1":cursor.setTextValue(m1);break;case "d1":cursor.setTextValue(d1);break;case "y2":cursor.setTextValue(y2);break;case "m2":cursor.setTextValue(m2);break;case "d2":cursor.setTextValue(d2);break;case "y3":cursor.setTextValue(y3);break;case "m3":cursor.setTextValue(m3);break;case "d3":cursor.setTextValue(d3);break;case "abb":cursor.setTextValue(abb);break;case "nb":cursor.setTextValue(nb);break;case "no":cursor.setTextValue(no);break;}for (Field field : fields) {field.setAccessible(true);String name = field.getName();Object ov = field.get(home);String value = "";if (null != ov) {value = ov.toString();}if (null != textValue && textValue.equalsIgnoreCase(name)) {cursor.setTextValue(value);break;}}}}}response.setContentType("multipart/form-data");response.setHeader("Content-Disposition", "attachment;fileName=" + home.getWrpNm() + "-" + fileName);OutputStream os = response.getOutputStream();doc.write(os);is.close();os.close();
 <w:r><w:rPr><w:noProof/></w:rPr><mc:AlternateContent><mc:Choice Requires="wps"><w:drawing><wp:anchor distT="0" distB="0" distL="114300" distR="114300" simplePos="0" relativeHeight="251680004" behindDoc="0" locked="0" layoutInCell="1" allowOverlap="1" wp14:anchorId="79BA2A69" wp14:editId="75F9FABF"><wp:simplePos x="0" y="0"/><wp:positionH relativeFrom="column"><wp:posOffset>4561840</wp:posOffset></wp:positionH><wp:positionV relativeFrom="page"><wp:posOffset>2543175</wp:posOffset></wp:positionV><wp:extent cx="752475" cy="396240"/><wp:effectExtent l="0" t="0" r="0" b="3810"/><wp:wrapNone/><wp:docPr id="13" name="abb"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"></a:graphicFrameLocks></wp:cNvGraphicFramePr><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"><wps:wsp><wps:cNvSpPr><a:spLocks noChangeArrowheads="1"/></wps:cNvSpPr><wps:spPr bwMode="auto"><a:xfrm><a:off x="0" y="0"/><a:ext cx="752475" cy="396240"/></a:xfrm><a:prstGeom prst="flowChartProcess"><a:avLst/></a:prstGeom><a:noFill/><a:ln><a:noFill/></a:ln></wps:spPr><wps:txbx><w:txbxContent><w:p w:rsidR="003A7D59" w:rsidRPr="008A7CBF" w:rsidRDefault="00ED4204" w:rsidP="00987190"><w:pPr><w:jc w:val="center"/><w:rPr><w:rFonts w:ascii="宋体" w:hAnsi="宋体"/><w:szCs w:val="21"/></w:rPr></w:pPr><w:r w:rsidRPr="008A7CBF"><w:rPr><w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:hint="eastAsia"/><w:szCs w:val="21"/></w:rPr><w:t>abb</w:t></w:r></w:p></w:txbxContent>

重点:游标的移动规则,在打印出xml之后,需要将xml的文本copy出来借助xml格式化工具,格式化之后便可以分析游标的移动步骤,第一层是0,然后依次进入子标签。例如:有这么一段xml

 <w:r w:rsidRPr="008A7CBF"><w:rPr><w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:hint="eastAsia"/><w:szCs w:val="21"/></w:rPr><w:t>abb</w:t>
</w:r>

现在我需要替换abb,那么游标移动的顺序则是
cursor.toChild(1);因为标签“w:rPr”的索引是0,“w:t”的索引则是1.在游标的移动分析中才是对文本框操作的重点,需要自己按照上面的规则测试分析。祝您好运。

使用poi操作word文档实现套打功能相关推荐

  1. poi操作word文档总结

    POI分段落生成纯Word动态模板并导入数据 导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过 freemarker去替换变量. 但是怎么导入word数据. ...

  2. POI操作Word文档工具

    POI操作Word文档工具 1.POI简单介绍 2.POI操作Word文档基本方法 3.POI操作Word文档基本方法应用 4.POI操作Word文档工具类 1.POI简单介绍 POIFS(可疑混淆执 ...

  3. Poi 操作Word文档设置页边距 解决CTPageMar类找不到

    Poi操作Word文档设置页边距 CTPageMar类找不到 已解决 在百度上搜了一顿,找到了相关的解决方案,但是缺失了一个类,在百度怎么也找不到! 给大家一个参考数据 1厘米≈567 CTSectP ...

  4. POI操作word文档-添加上标下标

    背景: 接了新需求,前端提供一个大概的word模板,包含通用信息,用户在前端填写可修改内容至模板完善,然后将整个数据传递给后端进行保存,后端提供导出word的功能. 数据中包含这种类型,由于前端输出框 ...

  5. POI操作word文档,生成书签

    近期做动态的word文档生成, 需要在指定XWPFRun生成书签的功能,有两种情况: 创建新word文档时候,直接在createRun前后调用生成书签的方法 XWPFRun oldRun = runs ...

  6. poi处理word内容的公式_利用poi操作word文档

    关键字:POI JAVA 批注 总页数 总字符数 一:认识POI Apache POI是一个开源的利用Java读写Excel.WORD等微软OLE2组件文档的项目.最新的3.5版本有很多改进,加入了对 ...

  7. 利用poi操作word文档(针对docx格式)

    一:认识POI  Apache POI是一个开源的利用Java读写Excel.WORD等微软OLE2组件文档的项目.最新的3.5版本有很多改进,加入了对采用OOXML格式的Office 2007支持, ...

  8. poi操作word文档(替换,插入图片)

    前段时间项目上要用到一个替换word中的字符以及插入图片并导出的功能,google了一番发现别人的代码跑起来多多少少有些问题,所以就自己照着poi的api写了一个工具类,在此记录下来,如果有需要的朋友 ...

  9. java用poi导出word,Java使用POI导出Word文档的操作教程,poiword

    Java使用POI导出Word文档的操作教程,poiword 一.主要pom依赖 org.apache.poi poi-ooxml 3.16 二.需要导出word模板 三.相关导出代码 package ...

最新文章

  1. 网站优化中导致关键词排名不稳定的原因有哪些?
  2. Quartz-JobListener解读
  3. Android第三十三天
  4. Nginx 模块的使用
  5. mysql 数据库表锁死_mysql 数据库表被锁住了_Mysql数据库表锁死如何处理?
  6. opencv之图像边界填充-- copyMakeBorder
  7. iframe调用父页面方法_5.1 vue中子组件调用父组件的方法,务必理解自定义事件的重要性...
  8. 超小股票行情查看软件
  9. 香港公司章程中英文样本
  10. D触发器的工作原理以及Verilog代码(一/二)
  11. 仿真软件proteus构建LCD1602四线驱动实验
  12. 《掌控习惯》读书笔记
  13. 2018计算机三级网络技术百度云,百度网盘2018旧版
  14. 阿里巴巴国际站九月大促直播准备工作及流程
  15. 一张我为写植物大战僵尸外.挂而画的草稿图...
  16. activity启动流程或工作流程
  17. 我带你去哪里 VIII
  18. 让人春分日 哈工科教110132.平面分割
  19. svn客户端在服务器创建项目,win7下安装svn服务器端及客户端详细步骤
  20. 基于Pytorch实现猫狗分类

热门文章

  1. Atitit 算法之道 attilax著 1. 编码算法 3 1.1. Base64 htmlencode urlencode 3 2. Ui方面的算法 3 2.1. 软键盘算法 计算软键盘上下
  2. 自定义POI的excel工具类-xls-xlsx
  3. MOVS,LODS,CMPS,SCAS,STOS
  4. [软件人生]IT168年会的一点感受——简评专题的内容和说实话的流氓
  5. java lang IllegalArgumentException Invalid character found
  6. 开发工具篇第三讲:Maven从入门到实战
  7. android酷炫转圈动画,android常用旋转线条加载动画
  8. python get score gain_机器学习的特征重要性究竟是怎么算的
  9. OPENCV例子\samples\cpp\tutorial_code\ImgProc\changing_contrast_brigh的代码分析
  10. python数据分析