Using DXL to run a macro in word

Hello

I was wondering if it's possible to write DXL code that would go into a word template (that is currently having items exported into) and run a few macros. If so, could someone explain how to do this?

Thanks in advance.
Eric_Hillen - Thu Mar 03 15:29:45 EST 2011

Re: Using DXL to run a macro in word
Mathias Mamsch - Thu Mar 03 16:57:17 EST 2011

Hmm ... without trying I would say:
 

string macroName = "postProcessMyExport"
OleAutoArgs args = create(); put (args, macroName)
oleMethod(oleObjWord, "Run", args)

 


Hope this helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Using DXL to run a macro in word
Eric_Hillen - Fri Mar 04 10:02:00 EST 2011

I think there are some missing peices or I'm putting it in wrong. The name of one of my macros is CaptionTable and the name given to the document being exported into is objDocument.

If this isn't going to work is there a way to take the VB code for the macro and manually put it into the DXL code?

Thanks

Re: Using DXL to run a macro in word
Eric_Hillen - Fri Mar 04 10:03:21 EST 2011

Eric_Hillen - Fri Mar 04 10:02:00 EST 2011
I think there are some missing peices or I'm putting it in wrong. The name of one of my macros is CaptionTable and the name given to the document being exported into is objDocument.

If this isn't going to work is there a way to take the VB code for the macro and manually put it into the DXL code?

Thanks

This is what I have in my DXL:

string CaptionTable = "postProcessMyExport"
OleAutoArgs args = create(); put (args, CaptionTable)
oleMethod(objDocument, "Run", args)

Re: Using DXL to run a macro in word
llandale - Fri Mar 04 14:05:14 EST 2011

Mathias Mamsch - Thu Mar 03 16:57:17 EST 2011

Hmm ... without trying I would say:
 

string macroName = "postProcessMyExport"
OleAutoArgs args = create(); put (args, macroName)
oleMethod(oleObjWord, "Run", args)

 


Hope this helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

You are in luck. I've been meaning to figure this out for a while. I generated a report in a buffer, write the buffer to a new *.rtf file, then invoke msword to open the file (system "../../winword.exe " NameFile).

Then I want to run a particular macro. This doesn't work:

OleAutoObj     objWord  = oleCreateAutoObject("Word.Application")
string          macroName       = "Main_DxlFormatReport"
OleAutoArgs     args            = create()
put (args, macroName)
 
infoBox "oljWord Null: " (null objWord) "\n"
oleMethod(objWord, "Run", args)


Am getting "This command is not available because no document is open", even though objWord is not null.

OK, maybe I'm in luck.

 

 

  • Louie

 

 

Re: Using DXL to run a macro in word
David_G_Bond - Fri Mar 04 14:32:22 EST 2011

Eric_Hillen - Fri Mar 04 10:03:21 EST 2011
This is what I have in my DXL:

string CaptionTable = "postProcessMyExport"
OleAutoArgs args = create(); put (args, CaptionTable)
oleMethod(objDocument, "Run", args)

Mathias indicated to use the method on the Word object, not the Document object.

  • David Bond

Re: Using DXL to run a macro in word
Eric_Hillen - Fri Mar 04 14:35:25 EST 2011

David_G_Bond - Fri Mar 04 14:32:22 EST 2011
Mathias indicated to use the method on the Word object, not the Document object.

  • David Bond

Seeing as that was declared no where in my code and would have no "value" I went with an assumption. I've looked at other code and it appears what goes there is whatever is representing the document being exported into and in my case it is represented as objDocument.

Re: Using DXL to run a macro in word
Mathias Mamsch - Sat Mar 05 18:03:14 EST 2011

llandale - Fri Mar 04 14:05:14 EST 2011

You are in luck. I've been meaning to figure this out for a while. I generated a report in a buffer, write the buffer to a new *.rtf file, then invoke msword to open the file (system "../../winword.exe " NameFile).

Then I want to run a particular macro. This doesn't work:

