This article is about MicroStation® Visual Basic for Applications (VBA).
It's written for developers using
Bentley Systems MicroStation.
Questions similar to this appear on the
Be Communities Forums.
This problem appeared in the
MicroStation Programming Forum.
This article discusses an interactive cell placement tool for MicroStation. It is written in MicroStation VBA. The VBA project is available for download.
A MicroStation Cell is a group of graphic elements that is used repeatedly.
Multiple cells are stored in a cell library.
An architect, for example, might have a cell library named furniture.cel
.
Cells in that library would probably include doors, windows and other fixtures.
A MicroStation user places, or instantiates, a cell by …
A
Before you create a CellElement
, you want to be sure it exists in a currently-attached
Cell Library. Here's one way, that works on the negative inversion principle.
Attempt to create a cell using the proposed name.
If the create method succeeds, the cell exists in the cell library …
Function CellExistsInLibrary (cellName As String) As Boolean CellExistsInLibrary = False On Error GoTo err_CellExistsInLibrary Dim oCell As CellElement Dim origin As Point3d, _ scale As Point3d origin = Point3dZero scale = Point3dOne Set oCell = CreateCellElement2 (cellName, origin, scale, True, Matrix3dIdentity)' If we get here, the cell exists in a library
CellExistsInLibrary = True Set oCell = Nothing Exit Function err_CellExistsInLibrary:' Cell doesn't exist
MsgBox "Cell '" & cellName & "' Not Found" End Function
Here's another way, by Ron Reemer, who contributed this to the MicroStation Programming Forum …
Function CellExists(cellName As String) As Boolean CellExists = False If IsCellLibraryAttached Then Dim celEnum As CellInformationEnumerator' Get list of cells
Set celEnum = GetCellInformationEnumerator(True, False)' Loop through cells
Do While celEnum.MoveNext If celEnum.Current.Name = cellName Then' Found the cell so return True
CellExists = True Exit Function End If Loop' Cell not found
MsgBox "Cell '" & cellName & "' Not Found" Else' No library attached
MsgBox "No Cell Library Attached" End If End Function
A We seek to replicate, more or less, MicroStation's built-in Place Cell command. The Cell Placer class provides that functionality.
A rider to the original question was "How do I enter a new cell name at any time to change the cell before it is placed?" We answer that question by allowing the user to key-in a cell name while our primitive command is operating.
A second rider to the original question was "How do I place a cell and immediately drop it?" That question is answered by the Cell Place and Drop class. It's identical to the first class except that, at the point of instantiation, the cell is dropped to its components. The components are added individually to the active model.
The VBA project has three modules …
modMain
provides two entry points, depending which version of
Cell Placer you want to start …
' ---------------------------------------------------------------------
' MicroStation key-in:
' vba run [CellPlacement]modMain.PlaceCell
' ---------------------------------------------------------------------
Public Sub PlaceCell()
Dim oCellPlacer As New clsCellPlacer
oCellPlacer.CellName = ActiveSettings.CellName
Const WantKeyins As Boolean = True
CommandState.StartPrimitive oCellPlacer, WantKeyins
End Sub
' ---------------------------------------------------------------------
' MicroStation key-in:
' vba run [CellPlacement]modMain.PlaceAndDropCell
' ---------------------------------------------------------------------
Public Sub PlaceAndDropCell()
Dim oCellPlacer As New clsCellPlaceAndDrop
oCellPlacer.CellName = ActiveSettings.CellName
Const WantKeyins As Boolean = True
CommandState.StartPrimitive oCellPlacer, WantKeyins
End Sub
The code, in each case, creates an object from the class definition.
It sets the class CellName
property to the active cell name.
It then assigns that object to MicroStation's state engine with
CommandState.StartPrimitive
.
This code demonstrates a little-used facility of a primitive command:
accepting a user key-in.
We start the primitive function with the optional WantKeyins
argument (Boolean True
).
While the primitive command is active, the MicroStation user can key-in text at any time.
In this example, the key-in is interpreted as a cell name. When the command starts, it uses the active cell. While the command is executing, the user may key-in a different cell name. If that cell exists in the attached cell library, the command immediately uses that cell.
This is a VBA class module.
It Implements IPrimitiveCommandEvents
, making it a primitive command class.
The cell name is stored in a class variable m_strCellName
…
Private m_strCellName As String
m_strCellName
is assigned the active cell name by the calling
subroutine in modMain.
The IPrimitiveCommandEvents_Start
subroutine implements the start event.
It initialises the command, setting the user prompts and command name.
It also starts dynamics, so that the user can see the cell as it is stuck to the cursor.
MicroStation calls the dynamics event repeatedly as the user moves the cursor.
We pass the cursor data point to the CreateCell
subroutine, along with the DrawMode
.
MicroStation calls the dynamics event once, when the user places a data point.
We pass the cursor data point to the CreateCell
subroutine, along with the DrawMode
msdDrawingModeNormal
.
The user may key-in a new cell name at any time.
The IPrimitiveCommandEvents_Keyin
copies the user key-in to member variable m_strCellName
.
The new cell name is used immediately.
CreateCell
Subroutine
The CreateCell
subroutine is called by both the
_Dynamics
event and the _Datapoint
event.
Each event passes the current datapoint and draw mode.
The _Datapoint
event always passes draw mode msdDrawingModeNormal
;
the _Dynamics
event passes one of several other MsdDrawingMode
values.
We create the cell using the cell name stored in member variable m_strCellName
.
We use the draw mode to either add the cell to the active model following a datapoint
(ActiveModelReference.AddElement oCell
),
or to display it at the current cursor position (oCell.Redraw
) …
Private Sub CreateCell(ByRef point As Point3d, ByVal drawMode As MsdDrawingMode) Dim oCell As CellElement Set oCell = CreateCellElement2(m_strCellName, point, Point3dOne, True, Matrix3dIdentity) If drawMode = msdDrawingModeNormal Then ActiveModelReference.AddElement oCell Else oCell.Redraw drawMode End If End Sub
This class is identical to clsCellPlacer until the user places a datapoint. Instead of adding the cell to the active model, we add its components …
Private Sub DropCell(ByVal oCell As CellElement) Dim oComponents As ElementEnumerator Set oComponents = oCell.Drop Do While oComponents.MoveNext Dim oElement As Element Set oElement = oComponents.Current ActiveModelReference.AddElement oElement Loop End Sub
The above code is available in this MicroStation
VBA project.
Unpack the ZIP archive and copy CellPlacement.mvba
to a location where MicroStation
can find it.
A good place to copy it would be \Workspace\Standards\vba
.
To start placing cells, key one of the following into MicroStation's keyin dialog …
vba run [CellPlacement]modMain.PlaceCell
vba run [CellPlacement]modMain.PlaceAndDropCell
Back to the VBA article index.