Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (1)


Delphi and Automation with WordFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi 3.x (or higher)
Category:
OLE
Skill Level:
Scoring:
Last Update:
02/07/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet OLE COM WinWord
Times Scored:
4
Visits:
9213
Uploader: Herbert Poltnik
Company:
Reference: http://vzone.virgin.net/graham.marshall/word.htm
 
Question/Problem/Abstract:
Automation allows one application to control another application. The application being controlled is called an automation server (in our case Word). The application controlling the server is called an automation controller.
Answer:



Delphi 3 and Automation with Word.

Automation allows one application to control another application. The application being controlled is called an automation server (in our case Word). The application controlling the server is called an automation controller.

There are two ways that automation servers can be accessed:

Late Binding (IDispatch interface)

When using this method, function names and parameter datatypes are resolved at runtime, all parameters are passed as variants.

As no errors in function names or parameter types are reported at compile time, this method is error prone.

As function names and parameter types need to be looked up at runtime, performance is slow.

The only advantage of this method for Delphi programming is that it is the only way optional parameters can be omitted from function calls.

Early Binding (Using type libraries/interfaces)

When using this method, function names and parameter datatypes are all resolved at compile time.

A type library needs to be imported into Delphi. A type library is a language neutral description of all the objects and functions exposed by a server. (This is similar in nature to a C header file).

All parameters need to be supplied, even when calling functions where the documentation states that some are optional. This enables many errors to be detected and corrected before ever running a program.

Performance is better than for late binding.

Due to the advantages of the second approach, the rest of the document demonstrates the basics of creating an application with early binding. All applications that use Word Automation should use this technique unless there is a strong justification for not doing so.

Preparing the Type Library.

A pascal unit needs to be created from the type library file.

Select Project|Import Type Library menu item.
Press the add button and select the following file
c:\program files\microsoft office\office\msword8.olb
Select OK.
Unfortunately, this leaves the project in a state that will not compile, this is because the word_tlb unit redefines the word application to mean something else.

The easiest way to resolve this is to remove the word_tlb unit from the project and only add it to the uses clause of the units that perform automation.

Documentation

The help file c:\program files\microsoft office\office\vbawrd8.hlp contains information about the objects available for Word.

The macro recorder allows VBA code to be created. This can then be taken and translated into Delphi quite easily.

Automation Example


The following example uses a Delphi wrapper class to hide direct calls to the Word objects. This makes word easier to use in the following ways:

Provides paramaters hiding. Allows default parameters to be set for many methods. Many of the word methods also take var paramaters. This means that constants cannot be used, parameter hiding overcomes this.
Provides type checking. Many of the methods are defined as taking OLEVariant parameters where integer or other types are appropriate.
The following wrapper class demonstrates the key techniques in automating word. The full class in listed in Appendix 1.
unit doc;

interface

uses

windows, sysutils, Word_TLB;

type

TWinWord = class

Private

App : _Application;

public

constructor Create;

destructor Destroy; override;

procedure NewDoc(Template : String);

procedure GotoBookmark(Bookmark : String);

procedure InsertText(Text : String);

procedure SaveAs(Filename : string);

end;

//------------------------------------------------------------------

implementation

//------------------------------------------------------------------

constructor TWinWord.Create;

begin

App := CoApplication.Create;

end;

//------------------------------------------------------------------

destructor TWinWord.Destroy;

var

SaveChanges : OLEVariant;

OriginalFormat : OLEVariant;

RouteDocument : OLEVariant;

begin

SaveChanges := wdDoNotSaveChanges;

OriginalFormat := unAssigned;

RouteDocument := unAssigned;

app.Quit(SaveChanges, OriginalFormat, RouteDocument);

inherited destroy;

end;

//------------------------------------------------------------------

procedure TWinWord.GotoBookmark(Bookmark : string);

var

What : OLEVariant;

Which : OLEVariant;

Count : OLEVariant;

Name : OLEVariant;

begin

What := wdGoToBookmark;

Which := unAssigned;

Count := unAssigned;

Name := Bookmark;

App.Selection.GoTo_(What, Which, Count, Name);

end;

//------------------------------------------------------------------

procedure TWinWord.InsertText(Text : String);

begin

App.Selection.TypeText(Text);

end;

//------------------------------------------------------------------

procedure TWinWord.NewDoc(Template : String);

var

DocTemplate : OleVariant;

