Just recently, Kofax published an article about the IntializeComboBox method not working as intended (or: not working at all). While the workaround presented is the correct (and only) way to populate a combobox in script, you can run into some troubles. Why? Well, here’s the basic concept behind having two different events:
- As the name suggests, InitializeComboBox is meant to populate a combobox with values that are not subject to change when processing an individual document.
- On the contrary, BeforeComboBoxDropDown can populate the combobox with certain values depending on other factors.
So, what is the general problem? InitializeComboBox is supposed to be called once per document. BeforeComboboxDropDown is called every time the user drops down the combobox. Imagine that your values are not static, but dynamically retrieved from a database. Imagine further that the select statement is quite expensive, potentially because of several joins being present. Alternatively, imagine that you have to call a web service that provides you with an xml that you have to parse before you can populate the combobox.. you see what’s my point. Expensive code is executed every time when the user drops down the combobox. Remember, the InitializeComboBox option would be the correct choice here, but it does not work.
So, here’s how you can work around this problem:
- Execute your expensive statement or web service call only once per batch
- Store the combobox items in a collection, for example a list
- On the BeforeComboboxDropDown, call a custom function that populates the combobox with the items from said list.
Here’s an example how you can solve it. The following code is executed on the project level – and the list cities is only populated once per batch.
'#Language "WWB-COM"
Option Explicit
' Project Script
Private ComboBoxItems_Cities As Object
Private Sub Batch_Open(ByVal pXRootFolder As CASCADELib.CscXFolder)
' populates the combobox items ONCE per batch, when the server opens the batch in KTM validation.
' useful when there's quite an expensive statement to execute
If Project.ScriptExecutionInstance = CscScriptExecutionMode.CscScriptModeValidation Then
Set ComboBoxItems_Cities = CreateObject("System.Collections.ArrayList")
' your expensive statement goes here..
ComboBoxItems_Cities.Add("Vienna")
ComboBoxItems_Cities.Add("London")
ComboBoxItems_Cities.Add("Madrid")
ComboBoxItems_Cities.Sort
End If
End Sub
Public Function GetComboboxItems_Cities(separator As String) As String
' must provide an ArrayList; returns comboboxitems using the given separator char
Dim i As Long
Dim cbxItems As String
cbxItems = ""
For i = 0 To ComboBoxItems_Cities.Count -1
cbxItems += ComboBoxItems_Cities(i) & separator
Next
' omit the last separator char
Return Left(cbxItems, Len(cbxItems) - 1)
End Function
The following few lines now are part of our document class script. Every time the user drops down the combobox, the existing collection will be re-used. The statement won’t be executed again unless we work with a new batch.
'#Language "WWB-COM"
Option Explicit
' Class script: base
Private Sub ValidationForm_BeforeComboBoxDropDown(ByVal ComboboxName As String, ByVal pXDoc As CASCADELib.CscXDocument, ByRef ComboboxItems As String)
Select Case ComboboxName
Case "Cities"
ComboboxItems = GetComboboxItems_Cities(";")
End Select
End Sub
There we go. Did you notice something? Not only did we work around the initial problem, that BeforeComboboxDropDown executes an expensive statement every time the element is dropped down, we also made sure said statement is executed only once per batch. That could make a difference in general validation performance, resulting in lower user satisfaction. And of course, here’s the result in validation: