Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QAxObject & MS Word 2016+
QtWS25 Last Chance

QAxObject & MS Word 2016+

Scheduled Pinned Locked Moved Unsolved General and Desktop
qaxobjectwordms office
8 Posts 3 Posters 1.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • U Offline
    U Offline
    UkoZL
    wrote on last edited by
    #1

    Qt Creator 4.4.1
    There is a program for working with a word document.

    #include <ActiveQt/QAxObject>
    #include <ActiveQt/qaxbase.h>
    #include <QDir>
    
    QString VbaScriptLine = "text text text";
    QString SaveFilePath  = "text text text";
    QAxObject *word, *objVBComp, *objCodeMod;
    
    word = new QAxObject( "Word.Application" );
    word->querySubObject( "Documents()" )->dynamicCall( "Open(FileName, ConfirmConversions, ReadOnly )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + OpenFilePath), false, false );
    objVBComp  = word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents" )->querySubObject( "Add(ComponentType)", 1 );
    objCodeMod = objVBComp->querySubObject("CodeModule");
    quint32 lLineNum = objCodeMod->property( "CountOfLines" ).toInt() + 1;
    objCodeMod->querySubObject( "InsertLines(Line, String)", lLineNum, VbaScriptLine );
    word->querySubObject( "Application" )->dynamicCall( "Run(MacroName)", MacroName );
    word->querySubObject( "ActiveDocument" )->dynamicCall( "SaveAs( FileName, FileFormat )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + SaveFilePath), 0 );
    word->dynamicCall( "Quit()" );
    
    delete word, objVBComp, objCodeMod;
    

    The program worked with word 2003-2013 installed. When installing word version 2016 and higher, when calling the InsertLines function, the error "Error calling IDispatch member InsertLines: Unknown error" occurs.
    What could be the problem?

    JonBJ 1 Reply Last reply
    0
    • U UkoZL

      Qt Creator 4.4.1
      There is a program for working with a word document.

      #include <ActiveQt/QAxObject>
      #include <ActiveQt/qaxbase.h>
      #include <QDir>
      
      QString VbaScriptLine = "text text text";
      QString SaveFilePath  = "text text text";
      QAxObject *word, *objVBComp, *objCodeMod;
      
      word = new QAxObject( "Word.Application" );
      word->querySubObject( "Documents()" )->dynamicCall( "Open(FileName, ConfirmConversions, ReadOnly )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + OpenFilePath), false, false );
      objVBComp  = word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents" )->querySubObject( "Add(ComponentType)", 1 );
      objCodeMod = objVBComp->querySubObject("CodeModule");
      quint32 lLineNum = objCodeMod->property( "CountOfLines" ).toInt() + 1;
      objCodeMod->querySubObject( "InsertLines(Line, String)", lLineNum, VbaScriptLine );
      word->querySubObject( "Application" )->dynamicCall( "Run(MacroName)", MacroName );
      word->querySubObject( "ActiveDocument" )->dynamicCall( "SaveAs( FileName, FileFormat )", QDir::toNativeSeparators(QDir::currentPath() + "\\" + SaveFilePath), 0 );
      word->dynamicCall( "Quit()" );
      
      delete word, objVBComp, objCodeMod;
      

      The program worked with word 2003-2013 installed. When installing word version 2016 and higher, when calling the InsertLines function, the error "Error calling IDispatch member InsertLines: Unknown error" occurs.
      What could be the problem?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @UkoZL
      This sounds like a Word VBA question, not a Qt one. Given you say it worked on old Word versions and gives the error it does on Word 16, where is your reference link page for using CodeModule.InsertLines(Line, String) under Word 16? Have you tested whether it works if you go into Word 16 and enter the corresponding VBA into its VBA/macro editor?

      1 Reply Last reply
      0
      • U Offline
        U Offline
        UkoZL
        wrote on last edited by UkoZL
        #3

        Yes, I checked through the VBA editor in Word 16 and there are no errors.

        Sub Test()
          ActiveDocument.VBProject.VBComponents.Add (1)
          VBCount = ActiveDocument.VBProject.VBComponents.Count
          LinesCount = ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.CountOfLines + 1
          ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.InsertLines Line:=LinesCount, String:="text text text"
        End Sub
        

        Works in old and new versions Word.

        JonBJ 1 Reply Last reply
        0
        • U UkoZL

          Yes, I checked through the VBA editor in Word 16 and there are no errors.

          Sub Test()
            ActiveDocument.VBProject.VBComponents.Add (1)
            VBCount = ActiveDocument.VBProject.VBComponents.Count
            LinesCount = ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.CountOfLines + 1
            ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.InsertLines Line:=LinesCount, String:="text text text"
          End Sub
          

          Works in old and new versions Word.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @UkoZL
          Yeah, this is not good, I looked it up too, and it does not seem to have changed! Which would have been "easy"....

          I'm afraid I think you are going to struggle to get an answer here. There is not going to be something obvious to say why it does not work from your Qt program when it works outside. As you know, QAxObject is really just a thin wrapper to the COM/Automation/VBA layer, it's not going to be apparent why this one call should seem to be failing.

          One thought is that somehow there is an Automation installation issue, like it's picking up a pre-Word-16 for this call. I don't know how likely and I don't know how you would determine. Do you have more than one Word version installed? Are you able to test your code on another machine? Given "Unknown Error", have you tested with simple values for Line & String? Like 0 (or 1 if that's what it counts from) and "Hello", in case the problem is in the parameter values? Verify what value your objCodeMod->property( "CountOfLines" ).toInt() has?

          Your test is ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.InsertLines Line:=LinesCount, String:="text text text". I don't know whether QAxObject does parameters by position or name, ought you test ActiveDocument.VBProject.VBComponents.Item(VBCount).CodeModule.InsertLines(LinesCount, "text text text")? Test some other methods like DeleteLines and ReplaceLine?

          You may be able to answer a question I have wondered about, and would try out if I had an error like Error calling IDispatch member InsertLines: there must be some call which would list/enumerate all the available methods/properties on an object, perhaps even to include their parameters? I should like to know what that would be if you know?

          1 Reply Last reply
          0
          • hskoglundH Offline
            hskoglundH Offline
            hskoglund
            wrote on last edited by
            #5

            Hi, just guessing, but perhaps in the Trust Center has a stricter setting in your Word 2016, so that vba code inside Word still works with R/W access but external code like Q only has read-only acess.
            If you try other properties on the CodeModule (the objCodeMod pointer) for example changing the Width, does it also crash in Qt?

            1 Reply Last reply
            2
            • U Offline
              U Offline
              UkoZL
              wrote on last edited by UkoZL
              #6

              In the document in the VBA editor, I created a CodeModule and added 4 lines there. In the program, I removed the addition of a new CodeModule to link to a pre-created one.

              1.png

              and I want to check what options are available CodeModule

              int Ztmp =  word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents" )->property( "Count" ).toInt();
              QVariant Z =  word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents(index)", Ztmp )->querySubObject( "CodeModule" )->propertyBag();
              
              

              Result:

              Word 2007 (Win10)
              2.png

              Word 2016/2019/2021 (Win7/Win10)
              3.png
              4.png

              The add module function works correctly and adds the module.

              word->querySubObject( "ActiveDocument" )->querySubObject( "VBProject" )->querySubObject( "VBComponents" )->querySubObject( "Add(ComponentType)", 1 );
              

              But when accessing the module, it seems to be absent.
              All other methods CodeModule give the same error "Error calling IDispatch member Method Name: Unknown error".

              1 Reply Last reply
              0
              • hskoglundH Offline
                hskoglundH Offline
                hskoglund
                wrote on last edited by
                #7

                Indeed it seems something's changed in Word's COM interface.
                Your Qt code might need some new (perhaps security-flavored) addition to enable CodeModule access.

                You could try running dcomcnfg.exe to see if there are some new security stuff that needs to enabled for Word 2016.

                Also you can try running the same VBA test() module from your Word 2007 but accessing Word 2016? That means you'll have to start with something like

                Dim WordApp As Word.Application2016 ' or similar incantation
                Set WordApp = New Word.Application
                ...
                

                to "reach across" from Word 2007 to Word 2016. (If they are on different PCs you can use dcomcnfg.exe to enable DCOM).
                If that VBA code also fails to access CodeModule properties then Qt is not the problem.

                Another approach is to check the COM interfaces to Word2007 and 2016 using OleView.exe and see if anything differs. Note it's an old program (I used it heavily in the previous century) and to make it work on Windows 10, first time you have to run it as an Administrator (after that it's fine).

                1 Reply Last reply
                2
                • U Offline
                  U Offline
                  UkoZL
                  wrote on last edited by
                  #8

                  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.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved