How to use OLE2 for Word
Date: 2000/08/01
Message-ID: <8m6fjh$md4$1_at_nnrp1.deja.com>
This is all the information I have acquired. Hope it helps someone as I could have done with it!
2. A new instance of Excel is created each time you initiate the server
even though the server is already up and running
Problem
In Forms, you can use OLE to call Microsoft Word or Microsoft Excel. For
example, you can create a button to invoke Excel. Consequently, more than one
Excel instance will be invoked if you press the button several times, which
uses unnecessary system resources and can lead to a system crash. To reproduce the problem:
- Create a button in a form.
- Create the following When-Button-Pressed trigger code: DECLARE appl OLE2.OBJ_TYPE; workbooks OLE2.OBJ_TYPE; workbook OLE2.OBJ_TYPE; BEGIN appl := OLE2.CREATE_OBJ('Excel.Application'); OLE2.SET_PROPERTY(appl, 'Visible', 'True'); workbooks := OLE2.INVOKE_OBJ(appl, 'Workbooks'); workbook := OLE2.INVOKE_OBJ(workbooks, 'Add'); END;
- Run the form, and press the button twice.
Note that two MS Excel instances are called.
Solution
It is not enough to check if the Excel server is already running because a handle to the Excel server is required. Instead, store the handle to the Excel server in a package variable that can be used throughout the form. Hence, OLE2.Create_Obj is performed only once in a Forms session, which opens one instance of Excel. To prevent ORA-305500 from occurring if the user closes Excel
(therefore, loses the handle to the server), trap this error and
issue OLE2.Create_Obj to reacquire the handle to the server.
OLE Automation of Word97 with Developer/2000 Forms ==================================================
INTRODUCTION:
This bulletin explains the Word97 Object model and how Oracle Forms can
make
use of the objects exposed by the Word97 OLE automation server. It
contains
examples of automating an independent Word97 application as well as for
embedded
or linked Word applications.
The bulletin does NOT talk about the OLE and OLE Automation features in
Oracle
Forms. References 1 & 2 are a good source of information on this
subject.
The focus here is on the Word97 Object model and it builds on the
examples
provided in Reference 3 (OLE Automation Guide - Oracle Forms to
Microsoft
Word95).
OLE/OLE2/OLE Automation concepts:
OLE(Object Linking and Embedding):
It is the technology that allows a programmer to build software components
(interoperalble objects) that adhere to a specific interface. This
enables
you to create applications for users that allows one large document to consist
of a variety of smaller documents, each created in a different application.
OLE2:
Extended the concept of OLE from compound documents to OLE Automation and a
number of other extensions to the original specification.
OLE Automation:
OLE server applications expose the properties and methods of their component
objects to other Windows applications. OLE client applications can programmatically manipulate OLE server applications through reading/writing
their exposed properties and invoking their exposed methods. This process of
controlling of OLE server applications from OLE client applications is known as 'OLE Automation'.
Object Models compared
Word6/Word7(Word95)
Word95 supported OLE Automation through a single 'Basic' object
(Word.Basic).
This was the Word's own Macro language interpreter.
While Word95 could provide an object to another application (like
Visual Basic
or Oracle Forms) for OLE Automation, it could not use OLE Automation to
access
objects in other applications. In other words, applications that
support OLE
Automation, such as Microsoft Excel95 or a Visual Basic application,
could use
OLE Automation to access Word, but Word could not use OLE Automation to
access
them.
Word97
In Word97 every element - documents, tables, paragraphs, bookmarks,
fields and
so on can be represented by an object in Visual Basic. The Word97
object
model
is based on the VBA (Visual Basic for Applications) instead of the
WordBasic
interpreter. The VBA is the edition of Visual Basic designed to
provide
development capabilities by embedding itself directly inside the host
application
and is standard across the Office97 suite.
The primary difference between Visual Basic for Applications and
WordBasic is
that whereas the WordBasic language consists of a flat list of
approximately
900
commands, Visual Basic consists of a hierarchy of objects, each of
which
exposes
a specific set of methods and properties (similar to statements and
functions
in
WordBasic). While most WordBasic commands can be run at any time,
Visual Basic
only exposes the methods and properties of the available objects at a
given
time.
You now have an OLE Automation object called 'Application'
(Word.Application)
which contains methods and properties which return other top-level
objects.
For
example, the 'ActiveDocument' property returns a 'Document' object.
This can be best visualised by looking at:
Microsoft Word Help
|
|-->Microsoft Word Visual Basic Reference
| |-->Getting Started with Visual Basic | |-->Microsoft Word Objects
In this hyperlinked chart you can see individual objects as well as the
Object
Collections (collection of similar objects).
Converting from WordBasic to Visual Basic
Microsoft Word Visual Basic Reference
|
|-->Getting Started with Visual Basic
| |-->Converting from WordBasic to Visual Basic | |-->Visual Basic Equivalents for WordBasic Commands
This section gives an alphabetical listing of the Visual Basic command
equivalents
for WordBasic commands.
The simplest example would be to display the main application window
for Word
on
the screen -
Word95
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
END; Word97
If you look under 'Visual Basic Equivalents for WordBasic Commands' in
the
on-line help, you can find the following entry for the 'AppShow'
command:
AppShow => Application.Visible = True
So the modified code should be:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
BEGIN
- Create the Word.Application object and make Word visible
- by setting the 'Visible' property to true application:=OLE2.CREATE_OBJ('Word.Application'); OLE2.SET_PROPERTY(application, 'Visible', 1);
END; OLE Automation examples with Word97
Example 1
This example creates a new Word document, inserts some text in it and saves
its contents into a new file.
DECLARE
- Declare the OLE objects MyApplication OLE2.OBJ_TYPE; MyDocuments OLE2.OBJ_TYPE; MyDocument OLE2.OBJ_TYPE; MySelection OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Create the Word.Application object and make Word visible
- by setting the 'Visible' property to true MyApplication:=OLE2.CREATE_OBJ('Word.Application'); OLE2.SET_PROPERTY(MyApplication, 'Visible', 1);
- get a handle on Documents collection MyDocuments:=OLE2.GET_OBJ_PROPERTY(MyApplication, 'Documents');
- Add a new document to the Documents collection Mydocument :=OLE2.INVOKE_OBJ(MyDocuments,'Add');
- get a handle on Selection object MySelection:=OLE2.GET_OBJ_PROPERTY(MyApplication, 'Selection');
- Insert the text 'Hello Word97!' into word document OLE2.SET_PROPERTY(MySelection, 'Text', 'Hello Word97!');
- Save the document to the filesystem as EXAMPLE.DOC args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'D:\VPURI\DOCS\EXAMPLE.DOC'); OLE2.INVOKE(MyDocument, 'SaveAs', args); OLE2.DESTROY_ARGLIST(args);
- Close the document OLE2.INVOKE(MyDocument, 'Close');
- Release the OLE objects OLE2.RELEASE_OBJ(MySelection); OLE2.RELEASE_OBJ(MyDocument); OLE2.RELEASE_OBJ(MyDocuments); OLE2.RELEASE_OBJ(MyApplication);
END; The Visual Basic code to achive the same functionality as above:
Sub Example1()
Set MyApplication = GetObject(, "Word.Application") MyApplication.Visible = True
Set MyDocuments = MyApplication.Documents Set MyDocument = MyDocuments.Add
Set MySelection = MyApplication.Selection MySelection.Text = "Hello Word97!"
MyDocument.SaveAs FileName:="D:\VPURI\DOCS\EXAMPLE.DOC" MyDocument.Close
Set MySelection = Nothing
Set MyDocuments = Nothing
Set MyApplication = Nothing
End Sub
Example 2
This example illustrates the use of a predefined bookmark in a Word document
DECLARE
- Declare the OLE objects MyApplication OLE2.OBJ_TYPE; MyDocuments OLE2.OBJ_TYPE; MyDocument OLE2.OBJ_TYPE; MySelection OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Create the Word.Application object and make Word visible
- by setting the 'Visible' property to true MyApplication:=OLE2.CREATE_OBJ('Word.Application'); OLE2.SET_PROPERTY(MyApplication, 'Visible', 1);
- get a handle on Documents collection MyDocuments:=OLE2.GET_OBJ_PROPERTY(MyApplication, 'Documents');
- Open a new document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'D:\VPURI\DOCS\EXAMPLE.DOC'); Mydocument :=OLE2.INVOKE_OBJ(MyDocuments,'Open',args); OLE2.DESTROY_ARGLIST(args);
- get a handle on Selection object MySelection:=OLE2.GET_OBJ_PROPERTY(MyApplication, 'Selection');
- Navigate to the Bookmark called 'MyBookmark'
- VBA Syntax: Selection.Goto(What, Which, Count, Name)
- Which, Count are optional and are specified only because the values
- of the parameters are position dependent.
args:=OLE2.CREATE_ARGLIST;
OLE2.ADD_ARG(args, -1); -- What => constant
'wdGoToBookmark' = -1
OLE2.ADD_ARG(args,0); -- Which OLE2.ADD_ARG(args,0); -- Count OLE2.ADD_ARG(args, 'MyBookmark'); -- Name => bookmark name OLE2.INVOKE(MySelection,'GoTo',args);
- Insert some text at the bookmark location OLE2.SET_PROPERTY(MySelection, 'Text', '** Inserting at MyBookmark **');
- Release the OLE objects OLE2.RELEASE_OBJ(MySelection); OLE2.RELEASE_OBJ(MyDocument); OLE2.RELEASE_OBJ(MyDocuments); OLE2.RELEASE_OBJ(MyApplication);
END; Visual Basic code:
Sub Example2()
Set MyApplication = GetObject(, "Word.Application") MyApplication.Visible = True
Set MyDocuments = MyApplication.Documents
Set MyDocument = MyDocuments.Open(FileName:="D:
\VPURI\DOCS\EXAMPLE.DOC")
Set MySelection = MyApplication.Selection
MySelection.GoTo What:=wdGoToBookmark, Name:="mybookmark"
'wdGoToBookmark = -1
MySelection.Text = "** Inserting at MyBookmark **"
Set MySelection = Nothing Set MyDocuments = Nothing Set MyDocuments = Nothing
Set MyApplication = Nothing
End Sub
Example 3
If the tasks you want to perform in Word are completely self-contained
and do
not require any parameters to be passed in from Oracle Forms, it may be
preferable to create a VBA macro within Word itself and invoke the
macro via
OLE automation. The following example opens a word document
EXAMPLE.DOC and
executes the VBA macro called 'MyMacro'
DECLARE
- Declare the OLE objects MyApplication OLE2.OBJ_TYPE; MyDocuments OLE2.OBJ_TYPE; MyDocument OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Create the Word.Application object and make Word visible
- by setting the 'Visible' property to true MyApplication:=OLE2.CREATE_OBJ('Word.Application'); OLE2.SET_PROPERTY(MyApplication, 'Visible', 1);
- get a handle on Documents collection MyDocuments:=OLE2.GET_OBJ_PROPERTY(MyApplication, 'Documents');
- Open a new document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'D:\VPURI\DOCS\EXAMPLE.DOC'); Mydocument :=OLE2.INVOKE_OBJ(MyDocuments,'Open',args); OLE2.DESTROY_ARGLIST(args);
- Execute the macro called 'MyMacro' args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'MyMacro'); OLE2.INVOKE(MyApplication,'Run',args); OLE2.DESTROY_ARGLIST(args);
- Release the OLE objects OLE2.RELEASE_OBJ(MyDocument); OLE2.RELEASE_OBJ(MyDocuments); OLE2.RELEASE_OBJ(MyApplication);
END; Example 4
This example shows the automation of an embedded/linked word document - it Runs a macro called 'MyMacro' in the embedded/linked document.
DECLARE
- Declare the OLE objects MyApplication OLE2.OBJ_TYPE; MyDocument OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Open Word97 and activate it FORMS_OLE.ACTIVATE_SERVER('OLEWORD.DOC');
- Verb index 1 => Open the embedded document for editing FORMS_OLE.EXEC_VERB('OLEWORD.DOC',1);
- Get a handle on the Word document in the OLE container MyDocument := FORMS_OLE.GET_INTERFACE_POINTER('OLEWORD.DOC');
- Get a handle on the Application object MyApplication := OLE2.GET_OBJ_PROPERTY(MyDocument,'Application');
- Execute the macro called 'MyMacro' args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'MyMacro'); OLE2.INVOKE(MyApplication,'Run',args); OLE2.DESTROY_ARGLIST(args);
- Release the OLE objects OLE2.RELEASE_OBJ(MyDocument); OLE2.RELEASE_OBJ(MyApplication);
- Close Word FORMS_OLE.CLOSE_SERVER('OLEWORD.DOC');
This bulletin compared the Word97 and Word95 Object models. It
explained
with the help of simple examples how you can make use of the new object
model to redesign your existing Oracle Forms Applications which can make
use of the advanced OLE Automation features in Word'97.
Guide to OLE Automation - Oracle Forms to Microsoft Word 95
Introduction
This article explains the basic concepts of OLE automation and in particular
how to use the OLE automation facilities within Oracle Forms V4.5 to automate
Microsoft Word. Code examples are included.
Basic OLE Automation principles
Objects are the fundamental components of OLE applications. Every element of
an OLE server application can be represented as an object. Each of these
objects is defined by its properties (physical and logical characteristics)
and its methods (actions which the object can perform).
OLE server applications expose the properties and methods of their
component
objects to other Windows applications. OLE client applications can
programmatically manipulate OLE server applications through
reading/writing
their exposed properties and invoking their exposed methods. This
process of
'remote control' of OLE server applications from OLE client
applications is
known as 'OLE Automation'.
The original OLE ('Object Linking and Embedding') specification,
created in
1991 concentrated on the creation of compound documents via the linking
or
embedding of server application documents inside container applications
(a process from which OLE gained its original and now obsolete title).
The much broader OLE2 specification introduced the concept of OLE
automation
along with a number of other extensions to the original OLE
specification.
Only applications supporting the OLE2 specification can therefore
participate
in OLE automation. Separate aspects of the OLE2 specification cover OLE
automation client and OLE automation server functionality so an
application
must support the respective aspects of the OLE2 specification to
function as
an OLE automation client, OLE automation server or both.
Before writing code to perform OLE automation, it is necessary for an application developer to understand the following things:
o The object classes exposed by the OLE automation server and the relationships between them (the OLE automation server's 'Object Model').
o The properties of the OLE automation server's objects, their datatypes and valid values
o The methods of the OLE automation server's objects, their syntax and arguments
o The methods used by the OLE automation client to access the methods and properties of the OLE automation server's objects
This article will describe the Object Model of Word and the methods
used by
Oracle Forms to perform OLE automation with Word.
The Microsoft Word Object Model
Microsoft Word can function as an OLE automation client or OLE automation
server. This section describes the Object Model which enables Word to be
used as an OLE automation server.
In most OLE server applications (e.g. Microsoft Excel) there are many
different OLE object classes in the Object Model (e.g. Worksheets,
Charts,
Titles in Excel) which can be individually manipulated via their
properties
and methods. In Microsoft Word there is just one object of interest.
This
is the WordBasic interpreter used by Microsoft Word to execute commands
written in Word's own macro language, WordBasic. Instead of executing
methods or setting properties for specific objects (e.g. Document,
Header,
Footer, Paragraph) within a Word document, WordBasic macro statements
are
sent to the WordBasic interpreter to perform the requested tasks on
behalf of
the OLE client application.
Although this method of automation doesn't strictly comply to the
spirit of
OLE, it does make the process of remote automation of Word simple. All
that
is required is to create an OLE object of the class "Word.Basic" and
send
WordBasic macro statements to this object for execution.
Oracle Forms and OLE Automation
Oracle Forms can operate as an OLE automation client only.
OLE automation client functionality is implemented in Oracle Forms
through a
number of built-in PL/SQL procedures and functions contained in the OLE2
PL/SQL package. The OLE2 PL/SQL package provides a PL/SQL API for
creating
OLE automation server objects and accessing the properties and methods
of
these objects.
The OLE2 PL/SQL package defines two additional PL/SQL datatypes which
are
used by the OLE2 built-ins:
OBJ_TYPE A handle to an OLE object LIST_TYPE A handle to an OLE argument list
Each of the PL/SQL procedures and functions in the OLE2 package is
described
below along with its PL/SQL specification:
Object Management
CREATE_OBJ
Creates an OLE object and returns an object handle.
CREATE_OBJ(OBJECT IN VARCHAR2) RETURN OBJ_TYPE
RELEASE_OBJ
Deallocates all resources for an OLE object created by CREATE_OBJ
and destroys the object handle.
RELEASE_OBJ(OBJECT IN OBJ_TYPE)
Object Property Access
GET_CHAR_PROPERTY
Reads a character property of an OLE object.
GET_CHAR_PROPERTY(OBJECT IN OBJ_TYPE, PROPERTY IN VARCHAR2, ARGLIST
IN LIST_TYPE) RETURN VARCHAR2
GET_NUM_PROPERTY
Reads a number property of an OLE object.
GET_NUM_PROPERTY(OBJECT IN OBJ_TYPE, PROPERTY IN VARCHAR2, ARGLIST
IN LIST_TYPE) RETURN NUMBER
GET_OBJ_PROPERTY
Reads an object property of an OLE object.
GET_OBJ_PROPERTY(OBJECT IN OBJ_TYPE, PROPERTY IN VARCHAR2, ARGLIST
IN LIST_TYPE) RETURN OBJ_TYPE
SET_PROPERTY
Sets the value of a number or character property of an OLE object.
SET_PROPERTY(OBJECT IN OBJ_TYPE, PROPERTY IN VARCHAR2, VALUE IN
NUMBER, ARGLIST IN LIST_TYPE)
or
SET_PROPERTY(OBJECT IN OBJ_TYPE, PROPERTY IN VARCHAR2, VALUE IN
VARCHAR2, ARGLIST IN LIST_TYPE)
Object Method Execution
INVOKE
Executes a method of an OLE object which returns nothing.
INVOKE(OBJECT IN OBJ_TYPE, METHOD IN VARCHAR2, ARGLIST IN
LIST_TYPE)
INVOKE_CHAR
Executes a method of an OLE object which returns a character
string.
INVOKE(OBJECT IN OBJ_TYPE, METHOD IN VARCHAR2, ARGLIST IN
LIST_TYPE) RETURN VARCHAR2
INVOKE_NUM
Executes a method of an OLE object which returns a number.
INVOKE(OBJECT IN OBJ_TYPE, METHOD IN VARCHAR2, ARGLIST IN
LIST_TYPE) RETURN NUMBER
INVOKE_OBJ
Executes a method of an OLE object which returns an object handle.
INVOKE(OBJECT IN OBJ_TYPE, METHOD IN VARCHAR2, ARGLIST IN
LIST_TYPE) RETURN OBJ_TYPE
Argument List Management
CREATE_ARGLIST
Creates an argument list to be used by an invoked method and
returns an argument list handle.
CREATE_ARGLIST RETURN LIST_TYPE
ADD_ARG
Appends a number or character string argument to an argument list.
ADD_ARG(LIST IN LIST_TYPE, VALUE IN NUMBER)
or
ADD_ARG(LIST IN LIST_TYPE, VALUE IN VARCHAR2)
DESTROY_ARGLIST
Destroys an argument list created by CREATE_ARGLIST.
DESTROY_ARGLIST(LIST IN LIST_TYPE)
Exception Handling
LAST_EXCEPTION
Returns the most recent OLE exception code. Some examples of
conditions when OLE exceptions are raised are
o sending OLE commands to an inactive server application
o invoking non-existent methods
LAST_EXCEPTION RETURN NUMBER
The OLE2 PL/SQL package can be used to automate an independently
executing
OLE automation server application. It can also be used to automate an
embedded or linked OLE object associated with an OLE container item in
an
Oracle Forms application. The remainder of this article will look at
automating Word using both methods.
Automating an independently executing Word application
Before any OLE automation to Word can be performed, the WordBasic interpreter
must be started. This is achieved through the creation of an OLE object representing the WordBasic interpreter. The creation of this WordBasic OLE
object (and an object handle for it) establishes an entry point to Word from
which OLE automation can begin.
The WordBasic interpreter is not visible. If you want to display the
Word
application on the screen during OLE automation you will need to send
the
macro command 'AppShow' to WordBasic.
The following PL/SQL example creates a WordBasic object, obtains an
object
handle to it and displays the main application window for Word on the
screen:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
END;
At this point there are no open documents in Word and OLE automation is
restricted only to the operations that can be performed from Word's
File menu
(e.g. create/open a document, create/open a template, execute a
macro). To
perform more extensive OLE automation, a Word document needs to be
opened.
The following PL/SQL example extends the previous example by creating a
new
document and inserting some text ( comments are preceded by -- ) :
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
- Create a new Word document OLE2.INVOKE(application, 'FileNew');
- Insert the text 'Hello there!' into the Word document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'Hello there!'); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Save the document to the filesystem args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'EXAMPLE.DOC'); OLE2.INVOKE(application, 'FileSaveAs', args); OLE2.DESTROY_ARGLIST(args);
- Release the OLE object OLE2.RELEASE_OBJ(application);
END; The equivalent WordBasic macro for these actions is shown below:
Sub MAIN FileNew .Template = "C:\OFFICE95\Templates\Normal.dot", .NewTemplate = 0 Insert "Hello there!" FileSaveAs .Name = "EXAMPLE.DOC", .Format = 0, .LockAnnot = 0, .Password = "",.AddToMru = 1, .WritePassword = "", .RecommendReadOnly = 0, .EmbedFonts = 0, .NativePictureFormat = 0, .FormsData = 0, .SaveAsAOCELetter = 0End Sub
The following points are worth noting :
o It is important to release all OLE objects and argument lists as
early as
possible to minimise Windows resource usage and at the very least
these
objects should be released at the end of the PL/SQL procedure.
o Argument names are not required for the WordBasic commands, just the values.
o Default values will be used in place of missing WordBasic arguments. (e.g. in the FileNew command it was not necessary to specify which document template should be used as this defaults to Normal.dot).
o The WordBasic arguments are position dependant so ensure values are
supplied for all arguments up to the highest positioned argument you
wish to
use.
o When using an argument list with a different set of arguments it is
necessary to destroy and recreate the argument list. Failing to do
this
will result in a new set of arguments being appended to an old set.
Word bookmarks can be used to position the insertion point at a specific
location within a document. These bookmarks can either be created and
named
in advance or can be created by macro commands (the latter is useful if
you
want to mark a location to revisit later). The following PL/SQL
procedure
illustrates the use of a predefined bookmark in a Word document:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
- Open a Word document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\EXAMPLE.DOC'); OLE2.INVOKE(application, 'FileOpen', args); OLE2.DESTROY_ARGLIST(args);
- Navigate to the bookmark called 'LetterHead' args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'LetterHead'); OLE2.INVOKE(application, 'EditGoto', args); OLE2.DESTROY_ARGLIST(args);
- Insert text at the bookmark location args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'OLE Automation Limited'); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Release the OLE object OLE2.RELEASE_OBJ(application);
END;
As well as executing WordBasic commands, it is possible to return
information
from Word to Oracle Forms by invoking WordBasic functions. For
example, the
WordBasic function FONT$() returns a character string with the name of
the
font in use at the insertion point of a document. The following PL/SQL
example demonstrates how this function can be called via OLE automation:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
- Declare the PL/SQL variable to receive the font name fontname VARCHAR2(30);
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
- Open a Word document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\EXAMPLE.DOC'); OLE2.INVOKE(application, 'FileOpen', args); OLE2.DESTROY_ARGLIST(args);
- Display the font in use at the insertion point fontname:=OLE2.INVOKE_CHAR(application, 'Font$'); MESSAGE(fontname);
- Release the OLE object OLE2.RELEASE_OBJ(application);
END; The following points are worth noting:
o To call a WordBasic function, the OLE2.INVOKE_CHAR or OLE2.INVOKE_NUM procedures are used instead of the OLE2.INVOKE procedure.
o To determine whether to use OLE2.INVOKE_CHAR or OLE2.INVOKE_NUM you
need to
know the datatype of the item being returned from the WordBasic
function.
You can derive this from the WordBasic function name. Functions
returning
a character string have a $ as the last letter of the function name
whereas
functions returning numbers do not.
o WordBasic functions are distinguished from commands by brackets
following
the function name. Do not use these brackets when referring to the
function in a PL/SQL procedure.
The following PL/SQL procedure illustrates how OLE automation can be
used to
perform a mail merge in Word. The example assumes that the main and
data
source documents have already been created and the placeholders for
data
source fields have been created in the main document (refer to the Word
online help for details of setting up mail merge documents). The
PL/SQL
procedure simply populates the data source document with data from the
Oracle
database, invokes the mail merge and saves the resulting file.
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
- Declare a SQL cursor to be used to fetch the records from
- the database. CURSOR emp_cursor IS select ename, sal from emp;
BEGIN
- Start WordBasic and make Word visible application:=OLE2.CREATE_OBJ('Word.Basic'); OLE2.INVOKE(application, 'AppShow');
- Open the mail merge data source document
args:=OLE2.CREATE_ARGLIST;
OLE2.ADD_ARG(args, 'C:\TEMP\MERGE1.DOC');
OLE2.INVOKE(application, 'FileOpen', args);
OLE2.DESTROY_ARGLIST(args);
- Move to end of first row in data table (merge field names) OLE2.INVOKE(application, 'NextCell');
- Fetch each employee record and pass values of employee name
- and salary into the mail merge data table
FOR emp_record IN emp_cursor LOOP
- Move onto next row of data table OLE2.INVOKE(application, 'NextCell');
- Insert employee name args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, emp_record.ename); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Move to next column of data table OLE2.INVOKE(application, 'NextCell');
- Insert salary args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, TO_CHAR(emp_record.sal)); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
END LOOP;
- Open the mail merge main document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\MERGE2.DOC'); OLE2.INVOKE(application, 'FileOpen', args); OLE2.DESTROY_ARGLIST(args);
- Perform the mail merge to create the merged document OLE2.INVOKE(application, 'MailMergeToDoc');
- Save the merged document to disk args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\MERGE3.DOC'); OLE2.INVOKE(application, 'FileSaveAs', args); OLE2.DESTROY_ARGLIST(args);
- Close all three documents (without prompting to save any changes)
- ( FileCloseAll 2 = close all without saving ) args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 2); OLE2.INVOKE(application, 'FileCloseAll', args); OLE2.DESTROY_ARGLIST(args);
- Release the OLE object OLE2.RELEASE_OBJ(application);
END; The following points are worth noting :
o It is not possible to use a numeric datatype as an argument to the
WordBasic Insert command. To insert a salary figure the TO_CHAR
function
was used to convert to a character string first.
The following example invokes Word to perform a spelling check against
an
Oracle Forms text field ('LONGFIELD1' in block 'CONTROL') and return the
corrected text:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
- Declare a temporary local variable for returned text sel_text VARCHAR2(1000);
BEGIN
- Start WordBasic application:=OLE2.CREATE_OBJ('Word.Basic');
- Create a temporary document to do the spell check in OLE2.INVOKE(application, 'FileNew');
- Insert the text of field CONTROL.LONGFIELD into temporary document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, :CONTROL.LONGFIELD1); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Invoke the spell checker OLE2.INVOKE(application, 'ToolsSpelling');
- Return corrected text to Oracle Forms OLE2.INVOKE(application, 'EditSelectAll'); sel_text:=OLE2.GET_CHAR_PROPERTY(application, 'Selection');
--Release the OLE object
OLE2.RELEASE_OBJ(application);
- The text brought back contains an extraneous control character
- (a paragraph marker) so get rid of it :CONTROL.LONGFIELD1:=SUBSTR(sel_text, 1, (LENGTH(sel_text)-1) );
END;
Generally, the best approach for developing PL/SQL code to perform
sophisticated OLE automation to Word is to use Word's own macro
recorder to
record a WordBasic macro for the required actions and convert the
resulting
WordBasic macro into a series of OLE2.INVOKE, OLE2.INVOKE_CHAR and
OLE2.INVOKE_NUM statements, using argument lists where appropriate.
For further information on the syntax of WordBasic commands refer to
Word's
own online help and the documentation supplied with the Microsoft
Office
Developer's kit.
Automating Embedded or Linked Word documents
The original concept behind OLE concerned the embedding or linking of objects
created by an OLE server application inside a document created by a different
application (referred to as an OLE container application). It is possible to
combine this aspect of OLE with OLE automation to automate an embedded or
linked object.
Oracle Forms includes a special OLE container item into which an OLE
object
can be embedded or linked. The OLE object classes which can be
embedded or
linked into an OLE container are registered in the Windows OLE
registration
database when an OLE server application is installed. The 'OLE Class'
property of an Oracle Forms OLE container indicates which object class
it
contains and must be one of those listed in the OLE registration
database.
The 'OLE Tenant Types' property indicates whether the OLE container
holds an
embedded or linked OLE object. The 'OLE In-Place Activation' property
indicates whether the OLE server application shares the Oracle Forms
application Window when it is activated or whether a separate Window is
opened.
For Word documents, the OLE container's 'OLE Class' property should be
set to
'Word.Document'. However, Word's simplified OLE object model does not
permit
direct automation of the embedded or linked 'Word.Document' object
class
(unlike Excel which allows direct automation of the 'Excel.Worksheet'
object
class). All OLE automation against the 'Word.Document' class must be
performed via the 'Word.Basic' class.
To automate an embedded or linked Word document, the OLE2 PL/SQL
package must
be used in conjunction with the following PL/SQL procedures from the
separate
PL/SQL built-in package FORMS_OLE:
ACTIVATE_SERVER
Activates an OLE server application associated with an OLE container
item
and prepares it for OLE automation. Takes the name or item id of an
Oracle
Forms OLE container item as an argument.
EXEC_VERB
Causes an OLE server to execute a verb identified by a verb name or
verb
index. An OLE verb specifies an action you can perform on an OLE
object.
CLOSE_SERVER
Deactivates an OLE server application associated with an OLE
container item.
Terminates the connection between the OLE server and the OLE
container.
The following example illustrates how the FORMS_OLE and OLE2 procedures
are
used to automate an embedded or linked Word document (in this case a
standard
letter template). The document is stored in the Oracle database and
displayed
in the OLE container item 'DOC' of block 'OLEWORD'. The PL/SQL
procedure
opens the template document and fills it in by sending the contents of
Oracle
Forms fields to bookmarks in the document. The resulting document is
then
saved to disk, the changes undone to restore the template to its
original
state and the document is closed:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Activate Word FORMS_OLE.ACTIVATE_SERVER('OLEWORD.DOC');
- Start WordBasic application:=OLE2.CREATE_OBJ('Word.Basic');
- Open the embedded document for editing FORMS_OLE.EXEC_VERB('OLEWORD.DOC',1);
- Go to EmployeeName bookmark args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'EmployeeName'); OLE2.INVOKE(application, 'EditGoto', args); OLE2.DESTROY_ARGLIST(args);
- Transfer contents of the EMP field to document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, :EMP.ENAME); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Go to Salary bookmark args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'Salary'); OLE2.INVOKE(application, 'EditGoto', args); OLE2.DESTROY_ARGLIST(args);
- Transfer contents of Salary field to document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, TO_CHAR(:EMP.SAL)); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Save the completed document to disk args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\LETTER1.DOC'); OLE2.INVOKE(application, 'FileSaveAs', args); OLE2.DESTROY_ARGLIST(args);
- Restore the letter template to it's original state OLE2.INVOKE(application, 'EditUndo'); OLE2.INVOKE(application, 'EditUndo');
- Release the OLE object OLE2.RELEASE_OBJ(application);
- Close Word FORMS_OLE.CLOSE_SERVER('OLEWORD.DOC');
o The ACTIVATE_SERVER, CREATE_OBJ and EXEC_VERB commands must be
performed in
the order given. Due to the relationship between the 'Word.Document'
and
'Word.Basic' object classes, failure to use this sequence may cause
unexpected behaviour (e.g. the Word application window does not close
when
the CLOSE_SERVER command is issued).
o Verb index 1 is used by EXEC_VERB to open a Word document for editing.
o There is no need to use an AppShow command as the EXEC_VERB statement
will
make Word visible.
o There is no need to close the embedded document via WordBasic. This
is
done implicitly by the CLOSE_SERVER command.
o In place of the FileSaveAs command a FilePrint could have been used
to send
the document to the printer rather than disk.
o If the embedded Word document is attached to a Word template (.DOT
file), a
copy of the .DOT file must exist on all PCs using the document from
within
Oracle Forms. The .DOT file is not stored in the database with the
embedded document. Without this file on the hard disk, macros,
autoText
entries and custom toolbar, menu and shortcut keys defined in the
.DOT file
will be inaccessible.
o With Word V7.0 for Windows 95, the previous example only works if the
'In-place Activation' property of the OLE container is set to 'False'.
If this property is set to 'True', WordBasic does not permit the use
of any
commands available from the File menu (e.g. FileSave, FileSaveAs,
FilePrint).
These commands will just be ignored.
If no commands from the File menu are issued via OLE automation,
'In-place Activation' can be set to 'True' or 'False'.
With Word V6.0 for Windows 3.x, even with 'In-place Activation' set to
'False' WordBasic (for some unknown reason) still disallows the use of
the
FileSave and FileSaveAs commands directly against an embedded or linked
document. However, the FileNew command can be used so a workaround to
this
limitation is to create a temporary copy of the embedded or linked
document
via OLE automation and work on that. This has the effect of reenabling
the
restricted commands. The following PL/SQL procedure illustrates the
previous
example modified to work with Word V6.0:
DECLARE
- Declare the OLE object application OLE2.OBJ_TYPE;
- Declare handle to the OLE argument list args OLE2.LIST_TYPE;
BEGIN
- Activate Word FORMS_OLE.ACTIVATE_SERVER('OLEWORD.DOC');
- Start WordBasic application:=OLE2.CREATE_OBJ('Word.Basic');
- Open the embedded document for editing FORMS_OLE.EXEC_VERB('OLEWORD.DOC',1);
- Create a temporary copy of the document to enable the FileSave
command
OLE2.INVOKE(application,'EditSelectAll');
OLE2.INVOKE(application,'EditCopy');
OLE2.INVOKE(application,'FileNew');
OLE2.INVOKE(application,'EditPaste');
- Go to EmployeeName bookmark args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'EmployeeName'); OLE2.INVOKE(application, 'EditGoto', args); OLE2.DESTROY_ARGLIST(args);
- Transfer contents of the EMP field to document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, :EMP.ENAME); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Go to Salary bookmark args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'Salary'); OLE2.INVOKE(application, 'EditGoto', args); OLE2.DESTROY_ARGLIST(args);
- Transfer contents of Salary field to document args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, TO_CHAR(:EMP.SAL)); OLE2.INVOKE(application, 'Insert', args); OLE2.DESTROY_ARGLIST(args);
- Save the completed document to disk args:=OLE2.CREATE_ARGLIST; OLE2.ADD_ARG(args, 'C:\TEMP\LETTER1.DOC'); OLE2.INVOKE(application, 'FileSaveAs', args); OLE2.DESTROY_ARGLIST(args);
- Close the temporary document (without prompting to save any changes)
args:=OLE2.CREATE_ARGLIST;
OLE2.ADD_ARG(args, 2); OLE2.INVOKE(application, 'FileClose', args); OLE2.DESTROY_ARGLIST(args);
- Close the embedded document FORMS_OLE.CLOSE_SERVER('OLEWORD.DOC');
- Release the OLE object OLE2.RELEASE_OBJ(application);
END; The following points are worth noting:
o In this procedure there is no need to undo changes as the embedded
document
is never modified. Only the temporary document is modified which is
discarded at the end.
o A FileClose is required to close the temporary document but not the embedded document as this is implicitly closed by the CLOSE_SERVER command.
Conclusion
This article has described the fundamental concepts of using the built- in
OLE automation features of Oracle Forms V4.5 to manipulate Microsoft Word.
Once these basic concepts and limitations are understood, the reader should
be able to adapt the examples given in this article using the documentation
provided with Microsoft Word to implement their specific OLE automation requirements.
for Word97 you need to reference MSWord8.olb (Microsoft Word 8.0 Object Library)
objActiveDoc := OLE2.GET_OBJ_PROPERTY(Word.hApp, 'ActiveDocument'); > objBookmarks := OLE2.GET_OBJ_PROPERTY(objActiveDoc, 'Bookmarks'); > numBookmarkCount := OLE2.GET_NUM_PROPERTY(objBookmarks, 'Count');
FUNCTION GotoBookMark (DocumentHandle in OLE2.OBJ_TYPE, Bookmark in
VARCHAR2) return OLE2.OBJ_TYPE is
hArgs OLE2.LIST_TYPE;
hRange OLE2.OBJ_TYPE;
begin
hArgs := OLE2.CREATE_ARGLIST;
OLE2.ADD_ARG(hArgs,-1); /* What? = wdGoToBookmark */ OLE2.ADD_ARG(hArgs, 0); /* Which? */ OLE2.ADD_ARG(hArgs, 0); /* Count */ OLE2.ADD_ARG(hArgs, Bookmark); /* Name */hRange := OLE2.INVOKE_OBJ(DocumentHandle,'Goto',hArgs); OLE2.DESTROY_ARGLIST(hArgs);
OLE2.INVOKE(hRange,'Select');
return hRange;
end;
--Print the Word document, nb. all arguements optional
ole_args:= ole2.create_arglist;
ole2.add_arg(ole_args,'True'); --Background ole2.add_arg(ole_args,'False'); --Append ole2.add_arg(ole_args,'wdPrintAllDocument'); --Range
-- wdPrintAllDocument,wdPrintCurrentPage,wdPrintFromTo,wdPrintRangeOfPages, wdPri ntS election ole2.add_arg(ole_args, 'False'); --OutputFileName ole2.add_arg(ole_args, 'null'); --From ole2.add_arg(ole_args, 'null'); --To ole2.add_arg(ole_args, 'wdPrintDocumentContent'); --Item -- wdPrintAutoTextEntries,wdPrintComments,wdPrintDocumentContent,wdPrintKey Assig nme nts,wdPrintProperties,wdPrintStyles. ole2.add_arg(ole_args, '1'); --Copies ole2.add_arg(ole_args, 'null'); --Pages ole2.add_arg(ole_args, 'wdPrintAllPages'); --PageType -- wdPrintAllPages,wdPrintEvenPagesOnly,wdPrintOddPagesOnly ole2.add_arg(ole_args, 'False'); --PrintToFile ole2.add_arg(ole_args, 'True'); --Collate ole2.add_arg(ole_args, 'null'); --FileName ole2.add_arg(ole_args, 'null'); -- ActivePrinterMacGX ole2.add_arg(ole_args, 'null'); -- ManualDuplexPrint --ole2.invoke(ole_application, 'PrintOut'); ole2.invoke(ole_application, 'PrintOut', ole_args); ole2.destroy_arglist(ole_args); elsif :cg$ctrl.cmm_code = 'MGW' then /* **** MAILING **** */ -- Create the Word.Application and make it visible ole_application:= ole2.create_obj('Word.Application'); ole2.set_property(ole_application,'Visible',1); -- Get a handle on the documents collection ole_document := ole2.get_obj_property(ole_application, 'Documents'); -- What word file to open ole_args:= ole2.create_arglist; /* * This is hardcoded stuff at the moment for testing purposes only */ message('file '|| 'q: \in.mgw\agee\'||:global.eas$mnt_id||:global.eas$mtn_seq_no||'.'||:cg$ctr l.cmm _co de); ole2.add_arg(ole_args, 'q: \in.mgw\agee\'||:global.eas$mnt_id||:global.eas$mtn_seq_no||'.'||:cg$ctr l.cmm _co de); -- Open Word document specified in the argument list ole_document := ole2.invoke_obj(ole_document, 'Open', ole_args); ole2.destroy_arglist(ole_args); --Mail the Word document ole_args:= ole2.create_arglist; --ole2.add_arg(ole_args, '?'); --Item ole2.invoke(ole_application, 'SendMail'); --ole2.invoke(ole_application, 'SendMail', ole_args); ole2.destroy_arglist(ole_args); elsif :cg$ctrl.cmm_code = 'FAX' then /* **** FAX ***** */ message('file '|| 'q: \in.mgw\agee\'||:global.eas$mnt_id||:global.eas$mtn_seq_no||'.'||:cg$ctr l.cmm _co de); ole2.add_arg(ole_args, 'q: \in.fax\agee\'||:global.eas$mnt_id||:global.eas$mtn_seq_no||'.'||:cg$ctr l.cmm _co de); -- Open Word document specified in the argument list ole_document := ole2.invoke_obj(ole_document, 'Open', ole_args); ole2.destroy_arglist(ole_args); --Fax the Word document ole_args:= ole2.create_arglist; ole2.add_arg(ole_args, '01865843967'); --fax number ole2.add_arg(ole_args, 'EASE TEST FAX'||to_char(sysdate,'DD-MON- YYYY HH24:MI')); --subject line <=255 characters --ole2.invoke(ole_application, 'SendFax'); ole2.invoke(ole_application, 'SendFax', ole_args); ole2.destroy_arglist(ole_args); else /* **** SOMETHING ELSE !!! should never happen ***** */ message('ERROR - :cg$ctrl.cmm_code ='||:cg$ctrl.cmm_code); end if; --Release the OLE objects ole2.release_obj(ole_application); ole2.release_obj(ole_document); else --must be using mapi.dll and intermediate datatype .dll null; end if; EXCEPTION when others then dbmserrcode :=DBMS_ERROR_CODE; dbmserrtext :=DBMS_ERROR_TEXT; message(to_char(dbmserrcode)||' - '||dbmserrtext); END; END; >I had done exactly this sometime ago but in MS Access as follows: > >1. Create a passthrough query in MS Access to get Oracle data using >ODBC. > >2. Create a form to compose email message and buttons etc. > >3. Merge the message with data from Oracle (using some simple lines of >code) and send as email (using sendobject macro which uses your >existing windows messaging profole to send email). > >Free free to email me directly if you want to have other infomration >regarding this. > >regards, >M. Armaghan Saqib >+--------------------------------------------------------------- >| 1. SQL PlusPlus => Add power to SQL Plus command line >| 2. SQL Link for XL => Integrate Oracle with XL >| 3. Oracle CBT with sample GL Accounting System >| Download free: http://www.geocities.com/armaghan/ >+--------------------------------------------------------------- > >In article <0722a78c.731dbc0b_at_usw-ex0107-050.remarq.com>, > Anne <goodwinakNOgoSPAM_at_kpt.nuwc.navy.mil.invalid> wrote: >> I need to create a process that will dump a flat file of records from >> an Oracle database, merge this data with a Microsoft Word Form, and >> email the merged document to multiple users. The merged document must >> be a 'form', ie., the recipient may only enter data in certain fields >> and the remainder of the field is not modifyable. Has anyone done >this >> before and can offer me some tips? Hi everyone, We are using Forms 4.5, Oracle Server 7.3.4 in a Win NT environment and we use the Forms package OLE2 to start and control Word PACKAGE BODY word IS wdWindowStateMaximize constant number := 1; wdtrue constant varchar2(4) := 'True'; wrd ole2.obj_type; procedure start_word is begin if wrd is null then wrd := ole2.create_obj ('Word.Application'); ole2.set_property(wrd,'visible',wdtrue); end if; word_venster_maximaal; end; procedure word_venster_maximaal is begin ole2.invoke (wrd, 'Activate'); ole2.set_property(wrd,'Windowstate',wdWindowStateMaximize); end; END; After starting Word Visual Basic commands are used to control Word. The Forms application only starts Word once, the next time Word is being started, the existing Word instance is used. See the code sample above. However if the user himself starts Word (for example from the start button), then this Word instance should be used by the Forms application. Any ideas how this can be done? Thanks Wilhelm Sent via Deja.com http://www.deja.com/ Before you buy.Received on Tue Aug 01 2000 - 00:00:00 CEST