POI解析Word2007并生成HTML内容标签

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 查阅一些资料后,经过不断地尝试和终于弄出想要的结果了。一些内容好多帖子都一样,实在看不出谁是原创,对于内容也给了一些灵感吧,那些都是实现读取之后又在转入另一个Word中,或者直接就把字符串内容拿出来。要么没有直接看到内容,要么与原Word中表格差异太大。简单的读取就不阐述了,下面说一下我的吧,主要是读出来生成相应的<table></table>标签,便于使用和展示。但是并没有读取表格的详细样式配置。实际只需要读取内容以及单元格的跨行跨列即可。

一、原理
首先doc与docx是现实不一样的,因此在读取的时候需要分开写。在Word2007(.docx)文档中的解析中,先是将文档当做.zip的压缩文件解压处理,其中包含一些.xml文件,其中就包含了文档中的内容以及样式参数。跨行跨列的xml信息获取方式不同。

1.1 跨行getVMerge
以下是我举得一个例子,是一个单元格的信息,其中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"
/>

1.2 跨列getGridSpan
对于跨列相对容易,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>

**三、效果展示
3.1Word内表格截图**
20200703144456909.png
20200703144518891.png

3.2 HTML效果
20200703144823679.png

相关文章
|
24天前
|
数据采集 移动开发 前端开发
HTML代码的革命:语义化标签的魅力,让你的网页结构焕然一新!
【8月更文挑战第26天】本文探讨了Web前端开发中的语义化标签概念及其重要性。语义化标签通过使用具有明确含义的HTML标签来构建页面结构,提升了网页的可访问性及搜索引擎优化效果,并增强了代码的可读性和维护性。文章还讨论了实际开发中遇到的问题及未来发展趋势。
29 0
|
16天前
|
数据采集 存储 JavaScript
如何使用Cheerio与jsdom解析复杂的HTML结构进行数据提取
在现代网页开发中,复杂的HTML结构给爬虫技术带来挑战。传统的解析库难以应对,而Cheerio和jsdom在Node.js环境下提供了强大工具。本文探讨如何在复杂HTML结构中精确提取数据,结合代理IP、cookie、user-agent设置及多线程技术,提升数据采集的效率和准确性。通过具体示例代码,展示如何使用Cheerio和jsdom解析HTML,并进行数据归类和统计。这种方法适用于处理大量分类数据的爬虫任务,帮助开发者轻松实现高效的数据提取。
如何使用Cheerio与jsdom解析复杂的HTML结构进行数据提取
|
9天前
|
前端开发 Windows
【前端web入门第一天】02 HTML图片标签 超链接标签 音频标签 视频标签
本文档详细介绍了HTML中的图片、超链接、音频和视频标签的使用方法。首先讲解了`&lt;img&gt;`标签的基本用法及其属性,包括如何使用相对路径和绝对路径。接着介绍了`&lt;a&gt;`标签,用于创建超链接,并展示了如何设置目标页面打开方式。最后,文档还涵盖了如何在网页中嵌入音频和视频文件,包括简化写法及常用属性。
28 13
|
9天前
|
搜索推荐 SEO
HTML中各种标题标签的正确使用方法及其特点
在HTML中,标题标签(`&lt;h1&gt;`至`&lt;h6&gt;`)用于定义文档的标题结构。`&lt;h1&gt;`表示主标题,每个页面应只有一个;`&lt;h2&gt;`至`&lt;h6&gt;`分别表示不同层级的子标题,可用于细分内容。正确使用这些标签不仅有助于文档的层次分明和可读性提升,还能优化SEO。使用时需注意保持层级结构连续、内容描述清晰。
|
9天前
|
Web App开发 前端开发 JavaScript
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
HTML/CSS/JS学习笔记 Day3(HTML--网页标签 下)
|
22天前
|
移动开发 数据安全/隐私保护 UED
HTML表单标签详解:如何用HTML标签打造互动网页?
通过合理使用HTML表单标签,可以构建功能丰富、用户友好的互动网页。HTML表单的元素和属性提供了丰富的输入选项和验证功能,使得收集和处理用户输入成为可能。随着HTML5的发展,表单元素的功能性和用户体验将继续得到提升。开发者应充分利用这些工具,为用户打造流畅、互动性强的网页体验。
32 4
|
1天前
|
移动开发 HTML5
这些年没来得及学习的一些 HTML5 标签
【9月更文挑战第16天】HTML5 引入了许多新标签,增强了网页的功能与便利性。这些标签包括结构标签如 `&lt;header&gt;`(定义页眉)、`&lt;footer&gt;`(定义页脚)、`&lt;nav&gt;`(定义导航链接)、`&lt;section&gt;`(定义文档节)和 `&lt;article&gt;`(定义独立内容),以及多媒体标签 `&lt;audio&gt;` 和 `&lt;video&gt;`,用于播放音频和视频。此外,还有表单相关标签,如 `&lt;datalist&gt。
HTML中font标签用法
这篇文章详细介绍了HTML中`<font>`标签的用法,包括如何分别设置字体风格(`font-style`)、字体粗细(`font-weight`)、字体大小(`font-size`)和字体类型(`font-family`),并通过实例代码演示了如何综合使用这些属性来定义文本的字体样式。
HTML中font标签用法
|
25天前
|
移动开发 前端开发 JavaScript
|
25天前
|
移动开发 前端开发 开发者
从 HTML4 到 HTML5 的迁移标签
【8月更文挑战第24天】
29 0

推荐镜像

更多