NewTemplate : OleVariant;

begin

DocTemplate := Template;

NewTemplate := False;

App.Documents.Add(DocTemplate, NewTemplate);

end;

//------------------------------------------------------------------

procedure TWinWord.SaveAs(Filename : string);

begin

OLEVariant(App).ActiveDocument.SaveAs(FileName);

end;

//------------------------------------------------------------------

end.



To create the class:

Add the type library unit to the uses clause.

uses

windows, sysutils, Word_TLB;

Create the class definition:

TWinWord = class

Private

App : _Application;

public

procedure NewDoc(Template : String);

procedure GotoBookmark(Bookmark : String);

procedure InsertText(Text : String);

procedure SaveAs(Filename : string);

constructor Create;

destructor Destroy; override;

end;

The App variable is a Word application variable reference. This allows the word methods to be called using early binding.

The public procedures are the procedures which can be called by the user of the class.

Implement the constructor.

constructor TWinWord.Create;

begin

App := CoApplication.Create;

end;

This is called when an instance of the class TWinWord is created. CoApplication.create creates a new instance of word and returns a reference to the Application interface. This will allow us to call methods of the app object.

Implement a destructor

destructor TWinWord.Destroy;

var

SaveChanges : OLEVariant;

OriginalFormat : OLEVariant;

RouteDocument : OLEVariant;

begin

SaveChanges := wdDoNotSaveChanges;

OriginalFormat := unAssigned;

RouteDocument := unAssigned;

app.Quit(SaveChanges, OriginalFormat, RouteDocument);

inherited destroy;

end;

The destructor MUST be called. The quit method of the Word application object closes word and frees all the memory allocated by it. As the parameters of the of the quit method are defined as var parameters of type OLEVaraint, storage must be allocated for them.

Implement the NewDoc method. This method creates a new word document based on the specified template.

procedure TWinWord.NewDoc(Template : String);

var

DocTemplate : OleVariant;

NewTemplate : OleVariant;

begin

DocTemplate := Template;

NewTemplate := False;

App.Documents.Add(DocTemplate, NewTemplate);

end;

This method forces stricter type checking within the Delphi class than is performed within the Word application. The parameter Template must be a valid word template in a string. Word’s Add method will take any datatype as the parameter. A better example of this can be seen in the MoveRight method in Appendix 1.

Impelement the SaveAs method. This method saves the current document as an operating system file.

procedure TWinWord.SaveAs(Filename : string);

begin

OLEVariant(App).ActiveDocument.SaveAs(FileName);

end;

This example uses late binding. This results in the method name and datatypes not being checked until runtime. Placing any method name will not cause a compile time error. This is useful in this case as the SaveAs method takes 12 parameters and only the filename is mandatory. As this call will be made infrequently, any performance loss from using late binding will be unnoticed.



The following code sample demonstrates using this class to create, edit, print and save a document based on a template:

Word := TWinWord.create;

try

Word.visible := true;

Word.NewDoc('c:\delphi\word\sample\Demo');

Word.GotoBookmark('From');

Word.InsertText('Graham Marshall');

Word.GotoBookmark('Dept');

Word.InsertText('Development');

Word.GotoBookmark('Phone');

Word.InsertText('111111');

Word.GotoBookmark('Now');

Word.InsertText(FormatDateTime('d-mmm-yyyy', now));

//SF Items

Word.GotoBookmark('Items');

Word.InsertText('112021');

Word.MoveRight(1);

Word.InsertText('PVCS');

Word.MoveRight(1);

Word.InsertText('1');

Word.MoveRight(1);

Word.InsertText('£ 305.99');

Word.MoveRight(1);

Word.InsertText('£ 305.99');

Word.MoveRight(1);

Word.UpdateFields;

Word.RunMacro('Demo');

Word.Print;

Word.SaveAs(filename);

finally

Word.Free;

end;





Summary

Where possible use early binding.
Typecast the application object to an OLEVariant to force late binding.
Do not include the type library unit within your project. Only add it to the uses clause of units which call automation objects.
Keep automation code within a separate unit. Encapsulate calls within a wrapper class.
Use the Word macro recorder to prototype your automation code.
Use the vbawrd8.hlp file for programming information.
Use the unit Word_tlb.pas to check for Delphi parameter types and numbers. If code completion does not seem to be working, press to recompile your code.
Base documents on word templates that contain predefined text and formatting and then super-impose data. This is faster and reduces the programming required to create formatted documents. Templates MUST be stored with the application in the application directory. This will remove the possibility of name clashes.
Use Bookmarks to define areas for text insertion by the Delphi Application.
Ensure that the quit method is called for the Word application object (app.quit). Not calling app.quit will quickly exhaust all windows resources as multiple instances of Word will be created. These may not be visible.
It is easy to check for multiple instances of Word by using the NT Task Manager Processes Page (press CTL+ALT+Del to access this.)



