解决 apache poi 转换 word(docx) 文件到 html 文件表格没边框的问题
一、起因
这几天在做电子签章问题,要通过替换docx文件中的占位符生成包含业务数据的合同数据,再转换成html文件,转换成pdf文件。遇到的问题是:通过apache poi转换docx到html时,原生的表格文件可以正常显示,但是我通过代码生成的表格只有数据,而不展示边框。
二、问题分析
google了一下发现有人碰到过类似问题,但是没有找到解决方法。现成的没有只能自己研究。
贴上简单的填充表格内容的java代码
private void replaceTable(XWPFDocument xdoc, List<List<String>> lines, int pos) {
if (CollectionUtils.isEmpty(lines)) {
List<String> th = new ArrayList<String>();
th.add("姓名");
th.add("身份证");
th.add("金额");
lines.add(th);
}
XWPFTable replace = xdoc.createTable(lines.size(), lines.get(0).size());
CTTbl cttbl = replace.getCTTbl();
cttbl.addNewTblPr().addNewTblW().setW(BigInteger.valueOf(8800));
CTTblGrid cg = cttbl.addNewTblGrid();
cg.addNewGridCol().setW(BigInteger.valueOf(2500));
cg.addNewGridCol().setW(BigInteger.valueOf(3800));
cg.addNewGridCol().setW(BigInteger.valueOf(2500));
if (CollectionUtils.isNotEmpty(lines)) {
for (int i = 0; i < lines.size(); i++) {
List<String> line = lines.get(i);
for (int j = 0; j < line.size(); j++) {
XWPFTableCell cell = replace.getRow(i).getCell(j);
cell.setText(line.get(j));
cell.getCTTc().addNewTcPr().addNewTcBorders().addNewTop();
}
}
}
xdoc.setTable(pos, replace);
xdoc.removeBodyElement(xdoc.getPosOfTable(replace));
}
逻辑很简单,通过生成一个新的表格来替换原来的表格。
然后看一下可正常显示的表格的doc xml代码
<xml-fragment xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<w:tblPr>
<w:tblW w:w="0" w:type="auto"/>
<w:tblBorders>
<w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/>
<w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="1984"/>
<w:gridCol w:w="2694"/>
<w:gridCol w:w="2885"/>
</w:tblGrid>
<w:tr w:rsidR="00D347DE" w:rsidRPr="00A709A0" w14:paraId="47BBA15B" w14:textId="77777777" w:rsidTr="00146A0B">
<w:tc>
<w:tcPr>
<w:tcW w:w="1984" w:type="dxa"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t>${表格匹配信息}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2694" w:type="dxa"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2885" w:type="dxa"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"></w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</xml-fragment>
然后看一下我们自己生成的替换表格
<xml-fragment xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<w:tblGrid>
<w:gridCol w:w="2500"/>
<w:gridCol w:w="3800"/>
<w:gridCol w:w="2500"/>
</w:tblGrid>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>姓名</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>身份证</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>金额</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>小七</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>12345</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>888888.00</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>合计笔数:1</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t/>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>合计:888888.00</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</xml-fragment>
可以很明显的看出,我们自己生成的表格在属性和元素数量上都比正常表格少了很多。
三、解决方法
好在apache的代码设计结构清晰,十分优美,弥补了资料较少的不足。刚开始我是想参考正常表格手动补全缺少的内容,后来发现这样的工作量大不说,补出来的东西多多少少还是和正常结构有差,还是没法正常显示,后来发现了XMLObject这个类有一个set方法,可以通过这个方法直接复制正常表格的内容。
最终的代码就是这样
private void replaceTable(XWPFDocument xdoc, List<List<String>> lines, int pos, XWPFTable table) throws XmlException {
if (CollectionUtils.isEmpty(lines)) {
List<String> th = new ArrayList<String>();
th.add("姓名");
th.add("身份证");
th.add("金额");
if (lines == null) {
lines = new ArrayList<List<String>>();
}
lines.add(th);
}
XWPFTable replace = xdoc.createTable(lines.size(), lines.get(0).size());
CTTbl cttbl = replace.getCTTbl();
cttbl.getTblPr().set(table.getCTTbl().getTblPr());
CTTblGrid cg = cttbl.addNewTblGrid();
cg.addNewGridCol().setW(BigInteger.valueOf(2500));
cg.addNewGridCol().setW(BigInteger.valueOf(3800));
cg.addNewGridCol().setW(BigInteger.valueOf(2500));
CTRow originalRow = table.getCTTbl().getTrArray(0);
if (CollectionUtils.isNotEmpty(lines)) {
for (int i = 0; i < lines.size(); i++) {
List<String> line = lines.get(i);
CTRow ctRow = cttbl.getTrArray(i);
ctRow.set(originalRow);
for (int j = 0; j < line.size(); j++) {
CTTc ctTc = ctRow.getTcArray(j);
ctTc.removeP(0);
CTText text = ctTc.addNewP().addNewR().addNewT();
text.setStringValue(line.get(j));
}
}
}
xdoc.setTable(pos, replace);
xdoc.removeBodyElement(xdoc.getPosOfTable(replace));
}
解决 apache poi 转换 word(docx) 文件到 html 文件表格没边框的问题的更多相关文章
- POI读写Word docx文件
使用POI读写word docx文件 目录 1 读docx文件 1.1 通过XWPFWordExtractor读 1.2 通过XWPFDocument读 2 写docx ...
- Java利用poi生成word(包含插入图片,动态表格,行合并)
转(小改): Java利用poi生成word(包含插入图片,动态表格,行合并) 2018年12月20日 09:06:51 wjw_11093010 阅读数:70 Java利用poi生成word(包含插 ...
- 使用POI读写word docx文件
目录 1 读docx文件 1.1 通过XWPFWordExtractor读 1.2 通过XWPFDocument读 2 写docx文件 2.1 直接通过XWPF ...
- POI读word docx 07 文件的两种方法
POI在读写word docx文件时是通过xwpf模块来进行的,其核心是XWPFDocument.一个XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档. ...
- 使用java Apache poi 根据word模板生成word报表
项目开发过程中,客户提出一堆导出报表的需求,需要导出word格式,页眉还需要加上客户公司的logo,试了几种方案,最后选择了用 Apache poi 加上自定义标签的方式实现. 目前功能还比较简单,一 ...
- POI实现word文档转html文件
POI word文件转html package com.feiruo.officeConvert; import java.io.BufferedWriter; import java.io.File ...
- Apache Poi 操作word,替换字符保留样式问题,runs段落混乱问题。
关于这个问题也是刚好遇到,一通搜索也没有找到类似的或者是有效的方法.下面介绍一下. 首先apache poi的引入 <dependency> <groupId>org.apac ...
- 批量转换word文档到pdf文件
最近在整理每周的工作记录.因为每周的工作记录大都是单独的word文件,有时候忘记了也不容易找出来,一个个打开查找太费劲,因此想着把这些文件通过word2016的另存为功能转换为pdf,然后永Acrob ...
- 使用POI转换word doc文件
目录 1 转换为Html文件 2 转换为Xml文件 3 转换为Text文件 在POI中还存在有针对于word doc文件进行格式转换的功能.我们可以将word的内容 ...
随机推荐
- Masonry 在swift下的使用
Masonry在oc下使用很方便,但是在swift下,由于oc方法和property都可以使用.fuc的语法,swift下只有属性可以使用.property的语法,方法只能写成.func().因此在s ...
- vue 基础-->进阶 教程(1): 基础(数据绑定)
第一章 建议学习时间4小时 课程共3章 前面的nodejs教程并没有停止更新,因为node项目需要用vue来实现界面部分,所以先插入一个vue教程,以免不会的同学不能很好的完成项目. 本教程,将从零 ...
- js判断密码强度是否符合
/** 判断密码强度是否符合 */ function check_passwd_intensity(password) { value = $.trim(password); if( value.le ...
- 错误Fatal error: Call to undefined function mb_strlen()的解决办法
其实这个就是没有开启php_mbstring模块.Windows下只需要修改安装目录下的php.ini文件把extension=php_mbstring.dll前面的“#”号注释符去掉保存后重启Apa ...
- 开始JAVA编程的敲门砖——JAVA开发环境搭建
从头开始的java编程--JAVA开发环境搭建 一.什么是java的开发环境? 顾名思义java的开发环境是提供并保证整个java程序开发运行的必要的环境,搭建java开发环境是开始java编程的敲门 ...
- ajax同步请求JS代码
ajax同步请求JS代码 <script type="text/javascript"> var txt = document.getElementById('txt' ...
- MyBatis-sql映射文件
Sql映射文件 MyBatis真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL映射的XML文件是相当的简单.当然如果你将它们和对等功能的JDBC代码来比较,你会发现映射文件节省了 ...
- Linux系统安全配置基线
一:共享账号检查 配置名称:用户账号分配检查,避免共享账号存在 配置要求:1.系统需按照实际用户分配账号: 2.避免不同用户间共享账号,避免用户账号和服务器间通信使用的账号共享. 操作指南:参考配置操 ...
- ecshop中smarty比较操作符(eq,ne,neq)含义
eq相等, ne.neq不相等, gt大于, lt小于, gte.ge大于等于, lte.le 小于等于, not非, mod求模. is [not] div by是否能被某数整除, is [not ...
- [图形学] Chp17 OpenGL光照和表面绘制函数
这章学了基本光照模型,物体的显示受到以下效果影响:全局环境光,点光源(环境光漫反射分量,点光源漫反射分量,点光源镜面反射分量),材质系数(漫反射系数,镜面反射系数),自身发光,雾气效果等.其中点光源有 ...