ere’s a genuine “real-world” problem: a particular company has a Web-based intranet for their document and content management. This system stores many hundreds of documents. Some of these are on related topics, such as organizational division constitutions, job descriptions. Sometimes the same document appears in different locations on the Web server, and often as different revisions of the same document.
What the client needs is a Web page where an administrator can enter the names of two documents, and get a new document that contains the text of the original two documents with any variations highlighted in some way. This way, users can inspect different versions of the same document, as well as different documents that deal with related matter.
This can be achieved by writing an ActiveX component in Visual Basic. The component is given the paths and names of two source documents, and a compare method turns out a brand new Word document that the administrator can save and deal with at leisure.
The data passed to the component is read from a simple Web form, which prompts the user for these source documents. This in turn calls an Active Server Page that invokes the component. However, ASP is not a requirement for this method. By coding the program logic within an ActiveX DLL it can be called from any Windows development environment?including “fat client” Visual Basic programs.
Here’s how this DLL works and how you can call and use it from within both Visual Basic and ASP.
Creating Your ActiveX DLL
The steps to create an ActiveX DLL are:
- Start the Visual Basic IDE.
- From the File menu, select New Project.
- Choose ActiveX DLL from the dialog box.
The IDE presents a blank window, with a new class module. Unlike a typical Visual Basic program or control, an ActiveX DLL has no GUI?nor does any server-side component. The class module is where the DLL’s functionality is implemented.
Visual Basic names the project Project1 and the class module Class1. In the case of an ActiveX DLL, it is especially important to change these names. The names are used when instantiating the object from any programming environment. For example, within an ASP page, you would use code like this:
set myObject = Server.CreateObject ("Project1.Class1")
This creates an object based on the Project1 project and Class1 class module.
Hence, not only is it good practice to change the project and class name, it is sensible. This changes the instantiation code. I called the project DWLib and the class WordComp:
Set myObject = Server.CreateObject ("DWLib.WordComp")
Properties, Methods, and Events
Objects use properties, methods, and events to communicate with their external (i.e. calling) environment. Properties act like simple variables?they can be read and have values assigned to them. However, a property may not necessarily be implemented as a simple variable. It can also be implemented by complex calculations.
Methods are the functions and routines the class exposes to implement its functionality. When an instance of a class is defined, the public methods can be called from whichever COM-enabled language is being used, whether VB, ASP, or something else.
Events are a way of reporting back to a calling program from within a class. Events fire when something important happenslike a command button is clicked on, or a timer control counts down to zero. Events allow a method to be called back in the controlling program whenever something of interest has occurred. The controlling program can then respond to this event in an appropriate fashion.
So, properties, methods, and events, or “PME,” are the programming building-blocks used to allow others to interact with an ActiveX DLL.
In the Word document comparison project, three properties are needed: InFile1, InFile2, and OutFile. These hold the two source documents to be compared and the resultant output file which is generated. Only the compare method is necessary.
Listing 1 contains the code for a class module to implement these properties and method. It first defines local variables for working storage space and then declares some API calls. When creating an output file, you want to be sure a name is not used that already exists on the hard diskotherwise, it will be overwritten. The safest way to achieve this is to use the Windows API to request a temporary filename that is guaranteed to be unique.
Let and Get methods are implemented for each property. These are called whenever the calling program tries to assign a value to (Let) or read (Get) a property.
The class module next has a Class_Initialize sub that is much like a VB form’s Form_Load method. This is automatically executed whenever a class is instantiated. This is a good point to initialize all variables.
The class module next defines the compare method, which in many ways is the “real guts” of the DLL. It’s where the real work is being performed to achieve the purpose of comparing Word documents.
Microsoft Word provides this functionality for you. Simply create an instance of a Word application and then use it to perform the comparison. To achieve this, the ActiveX DLL project uses the Microsoft Word Object Library. Click Project/References to add this library to the project references.
Here’s the code:
' Actual function to do the work.Public Sub Compare() On Error Resume Next Dim oDoc As Word.Application' Load first text file Set oDoc = CreateObject("Word.Application") oDoc.Documents.Open FileName:=strInPath2' If no output filename has been specified, then make a' temporary one up If strOutFile = "" Then strOutFile = CreateTempFile("DWWC") & ".doc" End If With oDoc.ActiveDocument .SaveAs FileName:=strOutFile .TrackRevisions = True .ShowRevisions = True .PrintRevisions = True .Compare Name:=strInPath1 .Close wdSaveChanges, wdWordDocument, False End With Set oDoc = NothingEnd Sub
Use the File menu to compile and build the DLL.
Testing and Debugging the DLL
Being a good programmer, you know you need to test code before releasing it. But how do you test a DLL when it has no user interface and no input or output screens? It’s not like a conventional VB application where you just execute a .exe file.
What you need is a simple driver program that quickly passes data to the DLL and allows its methods to be used. This will be a separate projecta standard Windows exe. The simplest thing to do is use File/Add Project (rather than New Project) to create a project group, containing both the DLL and the driver .exe projects. This allows both projects to be managed from the one project group.
|Figure 1: This is the user-interface of the driver program that tests the DLL.|
Listing 2 contains the code and form definition for a driver program. This program prompts for two input files and provides both a “Compare” button to perform the comparison and a “View” button to display the results.
The user can browse for two existing Word documents via the CommonDialog control. The View button opens Word and displays the resultant output document. A Label control displays status messages back to the user.
The driver program first declares an Object to make an instance of the class:
Dim objWDComp As Object
This object is then instantiated on the Form_Load:
Set objWDComp = CreateObject("DWLib.WordComp")
The user is able to locate and specify two input documents. The Compare button event-handler then passes the names of these to the object, and calls its compare method. The code for this is extremely simple:
Private Sub cmdCompare_Click() objWDComp.InFile1 = tPath1.Text objWDComp.InFile2 = tPath2.Text objWDComp.Compare lblStatus.Caption = "Created output file " & _ objWDComp.OutFileEnd Sub
|Figure 2: Clicking the Compare button invokes the ActiveX DLL, performs a comparison, and returns the name of a generated output file with the results of the comparison.|
Figure 2 shows the driver program in action.
Building an ASP Page
Now that the control has been tested, you can make an ASP page to achieve the same results. The DLL itself does not need to be modified.
Listing 3 contains a simple HTML form to accept filenames from the user. These filenames must be meaningful for the server and not just from the user’s own hard disk. The DLL is invoked and used in the ASP page once the user has submitted two filenames. The ASP code in Listing 4 receives fields passed in from the form and then performs a comparison. Again, the code to achieve this is very simple:
<% Set objWDComp = CreateObject("DWLib.WordComp") ObjWDComp.InFile1 = Request.Form("InFile1") ObjWDComp.InFile2 = Request.Form("InFile2") ObjWDComp.Compare%>
|Figure 3: Opening the generated output file in Word shows the revision marks where the source documents vary, allowing all differences to be seen clearly.|
Enterprise-enable this DLL
When building an ActiveX DLL, the Visual Basic IDE registers the DLL with Windows so that it can be used from other programs. If the DLL is simply copied to the hard disk of another computer, the version of Windows on that computer will have no knowledge of the DLL and will not be able to use it.
To fix this, use the command-line tool REGSVR32 on the second PC to register the DLL with Windows. REGSVR32 can be found in the Windows/WinNT system directory. Professional deployment tools like the VB deployment and packaging wizard or InstallShield will register the component for you at the time of installation.