欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

通过QT查找Word中的关键字,并做高亮或删除操作

程序员文章站 2022-07-10 11:40:01
最近由于项目需要,要用QT操作Word文档。具体的工作需求:在指定的Word文档(*.doc文件/*.docx文件)中查找关键字,找到后做高亮操作或者直接删除操作,然后另存为到别的目录(表示这个文件被操作过了)。 这个功能很简单,确实挺简单,但由于是第一次用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

有不足的地方,请指正。