引言
项目中需要生成word格式的报告文件,初探了Qt5通过word模板生成报告的方法,整理了使用时的环境配置、子线程中使用时的注意事项以及常用的操作方法,于此记录。
环境:vs2012+Qt5.2+word2016
一、使用ActiveQt模块
注意:ActiveQt只适用于windows平台下,linux和macOS版本的Qt中是没有这个库的
首先需要添加库文件,可以直接在VS2012菜单栏Qt5->Qt Project Setting->勾选Active Qt
勾选之后再次查看Qt Project Setting,发现自动勾上了Active Qt server,同时“项目属性->配置属性->链接器->输入->附加依赖性”中自动加入了Qt5AxContainerd.lib;Qt5AxBased.lib
此后便可成功include头文件
#include <QAxWidget>
#include <QAxObject>
二、子线程中使用
在使用过程中发现调用word过程比较耗时,会阻塞GUI线程,于是将保存报告操作移到子线程中.
不过在子线程中使用QAxWidget
会报错ASSERT failure in QWidget: "Widgets must be created in the GUI thread."
这是由于线程里面不能创建GUI对象。
解决方案是用 QAxObjec
取代QAxWidget
,初始化过程如下:
bool Report::Open(QString Dir)
{
// 新建一个word应用程序,并设置为不可见
//m_WordFile = new QAxWidget("Word.Application", 0, Qt::MSWindowsOwnDC);
m_WordFile = new QAxObject();//取代QAxWidget,使其在子线程中可用
bool bFlag = m_WordFile->setControl( "word.Application" );
if(NULL == m_WordFile)
{
// 尝试用wps打开
bFlag = m_WordFile->setControl( "kwps.Application" );
if(!bFlag)
{
return false;
}
}
m_WordFile->setProperty("Visible", false);
// 获取所有的工作文档
QAxObject *Documents = m_WordFile->querySubObject("Documents");
if(NULL == Documents)
{
return false;
}
// 以文件template.dot为模版新建一个文档
Documents->dynamicCall("Add(QString)", Dir);
// 获取当前激活的文档
m_Document = m_WordFile->querySubObject("ActiveDocument");
if(NULL == m_Document)
{
return false;
}
m_bInit = true;
return true;
}
同时由于在QApplication的主线程中,会自动初始化COM库,而新开辟的子线程不会自动初始化COM库,所以需要我们手动来初始化,方法如下:
添加头文件:
#include <windows.h>
构造函数中初始化COM库:
Report::Report(QObject *parent)
: QObject(parent)
{
HRESULT result = OleInitialize(0);
if (result != S_OK && result != S_FALSE)
{
qDebug()<<QString("Could not initialize OLE (error %x)").arg((unsigned int)result);
}
//moveToThread方法产生线程
this->moveToThread(&m_thread);
m_thread.start();
}
析构函数中释放:
Report::~Report()
{
OleUninitialize()<