通过QT查找Word中的关键字,并做高亮或删除操作
Posted amos-haoxh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过QT查找Word中的关键字,并做高亮或删除操作相关的知识,希望对你有一定的参考价值。
最近由于项目需要,要用QT操作Word文档。具体的工作需求:在指定的Word文档(*.doc文件/*.docx文件)中查找关键字,找到后做高亮操作或者直接删除操作,然后另存为到别的目录(表示这个文件被操作过了)。
这个功能很简单,确实挺简单,但由于是第一次用QT操作Word文档,所以仍需要经过一番查找资料。网上用QT操作Word文档的资料不是很多(可能是我没找对地方),所以经过了一段时间的碰壁之后(没有现成的,哪怕是半成品),我决定还是从源头看起:
1.查看帮助文档:Microsoft Word Visual Basic参考.chm。这是操作Word文档的VBA接口文档
2.查看官方网站的帮助文档:https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word?view=word-pia
“查找”在这:https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word.find.hithighlight?view=word-pia#Microsoft_Office_Interop_Word_Find_HitHighlight_System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__System_Object__
要想用QT操作office文档,就要用到QAxWidget类和QAxObject类首先要在pro文件中配置一个模块“qaxcontainer”,也就是添加一行代码,即:
CONFIG += qaxcontainer
在找到关键字之后,我还保存了一些数据:文件名、文件所在的路径、关键字所处的位置。如果你不需要这些数据,可以删减掉。
QList<QString> fileNameList; // 保存文件名
QList<QString> filePathList; // 保存文件路径
QList<QStringList> keyWordsPositionList; // 保存关键字所在位置
首先介绍一个函数,这个函数通过正则表达式用来定位关键字所处在的语句。这个函数会在后面的高亮操作函数和直接删除函数里调用到:
// 查找关键字的位置 // fileContent:文件内容;keyWord:关键字 QStringList findKeyWordsPosition(QString fileContent, QString keyWord) { QStringList resList; if (fileContent.contains(keyWord)){ qDebug() << QObject::tr("包含子字符串 : %1").arg(keyWord); int startIndex = 0; // int count = 0; int keyWordsLen = keyWord.length(); QRegExp rx(QObject::tr("[,。:\r]?([^,。:\r]*(%1)[^,。:\r]*)[,。:\r]?").arg(keyWord)); while ((startIndex = rx.indexIn(fileContent, startIndex)) != -1){ QString resStr = rx.cap(1).mid(0); // 提取子字符串所在的语句 if (resStr.contains("\r")) resStr.replace("\r", ""); resList << resStr; // 找到子字符串 int findIndex = fileContent.indexOf(keyWord, startIndex); // qDebug() << QObject::tr("keyWords 出现的位置 : %1").arg(findIndex); startIndex = findIndex + keyWordsLen; // qDebug() << QObject::tr("keyWords 出现的次数 : %1").arg(++count); qDebug() << "\n"; } return resList; } return resList << ""; }
首先是高亮操作函数:
// 高亮操作函数
// dirName:是待检查文件的路径;keyWords:是要查找的关键字(查找的关键字可能是多个) bool highLightKeyWordsinWordFile(QString dirName, QStringList keyWords) { int lastSeparatorIndex = dirName.lastIndexOf(QDir::separator()); QString saveAsFilePath = storeDir + dirName.mid(lastSeparatorIndex+1); // 另存为的路径 QAxWidget wordApplication("Word.Application"); QAxObject *documents = wordApplication.querySubObject("Documents"); documents->dynamicCall("Open(const QString&)", dirName); wordApplication.setProperty("Visible", QVariant(false)); QAxObject* m_doc = wordApplication.querySubObject("ActiveDocument"); // 获取当前工作簿 QAxObject* pRange = m_doc->querySubObject("Content()"); if (NULL != pRange) { // 查找关键字 QAxObject *pFind = pRange->querySubObject("Find()"); QStringList keyWordsPosition; if (NULL != pFind) { pFind->dynamicCall("ClearFormatting()"); pFind->setProperty("Format", true); pFind->setProperty("MatchCase", false); pFind->setProperty("MatchWholeWord", false); pFind->setProperty("MatchByte", true); pFind->setProperty("MatchWildcards", false); pFind->setProperty("MatchSoundsLike", false); pFind->setProperty("MatchAllWordForms", false); for (int i=0; i<keyWords.size(); ++i){ // 找到关键字所在的位置,得到一个position,将position添加到keyWordsPosition中。 QString keyWord = keyWords.at(i); QStringList position = findKeyWordsPosition(pRange->property("Text").toString(), keyWord); if (!position.contains("")){ keyWordsPosition << position; pFind->setProperty("Text", keyWord); pFind->dynamicCall("Execute()"); while (pFind->property("Found").toBool()) { bool isHighlight = pFind->parent()->setProperty("HighlightColorIndex","wdYellow"); pFind->dynamicCall("Execute()"); if (!isHighlight) { delete pFind; pFind = NULL; delete pRange; pRange = NULL; m_doc->dynamicCall("Close(boolean)", true); wordApplication.dynamicCall("Quit ()"); delete m_doc; m_doc = NULL; return false; } } } } } if (keyWordsPosition.size() >= 1){ QString fileName = dirName.mid(lastSeparatorIndex+1); QString filePath = dirName.mid(0, lastSeparatorIndex+1); fileNameList << fileName; filePathList << filePath; keyWordsPositionList << keyWordsPosition; m_doc->dynamicCall("SaveAs(const QString)", saveAsFilePath); } delete pFind; pFind = NULL; delete pRange; pRange = NULL; m_doc->dynamicCall("Close(Boolean)", true); m_doc->dynamicCall("Quit()"); delete m_doc; m_doc = NULL; return true; } return true; }
下面这个是直接删除操作函数
// dirName:是待检查文件的路径;keyWords:是要查找的关键字(查找的关键字可能是多个) bool directDeleteKeyWordsinWordFile(QString dirName, QStringList keyWords) { int lastSeparatorIndex = dirName.lastIndexOf(QDir::separator()); QString saveAsFilePath = storeDir + dirName.mid(lastSeparatorIndex+1); // 另存为的路径 QAxWidget wordApplication("Word.Application"); QAxObject *documents = wordApplication.querySubObject("Documents"); documents->dynamicCall("Open(const QString&)", dirName); wordApplication.setProperty("Visible", QVariant(false)); QAxObject* m_doc = wordApplication.querySubObject("ActiveDocument"); // 获取当前工作簿 QAxObject* pRange = m_doc->querySubObject("Content()"); QList<QVariant> vars; if (NULL != pRange) { // 查找关键字 QAxObject *pFind = pRange->querySubObject("Find()"); QStringList keyWordsPosition; if (NULL != pFind) { pFind->dynamicCall("ClearFormatting()"); QAxObject *replacement = pFind->querySubObject("Replacement()"); replacement->dynamicCall("ClearFormatting()"); for (int i=0; i<keyWords.size(); ++i){ QString keyWord = keyWords.at(i); // 找到关键字所在的位置,得到一个position,将position添加到keyWordsPosition中。 QStringList position = findKeyWordsPosition(pRange->property("Text").toString(), keyWord); if (!position.contains("")){ keyWordsPosition << position; vars << keyWord << false << false << false << false << false << true << 1<< false << "" << 2 << false << false << false << false; // wdReplaceNone-->0;wdReplaceAll-->2;wdReplaceOne-->1 bool isReplaced = pFind->dynamicCall("Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, " "MatchAllWordForms, Forward, Wrap, Format, ReplaceWith, " "Replace, MatchKashida, MatchDiacritics, MatchAlefHamza, MatchControl)", vars).toBool(); if (!isReplaced){ delete pFind; pFind = NULL; delete pRange; pRange = NULL; m_doc->dynamicCall("Close(Boolean)", true); m_doc->dynamicCall("Quit()"); delete m_doc; m_doc = NULL; QMessageBox openFileError(QMessageBox::Warning, QObject::tr("文件处理错误"), QObject::tr("文件 %1 处理错误,是否继续检查其他文件?").arg(dirName)); openFileError.addButton(QMessageBox::Yes); openFileError.addButton(QMessageBox::No); openFileError.setDefaultButton(QMessageBox::Yes); if (openFileError.exec() == QMessageBox::No) return false; } } } } if (keyWordsPosition.size() >= 1){ QString fileName = dirName.mid(lastSeparatorIndex+1); QString filePath = dirName.mid(0, lastSeparatorIndex+1); fileNameList << fileName; filePathList << filePath; keyWordsPositionList << keyWordsPosition; m_doc->dynamicCall("SaveAs(const QString)", saveAsFilePath); } delete pFind; pFind = NULL; delete pRange; pRange = NULL; m_doc->dynamicCall("Close(Boolean)", true); m_doc->dynamicCall("Quit()"); delete m_doc; m_doc = NULL; return true; } return false; }
好了,以上代码可能无法正常运行,因为缺少一些变量的定义、头文件的包含,我觉得这些你自己添加是完全OK的^-^。
因为自己需要的时候找不到资源,如果你也在找相似的资料,能给你带来帮助,我的目的就达到了,哈哈
我发现在网上下载Word VBA和Excel VBA帮助文档的时候需要金币什么的,很不方便。在此我还将Word VBA和Excel VBA帮助文档的百度网盘下载链接放在这里,供大家下载:
链接: https://pan.baidu.com/s/1-KTGdEVz_4C3yp_SBNlkIw 提取码: ri4p
有不足的地方,请指正。
以上是关于通过QT查找Word中的关键字,并做高亮或删除操作的主要内容,如果未能解决你的问题,请参考以下文章
QT如何获取QTableWidget表格中的高亮位置的行数?