Skip to content
  • 0 Votes
    5 Posts
    441 Views
    R

    Thank you Chris.

    I solved it by generating a text file with instructions in vbscript and executing it afterwards. With this variant I can manipulate word documents more easily but it only works for Windows.

    It's not that efficient but I have a lot more documentation for working with word.application in vbscript.

    I reiterate my thanks for answering me so quickly.

  • 0 Votes
    1 Posts
    267 Views
    No one has replied
  • 0 Votes
    3 Posts
    524 Views
    E

    @JonB

    Thank you for the link and your answer.

    I will do those things !

    Thanks again & have a nice day !

  • 0 Votes
    8 Posts
    1k Views
    U

    Noticed another feature (word 2007).
    Created this app:

    #include "mainwindow.h" #include "ui_mainwindow.h" #include <ActiveQt/QAxObject> #include <ActiveQt/qaxbase.h> #include <QDir> QAxObject *word, *objVBComp, *objCodeMod; QString VbaScriptLine = "Sub MacroCreatedByUser() : ActiveDocument.VBProject.References.AddFromGuid \"{00020802-0000-0000-C000-000000000046}\", 1, 5 : End Sub"; QString OpenFilePath = "input.doc"; QString SaveFilePath = "output.doc"; QString MacroName = "Test macros"; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_pressed() { word = new QAxObject( "Word.Application" ); word->setProperty("DisplayAlerts", - 1); word->setProperty("Visible", true); QString PathTmp = QDir::toNativeSeparators(QDir::currentPath() + "\\" + OpenFilePath); word->querySubObject( "Documents()" )->dynamicCall( "Open(FileName, ConfirmConversions, ReadOnly )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + OpenFilePath), false, false ); objCodeMod = word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents" )->querySubObject("Item(Index)", 1)->querySubObject( "CodeModule" ); objCodeMod->dynamicCall( "AddFromString(QString)", VbaScriptLine ); word->querySubObject( "Application" )->dynamicCall( "Run(MacroName)", MacroName ); word->querySubObject( "ActiveDocument" )->dynamicCall( "SaveAs( FileName, FileFormat )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + SaveFilePath), 0 ); word->querySubObject( "ActiveDocument" )->dynamicCall( "Close(SaveChanges)", 0 ); word->dynamicCall( "Quit()" ); delete word; }

    While executing the line: «objCodeMod->dynamicCall( "AddFromString(QString)", VbaScriptLine );» Windows OS fixes an error in the WINWORD.EXE application:
    win_error.png

    Despite the error, the macro is added and called as expected.

  • 0 Votes
    14 Posts
    3k Views
    J

    @SGaist Ok, I saw his user name is "china-Qter", so I used chinese.

  • 0 Votes
    24 Posts
    10k Views
    mrjjM

    Super :)
    oh it must have "()" on.
    The syntax is pretty funky via the automation server.
    Good work.

  • 0 Votes
    5 Posts
    2k Views
    M

    @mrjj thx,I am astonished and I will try it soon...:(

  • 0 Votes
    8 Posts
    3k Views
    hskoglundH

    2nd version, a bit more fancy, requiring you to run dumpcpp to get 2 files: word.cpp and word.h. Create a vanilla widget app, insert " axcontainer" in the .pro file (same as above). Add word.cpp into your project (so it wil compiled along with main.cpp and mainwindow.cpp.

    Then in mainwindow.cpp insert "#include word.h" at the top, and after ui->setupUi(this); insert:

    auto wApp = new Word::Application; if (nullptr == wApp) return; wApp->SetVisible(true); auto doc = wApp->Documents()->Add(); for (int p = 0; (p < 100); ++p) { auto para= doc->Content()->Paragraphs()->Add(); para->Range()->SetText("Four score and seven years ago our fathers " "brought forth on this continent a new nation, conceived in liberty, and dedicated to the " "proposition that all men are created equal. Now we are engaged in a great civil war, " "testing whether that nation, or any nation so conceived and so dedicated, can long endure."); para->Format()->SetSpaceAfter(20); para->SetWidowControl(0); // for false // para->setWidowControl(-1); // for true para->Range()->InsertParagraphAfter(); }

    These calls will be changed to dynamic calls inside word.h but it's nice to have command completions and syntax checking by the compiler.

    Note: when dealing with COM, thanks to it being used first by Visual Basic and VBA for Office, it's sometimes problems with the boolean chaps true and false, so I prefer to use 0 for false and -1 for true, same as in the Visual Basic.

  • 0 Votes
    5 Posts
    2k Views
    M

    Finally Solved.Luckily I found some posts told the reason----It seems the qt has to initialize and release OLE in a sub Thread(the GUI Thread has done this job so sometimes it may not show errors)

    Here is the code:

    #include <QCoreApplication> #include <QAxObject> #include "qt_windows.h" //Necessary #include <QVariant> #include <QDebug> int main(int argc, char *argv[]) { //Initialize OLE HRESULT r = OleInitialize(0); if (r != S_OK && r != S_FALSE) {qWarning("OLE initialize failure(error %x)",(unsigned int)r);} QCoreApplication a(argc, argv); QAxObject excel("Excel.Application"); excel.setProperty("Visible",false); QAxObject *workbooks = excel.querySubObject("WorkBooks"); workbooks->dynamicCall("Open (const QString&)",QString("d:/grade.xls")); QAxObject *workbook = excel.querySubObject("ActiveWorkBook"); QAxObject *worksheets = workbook->querySubObject("WorkSheets"); QAxObject *worksheet=worksheets->querySubObject("Item(int)",1); QAxObject *range; QString strVal; QAxObject *usedrange=worksheet->querySubObject("UsedRange"); int endrow=usedrange->querySubObject("Rows")->property("Count").toInt(); int endcolumn=usedrange->querySubObject("Columns")->property("Count").toInt(); for (int i=1;i<=endrow;i++){ for (int j=1;j<=endcolumn;j++){ range=worksheet->querySubObject("Cells(int,int)",i,j); strVal=range->dynamicCall("Value2()").toString(); qDebug()<<strVal; } qDebug()<<endl; } workbook->dynamicCall("Close()"); excel.dynamicCall("Quit()"); OleUninitialize(); return a.exec(); }
  • 0 Votes
    1 Posts
    619 Views
    No one has replied
  • 0 Votes
    8 Posts
    6k Views
    M

    Chris Kawa:
    Thank, Now it work, sorry for the misunderstanding "So instead of:"
    i get in this trouble because i read the generatedDocumentation()
    ´IDispatch * val = object->property("Systems").toIDispatch*();´

    Lack of knowledge and lack of samples.
    Greetings