CATScript - Questions & Answers
CATScript is a scripting language specific to CATIA, a widely used computer-aided design (CAD) software. CATScript allows users to automate repetitive tasks, customize the software, and create custom tools and functionalities.
It is based on Visual Basic for Applications (VBA) and provides access to CATIA’s Automation API, enabling interaction with CATIA’s objects, properties, and methods.
CATScript can be used to enhance productivity, streamline workflows, and extend the capabilities of CATIA through script-based automation.
Is it possible to determine the current macro directory at runtime?
The macro directory is meant to be the directory where the actual macro file is located on disc. In Catia it does not seem to be possible to retrieve this directory at runtime, or at least I was not able to figure it out.
So the only way is to hard-code e.g. a path to a support file which needs to be loaded from within a CATScript macro.
Is it possible to organize code in a separate file and to evaluate/execute it?
Yes, here is a sample code to illustrate the call:
' Option Explicit
Language = "VBSCRIPT"
Const PATH_NAME = "<your path here>"
Const CUSTOM_DLG = "CustomDialogClass.CATScript"
Const DELIM = "@"
Sub CATMain()
Dim usr As Variant
Dim params() As Variant
ReDim params(2)
params(0) = 350
params(1) = 420
params(2) = _
"The quick brown fox" + DELIM + _
"*jumps over" + DELIM + _
"the lazy dog."
usr = CATIA.SystemService.ExecuteScript ( _
PATH_NAME, catScriptLibraryTypeDirectory, _
CUSTOM_DLG, "CustomDialogClass_Cmd", params)
If (Len(usr) = 0) Then
MsgBox "Nothing selected!"
Else
MsgBox "You selected: '" + usr + "'"
End If
End Sub
How can I read the decimal separator value from registry ?
The following function might be useful to ensure that CDbl
works correctly
with the decimal separator setting.
' read decimal separator value from registry
'
Function GetInternationalDecimal (ByRef val As String) As Boolean
Dim wsh As IWshShell3
GetInternationalDecimal = False
Err.Clear : On Error Resume Next
val = ""
Set wsh = CreateObject("WScript.Shell")
val = wsh.RegRead("HKCU\Control Panel\International\sDecimal")
wsh = Nothing
On Error Goto 0
If (Err.Number <> 0 Or val = "") Then
Exit Function
End If
GetInternationalDecimal = True
End Function
' // Test Call
' //
Sub CATMain ()
Dim val,msg As String
' MsgBox CATIA.SystemConfiguration.OperatingSystem
If (Not GetInternationalDecimal(val)) Then
MsgBox "Error: unable to read current decimal setting!"
Exit Sub
End If
Select Case val
Case ".": msg = "point"
Case ",": msg = "comma"
Case Else: msg = val
End Select
MsgBox "Current international decimal setting: " + msg
End Sub
Can I declare an array with multiple variables per item ?
The solution is to define a class MyCustomData
with the data structure as required
and in a 2nd step create an array variable as usual.
For each item of the array, the custom class can be given as argument. Note that as the given argument is from type “Class”, the “Set” operator must be used.
Once this is done, the syntax arr(i).str = str can be used as a valid statement to refer each individual custom data item.
Class MyCustomData
Dim str As String
Dim val As Variant
End Class
Sub AddItem (_
ByRef arr() As Variant, _
ByVal str As String, ByVal val As Variant)
Dim i As Integer
ReDim Preserve arr(UBound(arr) + 1)
i = UBound(arr)
Set arr(i) = New MyCustomData
arr(i).str = str
arr(i).val = val
End Sub
Sub CATMain ()
Dim custom_array() As Variant
ReDim custom_array(0)
AddItem custom_array, "test", 99
AddItem custom_array, "width", 100
AddItem custom_array, "height", 20
AddItem custom_array, "dummy_value", "not set"
For i=1 To Ubound(custom_array)
MsgBox custom_array(i).str + " = " + CStr( custom_array(i).val)
Next
End Sub
Is it possible to get access to the Clipboard?
The clipboard offers a possibility to pass data to and from a separate process without the need of an intermediate transfer file. A use case could be e.g. an external dialog window (implemented as hta application for example) which can be called from within a CATScript main caller program.
Here are 2 functions which serve this purpose:
Function GetClipboardText() As String
Dim str As String
Dim html As HtmlDocument
Set html = CreateObject("htmlfile")
str = html.ParentWindow.ClipboardData.GetData("text")
Set html = Nothing
If (TypeName(str) = "Null") Then
GetClipboardText = ""
Else
GetClipboardText = str
End If
End Function
Sub CopyToClipboard(ByVal str As String) As String
Dim html As HtmlDocument
Set html = CreateObject("htmlfile")
html.ParentWindow.ClipboardData.SetData "text", str
Set html = Nothing
End Sub
A practical example of how to use excel from inside a CATScript macro
The following code example illustrates the possibility to call excel directly from CATScript. Excel will be launched and some sample information will then be written to it.
Hint: In this scenario it is important that the current excel file has a unique file name otherwise excel will possibly raise an error.
The code could be handy if e.g. during macro execution some kind of (process-) information needs to be written and kept as evidence/reference for the user.
Class CustomExcelFactory
' type declaration omitted, will be declared at runtime...
Private obj_excel, obj_sheet
Private keep_excel_on_screen As Boolean
' do something when the class is initialized
Private Sub Class_Initialize ()
keep_excel_on_screen = True
End Sub
Public Property Let KeepExcelOnScreen (ByVal excel_on_screen As Boolean)
keep_excel_on_screen = excel_on_screen
End Property
' define the public properties
Public Property Get objSheet ()
Set objSheet = obj_sheet
End Property
' // open Excel Application for writing
' //
Public Function OpenExcelAppForWriting () As Boolean
OpenExcelAppForWriting = False
Err.Clear : On Error Resume Next
Set obj_excel = CreateObject ("EXCEL.Application")
If Err.Number <> 0 Then
MsgBox "Warning: Excel application not found.", vbCritical
Err.Clear : On Error Goto 0
Exit Function
End If
If ( keep_excel_on_screen = True ) Then
obj_excel.Application.Visible = True
End If
' create a new workbook
Err.Clear : On Error Resume Next
set workbook = obj_excel.WorkBooks.Add()
' - disabled- non critical error message !
' If Err.Number <> 0 Then
' MsgBox "Error when trying to set the current workbook in Excel!"
' End If
Err.Clear : On Error Goto 0
Set obj_sheet = obj_excel.ActiveSheet
obj_sheet.Select
' obj_sheet.Name = "My Sheet Name"
OpenExcelAppForWriting = True
End Function
' // SaveAs... the spreadsheet.
' //
Public Sub SaveAsExcelApplication (ByVal fileName As String)
Dim fs As FileSystem
Set fs = CATIA.FileSystem
' ActiveWorkbook.SaveAs:
' if the file already exists, the user gets a dialog,
' to specify whether to overwrite the file or not...
' as a workaround, we delete the file prior to the save operation!
Err.Clear : On Error Resume Next
If ( fs.FileExists(fileName) ) Then
fs.DeleteFile fileName
If Err.Number <> 0 Then
MsgBox _
"Error when trying to delete excel file: " + fileName + vBNewLine _
+ "--> Please close Excel Application and try again!"
Err.Clear : On Error Goto 0
Exit Sub
End If
End If
' ??? problem on some workstations / excel versions:
Err.Clear : On Error Resume Next
obj_excel.ActiveWorkbook.SaveAs fileName
If Err.Number <> 0 Then
MsgBox _
"Error in excel - operation went wrong for: " + fileName + vBNewLine _
+ "--> Please save your Excel sheet manually!"
Err.Clear : On Error Goto 0
End If
Err.Clear : On Error Goto 0
End Sub
' // save the spreadsheet and close the workbook if required
' //
Public Sub CloseExcelApplication ()
obj_excel.ActiveWorkbook.Save
If ( keep_excel_on_screen = False) Then
obj_excel.ActiveWorkbook.Close
obj_excel.Application.Quit
End If
End Sub
End Class
The following procedure shows how to bring the CustomExcelFactory class to live.
After the Dim XLS As CustomExcelFactory initialization statement, the class object is instantiated with the Set XLS = New CustomExcelFactory command.
Once the class is available , the 1st command is XLS.OpenExcelAppForWriting which attempts to open or launch excel.
With XLS.SaveAsExcelApplication a new spreadsheet file is created.
Note that it is not required to expose the obj_excel to public, the only object which is required as public is XLS.objSheet which in fact refers to excel’s sheet object itself and thus knows all the sub-commands which can be used on CATScript level to define the spreadsheet properties.
Within the For loop some arbitrary data is written as an example and with the XLS.CloseExcelApplication procedure the excel sheet is finally saved to file. Depending on weather the XLS.KeepExcelOnScreen property is true or false Excel stays on screen or is closed again.
Hint: The created excel sheet is saved on the disk and the user has to take care to manage it afterwards.
' -----------------------------------------------------------------------------
' --- CustomExcelFactory.CATScript
' -----------------------------------------------------------------------------
' (c) 2023, Johann Oberdorfer - Engineering Support | CAD | Software
' johann.oberdorfer [at] gmail.com
' www.johann-oberdorfer.eu
' -----------------------------------------------------------------------------
' This source file is distributed under the BSD license.
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
' See the BSD License for more details.
' -----------------------------------------------------------------------------
' Option Explicit
Language = "VBSCRIPT"
' --- copy the CustomExcelFactory code to here ---
' --- BEGIN ---
' Class CustomExcelFactory
' ...
' End Class
' --- EOF ---
Sub CustomExcelFactory_test ()
Dim i,j, col_index, rowcnt As Integer
Dim temp_dir, time_stamp, _
spread_sheet_file, _
spread_sheet_path As String
Dim fs As FileSystem
Dim str As Folder
Dim XLS As CustomExcelFactory
Set XLS = New CustomExcelFactory
XLS.KeepExcelOnScreen = True
i = 1
j = 10
col_index = 1
rowcnt = 2
' get the user's temporary directory ...
Set fs = CATIA.FileSystem
Set str = fs.TemporaryDirectory
temp_dir = CATIA.SystemService.Environ(str.Name)
time_stamp = Replace (Time, ":", "", 1, -1, vbTextCompare)
spread_sheet_file = "Excel_Test_" + time_stamp + ".xls"
spread_sheet_path = fs.ConcatenatePaths(temp_dir, spread_sheet_file)
If (XLS.OpenExcelAppForWriting() <> True ) Then
Exit Sub
End If
' create new file...
XLS.SaveAsExcelApplication spread_sheet_path
XLS.objSheet.Name = "Result-List"
XLS.objSheet.Range("A1:C1").Font.Bold = True
XLS.objSheet.Range("A1:C1").Interior.ColorIndex = 15 ' COLOR_LIGHTGREY
' "A" / "B" / "C"
XLS.objSheet.Cells(1, col_index).Value = "Count:" : XLS.objSheet.Columns(col_index).ColumnWidth = 10
XLS.objSheet.Cells(1, col_index + 1).Value = "Item Name:" : XLS.objSheet.Columns(col_index + 1).ColumnWidth = 40
XLS.objSheet.Cells(1, col_index + 2).Value = "Value:" : XLS.objSheet.Columns(col_index + 2).ColumnWidth = 40
For i = 1 To j
rowcnt = rowcnt + 1
XLS.objSheet.Cells(rowcnt, 1).Value = CStr(i) + " of " + CStr(j)
XLS.objSheet.Cells(rowcnt, 2).Value = "Test " + CStr(i)
XLS.objSheet.Cells(rowcnt, 3).Value = "dummy " + CStr(i)
' scroll to current row...
XLS.objSheet.Cells(rowcnt, 1).Select
Next
' once finished, jump to the beginning of the sheet
XLS.objSheet.Cells(1, 1).Select
XLS.CloseExcelApplication
Set XLS = Nothing
MsgBox _
"Excel write test finished!", _
+ vbInformation + vbOKOnly, "User Information:"
End Sub
' execution starts here ...
Sub CATMain ()
Call CustomExcelFactory_test ()
End Sub