SO中已经有类似问题的answers,建议将QAxObject
与dynamicCall()
一起用于MS Office自动化。可以做到,而且会奏效,但我认为有一种更好,更有趣的方法。
我的建议是导入每个Office应用程序随附的COM类型库,从而生成C ++对象模型。这有两个优点:与C#和VB.NET中流行的互操作方法相似,甚至那些语言的示例也可以用作我们自己的Qt项目的模型。当然,您可以在Qt Creator中享受自动补全的类和成员名称。我已经提到好玩了吗?
这与ActiveQt示例中包含的Outlook应用程序的Qutlook Example非常相似。 documentation除了在应用程序的.pro文件中添加TYPELIBS
变量外,其他内容不多。转换由Qt bin目录中的dumpcpp.exe
utility执行。这是一个导入MS Word对象模型的简单命令行程序项目:
QT += widgets axcontainer
CONFIG += c++11 cmdline
DUMPCPP=$$absolute_path("dumpcpp.exe",$$dirname(QMAKE_QMAKE))
TYPELIBS = $$system($$DUMPCPP -getfile {00020905-0000-0000-C000-000000000046})
isEmpty(TYPELIBS) {
message("Microsoft Word type library not found!")
REQUIRES += MSWord
} else {
SOURCES = main.cpp
}
要发现其他类型库的GUID,可以使用oleview.exe
实用程序。
QMake创建一个源文件MSWORD.cpp
和一个头文件MSWORD.h
,您可以将其包含在自己的类中以访问生成的对象模型。此示例从头开始生成Word文档,并将其保存为两种格式:
#include <QApplication>
#include <QStandardPaths>
#include <QDir>
#include "MSWORD.h"
int main(int argc,char *argv[])
{
QApplication a(argc,argv);
Word::Application word;
if (!word.isNull()) {
word.SetVisible(false);
Word::Documents* docs = word.Documents();
Word::Document* newDoc = docs->Add();
Word::Paragraph* p = newDoc->Content()->Paragraphs()->Add();
p->Range()->SetText("Hello Word Document from Qt!");
p->Range()->InsertParagraphAfter();
p->Range()->SetText("That's it!");
QDir outDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
QVariant fileName = outDir.absoluteFilePath("wordaut.docx");
QVariant format = Word::wdFormatXMLDocument;
newDoc->SaveAs2(fileName,format);
QVariant fileName2 = outDir.absoluteFilePath("wordaut2.doc");
QVariant format2 = Word::wdFormatDocument;
newDoc->SaveAs2(fileName2,format2);
newDoc->Close();
word.Quit();
}
return 0;
}
如您所见,该代码可读性强,但代价是要包含大量代码。您#include
生成的标头MSWORD.h
,程序将创建一个新文档,用两行文本填充其内容,并两次保存该文档:首先以现代DOCX格式,然后以DOC格式与Word 97/2003兼容。
完整的项目可以在此GitHub repository中找到。
,
#if defined(Q_OS_WIN)
else if (mod == "DOCX" || mod == "DOC") {
QTemporaryDir tempDir;
QString text_filename;
QString outFile;
QString allMessage;
else if (mod == "DOCX") {
if(tempDir.isValid()){
const QString tempFile = tempDir.path() + "/docxTemplate.docx";
if(QFile::copy(":/docxTemplate.docx",tempFile)){
text_filename = tempFile;
} else {
qDebug()<< "cannot locate docxTemplate.docx";
}
}
else {
qDebug()<< "cannot access filesystem";
}
QString outFile(pathDirectory+"/"+filename+".docx");
}
else if (mod == "DOC") {
if(tempDir.isValid()){
const QString tempFile = tempDir.path() + "/docTemplate.doc";
if(QFile::copy(":/docTemplate.doc",tempFile)){
text_filename = tempFile;
} else {
qDebug()<< "cannot locate docTemplate.doc";
}
}
else {
qDebug()<< "cannot access filesystem";
}
QString outFile(pathDirectory+"/"+filename+".doc");
}
QString inFile(text_filename);
QAxObject axObject("Word.Application");
QAxObject *documents = axObject.querySubObject("Documents");
QAxObject *document = documents->querySubObject("Open(const QString&,bool)",inFile,true);
document->dynamicCall("SaveAs(const QString&)",outFile);
document->dynamicCall("Close()");
axObject.dynamicCall("Quit()");
QAxObject axObjectNew("Word.Application");
QAxObject *documentsNew = axObjectNew.querySubObject("Documents");
QAxObject *documentNew = documentsNew->querySubObject("Open(const QString&,outFile,true);
QAxObject *selection = axObjectNew.querySubObject("Selection");
selection->dynamicCall("TypeText(QString)",allMessage);
documentNew->dynamicCall("Close()");
axObjectNew.dynamicCall("Quit()");
}
#endif
本文链接:https://www.f2er.com/2766611.html