By Dan Tartaglia, Programming Support Specialist, Bentley Corporate Office
30 August 2002


The VBA object "ElementEnumerator" can make quick work of writing custom applications for MicroStation V8 to scan DGN files for specific objects.

Scanning a design file and processing specified elements is a common task assigned to MicroStation VBA programmers. The scanning process may be as general as cycling through all the elements in a model or perhaps scanning for specific saved view elements. The ElementEnumerator object is used for this purpose.

 

The "MicroStation V8 Visual Basic for Applications Help" window contains a number of examples that show how to scan; here is an example of using the ElementEnumerator object in its simplest form:

Sub ScanDGN()
Dim counter As Integer
Dim oEnumerator As ElementEnumerator

Set oEnumerator = ActiveModelReference.Scan

Do While oEnumerator.MoveNext
counter = counter + 1
Loop
MsgBox "The total number of elements scanned were: " & CStr(counter)
End Sub

The above scanner will find every graphical and non-graphical element in the active model. After the code runs, it displays the total number of elements that were found in a message box (using the Visual Basic MsgBox function).

Breaking Down the Code

First, we set the ElementEnumerator object to scan the active model:

Set oEnumerator = ActiveModelReference.Scan

Ø Tip: To scan for elements that are only within a Selection Set, you could replace the Scan method with the AnyElementsSelected method.

Using a Do While...Loop and calling the MoveNext method, the application moves incrementally through the enumerator, identifying each element found. Next, the counter will increment:

Do While oEnumerator.MoveNext

counter = counter + 1

Loop

Next the MsgBox object displays the number of elements that are found:

MsgBox "The total number of elements scanned were: " & CStr(counter)

For most purposes, the above example would not be efficient or recommended unless you wanted to get all the graphical and non-graphical elements.

Ø Tip: Whenever an object is declared, it needs to be Set before it can be used.

ElementScanCriteria object

The ElementScanCriteria object is used as an argument with the ElementEnumerator object to limit the set of elements generated by the scanner. The scanner can filter out elements much faster than the Visual Basic program can, so its use is recommended to make the ElementScanCritieria as precise as possible. The example below will scan the active model for only lines and text that of Color 5:

 

Sub ScanForElems()

Dim counter As Integer

Dim oEnumerator As ElementEnumerator

Dim oScanCriteria As New ElementScanCriteria

 

oScanCriteria.ExcludeAllTypes

oScanCriteria.IncludeType msdElementTypeLine

oScanCriteria.IncludeType msdElementTypeText

oScanCriteria.ExcludeAllColors

oScanCriteria.IncludeColor 5

 

Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)

 

Do While oEnumerator.MoveNext

counter = counter + 1

Loop

MsgBox "The total number of elements scanned were: " & CStr(counter)

End Sub

 

Breaking Down the Code

First, the application defines a new ElementScanCriteria object. It is possible to define and set an object with one statement using the keyword New.

Dim oScanCriteria As New ElementScanCriteria

By default, all elements are included in an ElementScanCriteria object. At this point, the application should first exclude all element types, then include just the types being sought:

oScanCriteria.ExcludeAllTypes

oScanCriteria.IncludeType msdElementTypeLine

oScanCriteria.IncludeType msdElementTypeText

In a similar manner, next exclude all the colors and include the only the colors you are interested in:

· oScanCriteria.ExcludeAllColors

oScanCriteria.IncludeColor 5

At this point, the application needs to set the ElementEnumerator object to locate only the elements that meet the specified criteria:

Set oEnumerator = ActiveModelReference.Scan(oScanCriteria)

The above example could also be modified to scan for saved View elements by replacing all the oScanCriteria statements with:

oScanCriteria.ExcludeAllTypes

oScanCriteria.IncludeType msdElementTypeView

These will change the criteria to scan for reference file attachments:

oScanCriteria.ExcludeAllTypes

oScanCriteria.IncludeType msdElementTypeReferenceAttachment

Scanning a Fence Contents

Now the application will modify the code so that it scans for elements that are in an active fence. Currently, the ElementEnumerator object does not allow the combining of ElementScanCriteria objects with a fence operation. The code below is modified so that it scans the active fence for all line and text elements of Color 5:

 

Sub ScanFence()

Dim counter As Integer

Dim oElement As Element

Dim oEnumerator As ElementEnumerator

Dim oFence As Fence

 

Set oFence = ActiveDesignFile.Fence

 

If oFence.IsDefined = True Then

Set oEnumerator = oFence.GetContents

 

Do While oEnumerator.MoveNext

Set oElement = oEnumerator.Current

If oElement.Color = 5 Then

If oElement.Type = msdElementTypeLine Or oElement.Type = msdElementTypeText Then

counter = counter + 1

End If

End If

Loop

MsgBox "The total number of elements scanned for are: " & CStr(counter)

Else

ShowError "A Fence Has Not Been Defined!"

End If

End Sub

 

Breaking Down the Code

First, the application defines an Elementobject and a Fenceobject:

 

Dim oElement As Element

Dim oFence As Fence

 

Next, the Fence object is set:

 

Set oFence = ActiveDesignFile.Fence

 

Before any processing begins, the application needs to determine if an active fence exists. If it does, it sets the ElementEnumerator object using the Fence object. If no fence exists, the application will display a message and end the processing:

 

If oFence.IsDefined = True Then

Set oEnumerator = oFence.GetContents

Else

ShowError "A Fence Has Not Been Defined!"

End If

 

The application again uses a similar Do While...Loop and a MoveNext method to loop through all elements found. Because the application can't use the ElementScanCriteria object, the application needs to determine if the elements contained in the Enumerator are Color 5 and if they are either a Line or a Text element. In the looping process, the application sets the Element object to "get" the current element from the Enumerator using the Currentmethod:

 

Set oElement = oEnumerator.Current

 

Next, the application uses a couple of If...End If statements to determine if the current element meets the specified criteria. If it does, the same logic is applied as in the previous examples, and one item is added to the counter. The totals are displayed:

 

If oElement.Color = 5 Then

If oElement.Type = msdElementTypeLine Or oElement.Type = msdElementTypeText Then ...

 

In this example, it was not necessary to use an Element object, but it is simpler to follow. This section could also have been written as:

 

If oEnumerator.Current.Color = 5 Then

If oEnumerator.Current.Type = msdElementTypeLine Or oEnumerator.Current.Type = _

msdElementTypeText Then ...