Question & Answer
Question
What are the options to migrate macros in Rational Rhapsody that use Visual Basic for Applications (VBA)?
Answer
Abstract:
The IBM Rational Rhapsody Visual Basic for Applications (VBA) Interface is no longer available for new purchases. Maintenance renewals are possible only for existing customers with Rational Rhapsody VBA Add On. See Rational Rhapsody 7.5.x Packaging Changes for more information. Existing users are strongly encouraged to migrate and re-use existing macros with other technologies as future Rational Rhapsody releases may not include VBA.
Much of the functionality of the VBA scripts can be converted to other technologies to continue to leverage the behavior. This document gives a short overview about the possible alternatives and proposes a workflow for converting the scripts.
This document provides overall guidance but does not cover all aspects of converting VBA projects.
In order to perform the following steps, a Rational Rhapsody 7.5.1 or earlier is needed with VBA installed to access the existing VBA scripts. .
VBA Project characteristics:
Storage:
VBA stored with Rhapsody Projects may contain forms, modules and class modules.
- Forms - are user designed UI including forms’ code.
- Modules - are global functions, containing the "macro" commands that can be called directly from Rhapsody.
- Class Modules - are classes with their methods and members.
The VBA project is stored in the file <project name>.vba besides the <project name>.rpy.
The VBA project is stored in a binary format. In order to read it, it should be exported to readable files. It should be opened using Rational Rhapsody 7.5.1 or lower.
One disadvantage of VBA for projects is that any user with VBA can open up the source code and modify it potentially causing maintenance issues with delivered macros. Migration away from VBA helps to mitigate this problem.
The Application Object:
When running a VBA script embedded into an Application, the top-level object of the script is the Application object and the script is implicitly aware of the methods of the Application. For a Rhapsody VBA script the top-level object is defined by the interface: RPApplication.
When using VBA with Rhapsody a user can call any method of RPApplication directly. When running this script from outside the Application, the Application needs to be accessed explicitly.
Example:
VBA from within Rhapsody:
openProject "L:\project.rpy"
From an external program explicit access is required:
Dim rhap As RPApplication
Set rhap = GetObject(,"Application.Rhapsody")
rhap.openProject "L:\project.rpy"
VBA Syntax
VBA syntax is based on Visual Basic 6 but the currently available VB.NET has many differences.
Note: "VB.NET" includes the versions Visual Basic 2003, Visual Basic 2005-Visual Basic 2008.
References:
- Documentation from Microsoft:
http://msdn.microsoft.com/en-us/library/aa192490%28office.11%29.aspx - Upgrading Visual Basic 6.0 Applications to Visual Basic .NET and Visual Basic 2005 http://www.microsoft.com/downloads/details.aspx?FamilyID=7c3fe0a9-cbed-485f-bfd5-847fb68f785d&DisplayLang=en
- Help for Visual Basic 6.0 Users
http://msdn.microsoft.com/en-us/library/kehz1dz1.aspx - Book: "Word 2007 Document Automation with VBA and VSTO", Wordware-Publishing, 2009, Scott Driza, see Chapter 13 - "Moving to Visual Studio 2008 from VBA"
Migration
Migrating to VB.NET
Unfortunately, there is no automatic import/conversion from VBA to Visual Basic (both VB6 and VB.NET). Since VBA is based on Visual Basic 6, if you have access to legacy Visual Basic 6 then it is possible to translate the code to Visual Basic 6 by copying and then resolving any ambiguous references. The code can then be run from Rhapsody as an external helper.
Since Visual Basic 6 is not available currently, migration to VB .NET is the more common requirement. Following references to Microsoft documentation at http://msdn.microsoft.com/en-us/library/aa192490%28office.11%29.aspx
The general process to follow is:
1. Re-create the UI (if exists) in VB environment;
2. Copy the VBA code and correct the syntax;
3. Add reference to Rhapsody COM interface;
4. Run the program externally, or create helper to be invoked from inside rhapsody.
The following example demonstrates the process.
Migration to VB.NET Example
In this example below, a VBA macro sample is migrated from VBA to VB.NET using Microsoft® Visual Studio 2008 to show the general migration process. The code below can be cut and pasted if you wish to follow the steps on your own.
The "RhapsodyVBHelper" is the sample which runs from within Rational Rhapsody allowing some operations to be performed on classes.
The sample contains:
- A Module: Containing the logic and macros that invokes a form.
- A Form: UI for activating some operations.
- In Rhapsody, we define a helper (from the Tools->Customize menu) that invokes this macro that is applicable to a class. This allows user to invoke the helper from the context menu of the class.
The RhapsodyVBHelper example review
The VBA Module:
Public context As RPClass
Public counter As Integer
Sub ShowForm()
Dim frm As New UserForm1
If (Not (getSelectedElement Is Nothing)) And (getSelectedElement.metaclass = "Class") Then
Set context = getSelectedElement
frm.Label1.Caption = context.name
frm.PopulateListBox
frm.Show
Else
MsgBox ("Please select class")
End If
End Sub
Sub PrintOverriddenProerties(element As RPModelElement)
Dim col As RPCollection
Set col = element.getOverriddenProperties(0)
Dim allProps As String
For Each prop In col
allProps = allProps & prop + vbLf
Next
If Not allProps = "" Then
MsgBox (allProps)
Else
MsgBox ("No Overridden Properties")
End If
End Sub
Sub addToClass(theClass As RPClass, metaType As String)
Select Case metaType
Case "Port"
Call theClass.addNewAggr(metaType, "Port" & counter)
counter = counter + 1
Case "Activity"
Set ad = theClass.addActivityDiagram
Case "StateChart"
Set sc = theClass.addStatechart
End Select
End Sub
The VBA form:
The Form contains
Name | Type |
UserForm1 | UserForm |
BtnPrintOverriddenProps | CommandButton |
btnAdd2Class | CommandButton |
ListBox1 | ListBox |
Label1 | Label |
The "Caption" property of the buttons is as shown on the form:
- btnPrintOverriddenProps : "Print Overridden Properties"
- btnAdd2Class : "Add to Class"
The code behind the form:
Sub PopulateListBox()
Dim MyArray As Variant
Dim Ctr As Integer
MyArray = Array("Port", "StateChart", "Activity")
For Ctr = LBound(MyArray) To UBound(MyArray)
Me.ListBox1.addItem MyArray(Ctr)
Next
End Sub
Private Sub btnAdd2Class_Click()
If (ListBox1.ListIndex = -1) Then
MsgBox ("Please select value form list")
Else
Call addToClass(context, ListBox1.value)
End If
End Sub
Private Sub BtnPrintOverriddenProps_Click()
Call PrintOverriddenProerties(context)
End Sub
Creating VB.NET project
Open Microsoft® Visual Studio 2008.
Create new VB Project: File->New->Project…
Select new Visual Basic Console Application:
Adding reference to Rhapsody
Add Rhapsody from Project->Add References…
Choose the COM tab and locate rhapsody:
Choose OK.
Adding the Form
Right click the project on the Solution Explorer and choose Add->Windows Form. The following dialog will appear. Change the name to UserForm1, in order to be the same as the old VBA project and press Add.
Adding the code to the module
Copy & Paste the code from the VBA module1 inside the module definition:
Module Module1
Public context As RPClass
Public counter As Integer
Sub ShowForm()
Dim frm As New UserForm1
If (Not (getSelectedElement Is Nothing)) And (getSelectedElement.metaclass = "Class") Then
context = getSelectedElement
frm.Label1.Caption = context.name
frm.PopulateListBox()
frm.Show()
Else
MsgBox("Please select class")
End If
End Sub
Sub PrintOverriddenProerties(ByVal element As RPModelElement)
Dim col As RPCollection
col = element.getOverriddenProperties(0)
Dim allProps As String
For Each prop In col
allProps = allProps & prop + vbLf
Next
If Not allProps = "" Then
MsgBox(allProps)
Else
MsgBox("No Overridden Properties")
End If
End Sub
Sub addToClass(ByVal theClass As RPClass, ByVal metaType As String)
Select Case metaType
Case "Port"
Call theClass.addNewAggr(metaType, "Port" & counter)
counter = counter + 1
Case "Activity"
ad = theClass.addActivityDiagram
Case "StateChart"
sc = theClass.addStatechart
End Select
End Sub
End Module
- Add "Imports rhapsody" before the first line.
- Add the Rhapsody Application Object as member of the module:
"Public rhap As RPApplication" - Initialize the Rhapsody Application object:
Add at the beginning of the "ShowForm" Subroutine:
rhap = GetObject(, "Rhapsody.Application") - For each method of RPApplication add the prefix: "rhap."
example: "getSelectedElement" -> "rhap.getSelectedElement" - Change "Caption" property of Label to "Text"
- Add declaration for undeclared objects.
- Change the Subroutine "ShowForm" to "Main"
The code should be like the following:
Imports rhapsody 'VB.NET addition
Module Module1
Public rhap As RPApplication 'VB.NET addition
Public context As RPClass
Public counter As Integer
Sub main()
rhap = GetObject(, "Rhapsody.Application") 'VB.NET addition
Dim frm As New UserForm1
If (Not (rhap.getSelectedElement Is Nothing)) And (rhap.getSelectedElement.metaClass = "Class") Then
context = rhap.getSelectedElement
'frm.Label1.Caption = context.name ***VBA code***
frm.Label1.Text = context.name 'VB.NET changed
frm.PopulateListBox()
frm.ShowDialog()
Else
MsgBox("Please select class")
End If
End Sub
Sub PrintOverriddenProerties(ByVal element As RPModelElement)
Dim col As RPCollection
col = element.getOverriddenProperties(0)
'Dim allProps As String ***VBA code***
Dim allProps As String = "" 'VB.NET changed
For Each prop In col
allProps = allProps & prop + vbLf
Next
If Not allProps = "" Then
MsgBox(allProps)
Else
MsgBox("No Overridden Properties")
End If
End Sub
Sub addToClass(ByVal theClass As RPClass, ByVal metaType As String)
Select Case metaType
Case "Port"
Call theClass.addNewAggr(metaType, "Port" & counter)
counter = counter + 1
Case "Activity"
'ad = theClass.addActivityDiagram ***VBA code***
Dim ad As RPFlowchart = theClass.addActivityDiagram 'VB.NET changed
Case "StateChart"
'sc = theClass.addStatechart ***VBA code***
Dim sc As RPStatechart = theClass.addStatechart 'VB.NET changed
End Select
End Sub
Creating the Form
The new project will be opened with an empty form
Using the toolbox add to the form controls like the VBA form.
Name | Type |
UserForm1 | System.Windows.Forms.Form |
BtnPrintOverriddenProps | Button (instead of CommandButton) |
btnAdd2Class | Button (instead of CommandButton) |
ListBox1 | ListBox |
Label1 | Label |
To set the Text visible on the Buttons change the "Text" property. (VBA eq. “Caption”)
Creating the code behind the form
Right click on the Form and choose "View Code" to show the code behind.
You can see that the code already contains:
Public Class UserForm1
End Class
In order to create the methods " BtnPrintOverriddenProps_Click() "and" btnAdd2Class_Click()" double click the buttons from the form.
The code will be modified as follows:
Public Class UserForm1
Private Sub btnPrintOverriddenProps_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintOverriddenProps.Click
End Sub
Private Sub btnAdd2Class_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd2Class.Click
End Sub
End Class
Now you can copy the code from the original VBA, including the subroutine "PopulateListBox", and change it slightly to fit VB.NET controls as follows:
Public Class UserForm1
Private Sub btnPrintOverriddenProps_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintOverriddenProps.Click
Call PrintOverriddenProerties(context)
End Sub
Private Sub btnAdd2Class_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd2Class.Click
' If (ListBox1.ListIndex = -1) Then ***VBA code***
If (ListBox1.SelectedIndex = -1) Then 'VB.NET changed
MsgBox("Please select value form list")
Else
'Call addToClass(context, ListBox1.value) ***VBA code***
Call addToClass(context, ListBox1.SelectedItem) 'VB.NET changed
End If
End Sub
Sub PopulateListBox()
'Dim MyArray As Object ***VBA code***
Dim MyArray As ArrayList 'VB.NET changed
Dim Ctr As Integer
'MyArray = Array("Port", "StateChart", "Activity") ***VBA code***
MyArray = New ArrayList() 'VB.NET changed
MyArray.Add("Port") 'VB.NET changed
MyArray.Add("StateChart") 'VB.NET changed
MyArray.Add("Activity") 'VB.NET changed
'For Ctr = LBound(MyArray) To UBound(MyArray) ***VBA code***
'Me.ListBox1.addItem(MyArray(Ctr)) ***VBA code***
For Ctr = 0 To MyArray.Count - 1
ListBox1.Items.Add(MyArray.Item(Ctr)) 'VB.NET changed
Next
End Sub
End Class
Testing the application
You can already test and debug the application. In this case open Rational Rhapsody and select a class. Then run the application and see the form loads and operates similar to the old VBA scripts.
You can now add this helper to Rational Rhapsody.
Adding the helper to Rational Rhapsody
Open Rhapsody and choose from the menu: Tools->Customize…
Create new helper:
- Click on the "new" icon and give it a name
- Chooses the executable created by Visual Studio (e.g. C:\RhapsodyVBHelper\bin\Debug\RhapsodyVBHelper.exe )
- Set Applicable to Class
- Notice that the type is "External program" and not "VBA macro"
Now you will be able to run it by right clicking the class:
Product Synonym
Rational Rhapsody
Was this topic helpful?
Document Information
Modified date:
27 May 2022
UID
swg21428105