简
在这篇帖子中我将详细讲述如何在Qt环境下使用已有Word模板文件创建新的文档,并对模板文档内容填充。目前,我只对替换文字和对表格进行操作进行了介绍,如何在文档插入图片未在本文中提及。
述
开发环境
本文中使用的开发环境是Qt5.10.0。由于本文中的实现方式是通过COM组件操作Word,需要在.pro文件中添加QT += axcontainer,在Qt4的版本中与Qt5是有点区别的,在Qt4中添加CONFIG += qaxcontainer。
从代码中看过程
多余的就不说了,具体过程看注释吧。
WordEngine.h
#ifndef WORDENGINE_H
#define WORDENGINE_H#include <QObject>
#include <QAxObject>
#include <QAxWidget>class WordEngine : public QObject
{Q_OBJECT
public:explicit WordEngine(QObject *parent = 0);public slots:bool open(const QString &file);//打开文档void save(const QString &savePath);//保存并关闭文档void replaceText(const QString &label,const QString &text);//替换文档中标签出的文字void alterTableRowCount(const QString &tabel, const int rowCount);//在表个中添加新行void fillTableCell(const QString &tabel,const QList<QStringList> &data);//填充表格内容private:QAxWidget *_word;//word主程序QAxObject *_workDocument;//工作簿bool _isOpen;//文档打开状态QMap<QString,int> _tabelIndex;//文档中的表格索引,注意word中表格的索引值是从1开始的,这里根据不同的情况单独实现
};#endif // WORDENGINE_H
WordEngine.cpp
#include "WordEngine.h"
#include "qt_windows.h"
#include <QMessageBox>WordEngine::WordEngine(QObject *parent) : QObject(parent)
{_word = NULL;_workDocument = NULL;_isOpen = false;/// 初始化表格索引,在word中可以直接获取表格的索引而不是书签来编辑表格内容,/// 所以,这里的索引是需要用户手动进行维护的_tabelIndex["table1"] = 1;_tabelIndex["table2"] = 2;
}/// Summary:根据传入的模板文件地址创建新的word文档并打开
/// parameters:
/// file:.dot模板文件的绝对地址,这里只能使用绝对地址,否则找不到文件,并且建议使用QDir::toNativeSeparators()将地址中的'/'转换成'\'
/// return:
/// 文档是否打开
bool WordEngine::open(const QString& file)
{_word = new QAxWidget("word.Application");QAxObject *document = _word->querySubObject("Documents");//获取所有打开的文档if (!document)return false;document->dynamicCall("Add(QString)",file);//使用模板文件创建新的文档_workDocument = _word->querySubObject("ActiveDocument");//激活文档if (_workDocument)_isOpen = true;else_isOpen = false;if (!_isOpen){QMessageBox box(QMessageBox::Information,QString("提示"),QString("未找到模板文件:%0").arg(file));box.addButton(QString("确定"),QMessageBox::AcceptRole);box.exec();}return _isOpen;
}/// Summary:将文档保存到指定地址,并关闭word程序
/// parameters:
/// savePath:word的保存地址
void WordEngine::save(const QString &savePath)
{//保存if (_isOpen && _workDocument){_workDocument->dynamicCall("SaveAs (const QString&)",savePath);}if (_word){_word->setProperty("DisplayAlerts",true);}//关闭文档if (_workDocument){_workDocument->dynamicCall("Close(bool)",true);delete _workDocument;_workDocument = NULL;}//推出word程序if (_word){_word->dynamicCall("Quit()");delete _word;_word = NULL;}_isOpen = false;
}/// Summary:替换指定书签处的内容
/// parameters:
/// label:书签名称,这里的书签对应的是在word中的插入->书签
/// text:内容
void WordEngine::replaceText(const QString &label, const QString &text)
{if (!_workDocument)return ;//查找书签QAxObject *bookmark = _workDocument->querySubObject("Bookmarks(QString)",label);if (bookmark){//选定书签,并替换内容bookmark->dynamicCall("Select(void)");bookmark->querySubObject("Range")->setProperty("Text",text);delete bookmark;}
}/// Summary:调整表格行数,目前只能插入不能删除,在word模板中,在表格中至少需要有一行内容空行,否则在插入新行的时候,数据内容会跟随表头行的格式,有时候导出结果会非常难看
/// parameters:
/// tabel:表格名称
/// rowCount:行数
void WordEngine::alterTableRowCount(const QString &tabel, const int rowCount)
{if (NULL == _workDocument) return;QAxObject *table = _workDocument->querySubObject("Tables(int)",_tabelIndex.value(tabel));//获取表格if (NULL == table) return;//获取表格目前的行数QAxObject *rows = table->querySubObject("Rows");qint32 count = rows->dynamicCall("Count").toInt();//插入行for (int i = count - 1; i < rowCount; ++i){rows->querySubObject("Add()");}
}/// Summary:填充表格内容
/// parameters:
/// tabel:表格名称
/// data:内容
void WordEngine::fillTableCell(const QString &tabel, const QList<QStringList> &data)
{if (NULL == _workDocument) return;QAxObject *table = _workDocument->querySubObject("Tables(int)",_tabelIndex.value(tabel));//获取表格if (NULL == table) return;//获取表格目前的行数QAxObject *rows = table->querySubObject("Rows");qint32 rowCount = rows->dynamicCall("Count").toInt();//获取表格目前的列数QAxObject *columns = table->querySubObject("Columns");qint32 columnCount = columns->dynamicCall("Count").toInt();//当前表格行数小于数据的行数,调整到数据的行数if (data.size()>rowCount){alterTableRowCount(tabel,data.size());}//填充表格内容for (int row = 0; row < data.size(); ++row){for (int column = 0; column < data.at(row).size() && column < columnCount; ++column){QAxObject *cell=table->querySubObject("Cell(int,int)",row+2,column+1);//获取单元格,注意word中的索引是从1开始的,再加上表头row应该+2if(!cell) return;cell->dynamicCall("Select(void)");cell->querySubObject("Range")->setProperty("Text",data.at(row).at(column));delete cell;}}
}
不足之处
这种方法读写文档的效率非常低,但是在Qt中Qwidget的派生类都无法在子线程中运行,所以当文件内容比较多的时候我们能做的只有等……或许你有更好的方法,请一定告诉我(_ _)。゜zzZ
结
以上就是如何在Qt中创建Word文档并修改word文档内容。如有不明白的地方欢迎留言或通过下面的邮件地址交流,若帖子中有错误的地方同样欢迎留言批评指正,在此谢过路过的各位大神。