Link to home
Start Free TrialLog in
Avatar of ClaudeMartel
ClaudeMartel

asked on

How to programmatically add a macro to a Word document

I need to know how to programmatically add a macro to a Word document. The macro is custom-generated for each document. Therefore, I cannot ask a user to manually add and run the macro each time a document is opened.

The macro needs to start upon document opening and will basically perform final processing on the document itself.

Consequently, I think I need, from another programming language, a way to merge a macro to an existing word document. Maybe another way would be to tell word to run an external macro, stored on the disk.

Is that feasible?
Avatar of tculler
tculler
Flag of United States of America image

Claude,

     You can use VBA from ANY of the Office Applications, and control any other application, as long as you reference the correct Object Library.  Since the Macro needs to run on each document that the user is working in, but you don't want the user to have to create it, I would suggest creating the macro somewhere else, like MS Access, where you could have it hooked to a command button on a form.  When the user clicks on the command button, it could reach out and process the word document.  You could use a text box (where the user filled in their path and filename) to tell it what document to open and process.

Here is some sample code to do something in Word from Access:
Private Sub cmdFixWordDoc_Click()
' this procedure uses Word Objects, and requires a reference to
' the Microsoft Word Object Library, under Tools, References
' from any module
On Error GoTo cmdFixWordDoc_Error
' variables for our User Input
Dim strPath As String

strPath = Me!txtPath


' Word Object Variables
Dim wdApp As Word.Application
Dim wdDoc As Word.Document
Dim r As Word.Range

Set wdApp = New Word.Application
  With wdApp
    Set wdDoc = .Documents.Open strPath
    With wdDoc

' DO YOUR PROCESSING HERE

      .SaveAs "C:\Practice\MyFinishedBillOfSale.doc"
     
       
        ' the following line will automatically send your results to the printer
        ' comment out if not needed
        .PrintOut
    End With
    ' this would let you see the document.  Comment out if not needed
    .Visible = True
  End With
  ' this is for testing, comment out when done
  Stop
' close object variables and release memory
wdDoc.Close
Set wdDoc = Nothing
wdApp.Quit
Set wdApp = Nothing

cmdFixWordDoc_Exit:
Exit Sub

cmdFixWordDoc_Error:
MsgBox "There was an error processing your Document!  Error No: " & Err.Number & vbCrLf & Err.Description
Resume cmdFixWordDoc_Exit

End Sub




Hope this helps!

Tim
Avatar of ClaudeMartel
ClaudeMartel

ASKER

I know I can automate Word from a lot of applications. I currently automate Word from a Delphi program. The problem is that performance is poor.

Typically, a Word macro will run 5 times faster than the equivalent automation program.

This is why I want my macro to reside in the Word document.
ClaudeMartel, Macros in Word can reside in documents and you can have them run upon immediately upon opening the document. We can give you more details on that if you want.

As for running an external macro, all macros in Word have to live in either a document or a template. So, for example, you could have a macro in a template in Word (say Normal or another global template) that then iterates through a series of documents to be named and performs certain processes on each of those documents.

Does that answer your question?
Well... my question being "How can I programmatically add a macro to a Word document?", I do not think I am getting an answer (By the way, I cannot be done is a valid answer)

Thanks.
But it can be done :)

I suppose you already created an instance of a Document object right? Very well, Document has a property VBProject that represents the VBA Project associated with the document. You just have to add VBComponents (aka modules) to it or edit the ones it already has. What would you prefer? You can look at the help for reference and post your doubts here or ask for some code snippets to help you. Just say which option you prefer.

As to making code run on opening the document you can trap the Open event of the document and perform the actions you want. On your document module just define the sub Document_Open like so:

--
Private Sub Document_Open()

End Sub
--

Hope this helps

Paulo
ASKER CERTIFIED SOLUTION
Avatar of pauloaguia
pauloaguia
Flag of Portugal image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks a lot.

I was just about to figure it out myself. The sample (Delphi code) I was testing is:

  W := TWordApplication.Create(self);
  W.Connect;
  W.Activate;

  Macro := W.ActiveDocument.VBProject.VBComponents.Add(1);
  Macro.CodeModule.AddFromString('Sub ShowHello()' + #13 + 'MsgBox("Hello")' + #13 + 'End Sub');
  W.Run('ShowHello');
  W.ActiveDocument.VBProject.VBComponents.Remove(Macro);

  W.Free;
Glad to help. Thanks for the points :)