Appendix A – Full TWinWord class source

The full source for the tWinWord class is show below. This include the implementation of all methods:

unit doc;

interface

uses

Word_TLB, windows, sysutils;

Type

TWinWord = class

Private

App : _Application;

function fGetVisible : boolean;

procedure fSetVisible(visible : boolean);

public

procedure NewDoc(Template : String);

procedure GotoBookmark(Bookmark : String);

procedure InsertText(Text : String);

procedure MoveRight(Count : integer);

procedure Print;

procedure UpdateFields;

procedure SaveAs(Filename : string);

Procedure RunMacro(MacroName : string);

constructor Create;

destructor Destroy; override;

property visible : boolean

read fGetVisible

write fSetVisible;

end;



implementation

//------------------------------------------------------------------

constructor TWinWord.Create;

begin

App := CoApplication.Create;

end;

//------------------------------------------------------------------

destructor TWinWord.Destroy;

var

SaveChanges : OLEVariant;

OriginalFormat : OLEVariant;

RouteDocument : OLEVariant;

begin

SaveChanges := wdDoNotSaveChanges;

OriginalFormat := unAssigned;

RouteDocument := unAssigned;

app.Quit(SaveChanges, OriginalFormat, RouteDocument);

inherited destroy;

end;

//------------------------------------------------------------------

function TWinWord.fGetVisible : boolean;

begin

result := App.Visible;

end;

//------------------------------------------------------------------

procedure TWinWord.fSetVisible(Visible : boolean);

begin

App.visible := Visible;

end;

//------------------------------------------------------------------

procedure TWinWord.GotoBookmark(Bookmark : string);

var

What : OLEVariant;

Which : OLEVariant;

Count : OLEVariant;

Name : OLEVariant;

begin

What := wdGoToBookmark;

Which := unAssigned;

Count := unAssigned;

Name := Bookmark;

App.Selection.GoTo_(What, Which, Count, Name);

end;

//------------------------------------------------------------------

procedure TWinWord.InsertText(Text : String);

begin

App.Selection.TypeText(Text);

end;

//------------------------------------------------------------------

procedure TWinWord.NewDoc(Template : String);

var

DocTemplate : OleVariant;

NewTemplate : OleVariant;

begin

DocTemplate := Template;

NewTemplate := False;

App.Documents.Add(DocTemplate, NewTemplate);

end;

//------------------------------------------------------------------

procedure TWinWord.MoveRight(Count : integer);

var

MoveUnit : OleVariant;

vCount : OleVariant;

Extended : OleVariant;

begin

MoveUnit := wdCell;

vCount := Count;

Extended := unassigned;

app.selection.MoveRight(MoveUnit, vCount, Extended);

end;

//------------------------------------------------------------------

procedure TWinWord.Print;

begin

OLEVariant(app).Printout;

end;

//------------------------------------------------------------------

procedure TWinWord.UpdateFields;

begin

App.ActiveDocument.Fields.Update;

end;

//------------------------------------------------------------------

procedure TWinWord.SaveAs(Filename : string);

begin

OLEVariant(App).ActiveDocument.SaveAs(FileName);

end;

//------------------------------------------------------------------

procedure TWinWord.RunMacro(MacroName : string);

begin

App.Run(MacroName);

end;

//------------------------------------------------------------------

end.






Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Too bad
    Jos Visser (Jun 27 2003 4:19PM)

You write a lot of info about how to import the type library and such. This is good, but it's general COM info, nog specific to Word. Then you start given numerous examples, which will eventually cover only a fraction of the total possibilities.
If you want a good documentation on what you can do with Word, just check Word's VBA documentation.

This VBA code can be easily translated to Delphi:

VBA:
Selection.Goto What:=what, Which:=which, ...

Delphi
App.Selection.Goto(what, which, ...)

Once you find your way in the VBA documentation, you can actually use every aspect of Word in your application.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
M. Kleiner
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)