Using C#.NET with the Kofax KTM Validation Module
My current project has a requirement to do several Oracle EBS validations and lookups from the Kofax KTM validation window. For example, one requirement is to present the validator with a list of Suppliers. Another is to check for a duplicate invoice number in EBS. I can easily add additional methods as needed.
Kofax KTM provides Win Basic scripting language that can accomplish some of this, but it’s difficult to use compared to modern programming languages. After a little research I discovered it was feasible to create and call methods in a COM object from KTM Win Basic. This meant I could expose a C#.NET dll via COM Interop but have all the power of any version of the .NET framework and Microsoft Visual Studio available to do the heavy lifting.
My C# methods return either arrays or booleans back to KTM where I then use the Win Basic language to present results to the validation user. I can debug my C# code by attaching to the KTM Project Builder exe while running validation tests.
Setting up the C# Class
The first step is to create a project in Visual Studio and set up a class to contain the methods you will call in KTM. The prefered method is to use interfaces in case you need to change the methods without breaking the inferface. Here is an example. You need to create your own unique GUIDs and expose the compiled dll to COM. The dll will need to be registered on all Kofax stations doing validation. Client setup will also involve setting up data base client drivers if validation will require lookups.
using System; using System.Data; using System.Runtime.InteropServices; using Oracle.DataAccess.Client; using System.Collections.Generic; namespace ImageSource.APInvoice { [ComVisible(true), GuidAttribute("D9675881-BC69-4e52-A45D-08F1025FFC28")] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface IKTMUtils { string[] LookupVendors(string searchString); bool CheckForDuplicateInvoice(string searchString); } /// /// Class that implements various Kofax KTM lookups and validations. /// [ComVisible(true), Guid("790A3156-5696-4601-8A26-D2B9446C9A2B"), ClassInterface(ClassInterfaceType.None)] [ProgId("ImageSource.KTMUtils")] public class KTMUtils : IKTMUtils { #region declarations and process entry point public KTMUtils() { } #endregion #region execute methods /// /// Retrieves a list of vendor names and id's. /// ///3 characters of Vendor name. /// String array containing pipe ///delimited vendor id and name. public string[] LookupVendors(string searchString) { List vendorInfo = GetVendorNameAndID(searchString); string[] vArray = new string[vendorInfo.Count]; int x = 0; foreach (var vendor in vendorInfo) { vArray [x] = vendor.VendorID.ToString() + "|" + vendor.VendorName; x++; } return vArray; }
rest of code truncated…
In the code above, GetVendorNameAndID calls a method that does the actual DB lookup. The calling method uses a Vendors class to type the vendor fields returned from the lookup. Note the creation of a simple array to hold the vendor data. Fields are delimited with a pipe, the array is filled up, then passed back to KTM. The search string is required to be at least 3 characters in KTM and restricts the vendor lookup.
The KTM Code
On the KTM side you need to respond to a button click to do the vendor lookup:
Private Sub ValidationForm_ButtonClicked(ByVal ButtonName As String, ByVal pXDoc As CASCADELib.CscXDocument) Select Case ButtonName Case "btnVendorLookup" ClearVendorFields(pXDoc) DisplayVendors(pXDoc) End Select End Sub
The Display Vendors code looks like this:
Private Sub DisplayVendors(ByVal pXDoc As CASCADELib.CscXDocument) On Error GoTo UhOh Dim lookupString$ lookupString = pXDoc.Fields.ItemByName("VendorName").Text lookupString = Trim$(lookupString) 'get results from c#.net dll... Dim o As Object Set o=CreateObject("ImageSource.KTMUtils") 'get handle to c# dll Dim x() As String 'create local array 'call the method in the c# dll to fill x = o.LookupVendors(lookupString) Set o = Nothing 'if null array bail... If IsNull(x) Then MsgBox("Error Accessing Vendors",vbCritical, "") Exit Sub End If 'if no values returned, bail... If UBound(x) = -1 Then MsgBox("No Vendor Found",vbInformation, "") Exit Sub End If 'display vendor... Dim numVendors% numVendors = UBound(x) + 1 '0 based array Dim VendorID$ Dim VendorName$ 'populate now if only one vendor... If numVendors = 1 Then VendorID = Split(x(0), "|") (0) VendorName = Split(x(0), "|") (1) pXDoc.Fields.ItemByName("VendorName").Text = VendorName pXDoc.Fields.ItemByName("VendorNum").Text = VendorID 'force vendor name valid... pXDoc.Fields.ItemByName("VendorName").Valid = True Exit Sub End If 'show a list box if more than one vendor... If numVendors > 1 Then 'list box Dim lists$() ReDim lists$(numVendors - 1) '0 based index 'populate list with vendors - vendorname - vendorsitecode... Dim i% For i = 0 To numVendors - 1 lists$(i) = Split(x(i), "|") (0) + " - " + Split(x(i), "|") (1) Next i 'display it... Begin Dialog Vendors 450,120,"Vendors" Text 10,10,180,15,"Please push the OK button" DropListBox 10,25,400,60,lists$(),.list1 OKButton 300,90,60,20 CancelButton 365,90,60,20 End Dialog Dim dlg As Vendors Dialog dlg ' show dialog (wait for ok) Dim chosenIndex% chosenIndex = dlg.list1 'assign array values from chosen vendor... VendorID = Split(x(chosenIndex), "|") (0) 'first dimension VendorName = Split(x(chosenIndex), "|") (1) 'display values in validation form... pXDoc.Fields.ItemByName("VendorName").Text = VendorName pXDoc.Fields.ItemByName("VendorNum").Text = VendorID 'force vendor name valid... pXDoc.Fields.ItemByName("VendorName").Valid = True pXDoc.Fields.ItemByName("VendorName").ExtractionConfident = True Exit Sub End If UhOh: If Err.Description = "User pressed cancel." Then Err.Clear Exit Sub End If MsgBox("Error Accessing Vendors: " + Err.Description,vbCritical, "") Err.Clear End Sub
There are a lot of details not discussed here but the above is the jist of it!
Clint Lewis
Senior Systems Engineer
ImageSource Inc.