查阅一些资料后,经过不断地尝试和终于弄出想要的结果了。一些内容好多帖子都一样,实在看不出谁是原创,对于内容也给了一些灵感吧,那些都是实现读取之后又在转入另一个Word中,或者直接就把字符串内容拿出来。要么没有直接看到内容,要么与原Word中表格差异太大。 简单的读取就不阐述了,下面说一下我的吧,主要是读出来生成相应的<table></table>标签,便于使用和展示。但是并没有读取表格的详细样式配置。实际只需要读取内容以及单元格的跨行跨列即可。
首先doc与docx是现实不一样的,因此在读取的时候需要分开写。在**Word2007(.docx)**文档中的解析中,先是将文档当做.zip的压缩文件解压处理,其中包含一些.xml文件,其中就包含了文档中的内容以及样式参数。跨行跨列的xml信息获取方式不同。
以下是我举得一个例子,是一个单元格的信息,其中w:val="restart" 表示此单元格为跨行信息。一般单元格不存在跨行时无此xml信息,对象为null。存在此xml信息并且存在w:val="restart"信息时为跨行首行,若存在此xml信息但并没有w:val="restart"信息时为跨行非首行。根据此信息加上自己的处理即可
<xml-fragment w:val="restart" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 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:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" 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:val="2"这个值就说跨两列。不存在垮列时则无此xml信息。
<xml-fragment w:val="2" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 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:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" 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"/>以下代码只是实例,实际不可能只有docx还会涉及doc、PDF、WPS等多种文档。写好接口做好不同实现就好。我的方法并不是最好的,只是根据想法先实现了出来,测试了不同复杂表格均可以表现出来。逻辑也都注释了,一目了然,代码直接用就可以。POI的jar就不多说了。
import org.apache.poi.xwpf.usermodel.XWPFDocument; 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.x2006.main.CTDecimalNumber; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import java.io.FileInputStream; import java.util.List; /* * 使用POI库对word进行处理的工具类 */ public class DocxPOIUtils { public static void main(String[] args) throws Exception { String sourceFile = "D:\\JetBrains\\Cloud\\测试表格.docx"; getAllTable2(sourceFile); } public static void getAllTable2(String sourceFile){ try{ XWPFDocument docx = new XWPFDocument(new FileInputStream(sourceFile)); List<XWPFTable> tables = docx.getTables(); List<XWPFTableRow> rows; List<XWPFTableCell> cells; for (XWPFTable table : tables) { String str = ""; str += "<table border='1px solid black' cellspacing='0'>"; // 获取表格对应的行 rows = table.getRows(); for (int i = 0; i < rows.size(); i++) { System.out.println("row---"+i); str += "<tr>"; // 获取行对应的单元格 cells = rows.get(i).getTableCells(); for (int j = 0; j < cells.size(); j++) { System.out.println("cell---"+j); CTVMerge rowspan = cells.get(j).getCTTc().getTcPr().getVMerge();//跨行 //------------------ int d = 1;//跨行行数//计算是从跨行下一行开始统计的,故加上首行 if (rowspan != null) {//rowspan存在未有跨行信息 //跨行的第一行为restart,其他行为null STMerge.Enum enum1 = rowspan.getVal(); if (enum1 != null && "restart".equals(enum1.toString())){//发现跨行信息为第一行时进行计算行数,非跨行首行则绕过不处理,已经计算在内 for (int k = i+1; k < rows.size(); k++) {//从当前单元格的跨行首行开始遍历,避免不必要的计算 if (rows.get(k).getTableCells().size() > j){ CTVMerge mer = rows.get(k).getTableCells().get(j).getCTTc().getTcPr().getVMerge(); if (mer != null) {//只要不为null就是存在连续的跨行 STMerge.Enum enum2 = mer.getVal(); if (enum2 != null && "restart".equals(enum2.toString())) {//若再次遇到restart,为下一次跨行,终止此次 break; }else {//只要不是restart就加计算 d++; } }else {//连续中断,出现null则为此单元格跨行结束 break; } }else { d++; } } } } //------------------ CTDecimalNumber colspan = cells.get(j).getCTTc().getTcPr().getGridSpan();//跨列 if (colspan != null && rowspan != null) { STMerge.Enum enum1 = rowspan.getVal(); if (enum1 != null) { str += "<td colspan='"+colspan.getVal()+"' rowspan='"+d+"'>"; } }else if (colspan == null && rowspan != null) { STMerge.Enum enum1 = rowspan.getVal(); if (enum1 != null) { str += "<td rowspan='"+d+"'>"; } }else if (colspan != null && rowspan == null) { str += "<td colspan='"+colspan.getVal()+"'>"; }else if (colspan == null && rowspan == null) { str += "<td>"; } str += cells.get(j).getText().trim().replaceAll("[\r\n]", "").toLowerCase(); str += "</td>"; } str += "</tr>"; } str += "</table>"; System.out.println(str); } }catch (Exception e) { e.printStackTrace(); } } }产出效果为标签字符串。有个问题就是标签样式,我并没有获取详细的样式
<table border='1px solid black' cellspacing='0'><tr><td colspan='3' rowspan='2'>跨行跨列</td><td>a</td><td colspan='20'>a课题</td></tr><tr></td><td colspan='7'></td><td colspan='5'>不规则位置跨列</td><td colspan='9'></td></tr><tr><td colspan='3' rowspan='2'>紧随跨行跨列</td><td colspan='3'></td><td colspan='3'>性别</td><td></td><td colspan='4'>民族</td><td colspan='2'></td><td colspan='5'>中间跨列1</td><td colspan='3'>年 月</td></tr><tr></td><td colspan='3'></td><td colspan='4'>职务</td><td colspan='6'></td><td colspan='5'>中间跨列2</td><td colspan='3'></td></tr><tr><td colspan='3'>跨列4</td><td colspan='3'></td><td colspan='4'>学位</td><td colspan='6'></td><td colspan='5'>中间跨列3</td><td colspan='3'></td></tr><tr><td colspan='3'>跨列5</td><td colspan='10'>不规则位置跨列</td><td colspan='6'>联系电话</td><td colspan='5'></td></tr><tr><td colspan='3'>跨列6</td><td colspan='17'></td><td colspan='2'>邮编</td><td colspan='2'></td></tr><tr><td colspan='3'>跨列7</td><td colspan='4'></td><td colspan='4'>职务</td><td colspan='2'></td><td colspan='5'>工作单位</td><td colspan='6'></td></tr><tr><td colspan='3'>跨列8</td><td colspan='4'></td><td colspan='4'>职务</td><td colspan='2'></td><td colspan='5'>工作单位</td><td colspan='6'></td></tr><tr><td colspan='2'>跨列9</td><td></td><td></td><td colspan='16'>a.专著b.译著c.工具书</td><td colspan='3'>字数</td><td>万字</td></tr><tr><td colspan='5'>跨列</td><td colspan='7'></td><td colspan='7'>时间</td><td colspan='5'>年 月 日</td></tr><tr><td rowspan='3'>同列隔行跨行</td><td colspan='2'>标题1</td><td>标题2</td><td colspan='4'>标题3</td><td colspan='3'>标题4</td><td colspan='3'>标题5</td><td colspan='3'>标题6</td><td colspan='3'>标题7</td><td colspan='4'>标题8</td></tr><tr></td><td colspan='2'></td><td></td><td colspan='4'></td><td colspan='3'></td><td colspan='3'></td><td colspan='3'></td><td colspan='3'></td><td colspan='4'></td></tr><tr></td><td colspan='2'></td><td></td><td colspan='4'></td><td colspan='3'></td><td colspan='3'></td><td colspan='3'></td><td colspan='3'></td><td colspan='4'></td></tr></table>
重点在于内容不再展示,因此表格边框字体等相关样式并未读取。有需要的伙伴可以自己研究一下。关于**Word2003(.doc)**文档,因为实现不同,也并没有看到好的POI接口,还不能很好地实现。后续有结果还会在发布,有相关经验的伙伴或有啥问题欢迎留言啊。