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
…
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!