Questions similar to this appear on the Bentley Discussion Groups. This problem appeared in the MicroStation Programming Forum.

Q Sometimes you need to verify programatically that a file is, or is not, compatible with MicroStation® before attempting to open it. Although we mentally associate a file having a .dgn extension with MicroStation, that concept is not cast in stone.

What if someone in your organisation has decided that .dgn means something else, such as a diagnostic log? What if you want to build a list of DGN files, for subsequent batch processing, from one or more folders when those folders contain a mix of drawings, spreadsheets, text files and other documents?

A MicroStation VBA does not include a method that can check a file before opening it. However, such a function does exist in the C++ MicroStationAPI (formerly MDL), and it's easy enough to use it in VBA if you know how. This article shows you how!

Before looking at the MicroStation VBA solution, note that the code shown on this page will not work with VBA in other applications such as Excel™ or Word™. However, an alternative solution exists for those cases.

Microsoft Scripting Runtime

The example below uses the functionality provided by the Microsoft Scripting Runtime DLL. This library is provided with Windows and is almost certainly installed on your computer.

We describe how to reference and use Microsoft Scripting Runtime.

The Solution

Although MicroStation VBA does not include a method to test an unopened file, the MicroStationAPI does include one. mdlFile_validDesignFile does exactly what we want, but we must write some slightly unusual VBA code in order to be able to use it.

When you use an MDL or other foreign function in VB or VBA you must Declare it. Declare is a VB keyword that tells the compiler about the function's arguments, and which DLL contains the implementation of that function. You can find more about Declare in VBA help.

The following VBA code wraps the MDL function so it's easy to use. The Main entry point simply passes the keyin argument to the VBA function that does the real work: CanMicroStationOpen. CanMicroStationOpen returns True if MicroStation can open the specified file, whether it be a V7 or V8 MicroStation design file, or an AutoCAD® DWG or DXF file.

To use this code, follow these steps…

Option Explicit
' ---------------------------------------------------------------------
'   Module CheckFile includes MicroStation VBA code that enables you
'   to test a file before attempting to open it in MicroStation.  This
'   lets you verify that it's a valid design file, irrespective of its
'   file extension (i.e. A .DGN file may not really be a design file,
'   and a .XYZ file could be a DGN file with an unusual extension).
'
'   The real work is done by function CanMicroStationOpen.  The Main
'   subroutine provides an interactive test capability
'
'	Function IsWritable tests a file to see whether it is read-only or
'	available for modification.  This function references Microsoft's
'	Scripting Runtime library.  The comments preceding the function
'	decribe how to reference that library
'
' ---------------------------------------------------------------------
Const MODULE_NAME                       As String = "CheckFile"
' ---------------------------------------------------------------------
'   Notice:
'   This code is supplied for illustration purposes by LA Solutions Ltd.
'   It is neither licensed nor supported.  You are free to copy this
'   code for your own use provided this notice is retained in full.
'   Visit our web site for more hints and tips about MicroStation VBA:
'   www.la-solutions.co.uk/content/Publications.htm
' ---------------------------------------------------------------------
'   MDL function declarations
' ---------------------------------------------------------------------
Declare PtrSafe Function mdlFile_validDesignFile Lib "stdmdlbltin.dll" ( _
    ByVal pThreeD As LongPtr, _
    ByVal pFormat As LongPtr, _
    ByVal pMajorVersion As LongPtr, _
    ByVal pMinorVersion As LongPtr, _
    ByVal ppThumbnail As LongPtr, _
    ByVal pThumbnailSize As LongPtr, _
    ByVal pfilePath As String) As Long
Option Explicit' ---------------------------------------------------------------------
'   Main
'   Main entry point.  Provide a file name with the MicroStation keyin
'   when calling this module.  For example:
'   vba run CheckFile.Main C:\projects\project1\dgn\myfile.dgn
' ---------------------------------------------------------------------
Public Sub Main()
    Const PROC_NAME     As String = "Main"
    On Error GoTo err_Main
    Dim filePath        As String
    filePath = KeyinArguments   ' Must be a complete path specification
    If (0 < Len(filePath)) Then
        '   Test whether MicroStation understands this file type
        If (CanMicroStationOpen(filePath)) Then
            '  Do something with file
        End If
    Else
        '  Advise user of correct command-line syntax
        Dim msg         As String
        msg = "CheckFile: keyin ""vba run CheckFile.Main """
        ShowMessage msg, msg, msdMessageCenterPriorityWarning
    End If

    '   Test whether this file can be opened for writing
    If (IsWritable(filePath)) Then
        msg = "File'" & filePath & "' may be opened for modification"
        ShowMessage msg, msg, msdMessageCenterPriorityInfo
    Else
        msg = "File'" & filePath & "' can be opened read-only"
        ShowMessage msg, msg, msdMessageCenterPriorityWarning
    End If

    Exit Sub

