Bentley Technology Partner
MicroStation VBA Tips Index
Bentley ColorPicker and ColorChooser Does a Cell Exist?
How do I change a MicroStation setting? Is a Database Connection Active?
Design File Information Formatting Numbers
Recalculate an element's range
Calculating & Formatting Dates Maximum vertex count in a shape or line
Objects & User-Defined Types Insist on Variable Declaration
Variable Initialisation Procedure Calling Convention
Pointers in VB Quoted Strings and File Names
Recording a VBA Macro Enable the scroll wheel in the VBA IDE
Windows Prompts for Installation CD Divide a text string into words
Convert an element to a Line String Run a VBA macro at Startup
Debugging Assistance Set the caption of MicroStation's main window

This page lists some solutions to common MicroStation VBA (MVBA) and VB problems. Few of these tips are original: some are repeated from Microsoft VB or VBA documentation, and some are paraphrased from the MVBA documentation. Unless declared explicitly, the content applies equally to VB or MVBA. Tips are published as examples and are not necessarily working code.

Design File Information

Q How do I get some basic information about the current file that I'm working with? I want to know the file name/file path/model name.

A  File Dimension is one of those mysterious TCB things: tcb->ndices. Here's more information about the TCB, and here's an example procedure that reveals the file dimension …

' ---------------------------------------------------------------------
'   IsThreeD
'   Returns:    True if the active file is 3D, 2D otherwise
' ---------------------------------------------------------------------
Public Function IsThreeD() As Boolean
    Select Case CLng(GetCExpressionValue("tcb->ndices"))
    Case 3
        IsThreeD = True
        Debug.Print "File is 3D"
    Case 2
        Debug.Print "File is 2D"
        IsThreeD = False
    Case Else
        MsgBox "DGN is neither 2D nor 3D!", vbCritical Or vbOKOnly, "Invalid File Dimension"
    End Select
End Function

A  The Application, DesignFile, and ModelReference objects have various properties that provide information about themselves. Some file properties are also exposed by the Windows API, by which we mean that you can write VB code for Windows (as contrasted with VBA code for MicroStation) that can see those same properties. Rather than repeat the help documentation, here's an example …

Sub Main()
    If (Application.HasActiveDesignFile) Then
        '   Design file
        ReportFileInfo ActiveDesignFile
        '   Model
        ReportModelInfo ActiveModelReference
    End If
End Sub
'
'  Note that we can get custom file properties, such as Company,
'  as well as Windows information such as Path and Name
Sub ReportFileInfo(dgn As DesignFile)
    Debug.Print "Design file info..."
    Debug.Print "  Author '" & dgn.Author & "'"
    Debug.Print "  Company '" & dgn.Company & "'"
    Debug.Print "  FullName '" & dgn.FullName & "'"
    Debug.Print "  Name '" & dgn.Name & "'"
End Sub
'
Sub ReportModelInfo(oModelRef As ModelReference)
    Debug.Print "Model info..."
    Debug.Print "  Name '" & oModelRef.Name & "'"
    Debug.Print "  Design file FullPath '" & oModelRef.DesignFile.FullName & "'"
End Sub

Back to contents

Bentley Systems ColorPicker and ColorChooser Controls

Q How can I include a ColorPicker or ColorChooser control in my UserForm?

A Microsoft VBA knows nothing about the application it's used with. The controls available to you as a UserForm designer are those provided with VBA and any that may be provided in control libraries.

Plain old VBA is generic: it doesn't know about CAD and therefore doesn't provide tools for browsing a colour palette or picking a colour from a palette. However, Bentley have provided two controls for colour manipulation: ColorPicker and ColorChooser. Bentley have indicated that they may provide with some versions of MicroStation XM, or you may be able to obtain them here (look for controls.zip).

Bentley ColorPicker and ColorChooser Controls

The screenshot above shows a ColorPalette control placed on a UserForm. The VBA Toolbox shows icons for the Bentley colour controls.


