CATScript - The Beauty of Code
CATScript is a scripting language specific to CATIA, a widely used computer-aided design (CAD) software.
In this article, I’d like to put down some more reusable code snippets to make a programme’s live easier.
Text Concatenation with Array
The following coding example is likely the most efficient way
of managing large amounts of text information.
Note when using the Join function, vbNewLine needs to be declared only once.
Option Explicit
Language="VBSCRIPT"
Sub CATMain()
Dim i As Integer
Dim msg As Array
msg = Array ( _
"entia non sunt",_
"multiplicanda praeter",_
"necessitatem",_
"",_
"Entities should not be",_
"multiplied beyond necessity."_
)
' loop through each individual array item
' For i = 0 To UBound(msg) MsgBox msg(i) Next
' show the array's content
MsgBox Join (msg, vbNewLine), vbOkOnly + vbInformation, "Message:"
End Sub
If you are short in time, don’t read any further in this chapter, use the above code, modify it as required and you are done.
Dictionaries
While I typically use the commands built into the CATScript language, there is also
additional functionality available via CreateObject.
This way, dictionary objects are provided and can be employed to address problems
requiring more complex data structures.
MsgBox Goodies
The array data type can also be used to implement a clean and lean MsgBox call.
I personally like the “Select Case” statement together with predefined enumerations.
This way, there is no need to hard code return values.
Sub UserSelectionCmd()
Dim msg As Array
msg = Array (_
"This function allows to ....",_
"<your text description here>",_
"<some more explanations...>",_
"","",_
"YES = " + vbTab + "Do you like to continue?",_
"No = " + vbTab + "<Do semething else instead...>")
Do While True
Select Case MsgBox ( _
Join (msg, vbNewLine),_
vbQuestion + vbYesNoCancel, "User Selection:")
Case vbYes: Exit Do
Case vbNo: Call DoSomethingElseCmd ()
Case vbCancel: Exit Sub
End Select
Loop
End Sub
Sub CATMain()
UserSelectionCmd
End Sub
More about Dynamic Arrays
I prefer dynamic array allocation because it is the most flexible approach. At the same time, I try to avoid writing excessive code, so I looked for a clean and concise solution to meet this requirement:
Standard way to set up some more array variables manually.
Sub CATMain ()
Dim i As Integer
Dim item, var() As Variant
ReDim var(0) : var(0) = 1
ReDim Preserve var(1) : var(1) = "Hello"
ReDim Preserve var(2) : var(2) = True
For i = LBound(var) To UBound(var)
MsgBox TypeName (var(i)) + " = " + CStr(var(i))
Next
' also possible:
For Each item In var
MsgBox TypeName (item) + " = " + CStr(item)
Next
End Sub
Accessing every element in an array can also be achieved using a For Each loop,
which is often the most readable and concise option.
The following code mimics a dynamic array. The size of the array is handled on the fly at the time when adding a new array item:
Sub Add (ByRef arr() As String, ByVal new_item As String)
ReDim Preserve arr (UBound(arr) + 1)
arr (UBound(arr)) = new_item
End Sub
Sub CATMain()
Dim arr() As String
ReDim arr(-1)
' Add items dynamically
Add arr, "First"
Add arr, "Second"
Add arr, "Third"
MsgBox Join(arr, vbNewLine)
End Sub
This is likely the most comprehensive version for a dynamically allocated array with the fewest lines of code.
Notes:
The array index starts at 0 which is the default behavior for array variables.
If the array would be declared as
Dim arr() As Variantthe array is capable to handle any kind of variable.Hint: If an object is assigned as array item, you probably would need to declare the
Setkeyword as usual.To loop through each item of the array, one can do this as usaully like toe following:
Dim arr() As String ' MsgBox CStr(LBound(arr)) + "/" + CStr(UBound(arr)) Dim i As Integer For i = LBound(arr) To UBound(arr) MsgBox "Index " & i & ": " & arr(i) Nextand as an alternative:
MsgBox Join(arr, vbNewLine)
Using brakets to access the value of an array element
The standard way to access the value of an array element is by using (). As usual, you need an array type declaration to do so.
When using the Split() command, a variation of the () cast statement can be used without requiring an extra variable.
Notice that the syntax also allows to append (0) to the Split() command in order
to access the specified array element. Because this style is not widely used, I’d like to draw special attention to it.
Example use case:
Const DELIMITER = "~"
Sub CATMain ()
Dim str As String
str = Join(Array("Hello", "world", "!"), DELIMITER)
MsgBox Split(str,DELIMITER )(0)
End Sub
Language specific notes
Option Explicite
' declaration at the very beginning of a macro:
Option Explicite
What does it mean?
This declaration tells the interpreter to check, if a variable hase been declared before usage (like e.g. Dim i As Integer : Dim str As Str, etc…).
All variables whatsoever will be checked before evaluation when loading the macro into memory.
I would highly recommend to use this option as it helps to produce more stable code.
CATScript allows to use variables on the fly and without declaration at all. Although possible, I would not recomment this style. It leads to more error prone code where errors might occure at runtime just like: “variable not set” (or similar).
Where to declare variables
A variable can be declared at any place in the source code. Never the less, I do not use this flexibility and tend to strictly declare variables at the beginning of a sub function.
Coding this way has the benefit so that the code is more readable and focusing on the logic rather than speding time too much on DIM statements.
Code structure:
- There is one block of DIM statements at the beginning.
- What follows next usually is to initialize the variables and
- subsequently the programming logic follows…
Error handling
In the example above, error handling is coded the most pragmatic way. Each individual command where an error might occure is surrounded by “On Error Resume Next” and corresponding “On Error Goto 0”.
Also notice that both calls clear the Error.Number so it is necessary to declare an interger variable in case the error number would be needed to code some more logic around the error. Due to this behavior “Err.Clear” command in most cases is not required.
Is it necessary to unset Variables
As CATScript has a build in garbage collector (gc), it is simply not needed to unset a variable or to use the Erase command to clean memory.
My strategy as of now is that I do not bother to try to clean up memory (any more). We are dealing with an interpreter with a build-in gc, so it is save to do so. I never faced memory problems with CATScript in any way.
