从一个word文件中读取所有的表格和标题

Posted 随性者也

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从一个word文件中读取所有的表格和标题相关的知识,希望对你有一定的参考价值。

首先讲需求:

从word文件中读表格里的数据,然后插入数据库中。word文件中的表格是带有标题的,把标题读出来,进行匹配数据库。

需求分析:

word2007底层是以xml文件存储的,所以分析xml的格式,进行读取相应数据。

表格数据如下:

表 1 分类统计表

 

分类

总计

1类

2类

软件

4

3

7

硬件

5

6

11

word底层xml组成如下分析:

技术分享
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:pStyle w:val="a4"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
<w:ind w:firstLineChars="0"/>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>分类统计表</w:t>
</w:r>
</w:p>

<w:tbl>
<w:tblPr>
<w:tblStyle w:val="a3"/>
<w:tblW w:w="0" w:type="auto"/>
<w:jc w:val="center"/>
<w:tblBorders>
<w:left w:val="none" w:color="auto" w:space="0" w:sz="0"/>
<w:right w:val="none" w:color="auto" w:space="0" w:sz="0"/>
</w:tblBorders>
<w:tblLook w:val="04A0" w:noVBand="1" w:noHBand="0" w:lastColumn="0" w:firstColumn="1" w:lastRow="0" w:firstRow="1"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
</w:tblGrid>
<w:tr w:rsidR="009F1A99" w:rsidTr="009F1A99">
<w:trPr>
<w:jc w:val="center"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vMerge w:val="restart"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="4148" w:type="dxa"/>
<w:gridSpan w:val="2"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>分类</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vMerge w:val="restart"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>总计</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr w:rsidR="009F1A99" w:rsidTr="009F1A99">
<w:trPr>
<w:jc w:val="center"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vMerge/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>1类</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>2类</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vMerge/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
</w:p>
</w:tc>
</w:tr>
<w:tr w:rsidR="009F1A99" w:rsidTr="009F1A99">
<w:trPr>
<w:jc w:val="center"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>软件</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>4</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>3</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>7</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr w:rsidR="009F1A99" w:rsidTr="009F1A99">
<w:trPr>
<w:jc w:val="center"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>硬件</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>5</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>6</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p w:rsidRDefault="009F1A99" w:rsidR="009F1A99" w:rsidP="009F1A99">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>11</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
View Code

分析上面的表格标签可以得出如下结论:

段落标签:p

段落内容:t

表格标签:tbl

表格行标签:tr

表格标签:tc

水平合并标签:gridSpan  属性:w:val等于合并项

垂直合并标签:vMerge 属性:w:val等于restart表示垂直合并的开始

下面是读取代码:

头文件:

技术分享
#ifndef READERXML_H
#define READERXML_H

//定义一个单元格属性
class Cell
{
public:
    Cell() : m_value(""), m_hSpan(1), m_vSpan(false)
    {

    }

    QString m_value;                    //表格内容
    int m_hSpan;                        //水平合并数
    bool m_vSpan;                        //是否垂直合并
    QList<QList<Cell *> > m_subTable;    //是否存在子表格
};


class ReaderXml
{
public:

    //对外接口 参数1:xml文件名 参数2:表格标题 参数3:表格数据
    void reader(const QString &filename, QStringList &tableHeader, QList<QList<QStringList> > &tableData);

private:
    void getParagraph(QString &header);                //获取段落
    void getTableData(QList<QStringList> &data);    //读取表格数据
    void getTableLine(QList<Cell> &tableLine);        //读取表格一行
    void getCell(Cell &cell);                        //读取一个单元格

private:
    QXmlStreamReader m_reader;
};

#endif // READERXML_H
头文件

源文件

技术分享
#include "StdAfx.h"
#include "ReaderXml.h"

void ReaderXml::reader( const QString &filename, QStringList &tableHeader, QList<QList<QStringList> > &tableData )
{
    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return ;
    }
    m_reader.setDevice(&file);

    QStringList strList;
    m_reader.readNext();
    while(!m_reader.atEnd())
    {
        if(m_reader.isStartElement())
        {
            if(m_reader.name() == "p") //段落标签
            {
                QString str;
                getParagraph(str);
                strList.append(str);
            }
            else if(m_reader.name() == "tbl") //表格标签
            {
                QList<QStringList> data;
                getTableData(data);
                tableData.append(data);
                tableHeader.append(strList.last()); //表格上的段落是表格的标题
            }
        }
        m_reader.readNext();
    }

    m_reader.clear();
    file.close();
}

void ReaderXml::getParagraph( QString &header )
{
    m_reader.readNext();
    while(!m_reader.atEnd())
    {
        if(m_reader.isStartElement())
        {
            if(m_reader.name() == "t") //数据
            {
                header += m_reader.readElementText();
            }
        }
        else
        {
            if(m_reader.name() == "p")
            {
                return ;
            }
        }
        m_reader.readNext();
    }
}

void ReaderXml::getTableData( QList<QStringList> &data )
{
    m_reader.readNext();
    while(!m_reader.atEnd())
    {
        if(m_reader.isStartElement())
        {
            if(m_reader.name() == "tr") //表格行标签
            {
                QList<Cell> lineData;
                QStringList strList;
                getTableLine(lineData);
                for(int i = 0, len = lineData.size(); i != len; ++i)
                {
                    if(lineData[i].m_vSpan && !data.isEmpty())        //表格是否存在垂直合并的情况
                        lineData[i].m_value = data.last().at(i);
                    
                    for(int j = 0; j != lineData[i].m_hSpan; ++j)    //表格是否存在水平合并的情况
                        strList.append(lineData[i].m_value);
                }
                data.append(strList);
            }
        }
        else
        {
            if(m_reader.name() == "tbl")
            {
                return ;
            }
        }
        m_reader.readNext();
    }
}

void ReaderXml::getTableLine( QList<Cell> &tableLine )
{
    m_reader.readNext();
    while(!m_reader.atEnd())
    {
        if(m_reader.isStartElement())
        {
            if(m_reader.name() == "tc") //单元格标签
            {
                Cell cell;
                getCell(cell);
                tableLine.push_back(cell);
            }
        }
        else
        {
            if(m_reader.name() == "tr")
            {
                return ;
            }
        }
        m_reader.readNext();
    }
}

void ReaderXml::getCell( Cell &cell )
{
    m_reader.readNext();
    while(!m_reader.atEnd())
    {
        if(m_reader.isStartElement())
        {
            if(m_reader.name() == "t") //数据标签
            {
                cell.m_value += m_reader.readElementText();
            }
            else if(m_reader.name() == "gridSpan") //水平合并标签
            {
                cell.m_hSpan = m_reader.attributes().value("w:val").toString().toInt(); //合并数
            }
            else if(m_reader.name() == "vMerge") //垂直合并标签
            {
                cell.m_vSpan = true;
            }
        }
        else
        {
            if(m_reader.name() == "tc")
            {
                return ;
            }
        }
        m_reader.readNext();
    }
}
源文件

 

以上是关于从一个word文件中读取所有的表格和标题的主要内容,如果未能解决你的问题,请参考以下文章

java读取带格式word内容

PHP实现对word文档的读取

python实现Excel邮件合并

VBA SQL写入语句,从一个表格写入令一个表格?

用C#把word中的表格数据读取到xml文件

如何用C语言读取word中的数据