OleAutoObj     objWord  = oleCreateAutoObject("Word.Application")
string          macroName       = "Main_DxlFormatReport"
OleAutoArgs     args            = create()
put (args, macroName)
 
infoBox "oljWord Null: " (null objWord) "\n"
oleMethod(objWord, "Run", args)


Am getting "This command is not available because no document is open", even though objWord is not null.

OK, maybe I'm in luck.

 

 

  • Louie

 

 

@Louie:

If you start your word using system() then you will start a new word application. If you do this you need to do "oleGetAutoObject" instead of "oleCreateAutoObject" since the latter one will start a new Word session. But this will only give you the right Word Application object, if word was not started before. So I suggest you to open the RTF document in Word using the "Documents.Open" method of the word application object (see below).

@Eric: Note that if your macro is called "CaptionTable", you need to put this in the OLE arguments, not the "PostProcessExport" stuff I posted as an example macro name.

The following works for me (on the appended AWordFile.doc, which contains a macro "TehMacro")
 

OleAutoObj     objWord  = oleCreateAutoObject("Word.Application")
if (null objWord) error "Could not open word!"
 
OleAutoObj      objWBS  = null
string          macroName       = "TehMacro"
string      fileName    = "C:\\Temp\\AWordFile.doc" 
OleAutoArgs     args            = create()
 
olePut (objWord, "Visible", true)
oleGet (objWord, "Documents", objWBS)
 
if (null objWBS) error "Documents not found!"
 
clear args; put (args, fileName); oleMethod (objWBS, "Open", args) 
clear args; put (args, macroName); oleMethod(objWord, "Run", args)

 


Hope this helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 


Attachments

attachment_14590831_AWordFile.zip

Re: Using DXL to run a macro in word
Eric_Hillen - Mon Mar 07 09:26:59 EST 2011

Mathias Mamsch - Sat Mar 05 18:03:14 EST 2011

@Louie:

If you start your word using system() then you will start a new word application. If you do this you need to do "oleGetAutoObject" instead of "oleCreateAutoObject" since the latter one will start a new Word session. But this will only give you the right Word Application object, if word was not started before. So I suggest you to open the RTF document in Word using the "Documents.Open" method of the word application object (see below).

@Eric: Note that if your macro is called "CaptionTable", you need to put this in the OLE arguments, not the "PostProcessExport" stuff I posted as an example macro name.

The following works for me (on the appended AWordFile.doc, which contains a macro "TehMacro")
 

OleAutoObj     objWord  = oleCreateAutoObject("Word.Application")
if (null objWord) error "Could not open word!"
 
OleAutoObj      objWBS  = null
string          macroName       = "TehMacro"
string      fileName    = "C:\\Temp\\AWordFile.doc" 
OleAutoArgs     args            = create()
 
olePut (objWord, "Visible", true)
oleGet (objWord, "Documents", objWBS)
 
if (null objWBS) error "Documents not found!"
 
clear args; put (args, fileName); oleMethod (objWBS, "Open", args) 
clear args; put (args, macroName); oleMethod(objWord, "Run", args)

 


Hope this helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Could you possibly explain the use of "oleGetAutoObject" and "oleCreateAutoObject"?

My use of this is that it will be run after everything is exported into Word. Also, it doesn't have a concrete filename so I'm not sure if that poses a problem.

As I've said before, I'm new to DOORS especially the idea of exporting into Word. I'm going to try and figure this out between responses.

Thanks

Re: Using DXL to run a macro in word
Eric_Hillen - Mon Mar 07 09:54:20 EST 2011

Eric_Hillen - Mon Mar 07 09:26:59 EST 2011
Could you possibly explain the use of "oleGetAutoObject" and "oleCreateAutoObject"?

My use of this is that it will be run after everything is exported into Word. Also, it doesn't have a concrete filename so I'm not sure if that poses a problem.

As I've said before, I'm new to DOORS especially the idea of exporting into Word. I'm going to try and figure this out between responses.

