一个Qt的项目,项目中要求生成doc格式的报表,查阅发现这方面的资料比较少,通过有限的资料,自己研究了一下午,终于搞明白了一些。
Qt通过QAxWidget和QAxObject来使用ActiveX控件
其中QAxWidget扮演着ActiveX控制器的角色
而QAxObject扮演着COM对象容器的角色
需要引用如下头文件
#include <QAxWidget> #include <QAxObject>
CONFIG += qaxcontainer
#include <QApplication> #include <QAxWidget> #include <QAxObject> #include <QFile> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 新建一个word应用程序,并设置为不可见 QAxWidget *word=new QAxWidget("Word.Application", 0, Qt::MSWindowsOwnDC); word->setProperty("Visible", false); // 获取所有的工作文档 QAxObject * documents = word->querySubObject("Documents"); // 以文件template.dot为模版新建一个文档 documents->dynamicCall("Add(QString)",QString("D:/template.dot")); // 获取当前激活的文档 QAxObject *document=word->querySubObject("ActiveDocument"); // 获取文档中名字为label1的标签 QAxObject*bookmark_text=document->querySubObject("Bookmarks(label1)"); // 选中标签,将字符InsertText插入到标签位置 if(!bookmark_text->isNull()) { bookmark_text->dynamicCall("Select(void)"); bookmark_text->querySubObject("Range")->setProperty("Text","InsertText"); } // 获取文档中名字为label2的标签 QAxObject *bookmark_pic = document->querySubObject("Bookmarks(label2)"); // 选中标签,将图片插入到标签位置 if(!bookmark_pic->isNull()) { bookmark_pic->dynamicCall("Select(void)"); QAxObject *Inlineshapes = document->querySubObject("InlineShapes"); Inlineshapes->dynamicCall("AddPicture(const QString&)","D:\\123.jpg"); //路径必须为windows路径格式 } // 将文件另存为docbyqt.doc,关闭工作文档,退出应用程序 document->dynamicCall("SaveAs (const QString&)", QString("D:/docbyqt.doc")); document->dynamicCall("Close (boolean)", false); word->dynamicCall("Quit()"); delete bookmark_text; delete bookmark_pic; delete document; delete documents; delete word; return 0; }
QAxObject *subobject = object->querySubObject("name"); subobject->dynamicCall("function(paraList)",para);
object->setProperty("property_key",property_value);
方法就是在word中录制操作的宏,然后查看宏的内容。
注意要点是要尽量保证操作的有效性,使宏尽可能的简介。
下面是一个插入一个图片,并设置阴影的宏。
Sub 宏1() Selection.InlineShapes.AddPicture FileName:="D:\123.jpg", LinkToFile:= _ False, SaveWithDocument:=True Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend Selection.InlineShapes(1).Shadow.Type = msoShadow5 End Sub
先以第一句代码为例:
忽略Selection,看后面的内容。
selection应该是指选中当前选中的位置,可以用Range和select等函数定位。
倒序读取这行的内容,AddPicture 后面是空格和一些属性,所以AddPicture 是一个函数,而空格后面则是函数对应的参数
InlineShapes 就是拥有函数 AddPicture 的对象
我们就可以用如下语句创建一个InlineShapes 的对象,并调用使用他的方法
QAxObject *Inlineshapes = document->querySubObject("InlineShapes"); Inlineshapes->dynamicCall("AddPicture(const QString&)","D:\\123.jpg");
还是忽略Selection,看后面的内容。
selection如上所示
依旧倒序读取,最后是一个赋值操作,所以Type是一个属性。而前面每一个被“.”隔开的变量都是一个对象。
我们可以用如下语句完成上述VB的功能:
QAxObject *Inlineshape = document->querySubObject("InlineShapes(1)"); QAxObject *Shadow = Inlineshape->querySubObject("Shadow"); Shadow->dynamicCall("SetType(Office::MsoShadowType)", 5);
当我们想系统的了解一个类的时候,最方便的就是读API文档。幸运的是,Qt能够生成COM的API
方法如下:
QString doc=object->generateDocumentation(); QFile outFile("d:/object.html"); outFile.open(QIODevice::WriteOnly|QIODevice::Append); QTextStream ts(&outFile); ts<<doc<<endl;
word有模版和标签机制,可以方便的创建一个框架并且标记要插入内容的位置,非常便于生成word文件。
利用word模版,标记书签(bookmark),然后通过Qt读取书签,在相应位置插入内容,将大大简化Qt的代码。
使用书签的方法与使用其他的对象没有大的区别,代码如下:
QAxObject *document=word->querySubObject("ActiveDocument"); // 获取文档中名字为label1的标签 QAxObject*bookmark_text=document->querySubObject("Bookmarks(label1)"); // 选中标签,将字符InsertText插入到标签位置 if(!bookmark_text->isNull()) { bookmark_text->dynamicCall("Select(void)"); bookmark_text->querySubObject("Range")->setProperty("Text","InsertText"); }
另附一个msdn关于VB和C#的页面:http://msdn.microsoft.com/zh-cn/library/y1xatbkd%28v=vs.80%29.aspx