Toflidium.com Articles

Calling Word Macros from a Delphi Application.

By Toby Allen
Tuesday, January 09, 2001

Download the source

Recently I've seen this question being asked a number of times on the borland Newgroups.  It goes something like.

"I've got this word document and it has a macro on it, and I've tried everyway I can think of but I cant call the macro from Delphi.  Someone told me this was possible.  How do I do it?"

Well it is indeed possible, and is actually very simple as long as you follow a couple of simple steps.

  • Declare you word subs as Public
  • In Delphi Reference your Word Document as an Olevariant.
  • Use standard ole types for argument values.
  • Debug with Word Visible!!!

How to get it to work.

In order to make it work, you just need to write code that

  1. Creates a word application.
  2. Opens the word document or template with the macro in it.
  3. Keep a reference to the word document as an olevariant.
  4. Call the function/Sub as a method of the document.

Here is some pascal code (the full source for a demo is also available for download) that shows how we do this.

procedure TForm1.Button1Click(Sender: TObject);
var
  Wordapp : oleVariant;
  Doc : olevariant;// Will hold the word document, we wish to call the macro on.
begin
  {Create the word application, and make it visible.  Always make your
  word application visible while you are debugging. }
  Wordapp := CreateOleObject('Word.Application') ;
  Wordapp.visible := true;

  {Open a doc file.  Call one of its
  public methods with an argument value.}
  Doc := Wordapp.documents.Open(ExtractFilePath(Application.ExeName)
				+ '\docwithmacro.doc');

  {This function, which is a function I wrote in the
  word document, simply add some
  text to the body of the document, which is an easy thing to do,
  but illustrates the technique.}
  Doc.AddWordsToDocument(edAddText.text);

end;
That is all there is to it. Its not complicated or difficult. You must however use latebinding (as I try and explain below). You might be able to actually refer to the Word.Application as early binding, and the Word.Document as an olevariant and latebinding, but I havent tried that. I suggest you use this technique when it is essential that you call a macro on a word document.

But I want to use early Binding!

Well unfortunatly you can't. COM is based around defined interfaces, and a word document implements one such interface, which gives us all the normal methods that we can call on a word document, such as inserting text, setting footers etc, however there is no methods in the interface for any new methods that we might add to the document. Therefore if we reference the document using Early binding, ie., as a Document type, we can only see the methods that the interface supports. However when you call by late binding it is possible for word to check if the method exists. If your interested in my personal thoughts on why this is possible, read on.

Why is this possible?

This is my own theory, and may be miles off the ball, but I like it. If you know of a better reason email me.

Essentially what I reckon happens is that through some use of IDispatch, microsoft is able to intercept any late bound call to a method in a word document, see if it exists as a Word Macro in the document and call it if it does. If it does not, then the function call returns "Interface does not support this property or method."

Comment on this article in the forums

About Us | Site Map | Contact Us | ©2003 Toby Allen - Toflidium Software