VFE files zipped up: StringBuilder Example
I cringe whenever I see an endif followed by an endif followed by an endif followed by an endif endif endif endif......
I have a couple of utility functions (housed in Function Libraries) to help with situations like these: StringBuilder() & NotNullOrEmpty()
StringBuilder() takes an array of strings (I'll usually take advantage of MEL's built-in CFMT() function for formatting purposes) and stacks them together side-by-side. While looping through the string array, if the current string is empty, it'll skip over it and go onto the next one, eventually returning a final string.
{fn StringBuilder(stringArray)
{
local finishedString = ""
local stringArrayLength = size(stringArray)
local currentIndex
for i = 1, i <= stringArrayLength, i = i + 1 do
currentIndex = stringArray[i]
if (NotNullOrEmpty(currentIndex)) then
if (NotNullOrEmpty(finishedString)) then
finishedString = finishedString + currentIndex
else
finishedString = currentIndex
endif
endif
endfor
return finishedString
}}
NotNullOrEmpty() simply returns a boolean of whether the object passed to it (in this case, a string) is null or an empty string.
{fn NotNullOrEmpty(obj)
{
return (obj <> Null AND obj <> "")
}
Using these two utility functions we can concatenate any number of check/list boxes. I've thrown together a simple form with 10 separate check boxes and a couple of list boxes, along with a Multi-line Edit Box. Within a Watcher Expression we can house our logic to update the Multi-line Edit Box whenever one of our options is de/selected. We do this by assigning our Multi-line Edit Box to the result returned from passing our check/list boxes to our StringBuilder() function. And assuming we would like some consistent punctuation to separate our options, we assign a variable to a simple string for this purpose as well.
{
global punctuation = "," + HRET
DOCUMENT.EDITBOX = StringBuilder(array(
CFMT(DOCUMENT.CHECKBOX01,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX02,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX03,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX04,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX05,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX06,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX07,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX08,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX09,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX10,"","","B", punctuation),
CFMT(DOCUMENT.LISTBOX01,"","","B", punctuation),
CFMT(DOCUMENT.LISTBOX02,"","","B", punctuation)
))
}
You'll notice inside of our StringBuilder function we've passed an array full of CFMT() functions. As noted earlier, since CFMT() returns a string, this allows us some further control as to how we would like our end result to be, for instance, adding punctuation at the end of each selected option.
At this point we have a working form; as we check and uncheck boxes our final string residing in our Multi-line Edit Box updates accordingly. The only problem is that we have some trailing punctuation left over at the end of our string >.<
To remedy this we can add some additional logic to the end of our Watcher Expression to find the trailing punctuation and remove it, utilizing a bit of math and MEL's remove() function.
global endOfString = size(DOCUMENT.EDITBOX)
global PUNCTUATION_OFFSET = endOfString - size(punctuation)
global punctuationFirstChar = punctuation[1]
global startOfMatch = match(DOCUMENT.EDITBOX, PUNCTUATION_OFFSET, punctuationFirstChar)
global length = endOfString - startOfMatch
/* Remove trailing punctuation */
DOCUMENT.EDITBOX = remove(DOCUMENT.EDITBOX, startOfMatch, length)
With that in place within our Watcher Expression, we can now check and uncheck boxes, have our Multi-line Edit Box update accordingly, and not have any trailing punctuation.
Here it is all put together (again, I would recommend placing utility functions inside Function Libraries so as not to clutter up your form's Function View - and for re-use purposes):
/* Watcher Expression to update Multi-line Edit Box */
{
global punctuation = "," + HRET
DOCUMENT.EDITBOX = StringBuilder(array(
CFMT(DOCUMENT.CHECKBOX01,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX02,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX03,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX04,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX05,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX06,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX07,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX08,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX09,"","","B", punctuation),
CFMT(DOCUMENT.CHECKBOX10,"","","B", punctuation),
CFMT(DOCUMENT.LISTBOX01,"","","B", punctuation),
CFMT(DOCUMENT.LISTBOX02,"","","B", punctuation)
))
global endOfString = size(DOCUMENT.EDITBOX)
global PUNCTUATION_OFFSET = endOfString - size(punctuation)
global punctuationFirstChar = punctuation[1]
global startOfMatch = match(DOCUMENT.EDITBOX, PUNCTUATION_OFFSET, punctuationFirstChar)
global length = endOfString - startOfMatch
/* Remove trailing punctuation */
DOCUMENT.EDITBOX = remove(DOCUMENT.EDITBOX, startOfMatch, length)
}
{fn StringBuilder(stringArray)
{
local finishedString = ""
local stringArrayLength = size(stringArray)
local currentIndex
for i = 1, i <= stringArrayLength, i = i + 1 do
currentIndex = stringArray[i]
if (NotNullOrEmpty(currentIndex)) then
if (NotNullOrEmpty(finishedString)) then
finishedString = finishedString + currentIndex
else
finishedString = currentIndex
endif
endif
endfor
return finishedString
}}
{fn NotNullOrEmpty(obj)
{
return (obj <> Null AND obj <> "")
}
Caleb Bergman
Systems Analyst
Valley Medical Center, PLLC