err_Main:
    ReportError PROC_NAME, MODULE_NAME
End Sub
Option Explicit
' ---------------------------------------------------------------------
'   CanMicroStationOpen
'   This is a wrapper around the MDL function mdlFile_validDesignFile
'   Args:
'   Full path of file to test
'   Returns: True if file can be opened by MicroStation
' ---------------------------------------------------------------------
Public Function CanMicroStationOpen(ByVal filePath As String) As Boolean
    CanMicroStationOpen = False
    On Error GoTo err_CanMicroStationOpen
    Const PROC_NAME     As String = "CanMicroStationOpen"
    Dim threeD          As Long, _
        format          As Long, _
        major           As Long, _
        minor           As Long
    Dim msg             As String

    If (0 <> mdlFile_validDesignFile(threeD, format, major, minor, 0, 0, filePath)) Then
        Dim dimension   As String
        If (threeD) Then
            dimension = "3D"
        Else
            dimension = "2D"
        End If
        Select Case format
        '	Note: msdDesignFileFormatV7 is invalid from MicroStation CONNECT Update 17
        'Case msdDesignFileFormatV7
        'msg = "'" & filePath & "' is a " & dimension & " V7 DGN file"
        Case msdDesignFileFormatV8
        msg = "'" & filePath & "' is a " & dimension & " V8 DGN file"
        Case msdDesignFileFormatDWG
        msg = "'" & filePath & "' is a DWG file"
        Case msdDesignFileFormatDXF
        msg = "'" & filePath & "' is a DXF file"
        End Select
        ShowMessage msg, msg, msdMessageCenterPriorityInfo
        CanMicroStationOpen = True
    Else
        msg = "'" & filePath & "' is not a MicroStation design file"
        ShowMessage msg, msg, msdMessageCenterPriorityWarning
    End If
    Exit Function

err_CanMicroStationOpen:
    ReportError PROC_NAME, MODULE_NAME
End Function
Option Explicit
' ---------------------------------------------------------------------
'   IsWritable
'   Determine whether a particular file is read-write or read-only.
'   This function is generic: it just tests a file without concern for its type
'
'   This function references Microsoft's Scripting Runtime library (scrrun.dll),
'   which provides an invaluable library of functions for file and
'   folder interrogation and manipulation
'
'   Use VBA's Tools|References menu to pop the References dialog.
'   Search for "Microsoft Scripting Runtime" and check the box beside it.
'
'   Returns: True if file is read-write
' ---------------------------------------------------------------------
Public Function IsWritable(ByVal filePath As String) As Boolean
    IsWritable = False
    On Error GoTo err_IsWritable
    Const PROC_NAME                 As String = "IsWritable"

    Dim oFileSystem                 As New Scripting.FileSystemObject
    If (oFileSystem.FileExists(filePath)) Then
        Dim oFile                   As Scripting.File
        Set oFile = oFileSystem.GetFile(filePath)
        If (Not (oFile.Attributes And ReadOnly) = ReadOnly) Then
            IsWritable = True
        End If
        Set oFile = Nothing
    End If
    Set oFileSystem = Nothing
    Exit Function

err_IsWritable:
    ReportError PROC_NAME, MODULE_NAME
End Function
Option Explicit
' ---------------------------------------------------------------------
'   ReportError provides generic error-reporting functionality
' ---------------------------------------------------------------------
Public Sub ReportError(ByVal procName As String, ByVal moduleName As String)
    MsgBox "Error no. " & CStr(Err.Number) & ": " & Err.Description, vbOKOnly Or vbCritical, "Error in " & moduleName & ":" & procName
End Sub

Questions

Post questions about MicroStation programming to the MicroStation Programming Forum.