Q These questions are about MicroStation VBA and levels. Similar questions crop up now and then on the BE Community forums.
There are several examples of level manipulation here. There's an example VBA module that removes a named level, then recreates it and sets some level symbology properties.
As a VBA (or MDL) programmer you are privileged: you can see both the internal level ID and the visible level code. What's the difference?
The level ID is assigned by MicroStation and is read-only. It's a 32-bit number, unique within a given DGN file (or DGNLIB).
The level code is assigned by an administrator or user, using the Level Manager dialog. The level code is a numerical alias for the level name. It must be unique, but other than that can have any value: MicroStation doesn't use it or care about it.
Often, levels are defined and stored in a Design File Library (DGNLIB).
DGNLIBs are also known asLevel libraries, although they are used to store many other types of drawing standard.
A DGNLIB is a DGN file having a .dgnlib extension.
You can open a DGNLIB for editing just like any other DGN file.
Level libraries (DGNLIBs) are great for sharing level definitions among many users. If you're interested in level libraries (DGNLIBs) and VBA programming, there's more information about DGNLIBs.
Q How do I turn on all levels in all views?
A We wrote this example to illustrate one solution to this question.
We declare oView as a variable that references an MVBA View object.
We iterate all the available views in the ActiveDesignFile.Views collection.
The inner loop (For Each … Next) iterates all the DGN levels,
and obliges the view to display that level.
Public Sub DisplayAllLevelsInAllViews()
Dim oView As View
Dim oLevel As Level
For Each oView In ActiveDesignFile.Views
For Each oLevel In ActiveDesignFile.Levels
oLevel.IsDisplayedInView(oView) = True
Next oLevel
oView.Redraw
Next oView
End Sub
Q I need to make a list of levels in my DGN file.
A We wrote this simple example to illustrate one approach.
Public Sub TraceLevelNames()
Dim oLevel As Level
For Each oLevel In ActiveDesignFile.Levels
Debug.Print "Level '" & oLevel.Name & "'"
Next oLevelEnd Sub
End Sub
Q I need to delete a level from my DGN file.
A You can't delete a level if that level is used anywhere in your DGN model. Shared cell definitions are invisible but nevertheless use levels. If you can't delete a level, check that there is not a hidden shared cell definition that is thwarting your intent.
Whenever you add, remove, or change a level definition, you must call Levels.Rewrite to make your change permanent.
Here's a function that removes a named level from your DGN model …
' --------------------------------------------------------------------- ' RemoveLevel ' Removes the named level. This only works if this level is not ' used by any element (including shared cell definitions) in the DGN file. ' Returns: True if the level existed ' ---------------------------------------------------------------------Function RemoveLevel(ByVal levelName As String) As Boolean RemoveLevel = False Dim oLevels As Levels Dim oLevel As Level Set oLevels = ActiveDesignFile.Levels Set oLevel = oLevels.Find(levelName) If (oLevel Is Nothing) Then' Level does not existElse' Level existsIf (oLevel.IsInUseWithinModel(ActiveModelReference)) Then MsgBox "Level '" & levelName & "' is in use", vbExclamation Or vbOKOnly, "Unable to Delete Level" Else ActiveDesignFile.DeleteLevel oLevel' Persist changeoLevels.Rewrite RemoveLevel = True End If End If End Function
Q I need to create a level legend in my DGNLIB.
A Open the DGNLIB as a normal file. Iterate the level collection in the DGNLIB, and for each level create a sample graphic & descriptive text.
Alternative, use FlexiTable™. FlexiTable can acquire various sorts of data from your DGN files, including level definitions. It can create a level legend with programming required …
Q I need to create a level in my DGN file.
A You can create a named level and assign it properties (e.g. override colour) programmatically.
Whenever you add, remove, or change a level definition, you must call Levels.Rewrite to make your change permanent.
Here's a function that creates a named level in your DGN model, and assigns it a level code …
' --------------------------------------------------------------------- ' CreateLevel ' Create a new level in the active design file with the given name ' Returns: True if the new level was created ' ---------------------------------------------------------------------Function CreateLevel(ByVal levelName As String, _ ByVal levelCode As Long, _ ByVal colorByLevel As Long, _ ByVal colorOverride As Long, _ ByVal styleByLevel As Long, _ ByVal styleOverride As Long) As Boolean CreateLevel = False Dim oLevel As Level Set oLevel = ActiveDesignFile.AddNewLevel(levelName) If (oLevel Is Nothing) Then MsgBox "Failed to create new level '" & levelName & "'", vbExclamation Or vbOKOnly, "Level Creation Failed" Else MsgBox "Created new level '" & levelName & "'", vbInformation Or vbOKOnly, "Level Created" CreateLevel = True' Level.Number is user-assigned, in contrast to the MicroStation-assigned Level.IDoLevel.Number = levelCode' Colours are assigned by valueoLevel.ElementColor = colorByLevel oLevel.OverrideColor = colorOverride' Line styles take an object referenceDim oStyle As LineStyle Set oStyle = ActiveDesignFile.LineStyles.Item(styleByLevel) If (oStyle Is Nothing) Then MsgBox "Invalid line style '" & CStr(styleByLevel) & "'", vbExclamation Or vbOKOnly, "Invalid Line Style" Else Set oLevel.ElementLineStyle = oStyle End If Set oStyle = ActiveDesignFile.LineStyles.Item(styleOverride) If (oStyle Is Nothing) Then MsgBox "Invalid line style '" & CStr(styleOverride) & "'", vbExclamation Or vbOKOnly, "Invalid Line Style" Else Set oLevel.ElementLineStyle = oStyle End If End If End Function
Transparency and Priority are properties of a level that don't seem to have made it into VBA.
However, you can set level priority using MDL. Here is the function declaration …
Declare Function mdlLevel_setDisplayPriority Lib "stdmdlbltin.dll" ( _ ByVal modelRefIn As Long, _ ByVal levelIdIn As Long, _ ByVal priorityIn As Long) As Long
priorityIn is an arbitrary positive or negative integer value.
Here's an example usage …
Dim oLevel As Level Dim oModel As ModelReference... get oLevel and oModel from somewhereDim levelId As Long levelId = oLevel.ID Dim modelRef As Long' MDL PointermodelRef = oModel.MdlModelRefP Const Priority As Long = 100 mdlLevel_setDisplayPriority modelRef, levelId, Priority
Transparency and Priority are properties of a level that don't seem to have made it into VBA.
However, you can set level transparency using MDL. Here is the function declaration …
Declare Function mdlLevel_setTransparency Lib "stdmdlbltin.dll" ( _ ByVal modelRefIn As Long, _ ByVal levelIdIn As Long, _ ByVal transparencyIn As Double ) As Long
transparencyIn is a Double value in the range 0.0 to 1.0.
Here's an example usage …
Dim oLevel As Level Dim oModel As ModelReference... get oLevel and oModel from somewhereDim levelId As Long levelId = oLevel.ID Dim modelRef As Long' MDL PointermodelRef = oModel.MdlModelRefP Const Transparency As Double = 0.5 mdlLevel_setTransparency modelRef, levelId, Transparency
Here's an example VBA module that deletes a named level from your DGN model,
then recreates it and specifies some level symbology properties.
It illustrates how the above RemoveLevel and CreateLevel functions are used …
Option Explicit' --------------------------------------------------------------------- ' Create a new level and assign symbology and properties ' --------------------------------------------------------------------- ' Notice: ' Source code provided by LA Solutions Ltd as-is without warranty of ' fitness for purpose. You may use this code for whatever purpose ' private or commercial ' www.la-solutions.co.uk ' End of notice ' ---------------------------------------------------------------------Public Sub Main()' Example level property definitionsConst strLevelName As String = "Example Level" Const nColorByLevel As Long = 7 Const nColorOverride As Long = 96 Const nStyleByLevel As Long = 1 Const nStyleOverride As Long = 2 If (RemoveLevel(strLevelName)) Then Dim oLevel As Level Dim oLevels As Levels Set oLevels = ActiveDesignFile.Levels Set oLevel = oLevels.Find(strLevelName) If (oLevel Is Nothing) Then If (CreateLevel(strLevelName, nColorByLevel, nColorOverride, nStyleByLevel, nStyleOverride)) Then' Make new level activeSet oLevel = oLevels.Find(strLevelName) oLevel.IsActive = True' Persist our changesoLevels.Rewrite End If End If Else MsgBox "Unable to remove level '" & strLevelName & "' already exists", vbExclamation Or vbOKOnly, "Unable to Remove Level" End If End Sub