Thanks

And another note that I'm trying to figure out is that this document isn't being saved during the process so it doesn't really have a location in which it could be found. So my complications with that seems like it would be with the filename.

Re: Using DXL to run a macro in word
Mathias Mamsch - Tue Mar 08 02:58:27 EST 2011

Eric_Hillen - Mon Mar 07 09:26:59 EST 2011
Could you possibly explain the use of "oleGetAutoObject" and "oleCreateAutoObject"?

My use of this is that it will be run after everything is exported into Word. Also, it doesn't have a concrete filename so I'm not sure if that poses a problem.

As I've said before, I'm new to DOORS especially the idea of exporting into Word. I'm going to try and figure this out between responses.

Thanks

Hi Eric,

OLE is basically an interface between applications, which allows you to remote control those. With MS Word (so called 'out of process server') you will control a MS Word application, that is started on your PC. It might be one, you started by hand or by the menu - you can also create a new one programmatically. That is the difference between "oleGetAutoObject" and "oleCreateAutoObject". The former one will take the FIRST Word Application that was started on your computer and return an OLE-remote-control handle. The latter one will start a new Word application and return a remote control OLE handle for this one.

So you see, your exporter will have a handle to the Word Application, during the export - if you want to modify your exporter to run your macro, you can reuse that handle. Just look for a line in the exporter code: <variable> = oleCreateAutoObject "Word.Application" or <variable> = oleGetAutoObject "Word.Application". Normally these variables are called something like objWord, oleObjWord, etc. This code might also be in an include file (e.g. for the standard exporters). In this case you can directly call "Run" as stated in the posts above. If you want to start your macros in your word file, but not from the export script, you need to obtain a handle to your Word application using oleGetAutoObject or you could just open a new word application with oleCreateAutoObject, load the word file, then run your macro in this application, then close it again. Hope that helps, regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: Using DXL to run a macro in word
llandale - Tue Mar 08 17:20:15 EST 2011

Mathias Mamsch - Sat Mar 05 18:03:14 EST 2011

@Louie:

If you start your word using system() then you will start a new word application. If you do this you need to do "oleGetAutoObject" instead of "oleCreateAutoObject" since the latter one will start a new Word session. But this will only give you the right Word Application object, if word was not started before. So I suggest you to open the RTF document in Word using the "Documents.Open" method of the word application object (see below).

@Eric: Note that if your macro is called "CaptionTable", you need to put this in the OLE arguments, not the "PostProcessExport" stuff I posted as an example macro name.

The following works for me (on the appended AWordFile.doc, which contains a macro "TehMacro")
 

OleAutoObj     objWord  = oleCreateAutoObject("Word.Application")
if (null objWord) error "Could not open word!"
 
OleAutoObj      objWBS  = null
string          macroName       = "TehMacro"
string      fileName    = "C:\\Temp\\AWordFile.doc" 
OleAutoArgs     args            = create()
 
olePut (objWord, "Visible", true)
oleGet (objWord, "Documents", objWBS)
 
if (null objWBS) error "Documents not found!"
 
clear args; put (args, fileName); oleMethod (objWBS, "Open", args) 
clear args; put (args, macroName); oleMethod(objWord, "Run", args)

 


Hope this helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Thanks. Turned your code into this library function, which I will now start using:

