1. 程式人生 > >通過QT查找Word中的關鍵字,並做高亮或刪除操作

通過QT查找Word中的關鍵字,並做高亮或刪除操作

直接 card 表達 鏈接 代碼 car box nbsp name

最近由於項目需要,要用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中的關鍵字,並做高亮或刪除操作