首先讲需求:
从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>
分析上面的表格标签可以得出如下结论:
段落标签: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(); } }