Back to contents

Is a Database Connection Active?

Q How can I tell if MicroStation has an active database connection?

A Use the MDL function mdlDB_isActive(). This example by Jerry Walter at Bentley Systems shows you how …

Declare Function mdlDB_isActive Lib "stdmdlbltin.dll" () As Long
' ---------------------------------------------------------------------
Sub isDbAttachedTest() If IsDbAttached() Then MsgBox "Database is attached", vbOKOnly, "Database" Else MsgBox "Database is not attached", vbOKOnly, "Database" End If End Sub
' ---------------------------------------------------------------------
Function IsDbAttached() As Boolean IsDbAttached = CBool(mdlDB_isActive()) End Function

Back to contents

Running a VBA Macro at Startup

Q How do I run a VBA macro at startup

A You can run a VBA macro as MicroStation starts up, or each time you open a design file.

The answer is at Ask Inga: tip 174.


Back to contents

Procedure Calling Convention

Q When should I use parentheses in a procedure call? When should I not use parentheses in a procedure call?

A A procedure in VB and VBA is either a Function or a Subroutine. A Function returns a value, a Subroutine returns nothing. When a procedure accepts one or more parameters, you pass a variable or value to the procedure.

Subroutines

Suppose we have a simple Subroutine that modifies a variable. This example multiplies the passed variable by a passed value …

Sub Multiply (ByRef change As Double, ByVal value As Double)
  change = change * value
End Sub

You might call the Subroutine like this …

  Dim variable  As Double
  Const multiplier As Double = 2.5
  variable = 2.0 ' VB changes this to 2# because It Knows Best 

  Multiply variable, multiplier

But, if you call it like this …

   Multiply (variable, multiplier)

The VB syntax checker doesn't like the parentheses and highlights the line in red to indicate its anger. The IDE may pop a message box with this enigmatic admonishment: Compile Error Expected:=

However, you may invoke the subroutine like this, enclosing the arguments in parentheses and using the Call keyword …

  Call Multiply (variable, multiplier)

With the Call keyword, the VB syntax checker accepts the parentheses. Here's a quotation from the MVBA online help that may, or may not, clarify this point for you …

You are not required to use the Call keyword when calling a procedure. However, if you use the Call keyword to call a procedure that requires arguments, argumentlist must be enclosed in parentheses. If you omit the Call keyword, you also must omit the parentheses around argumentlist.

Functions

Suppose we have a simple Function that modifies a variable. This example multiplies the passed variable by a passed value and returns the new value …

Function Multiply (ByVal original As Double, ByVal value As Double)
  Multiply = original * value
End Function

You might call the Function like this …

  Dim variable  As Double
  Const multiplier As Double = 2.5
  variable = 2.0 ' VB changes this to 2# because It Knows Best 

  Multiply variable, multiplier

The code is perfectly valid and perfectly useless. The syntax is fine, so the VB editor doesn't complain. However, you're not using the returned value, so why invoke the function?

Let's try again, this time assigning the value returned by the function to a variable …

  Dim variable  As Double
  Dim result  As Double
  Const multiplier As Double = 2.5
  variable = 2.0 ' VB changes this to 2# because It Knows Best 

  result = Multiply variable, multiplier	

VB doesn't like that syntax for a function: you must enclose the function arguments in parentheses when you assign the result. Here's the correct invocation …

  Dim variable  As Double
  Dim result  As Double
  Const multiplier As Double = 2.5
  variable = 2.0

  result = Multiply (variable, multiplier)

The VB syntax requires the parentheses around the arguments to a function call. Here's a quotation from the MVBA online help that may, or may not, clarify this point for you …

You are not required to use the Call keyword when calling a procedure. However, if you use the Call keyword to call a procedure that requires arguments, argumentlist must be enclosed in parentheses. If you omit the Call keyword, you also must omit the parentheses around argumentlist. If you use either Call syntax to call any intrinsic or user-defined function, the function's return value is discarded.

