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.

Level Numbers & Codes

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.

DGNLIBs

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 exist
    Else
        '   Level exists
        If (oLevel.IsInUseWithinModel(ActiveModelReference)) Then
            MsgBox "Level '" & levelName & "' is in use", vbExclamation Or vbOKOnly, "Unable to Delete Level"
        Else
            ActiveDesignFile.DeleteLevel oLevel
        	'   Persist change
            oLevels.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 …

Level Legend created by FlexiTable

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.ID
        oLevel.Number = levelCode
        '   Colours are assigned by value
        oLevel.ElementColor = colorByLevel
        oLevel.OverrideColor = colorOverride
        '   Line styles take an object reference
        Dim 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

Set Level Display Priority

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 somewhere
Dim levelId As Long
levelId = oLevel.ID
Dim modelRef As Long ' MDL Pointer
modelRef = oModel.MdlModelRefP

Const Priority As Long = 100
mdlLevel_setDisplayPriority modelRef, levelId, Priority

Set Level Display Transparency

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 somewhere
Dim levelId As Long
levelId = oLevel.ID
Dim modelRef As Long ' MDL Pointer
modelRef = oModel.MdlModelRefP

Const Transparency As Double = 0.5
mdlLevel_setTransparency modelRef, levelId, Transparency

Example VBA Module

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 definitions
    Const 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 active
                Set oLevel = oLevels.Find(strLevelName)
                oLevel.IsActive = True
                '   Persist our changes
                oLevels.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