How to find/replace text in a .docx file using QAxObject ?
-
wrote on 21 Aug 2017, 19:51 last edited by
Hey there,
I wish if someone could help me, how we can find & replace text in a .docx file using QAxObject.
And Thanks. -
wrote on 22 Aug 2017, 09:13 last edited by
@hskoglund Thanks for the quick reply, but inforutly that code seems not working "successfully", I'm wondering if you had tried to run it, because once I compile it, I got 4 problems (lignes: 6-7-8-10: -> /.), and even if you fix them, in the and you will have a .docx file that contains: "hello", instead of "word".
So anyway, thanks for your time. -
wrote on 22 Aug 2017, 10:57 last edited by
Hi, sorry no I didn't test it, and agreed it looks very complicated. There should be a simpler way, I can look later today.
-
Hi, sorry no I didn't test it, and agreed it looks very complicated. There should be a simpler way, I can look later today.
wrote on 22 Aug 2017, 11:34 last edited by@hskoglund Thanks so much for your help.
-
wrote on 23 Aug 2017, 04:26 last edited by
Hi, I got 2 examples for you. Note: they both require Word to be installed so it can open the .docx file, I forgot to ask if you wanted to manipulate the file without Word, i.e. only with Qt? (That's a different story altogether :-)
First the simple one, it assumes you already have started Word and opened the .docx file:
I created a vanilla Widgets app, added "axcontainer" to the .pro file, e.g.:QT += core gui axcontainer
#include "qaxobject.h" at the top of mainwindow.cpp and then inserted this code after "ui->setupUi(this);" :// connect to an existing opened docx file auto wApp = new QAxObject(this); wApp->setControl(("{000209FF-0000-0000-C000-000000000046}&")); wApp->setProperty("Visible",true); auto sel = wApp->querySubObject("Selection"); auto find = sel->querySubObject("Find"); QString sOld = "old"; // change from this QString sNew = "new"; // to this one at the time find->dynamicCall("Execute(QString)",sOld); sel->dynamicCall("TypeText(QString)",sNew);
The search sets the selection, which the TypeText() call just replace.
I'll post the more advanced example after this one.
-
wrote on 23 Aug 2017, 04:56 last edited by
The more advanced one uses the same Execute call is in my link above, but I managed to clean up and simplify it slightly.
The Execute call takes 15 (!) arguments:
findText,
matchCase, matchWholeWord, matchWildCards, matchSoundsLike, matchAllWordForms, forward,
wrap,
format,
replaceWithText
replace,
matchKashida, matchDiacritics, matchAlefHamza, matchControl.All the "matchXxxx", "forward" and "format" arguments are booleans, "wrap" and "replace" are integers and the rest are strings.
Let's look at the code, in this example I'm opening the .docx file and not using any selections (which makes it faster). Start with the same vanilla Widget example as above and add this after "ui->setupUi(this);":
// opens a .docx file auto wApp = new QAxObject("Word.Application"); auto docs = wApp->querySubObject("Documents"); auto doc = docs->querySubObject("Open(QString)","c:/temp/test.docx"); if (nullptr == doc) qFatal("File not found"); auto active = wApp->querySubObject("ActiveDocument()"); auto content = active->querySubObject("Content()"); auto find = content->querySubObject("Find"); QString sOld = "old"; QString sNew = "new"; bool bMatchCase = false; bool bMatchWholeWord = false; bool bMatchWildCards = false; bool bReplaceAll = true; QVariantList vl = { sOld, bMatchCase, bMatchWholeWord, bMatchWildCards, false, false, true, 1, false, sNew, bReplaceAll ? "2" : "1" }; find->dynamicCall("Execute(QString,bool,bool,bool,bool,bool,bool,int,bool,QString,int)",vl);
Because the dynamicCall accepts at most 9 arguments, instead I pack them in a variantlist. Also the last 4 arguments I didn't bother to fill in, and I assume Word defaults them to false.
-
The more advanced one uses the same Execute call is in my link above, but I managed to clean up and simplify it slightly.
The Execute call takes 15 (!) arguments:
findText,
matchCase, matchWholeWord, matchWildCards, matchSoundsLike, matchAllWordForms, forward,
wrap,
format,
replaceWithText
replace,
matchKashida, matchDiacritics, matchAlefHamza, matchControl.All the "matchXxxx", "forward" and "format" arguments are booleans, "wrap" and "replace" are integers and the rest are strings.
Let's look at the code, in this example I'm opening the .docx file and not using any selections (which makes it faster). Start with the same vanilla Widget example as above and add this after "ui->setupUi(this);":
// opens a .docx file auto wApp = new QAxObject("Word.Application"); auto docs = wApp->querySubObject("Documents"); auto doc = docs->querySubObject("Open(QString)","c:/temp/test.docx"); if (nullptr == doc) qFatal("File not found"); auto active = wApp->querySubObject("ActiveDocument()"); auto content = active->querySubObject("Content()"); auto find = content->querySubObject("Find"); QString sOld = "old"; QString sNew = "new"; bool bMatchCase = false; bool bMatchWholeWord = false; bool bMatchWildCards = false; bool bReplaceAll = true; QVariantList vl = { sOld, bMatchCase, bMatchWholeWord, bMatchWildCards, false, false, true, 1, false, sNew, bReplaceAll ? "2" : "1" }; find->dynamicCall("Execute(QString,bool,bool,bool,bool,bool,bool,int,bool,QString,int)",vl);
Because the dynamicCall accepts at most 9 arguments, instead I pack them in a variantlist. Also the last 4 arguments I didn't bother to fill in, and I assume Word defaults them to false.
wrote on 23 Aug 2017, 15:16 last edited by SamurayHThanks so much @hskoglund , it's really working now.
Reputation++ , +Follower...
1/8