The last sentence means that, if you Call a function, there's no way to obtain its return value. So this invocation is pointless if you want to know the answer …

  Dim variable  As Double
  Dim result  As Double
  Const multiplier As Double = 2.5
  variable = 2.0

  Call Multiply (variable, multiplier) ' Where's my return value?

By the way, a Function defined in a class is known as a Method of that class. The world of object-oriented-design (OOD) has invented its own jargon: refuse to be intimidated!


Back to contents

Quoted Strings and File Names

Q  How do I tell MicroStation to use a file when the file name includes spaces?

A  We often need to tell MicroStation about a file when changing a setting. For example, when you want to assign a colour table you must pass the full path of the table file. When the file path contains spaces you must wrap the entire path in double-quote characters. Otherwise, the spaces confuse MicroStation.

Here's a simple function that wraps a string in double-quote characters …

'-------------------------------------------------------------
'   DoubleQuote
'   Wraps a string in double-quote marks
'-------------------------------------------------------------
Public Function DoubleQuote(ByVal s As String) As String
    Const sDOUBLE_QUOTE  As String = """"
    DoubleQuote = sDOUBLE_QUOTE & s & sDOUBLE_QUOTE
End Function

Here's how you might call that function …

Dim fileName As String
fileName = "N:\Projects\New Project\Color Tables\masterplan.tbl"
Debug.Print "Raw file name: " & fileName
Dim quotedName As String
quotedName = DoubleQuote (fileName)
Debug.Print "Quoted file name: " & quotedName

Dim keyin As String
keyin = "print pentable attach " + quotedName
Debug.Print "Keyin: " & keyin

'   Assign MicroStation color table
CadInputQueue.SendCommand keyin

Back to contents

Change a MicroStation Setting

Q  How do I change MicroStation setting XYZ using VBA?

A  Record a VBA macro as described while you manually change the setting. Usually, you will find some cryptic code in the recording that you can copy and paste into another macro.


Back to contents

Objects & User-Defined Types

Q I'm confused by objects and User-Defined Types. They both support dot notation, but how do I know when and where to put that dot?

A MVBA makes extensive use of objects and User-Defined Types (UDTs). MicroStation's geometric element types are represented by classes: when you use a variable that represents a class you have created an object. The Set keyword is exclusive to objects. If you omit the Set keyword, your code will compile but not execute: you will receive a run-time error …

  Dim oLine  As LineElement	' LineElement is a class provided by MVBA
  Dim vertices (0 To 1) As Point3d	' Point3d is a user-defined-type provided by MVBA
  ' Assign values to vertex 1 and vertex 2
  vertices(0).X = 10
  vertices(0).Y = 10
  vertices(0).Z = 0
  vertices(1).X = 20
  vertices(1).Y = 20
  vertices(1).Z = 0

  ' The next two lines are accepted by the VB editor	
  Set oElement = Application.CreateLineElement1 (Nothing, vertices)
  oElement = Application.CreateLineElement1 (Nothing, vertices)	' Run-time error!

As you probably noticed in the above example, we used an array of Point3d to supply a vertex list to the CreateLineElement1 method. A Point3d is a UDT pre-defined by MVBA. It's equivalent to this definition in your own code …

Type Point
  X As Double
  y As Double
  z As Double
End Type

A UDT is used like a primitive data type such as an Integer, Double, etc. It's not a class, and it's incorrect to confuse it with a class …

  '  Declare a variable of type Point	
  Dim point As Point

  '  Use a point variable	
  point.X = 1234
  point.Y = 2345
  point.Z = 0

Unfortunately, the VB editor doesn't complain when you confuse a UDT with a class. It accepts this code when you type it but rejects at compile-time …

  Dim point As Point

  '  Use a point variable incorrectly with Set keyword	
  Set point.X = 1234
  Set point.Y = 2345
  Set point.Z = 0

The worst thing about this error is the misleading message from VB: Compile error: Object required. The wording makes you think that you've used an object incorrectly, whereas the real mistake is attempting to use a UDT as if it were an object.

Because UDTs are similar to built-in data types, you can legally assign a variable to another variable provided each is declared as the same UDT. You can't do this with an object …

  '  Declare two variables of type Point	
  Dim point1 As Point
  Dim point2 As Point

  point1.X = 1234
  point1.Y = 2345
  point1.Z = 0

  '  Assign one point to another	
  point2 = point1	'  point2 now has the same X, Y, Z values as  point1

Note that I've defined the Point type purely for illustration. With MVBA, you should liberally sprinkle your code with variables declared as Point3d & Point2d data types. Those types are pre-defined for you by the kind folks at Bentley Systems.


Back to contents

Debugging Assistance

Q How do I verify during development that some value is correct?

A VB and MVBA make it easy to be a sloppy programmer. However, help is at hand! The Debug object provides two useful methods: Debug.Print and Debug.Assert. Both methods only work while you, the programmer, are stepping through code in debug mode or running from the IDE. Your user will not see the results of the Debug object.

Debug.Print does what it says on the tin: it prints whatever text you tell it to print. The text is written to VBA's Immediate window.

Debug.Assert tests whatever you pass to it for Boolean True or False. If the argument fails the test (i.e. it evaluates to False) then your program halts. Here's an example that verifies that you have passed a valid file name …

' ---------------------------------------------------------------------
'   Start here: this procedure first tests a file that should exist,
'   regedit.exe in your Windows folder (typically C:\Windows).
'   Next it tests for a non-existent file:
'   VBA will halt executiong during debug at the Debug.Assert statement
' ---------------------------------------------------------------------
Sub TestAssert()
    AssertExample Environ("WINDIR") & "\regedit.exe"  ' File exists
    AssertExample "C:\nonexistent"                    ' File does not exist
End Sub
' ---------------------------------------------------------------------
Sub AssertExample(ByVal fileName As String)
    Debug.Print "Assert test on '" & fileName & "'"
    Debug.Assert FileExists(fileName)
End Sub
' ---------------------------------------------------------------------
'   FileExists
'   The code in this procedure uses the Microsoft Scripting Runtime library.
'   Use the Tools|References menu to add that library (scrrun.dll) to your VBA project
'   Returns: True if the file exists
' ---------------------------------------------------------------------
Public Function FileExists(ByVal fileName As String) As Boolean
    Dim oFileSystem                         As New Scripting.FileSystemObject
    FileExists = oFileSystem.FileExists(fileName)
    Set oFileSystem = Nothing
End Function

Back to contents

Insist on Variable Declaration

Q I used to be a sloppy programmer, but I want to reform my style. How do I go about achieving that goal?

A VB and MVBA make it easy to be a sloppy programmer. One way is to let you use a variable without declaring it first …

  skunk = 1234	  ' skunk is an Integer
  skunk = 1234.5  ' skunk is a Double
  skunk = "abc"   ' skunk is a String

Save your self trouble! Put the Option Explicit statement at the beginning of every module you write …

Option Explicit
  skunk = 1234	  ' Compile Error: Variable not defined

VB now wants you to declare each and every variable, so the compiler knows its data type and can detect an inappropriate assignment. Well, most of the time …

Option Explicit
  Dim skunk As Integer
  skunk = 1234	  ' OK
  skunk = 1234.5  ' Runs, but what is in variable skunk now?
  skunk = "abc"	  ' Run-time error

The second assignment was to test if you're still awake. The compiler accepts the assignment of a Double value (1234.5) to the Integer variable skunk. At run-time, VB truncates the floating-point number to fit into your Integer variable, so skunk contains the value 1234. In other words, your data have been silently mangled at run-time.

You can automate Option Explicit in the Options dialog of the VB IDE: select this from the Tools menu and toggle the check-box Require Variable Declaration. Once you've done this, VB writes Option Explicit at the start of each new module …


Back to contents

Initialise your Variables

Q I place a cell using VBA, but it appears as a dot. What happened?

Dim scale As Point3d
Dim origin As Point3d

origin.x = 100
origin.y = 200
origin.z = 0

Dim oCell As CellElement
Set oCell = Application.CreateCellElement2("example", origin, scale, False, Nothing)

A Visual Basic (VB) and Visual Basic for Applications (VBA) try to be your friends. They initialise variables for you. Unfortunately, VB and VBA know nothing about 3D geometry: they are ignorant about points, vectors, transforms, and matrices. If you initialise your scale variable to zero (or let VBA initialise it to zero for you), then any object scaled using that variable will have zero size. The proper initialisation for a scale is unity. MicroStation VBA offers the convenient method Point3dOne, which sets the X, Y and Z members of a Point3d data type to 1.0.

What happened in the above example is that the author declared a Point3d variable named scale to store the scale of the cell. Probably, she planned to set scale to a suitable value as she revised her code. Unfortunately, VBA initialised scale to zero. Placing a cell with scale zero results in a rather small object. MicroStation shows it as a dot, and you can use the Analyse Element tool to see that it really is a cell, but with negligible dimensions.

Probably the default value for scale should be unity, which you can achieve like this …

Dim scale As Point3d
scale = Point3dOne	' all components 1.0

Another trap for the uninitiated is a rotation matrix. A rotation in MicroStation VBA is expressed not in degrees but by a Transform. The Transform data type is provided with MicroStation VBA to store rotation matrices and other transform matrices. In 3D it's inconvenient to use simple rotations (and 2D is just a special case of 3D, but you knew that). Unfortunately, a Transform initialised to zero has no meaning: it's mathematically incompetent. If you let VBA initialise a Transform for you, then expect unexpected results. Instead, assign a meaningful value to your rotation variable like this …

Dim rotation As Transform
rotation = Transform3dIdentity	' zero rotation

Now, you can use the properly initialised scale and rotation variables …

Dim scale As Point3d
scale = Point3dOne	' all components 1.0

Dim rotation As Transform
rotation = Transform3dIdentity	' zero rotation

Dim origin As Point3d

origin.x = 100
origin.y = 200
origin.z = 0

Dim oCell As CellElement
Set oCell = Application.CreateCellElement2("example", origin, scale, False, rotation)

With meaningful initialisation of variables scale and rotation, the cell placement works as expected.


Back to contents

Windows Caption

Q How do I set the caption of MicroStation's main window?

A All VBA applications provide an Application object. The Application object is the root of the VBA hierarchy and is the interface with Windows. The MicroStation main window is a Windows window, if you'll pardon the excessive fenestration. Therefore, use the Application object to change the main window caption.

Customised caption for MicroStation's main window

Here's a code sample, probably the simplest you'll find on this page …

Sub TitleTest()
    SetWindowCaption "LA Solutions VBA Example"
End Sub
Sub SetWindowCaption(ByVal caption As String)
    Application.caption = caption
End Sub

Back to contents

Windows Prompts for Installation CD

Q Why does Windows prompt me for an installation CD when I run my VBA macro?

A The problem arises because various products that install VBA may have implemented slightly different versions. Microsoft's installer is attempting to repair what it thinks is a damaged Office installation. Because MicroStation delivers VBA, it's causing a version clash with Office.

Microsoft have provided an installer patch to fix this problem. There's more information in this Bentley Tech Note.

Maximum Number of Points in a Line

Q What is the maximum number of vertices in a line or shape?

A The answer is 5,000 although I don't see this mentioned in the VBA help. However, it is documented in MDL and there's even a function to return the value, so we can use it in VBA like this …

'  MDL function declaration 
Declare Function mdlElement_maxLineStringPoints Lib "stdmdlbltin.dll" ( ) As Long

'  Return the maximum vertex count in a line or shape 
Function MaxLineStringPoints () As Integer
  MaxLineStringPoints = mdlElement_maxLineStringPoints ()
End Function

'  Test vertex count function 
Sub TextMaxVertexCount ()
  Debug.Print "Max line vertex count=" & CStr(MaxLineStringPoints())
End Sub

If you want to create a shape or line having more than the maximum number of vertices, you should create a number of lines (ChainableElements) having 5,000 or fewer vertices, then combine them into a ComplexStringElement or ComplexShapeElement. The following VBA methods will help you …

Does a Named Cell Exist in a Library?

Q How can I tell if a named cell exists in a library?

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 succeeds, you have a duplicate name …

Function CellExistsInLibrary (name 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 (name, 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	
End Function

Here's another way, by Ron Reemer, who contributed this to the Bentley Discussion Groups …

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

Back to contents

Divide a String into Words

Q How do I extract the words from a text string?

A You need VB's Split function. Split converts a text string into an array of strings. It uses a separator string that you specify to work out how the source string should be carved up.

A common requirement is to divide a string where the words are separated by space characters. You would write code something like this  …

Dim strSource       As String
Dim strWords()      As String
Const strSeparator  As String = " "

strSource = "Divide this string into words"
strWords  = Split (strSource, strSeparator)

Dim i               As Integer, _
    nWords          As Integer

nWords = UBound (strWords) - LBound (strWords) + 1

Debug.Print "strWords array contains " & CStr (nWords) & " words"

For i = LBound (strWords) To UBound (strWords)
  Debug.Print "Word [" & CStr (1 + i) & "]='" & words(i) & "'"
Next i

The opposite of Split, by the way, is Join.

Dates: Formatting and Calculating

Q VB's Format() and Date() functions provide answers to common questions along these lines …

A Suppose you want to obtain today's date: VB and VBA provide a Date data type and various functions that manipulate dates. The Now() function returns the current date and time from your computer's clock. Here's an example …

Sub TodaysDate()
    Dim strDate     As String
    Dim oDate       As Date

    oDate = Now()

    strDate = Format(oDate, "Medium Date")	' or "Short Date" or "Long Date" or your own custom date format
    Debug.Print "Today's date: " & strDate
End Sub

Here are some examples of date format strings for the date Friday, 12 January 2007 …

Format Comment Example Result
yyyy 4-digit year Format (Now(), "yyyy") 2007
yy 2-digit year Format (Now(), "yy") 07
mmmm full month name Format (Now(), "mmmm") January
mmm short month name Format (Now(), "mmm") Jan
mm numeric month Format (Now(), "mm") 01
dddd full day name Format (Now(), "dddd") Friday
ddd short day name Format (Now(), "ddd") Fri
dd numeric day Format (Now(), "dd") 12
dd-mmm-yyyy custom date Format (Now(), "dd-mmm-yyyy") 12-Jan-2007
mmm/dd/yy custom date Format (Now(), "mmm/dd/yy") Jan/12/07

A VB and VBA provide a number of functions that operate on Date data. For example, if you want to calculate the date 90 days from now, you could use the DateAdd() function. The DateDiff() function calculates the difference between two dates. The following example shows the difference between today's date and the fourth of July 2007 …

Function ElapsedTimeSince4thJuly2007() As Long
    Dim strDate     As String
    Dim oDate1      As Date, _
        oDate2      As Date
    Dim elapsed     As Long

    oDate1 = #7/4/2007#
    oDate2 = Now()

    elapsed = DateDiff("d", oDate1, oDate2) ' Compute difference in days

    If (0 < elapsed) Then
    	Debug.Print "It is " & CStr(elapsed) & " days after " & Format(oDate1, "Medium Date")
    Else
    	Debug.Print "There are " & CStr(elapsed) & " days before " & Format(oDate1, "Medium Date")
    End If

    ElapsedTimeSince4thJuly2007 = elapsed
End Function

Back to contents

Element Range

Q How do I set an element's range in VBA?

A The range of an element is an imaginary box around the object. MicroStation uses each element's range to acquire summary information when it doesn't need to know the exact details of an element's geometry. For example, when updating a view, MicroStation needs to know which elements are contained by that view: it's far quicker to perform an approximate calculation using each element's range than to perform some complex geometrical analysis.

The MDL function mdlElmdscr_validate() recalculates an element's range. Here's how to call it from VBA …

' ---------------------------------------------------------------------
'   MDL function declarations (copy this section to the beginning of your VBA module)
' ---------------------------------------------------------------------
Declare Sub mdlElmdscr_validate Lib "stdmdlbltin.dll" (ByVal p As Long, ByVal modelRef As Long)

' ---------------------------------------------------------------------
'   SetElementRange
'   Invoke MDL function to validate an element, which has the effect of
'   recalculating the element's range
'   Returns: Nothing
' ---------------------------------------------------------------------
Sub SetElementRange(ByVal oElement As Element, ByVal oModel As ModelReference)
    mdlElmdscr_validate oElement.MdlElementDescrP, oModel.MdlModelRefP
End Sub

Back to contents

Formatting Numbers

The note about formatting numbers has been expanded and moved to its own numeric formatting with VBA page.


Back to contents

Convert a Curve (or any other element) to a Line String

Q  How do I convert an Arc or Curve element to a Line String?

A  The Element.ConstructVertexList() method provides a way to simplify or stroke a curve to an array of vertices. Once you have an array of vertices, you can analyse it or convert it into another element, such as a Line String or B-Spline curve.

If you have an MDL background, then we believe that ConstructVertexList() is a wrapper around the MDL function mdlElmdscr_stroke().

Here's a suggestion from Gerald Hernandez, a frequent contributor to the Bentley Discussion Groups on how to use ConstructVertexList() to convert an Arc to a Line String …

Function StrokeArc(ByVal oArc As ArcElement, ByVal tolerance as Double) As LineElement
  Dim strokePoints() as Point3d

  strokePoints = oArc.ConstructVertexList (tolerance)
  '	Create a Line String using the original Arc as a template.
  '	The new Line String inherits the properties and symbology of the Arc
  Set StrokeArc= CreateLineElement1(oArc, strokePoints)

  Erase strokePoints
End Function

The tolerance argument tells the function how closely the array of points should match the original element. The finer the tolerance, the closer the result is to the original. When stroking an Arc, for example, you might set the tolerance to some fraction of the Arc's radius.

Recording a VBA Macro

Q  How do I record a VBA macro?

A  You can record a VBA macro from the VBA Projects dialog.

Open the VBA Projects dialog from the MicroStation menu Utilities|Macro|Project Manager. Select a project to make the Record button active, then perform a few operations using MicroStation's normal commands. Press the Stop button when you want to finish recording, and click the Edit button. You may have to hunt through the project file in the editor to find the macro you just recorded. VBA assigns an arbitrary name to your macro, and if you record several it's easy to become confused.

Hint: start the VBA editor, then rename your macro to something memorable as soon as you press the Stop button.

Using the Scroll Wheel in the VBA IDE

Q  How do I use the Scroll Wheel on my mouse in the VBA IDE?

A  VBA is showing its age: the Microsoft code base predates the arrival of mice having a scroll wheel.

The problem lies firmly in Microsoft's court. Fortunately, they have come up with a solution. Visit this Microsoft link to find how to enable the Scroll Wheel in the VBA IDE.

Pointers in Visual Basic

Q  How do I use pointers in VB?

A  Sometimes you just have to do those C things in VB. Here are some ideas from the Code Project.