Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 1215|回复: 0

解决 apache poi 转换 word(docx) 文件到 html 文件表格没边框的问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-14 10:55:16 | 显示全部楼层 |阅读模式

    一、起因
      这几天在做电子签章问题,要通过替换docx文件中的占位符生成包含业务数据的合同数据,再转换成html文件,转换成pdf文件。遇到的问题是:通过apache poi转换docx到html时,原生的表格文件可以正常显示,但是我通过代码生成的表格只有数据,而不展示边框。

     

    二、问题分析
      google了一下发现有人碰到过类似问题,但是没有找到解决方法。现成的没有只能自己研究。

      贴上简单的填充表格内容的java代码

     1 private void replaceTable(XWPFDocument xdoc, List<List<String>> lines, int pos) {
     2         if (CollectionUtils.isEmpty(lines)) {
     3             List<String> th = new ArrayList<String>();
     4             th.add("姓名");
     5             th.add("身份证");
     6             th.add("金额");
     7             lines.add(th);
     8         }
     9         XWPFTable replace = xdoc.createTable(lines.size(), lines.get(0).size());
    10         CTTbl cttbl = replace.getCTTbl();
    11         cttbl.addNewTblPr().addNewTblW().setW(BigInteger.valueOf(8800));
    12         CTTblGrid cg = cttbl.addNewTblGrid();
    13         cg.addNewGridCol().setW(BigInteger.valueOf(2500));
    14         cg.addNewGridCol().setW(BigInteger.valueOf(3800));
    15         cg.addNewGridCol().setW(BigInteger.valueOf(2500));
    16         if (CollectionUtils.isNotEmpty(lines)) {
    17             for (int i = 0; i < lines.size(); i++) {
    18                 List<String> line = lines.get(i);
    19                 for (int j = 0; j < line.size(); j++) {
    20                     XWPFTableCell cell = replace.getRow(i).getCell(j);
    21                     cell.setText(line.get(j));
    22                     cell.getCTTc().addNewTcPr().addNewTcBorders().addNewTop();
    23                 }
    24             }
    25         }
    26         xdoc.setTable(pos, replace);
    27         xdoc.removeBodyElement(xdoc.getPosOfTable(replace));
    28     }

      逻辑很简单,通过生成一个新的表格来替换原来的表格。


      然后看一下可正常显示的表格的doc xml代码

     1 <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">
     2   <w:tblPr>
     3     <w:tblW w:w="0" w:type="auto"/>
     4     <w:tblBorders>
     5       <w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
     6       <w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>
     7       <w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
     8       <w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
     9       <w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/>
    10       <w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/>
    11     </w:tblBorders>
    12     <w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/>
    13   </w:tblPr>
    14   <w:tblGrid>
    15     <w:gridCol w:w="1984"/>
    16     <w:gridCol w:w="2694"/>
    17     <w:gridCol w:w="2885"/>
    18   </w:tblGrid>
    19   <w:tr w:rsidR="00D347DE" w:rsidRPr="00A709A0" w14:paraId="47BBA15B" w14:textId="77777777" w:rsidTr="00146A0B">
    20     <w:tc>
    21       <w:tcPr>
    22         <w:tcW w:w="1984" w:type="dxa"/>
    23       </w:tcPr>
    24       <w:p>
    25         <w:pPr>
    26           <w:jc w:val="center"/>
    27         </w:pPr>
    28         <w:r>
    29           <w:t>${表格匹配信息}</w:t>
    30         </w:r>
    31       </w:p>
    32     </w:tc>
    33     <w:tc>
    34       <w:tcPr>
    35         <w:tcW w:w="2694" w:type="dxa"/>
    36       </w:tcPr>
    37       <w:p>
    38         <w:pPr>
    39           <w:jc w:val="center"/>
    40         </w:pPr>
    41         <w:r>
    42           <w:t xml:space="preserve"></w:t>
    43         </w:r>
    44       </w:p>
    45     </w:tc>
    46     <w:tc>
    47       <w:tcPr>
    48         <w:tcW w:w="2885" w:type="dxa"/>
    49       </w:tcPr>
    50       <w:p>
    51         <w:pPr>
    52           <w:jc w:val="center"/>
    53         </w:pPr>
    54         <w:r>
    55           <w:t xml:space="preserve"></w:t>
    56         </w:r>
    57       </w:p>
    58     </w:tc>
    59   </w:tr>
    60 </xml-fragment>

     

      然后看一下我们自己生成的替换表格

     1 <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">
     2   <w:tblGrid>
     3     <w:gridCol w:w="2500"/>
     4     <w:gridCol w:w="3800"/>
     5     <w:gridCol w:w="2500"/>
     6   </w:tblGrid>
     7   <w:tr>
     8     <w:tc>
     9       <w:p>
    10         <w:r>
    11           <w:t>姓名</w:t>
    12         </w:r>
    13       </w:p>
    14     </w:tc>
    15     <w:tc>
    16       <w:p>
    17         <w:r>
    18           <w:t>身份证</w:t>
    19         </w:r>
    20       </w:p>
    21     </w:tc>
    22     <w:tc>
    23       <w:p>
    24         <w:r>
    25           <w:t>金额</w:t>
    26         </w:r>
    27       </w:p>
    28     </w:tc>
    29   </w:tr>
    30   <w:tr>
    31     <w:tc>
    32       <w:p>
    33         <w:r>
    34           <w:t>小七</w:t>
    35         </w:r>
    36       </w:p>
    37     </w:tc>
    38     <w:tc>
    39       <w:p>
    40         <w:r>
    41           <w:t>12345</w:t>
    42         </w:r>
    43       </w:p>
    44     </w:tc>
    45     <w:tc>
    46       <w:p>
    47         <w:r>
    48           <w:t>888888.00</w:t>
    49         </w:r>
    50       </w:p>
    51     </w:tc>
    52   </w:tr>
    53   <w:tr>
    54     <w:tc>
    55       <w:p>
    56         <w:r>
    57           <w:t>合计笔数:1</w:t>
    58         </w:r>
    59       </w:p>
    60     </w:tc>
    61     <w:tc>
    62       <w:p>
    63         <w:r>
    64           <w:t/>
    65         </w:r>
    66       </w:p>
    67     </w:tc>
    68     <w:tc>
    69       <w:p>
    70         <w:r>
    71           <w:t>合计:888888.00</w:t>
    72         </w:r>
    73       </w:p>
    74     </w:tc>
    75   </w:tr>
    76 </xml-fragment>

     

      可以很明显的看出,我们自己生成的表格在属性和元素数量上都比正常表格少了很多。

     

    三、解决方法

      好在apache的代码设计结构清晰,十分优美,弥补了资料较少的不足。刚开始我是想参考正常表格手动补全缺少的内容,后来发现这样的工作量大不说,补出来的东西多多少少还是和正常结构有差,还是没法正常显示,后来发现了XMLObject这个类有一个set方法,可以通过这个方法直接复制正常表格的内容。

      最终的代码就是这样

     1     private void replaceTable(XWPFDocument xdoc, List<List<String>> lines, int pos, XWPFTable table) throws XmlException {
     2         if (CollectionUtils.isEmpty(lines)) {
     3             List<String> th = new ArrayList<String>();
     4             th.add("姓名");
     5             th.add("身份证");
     6             th.add("金额");
     7             if (lines == null) {
     8                 lines = new ArrayList<List<String>>();
     9             }
    10             lines.add(th);
    11         }
    12         XWPFTable replace = xdoc.createTable(lines.size(), lines.get(0).size());
    13         CTTbl cttbl = replace.getCTTbl();
    14 
    15         cttbl.getTblPr().set(table.getCTTbl().getTblPr());
    16 
    17         CTTblGrid cg = cttbl.addNewTblGrid();
    18         cg.addNewGridCol().setW(BigInteger.valueOf(2500));
    19         cg.addNewGridCol().setW(BigInteger.valueOf(3800));
    20         cg.addNewGridCol().setW(BigInteger.valueOf(2500));
    21 
    22         CTRow originalRow = table.getCTTbl().getTrArray(0);
    23         if (CollectionUtils.isNotEmpty(lines)) {
    24             for (int i = 0; i < lines.size(); i++) {
    25                 List<String> line = lines.get(i);
    26                 CTRow ctRow = cttbl.getTrArray(i);
    27                 ctRow.set(originalRow);
    28                 for (int j = 0; j < line.size(); j++) {
    29                     CTTc ctTc = ctRow.getTcArray(j);
    30                     ctTc.removeP(0);
    31                     CTText text = ctTc.addNewP().addNewR().addNewT();
    32                     text.setStringValue(line.get(j));
    33 
    34                 }
    35             }
    36         }
    37         xdoc.setTable(pos, replace);
    38         xdoc.removeBodyElement(xdoc.getPosOfTable(replace));
    39     }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-3 17:24 , Processed in 0.099224 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表