Questions similar to this appear on the Be Community Forums. This problem appeared in the VBA Forum.

Q How do I find elements on a specific level using VBA?

Q How do I find elements of a particular type (e.g. text elements) using VBA?

A MicroStation includes a scanning engine that is used for many purposes. It's available to you in VBA as the ModelReference.Scan method. You specify what you want to search for (e.g. levels) through the ElementScanCriteria object.

The methodology of scanning a model is straightforward …

Enumeration provides you with a list of elements, each of which has already passed the test you imposed with your scan criteria. So, if you specified a level filter, you know that each element received from the enumerator belongs to one of the levels specified. If your scan criteria requested only text elements, then each element returned by the enumerator will be a TextElement.

Example 1: Scan by Level

There are a number of scanning examples provided in the VBA help. Search help for scan criteria or scan to find them. Here's an example that searches for elements on a named level: copy this code into a module in the VBA editor, supply a valid level name, and vba run Main …

Main entry point 
Sub Main()
    Dim nElements   As Long
    Const levelName As String = "Level 11"
    nElements = ScanByLevel(levelName)
    MsgBox "Found " & CStr(nElements) & " elements on level '" & levelName & "'", vbInformation Or vbOKOnly, "Scanned Elements"
End Sub
' -------------------------------------------------------------- 
' Process any element that meets the scan criteria: named level 
' -------------------------------------------------------------- 
Function ScanByLevel(levelName As String) As Long
    Dim oScanCriteria   As ElementScanCriteria
    Dim oEnumerator     As ElementEnumerator
    Set oScanCriteria = New ElementScanCriteria
    Dim nElements       As Long

    Dim oLevel          As Level
    Set oLevel = ActiveModelReference.Levels(levelName)
    If (oLevel Is Nothing) Then
        MsgBox "Level '" & levelName & "' does not exist", vbCritical Or vbOKOnly, "Nonexistent Level"
        Exit Function
    End If
    oScanCriteria.ExcludeAllLevels
    oScanCriteria.IncludeLevel oLevel

    Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)
    While oEnumerator.MoveNext = True
        oEnumerator.Current.Redraw msdDrawingModeHilite
        nElements = nElements + 1
    Wend
    ScanByLevel = nElements
End Function

Example 2: Scan for Text Elements

There are a number of scanning examples provided in the VBA help. Search help for scan criteria or scan to find them. Here's an example that searches for text elements and processes only those text elements of a certain size: copy this code into a module in the VBA editor and vba run Main …

Main entry point 
Sub Main()
    Dim nElements   As Long
    nElements = ScanForText(levelName)
    MsgBox "Found " & CStr(nElements) & " text elements", vbInformation Or vbOKOnly, "Text Elements"
End Sub
' -------------------------------------------------------------- 
' Process text elements                                          
' -------------------------------------------------------------- 
Function ScanTextElements() As Long
    Dim nElements       As Long
    Dim oScanCriteria   As ElementScanCriteria
    Dim oEnumerator     As ElementEnumerator
    Set oScanCriteria = New ElementScanCriteria

    Const MatchHeight As Double = 0.0035
    Const MatchWidth As Double = 0.0025
    Const Epsilon As Double = 0.00001

    nElements = 0

    oScanCriteria.ExcludeAllTypes
    oScanCriteria.IncludeType msdElementTypeText

    Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)
    While oEnumerator.MoveNext = True
        oEnumerator.Current.Redraw msdDrawingModeHilite
        With oEnumerator.Current.AsTextElement
            Dim width   As Double, _
                height  As Double

            width = .TextStyle.width
            height = .TextStyle.height
            Debug.Print "Found text '" & .Text & "' width=" & FormatNumber(width, 6, True) & " height=" & FormatNumber(height, 6, True)

            If (Epsilon > Abs(MatchWidth - width)) Then
                Debug.Print "Matched width " & FormatNumber(width, 6, True)
            End If

            If (Epsilon > Abs(MatchHeight - height)) Then
                Debug.Print "Matched height " & FormatNumber(height, 6, True)
            End If

            If ((Epsilon > Abs(MatchWidth - width)) _
                And _
                (Epsilon > Abs(MatchHeight - height))) Then
                Debug.Print "Matched text '" & .Text & "'"
                MsgBox "Matched Text Element!"
                nElements = 1 + nElements
            End If
        End With
        oEnumerator.Current.Redraw msdDrawingModeNormal
    Wend
    ScanTextElements = nElements
End Function