PowerBuilder Authors: Chris Pollach, Yeshim Deniz, Jayaram Krishnaswamy, Kevin Benedict, Avi Rosenthal

Related Topics: PowerBuilder

PowerBuilder: Article

OLE - Extending the Capabilities of PowerBuilder

Part 2

This two-part article provides a primer on OLE, some practical examples of its use, and demonstrates some methods for addressing the limitations of PowerBuilder's implementation of OLE.

In Part 1 I provided some background information for OLE and discussed the use of custom controls, in Part 2 I talk about OLE Automation and OLE objects.

OLE Automation
OLE Automation is the interface through which one application (e.g., Microsoft Outlook) makes the methods, properties, and events of its objects (e.g., Folders, Messages, Address Book) available for use within another application. Using OLE Automation, a developer could automate another application (e.g., creating and then printing form letters from Microsoft Word) or they may just use a portion of another application within their own (e.g., using the spell-check capability within Microsoft Word to spell-check text in a control within PowerBuilder).

OLE Automation defines an application programming interface (API) for an application. Unlike something like MAPI, however, that was designed to be a common API across a number of different mail clients, the OLE Automation syntax for one application is unique to that particular application, and in fact can differ between versions of that same application. That is, while the method of OLE Automation provides a standard method through which applications can interact, the specific syntax they use to do that interaction is application-specific.

This results in two important consequences. First, because the syntax is defined by the target application, a developer faces a task whose difficulty ranges from difficult to impossible, if they are attempting to implement OLE Automation without proper documentation for the objects and their methods, properties, and events of the target application. There are object browsers available that can help the developer explore the OLE Automation interface of the target application.

Note: One is provided with Microsoft Visual Basic. The Roman Press provides a third-party alternative (www.romanpress.com/Browser/ObjectBrowser.htm).

However, using those alone would be equivalent to trying to learn how to develop in PowerBuilder without using the online help file or documentation, simply by exploring the objects in the system tree. Second, because the syntax for the target application can vary between versions, it's not enough for the developer to ensure that the client has the target application installed. They must also ensure that the version of that application is one for which they have provided an implementation (or compatible with those versions).

Because they generate by far the most common questions concerning OLE Automation, I'm going to use Microsoft Word, Excel, and Outlook for demonstrations of how to use OLE Automation. The first issue raised above is documentation. What many PowerBuilder developers don't seem to realize is that Microsoft provides documentation (referred to as the "object model") for these Office applications. The reason they often don't realize that documentation is readily available is because it's not installed by default but instead requires a custom installation of Microsoft Office. The documentation is provided as a set of help files as indicated in Table 1.

The VBA scripting utility that comes with those products also contains an object browser that can be used to determine which functions are accessible on different objects and the syntax for using them (see Figure 1). You access the VBA scripting utility from Tools->Macro->Visual Basic Editor within the application, and then the object browser is available from the toolbar, from the View menu item, or by hitting F2. From within the VBA Scripting utility you can bring up the documentation for a particular method, property, or event by hitting F1 after selecting it (assuming that the help files have been installed).

The second issue raised above is the compatibility between versions of the same target application. Fortunately, at least with the Microsoft products, there is a fairly easy way to determine which version of the target application is installed. (This will be demonstrated once we get into the source code.) In addition, the OLE Automation syntax for these applications is highly backward-compatible. When objects (or methods, properties, or events of an object) are depreciated by Microsoft in a new version of the application, they usually mark those as "hidden." Hidden objects (or methods, properties, or events) still work with the newer version, but they don't appear in the object model for that new version. Obviously, because each new version of the application adds additional features that were not present in earlier versions, the syntax developed using a newer version of the object model will not always work for an older version.

As mentioned previously, PowerBuilder uses late binding to interface with OLE Automation objects, so we are unable to use the constants provided in the Word type library. However, Microsoft does provide an Excel spreadsheet on their MSDN site that contains all of the constants and their values used within Office. (Those constants are also defined in the Microsoft supplied help files and can be browsed using the VBA scripting utility.) I downloaded that file and used that information to create an autoinstantiating nonvisual user object that could be used for a similar purpose as the type library, at least with respect to the constants (see Figure 2).

The n_cst_constants_word_ole class contains the constants and is defined as an instance variable on another class, n_cst_ole_word. That class is basically a "virtual" class; it's never actually called directly. Instead, descendants of it are created to handle each of the different versions of Word we might actually interact with. The virtual class determines which methods we are going to make available, and the descendants actually implement those methods as appropriate. The virtual class returns an error message if the method is called, so if the method is not implemented on a descendant, it implies that particular version of Word does not support the method. This allows us to add additional methods to the virtual class as new versions of Word, and add new functions and implement them in whichever descendants actually support them without having to modify the classes representing earlier versions of Word. n_cst_word acts as a wrapper class so that the instantiation of the appropriate descendant of n_cst_ole_word and calls to its methods are handled automatically.

In the of_connect method of n_cst_word, the object determines which version of Word the user has installed and creates the appropriate descendant of n_cst_ole_word (see Listing 1).

Prior to version 8 of PowerBuilder, the standard method for handling errors in OLE Automation was to create a user object that inherited from the OLEObject class and then code its Error and ExternalException events. Then that class, rather than the OLEObject class, would be used for the ConnectToObject or ConnectToNewObject call. One problem with that approach is that some OLE Automation properties and method returns are themselves OLEObjects, and would not allow themselves to be cast into the descendant user object. Instead, a user object based on OLEObject would have to be used, and then the SetAutomationPointer function of that object would be used to redirect processing to an instance of the custom class.

That was all very complicated. It also tended to disassociate the error-handling logic from the code that was making the call to the object that caused the error, which made recovery from the error somewhat problematic.

Fortunately version 8 of PowerBuilder introduced structured exception handling, which greatly simplifies this for us. The object that we are using in this sample to interact with Word is the inv_word instance variable in the n_cst_word class, and you can see from Figure 3 that the class we are using for it is OLEObject. We simply wrap our OLE Automation calls in a try...catch...end try block and can deal with any errors that occur within that block.

We're going to review some of the code from the sample application (which can be downloaded from pbdj.sys-con.com), certainly not all of it, just certain code that illustrates some important concepts.

The of_visible function determines whether or not Word will actually be visible to the end user. It's fairly straightforward, simply setting the visible property of the Word application (not a PowerBuilder object visible property).

public function integer of_visible (boolean ab_status);
IF IsNull ( inv_word ) THEN Return -1
    inv_word.Visible = ab_status
catch (OLERuntimeError MyOLEError )
    Return -1
end try
Return 1
end function

The of_open function demonstrates the use of multiple catch portions of the try...catch...end try block to handle different types of errors.

More Stories By Bruce Armstrong

Bruce Armstrong is a development lead with Integrated Data Services (www.get-integrated.com). A charter member of TeamSybase, he has been using PowerBuilder since version 1.0.B. He was a contributing author to SYS-CON's PowerBuilder 4.0 Secrets of the Masters and the editor of SAMs' PowerBuilder 9: Advanced Client/Server Development.

Comments (2)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.