Q Similar questions to those below crop up now and then on the MicroStation Programming Forum.

A How do I attach a reference file using VBA? We wrote the example AttachRef to illustrate one approach.

The source code is provided in the VBA module AttachRef.mvba ZIP archive. Copy this file to a VBA folder, such as …

C:\Program Files\Bentley\Workspace\Standards\vba

Then you can use the code as supplied, or open it with the VBA Project Manager to examine the source code. If you want to use it without modification, the MicroStation keyin is …

vba run [AttachRef]modAttachRef.Main <fileName> [, <logical name>> [ , <description> ]]

The logical name and description are optional. The file should exist in one of the folders specified by your MS_RFDIR configuration variable. This code always attempts to attach the file coincidentally.

A How do I clip an attachment's boundary using VBA? We wrote an example to illustrate one approach.

There's no VBA method to clip an attachment boundary: we need to call an MDL function. To call an MDL function, you must declare it at the beginning of your code module, before any procedure calls. Here's the declaration of MDL function mdlRefFile_setClip …

Note: Untested in CONNECT

This code has not been tested with MicroStation CONNECT.

' ---------------------------------------------------------------------
'   Declare MDL functions to be called in this VBA module
' ---------------------------------------------------------------------
Declare PtrSafe Function mdlRefFile_setClip Lib "stdmdlbltin.dll" ( _
    ByVal modelRef As LongPtr, _
    ByRef pts As Point2d, _
    ByVal nverts As Long) As Long

We define symbolic constants to represent the function's return codes. The names are more meaningful than negative integers, and make it easier to correlate the code with the MDL documentation and header files …

' ---------------------------------------------------------------------
'   MDL function return codes
' ---------------------------------------------------------------------
Private Const MDLERR_BADMODELREF            As Long = -107   '   See mdlerrs.h
Private Const MDLERR_INVALIDCLIP            As Long = -743   '   See mdlerrs.h
Private Const SUCCESS                       As Long = 0

The MDL function is wrapped in VBA function SetAttachmentClipBoundary shown below. The function expects an array of vertices, representing the clip boundary, passed in the active model's master units. MDL functions usually work in units-of-resolution (UORs), so we convert the vertices from master units to UORs before passing to mdlRefFile_setClip.

' ---------------------------------------------------------------------
'   SetAttachmentClipBoundary
'   Set an attachment clip boundary from an array of Point2d.
'   Parameters:
'   Attachment [in] reference to a vector reference attachment
'   Point2d() [in] array of vertices in master units.  First and last points must be coincident
'   Returns: True on success
' ---------------------------------------------------------------------
Public Function SetAttachmentClipBoundary(ByVal oAttachment As Attachment, ByRef vertices() As Point2d) As Boolean
    SetAttachmentClipBoundary = False
    If (oAttachment Is Nothing) Then
        Dim msg                             As String
        msg = "SetAttachmentClipBoundary: oAttachment Is Nothing"
        ShowMessage msg, msg, msdMessageCenterPriorityError, True
        Exit Function
    End If

    On Error GoTo err_SetAttachmentClipBoundary
    Dim nVertices                           As Integer
    nVertices = UBound(vertices) - LBound(vertices) + 1
    '   Scale clip points from master units to UORs
    Dim master2uor                          As Long
    master2uor = ActiveModelReference.UORsPerMasterUnit
    Dim i                                   As Integer
    Dim verts2d()                           As Point2d
    ReDim verts2d(0 To nVertices - 1)
    For i = 0 To nVertices - 1
        verts2d(i).X = vertices(i).X * master2uor
        verts2d(i).Y = vertices(i).Y * master2uor
    Next i
    Dim status                              As Long
    status = mdlRefFile_setClip(oAttachment.MdlModelRefP, verts2d(LBound(verts2d)), nVertices)
    Select Case status
        Case SUCCESS
            SetAttachmentClipBoundary = True
            'oAttachment.Redraw
            oAttachment.Rewrite
        Case MDLERR_BADMODELREF
            Debug.Print "SetAttachmentClipBoundary: invalid ModelRef from Attachment"
        Case MDLERR_INVALIDCLIP
            Debug.Print "SetAttachmentClipBoundary: clip points must have 4 or more vertices but less than 2500"
        Case Else
            Debug.Print "SetAttachmentClipBoundary: unknown problem status=" & CStr(status)
    End Select
    Exit Function

err_SetAttachmentClipBoundary:
    ReportError strMODULE_NAME, "SetAttachmentClipBoundary"
End Function

Here's a test function that obtains a reference to an attachment, and initialises an array of vertices to a rectangle. Then it calls the above function to clip the attachment's boundary to the rectangle …

' ---------------------------------------------------------------------
Sub TestSetAttachmentClipBoundary()
    Dim vertices(0 To 4)                    As Point2d
    '   Clip boundary in master units
    vertices(0).X = 1.41
    vertices(0).Y = 2.86

    vertices(1).X = 1.95
    vertices(1).Y = 2.86

    vertices(2).X = 1.95
    vertices(2).Y = 3.37

    vertices(3).X = 1.41
    vertices(3).Y = 3.37
    '   Last point coincident with first point
    vertices(4).X = 1.41
    vertices(4).Y = 2.86
    Dim oAttachment                         As Attachment
    Const strLOGICAL_NAME                   As String = "clip_test"
    Set oAttachment = ActiveModelReference.Attachments.FindByLogicalName(strLOGICAL_NAME)
    Dim msg                                 As String
    If (SetAttachmentClipBoundary(oAttachment, vertices)) Then
        msg = "Attachment '" & strLOGICAL_NAME & "' clipped successfully"
        ShowMessage msg, msg, msdMessageCenterPriorityInfo, False
    Else
        msg = "Attachment '" & strLOGICAL_NAME & "' not clipped"
        ShowMessage msg, msg, msdMessageCenterPriorityWarning, True
    End If
End Sub

The code above is available in a complete MVBA project ReferenceFile.mvba. Download the ZIP archive, then unpack it to examine the source code and start clipping your reference attachments!