//**********************************************
OleAutoObj    fWord_OpenFile(string in_NameFile, in_NameMacro, string &out_ErrMess)
{     // Open the specified file with MS-Word, and return the OLE handle.
        // Handle is null upon failure
        // When non-null, attempt to run the specified Macro
        // If there was some error then return some message.
 
        // Original code by Mathias Mamsch 2011-Mar-05 posted on IBM forums here:
        //      http://www.ibm.com/developerworks/forums/thread.jspa?threadID=363362&tstart=0
 
        out_ErrMess                     = ""
        OleAutoObj      objWord         = oleCreateAutoObject("Word.Application")
        string  ErrMess = ""
 
        if (null objWord)
        {  out_ErrMess        = "Cannot open Word"
           return(objWord)
        }
 
        OleAutoObj      objWBS  = null
        OleAutoArgs     args            = create()
 
        olePut (objWord, "Visible", true)
        oleGet (objWord, "Documents", objWBS)
 
        if (null objWBS)
        {  out_ErrMess        = "Word Documents not found!"
           return(OleAutoObj)
        }
 
        clear args
        put (args, in_NameFile)
        ErrMess = oleMethod (objWBS, "Open", args) 
        if (!null ErrMess)
        {  out_ErrMess        = ErrMess
           return(objWord)
        }
 
        if (!null in_NameMacro)
        {  clear args
           put (args, in_NameMacro)
           oleMethod(objWord, "Run", args)
        }
        delete(args)
        return(objWord)
}    // end fWord_OpenFile()
 
//------------------------------------------
bool    fWord_OpenFile(string in_NameFile, in_NameMacro)
{    // Overloaded, close the returned OleAutoObj and ack the error message
        // Return if it worked OK
        string  ErrMess = ""
        OleAutoObj      objWord = fWord_OpenFile(in_NameFile, in_NameMacro, ErrMess)
        oleCloseAutoObject(objWord)
        if (!null ErrMess)
        {  warningBox("Word Error for file:\n'" in_NameFile "':\n" ErrMess)
           return(false)
        }
        else return(true)
}
 
string NameFile = "C:\\Doors-Stuff\\Reports\\ReportsRaw\\ReportObjHist_LPD26-IRLM-000541_2011-Feb-23_000.rtf"
 
fWord_OpenFile(NameFile, "Main_DxlFormatReport")              // Works
fWord_OpenFile(NameFile "xx", "Main_DxlFormatReport")               // Correctly fails, but opens empty Word
fWord_OpenFile(NameFile, "")                                  // Prompts to open read-only, doesn't run Macro


The Overloaded function is the one I'll use the fast majority of the time. Perhaps I'll add checks to see if the macro indeed ran OK.

This replaces my hopeless existing code that tries to find out where "WinWord.exe" is on the current system; looking in these locations, and THEN invoking "system" on that exectuable, along with the name of the file.

 

const string    cl_OfficeLocs[] = {
 
        getRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\13.0\\Common\\InstallRoot", "Path"),
        getRegistry( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\13.0\\Common\\InstallRoot", "Path"),
 
        getRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path"),
        getRegistry( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path"),
 
        getRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\11.0\\Common\\InstallRoot", "Path"),
        getRegistry( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\11.0\\Common\\InstallRoot", "Path"),
 
        getRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\10.0\\Common\\InstallRoot", "Path"),
        getRegistry( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\10.0\\Common\\InstallRoot", "Path"),
 
        getRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Office\\9.0\\Common\\InstallRoot",  "Path"),
        getRegistry( "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Office\\9.0\\Common\\InstallRoot",  "Path"),
 
        "Desktop\\",
        getenv("USERPROFILE") + "\\Desktop\\",
        "c:\\Program Files\\Microsoft Office\\Office\\",
        "c:\\Program Files\\Microsoft Office\\Office10\\",
        "c:\\Program Files\\Microsoft Office\\Office11\\",
        "c:\\Program Files\\Microsoft Office\\Office12\\",
        "c:\\Program Files\\Microsoft Office\\Office13\\",
        "d:\\Program Files\\Microsoft Office\\Office\\",
        "d:\\Program Files\\Microsoft Office\\Office10\\",
        "d:\\Program Files\\Microsoft Office\\Office11\\",
        "d:\\Program Files\\Microsoft Office\\Office12\\",
        "D:\\Program Files\\Microsoft Office\\Office13\\"
                                }    // end definition of cl_OfficeLocs[]


Yuuck, no laughing please! Like I said, I'm not very good at this API stuff!

Thanks. - Louie