Using VBA in Command or Expression Fields
- Last UpdatedJul 18, 2023
- 6 minute read
Plant SCADA expects that all code contained within a Plant SCADA Command or Expression field to be Cicode by default. When using VBA code script directly in a Plant SCADA Command or Expression field within Plant SCADA, you must precede the VBA script with the keyword CiVBA, as shown here:
CiVBA
TestTag_1 = TestTag_1 + 1
This is known as the language override command. When the Plant SCADA compiler reads the keyword CiVBA, it knows to handle that code (within the same Plant SCADA Command or Expression field) as VBA script, and compiles it as such. No such override command is required to use Cicode.
The CiVBA language override statement must be placed first in the Plant SCADA Command or Expression field if you want to use VBA script code instead of Cicode in that Plant SCADA Command or Expression field.
Note: You must use either Cicode or VBA in a Plant SCADA Command or Expression field. You cannot change or swap between the two programming languages (within the same Plant SCADA Command or Expression field) once you've started using one or the other.
You can, however, call a single Cicode function from within VBA script if you wrap the Cicode call within special VBA functions CicodeCallOpen() and CicodeCallReturn().
Calling Cicode from VBA
Calling a Cicode function from VBA is accomplished by two VBA functions: CicodeCallOpen() and CicodeCallReturn().
To call a given Cicode function, use the CicodeCallOpen function which will create and execute a Cicode thread that runs the function. For multitasking purposes, a separate function CicodeCallReturn is used to obtain the return-value of the completed Cicode function most recently called by the CicodeCallOpen function.
|
|
|
UNINTENDED EQUIPMENT OPERATION Do not nest the CicodeCallOpen and CicodeCallReturn functions. Nesting these functions can lead to unintended equipment operation when your program is run. Failure to follow these instructions can result in death, serious injury, or equipment damage. |
The return value is initialized when control is returned to the Plant SCADA kernel. This occurs only after completion of the line of VBA code containing CicodeCallOpen. For details on multithreading in VBA, see Multithread Considerations with VBA.
To call a given Cicode function or subroutine from VBA, use the CicodeCallOpen function. Upon return from CicodeCallOpen, you can call the CicodeCallReturn function to obtain the return value of the Cicode function called.
The CicodeCallOpen function is a VBA function used to call a Cicode function from VBA. It is used to initiate and execute a call to the Cicode function and returns an integer value representing the success or the type of error encountered by the CicodeCallOpen function.
<ReturnValue> = CicodeCallOpen(<FunctName>, <ArgList>)
Where:
-
<ReturnValue> represents the return value of:
-
0 if CicodeCallOpen function was successful
-
1 for CicodeCallOpen function general error
-
2 for specified Cicode function not found
-
3 for incorrect number of arguments for specified Cicode function passed in <ArgList>.
-
-
<FunctName> is a string representing the name of the Cicode function being called. The function name should be enclosed in double quotes.
-
<ArgList> represents a variable length comma separated argument list of all the arguments to be passed to the Cicode function being opened (dependant upon which Cicode function is being called and the arguments that Cicode function requires). The argument list should not be enclosed within brackets, although when using variable names as arguments, those variable arguments within the list need to be individually enclosed within brackets to force the passing of the variable to Cicode by value.
The CicodeCallReturn function is a VBA function used to obtain the return value of the most recently completed Cicode function opened with the VBA CicodeCallOpen function.
<ReturnValue> = CicodeCallReturn()
Where:
-
<ReturnValue> represents the return value of the Cicode function specified in the most recent call of the CicodeCallOpen function. Note that the return data type of CicodeCallReturn will depend upon the return data type of the Cicode function called in the most recent call of the CicodeCallOpen function.
No arguments are passed to the CicodeCallReturn function, as it can only return the result of the most recent return-value for the Cicode function called by the VBA CicodeCallOpen function.
Note: In the following example, a VBA variable is enclosed in brackets to force the passing of the variable by value. See Passing Variables Byref and Byval.
VBA
' declare modular variant variable to store function results
Dim vntRet as Variant
Function TestCicode() As Integer
' declare local variables
Dim intRet As Integer
Dim strReply as String
Dim intMaxScale as Integer
' copy current tag value to variable
' uses the project variable tag named MAX_SCALE
intMaxScale = MAX_SCALE
' call Cicode function
' for example: TrnSetScale( AN, Pen, Percent, Scale)
intRet = CicodeCallOpen( "TrnSetScale", 53, -1, 100, (IntMaxScale) )
' Note the syntax used:
'- brackets around the VBA function argument list
'(Only necessary when the VBA function is preceded by an equals (=) sign .)
' - double quotes around the Cicode function name
'- no brackets around the Cicode function argument list
'- brackets around individual variable arguments
' test results
If intRet = 0 Then
'
' insert code for successful completion here
'
vntRet = CicodeCallReturn()
strReply = "CicodeCallOpen Function successfully called"
Else
'
' insert code for unsuccessful completion here
'
Select Case intRet
Case = 1
' assign return comment for this case
strReply = "CicodeCallOpen Function call general error"
Case = 2
' assign return comment for this case
strReply = "Cicode Function not found"
Case = 3
' assign return comment for this case
strReply = "Wrong number of arguments "_
& "in Cicode CallOpen function call"
Case Else
' assign return comment for this case
strReply = "Unknown error"
End Select
End If
' display return comment for your information
MsgBox strReply
' assign return value for this function
TestCicode = intRet
End Function
Alternatively, to call a single VBA function (from within the Plant SCADA Command or Expression field) after you have already used Cicode in that field, you can wrap the VBA within three nested special Cicode functions: VbCallOpen(), VbCallRun() and VbCallReturn().
Calling VBA from Cicode
Three new Cicode functions allow VBA code to be called from within Cicode script, and be pre-emptively multitasked by Plant SCADA. These calls VbCallOpen(), VbCallRun(), and VbCallReturn() can be nested to implement the entire function set with a single line of Cicode.
Note: When using the CiVBA language override in a Command field, the compiler constructs the nested call for you. The same mechanism is used even though it is not self evident. For details, see .
For information on multithreading in VBA, see Multithread Considerations with VBA.
To call a given VBA function or subroutine from Cicode, use the VbCallOpen function. This returns a handle which can then be used to execute the call by passing it to the VbCallRun function. Upon return from VbCallRun, you can call the VbCallReturn function to get the return value of the VBA function called.
The Cicode VbCallOpen() function is used to initiate a call to the VBA function or subroutine, and returns a handle to the open function.
<ReturnValue> = VbCallOpen(<FunctName>, <ArgList>)
Where:
-
<ReturnValue> represents the handle to the opened function.
-
<FunctName> represents the name of the VBA function or subroutine being called.
-
<ArgList> represents a comma separated list of arguments to pass to the opened VBA function or subroutine named in <FunctName>.
The Cicode VbCallRun() function is used to execute the VBA function or subroutine (previously opened with the Cicode VbCallOpen function), and requires the handle returned from the VbCallOpen function call. The VbCallRun function provides an opportunity for the opened VBA function to complete and return a value in the multi-threaded Plant SCADA environment. It passes its argument value (of OBJECT data type) through as its return value upon completion.
<ReturnValue> = VbCallRun(<CallHandle>)
Where:
-
<ReturnValue> represents the handle to the opened VBA function passed through for the <CallHandle>argument.
-
<CallHandle> represents the handle to the previously opened VBA function as returned by the Cicode VbCallOpenfunction.
The Cicode VbCallReturn() function is used to obtain the return value of the completed VBA function (previously opened with the Cicode VbCallOpen function), and requires the handle returned from the VbCallRun function call.
<ReturnValue> = VbCallReturn(<CallHandle>)
Where:
-
<ReturnValue> represents the value returned by the completed VBA function (which was previously opened by the Cicode VbCallOpen function). The data type of the return value is dependent upon the data type of the return value for the VBA function opened.
-
<CallHandle> represents the handle to the previously opened VBA function as returned by the Cicode VbCallRun function.
Example
FUNCTION
TestCitectVBA()
INT iRet;
STRING sMsg = "Hello";
INT iVal = 123;
iRet = VbCallReturn(VbCallRun(VbCallOpen("CiVBATest", iVal)));
Message("TestCitectVBA Function", "CiVBATest = " + IntToStr(iRet), 0);
END
Example
Function CiVBATest(Value As Integer) As Integer
CiVBATest = Value * 2
End Function
