Questions similar to this appear on the Bentley Discussion Groups. This problem appeared in the VBA discussion group.
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 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 either for pure Visual Basic (VB) or with VBA in other applications such as Excel™ or Word™. However, an alternative solution exists for those cases.
LA Solutions developed the MicroStationDetector for programmers using VB or another COM-compatible language. The MicroStationDetector works with VB and non-MicroStation VBA. It provides a number of functions, including file verification similar to that which is described here.
Although MicroStation VBA does not include a method to test an unopened file, MDL 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…
CheckFile vba run CheckFile.Main <file path> 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 Function mdlFile_validDesignFile Lib "stdmdlbltin.dll" ( _ ByRef pThreeD As Long, _ ByRef pFormat As Long, _ ByRef pMajorVersion As Long, _ ByRef pMinorVersion As Long, _ ByRef ppThumbnail As Long, _ ByRef pThumbnailSize As Long, _ ByVal pFileName As String) As Long' --------------------------------------------------------------------- ' 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 fileName As String fileName = KeyinArguments ' Must be a complete path specification If (0 < Len(fileName)) Then' Test whether MicroStation understands this file typeIf (CanMicroStationOpen(fileName)) Then' Do something with fileEnd If Else' Advise user of correct command-line syntaxDim msg As String msg = "CheckFile: keyin ""vba run CheckFile.Main""" ShowMessage msg, msg, msdMessageCenterPriorityWarning End If ' Test whether this file can be opened for writingIf (IsWritable(fileName)) Then msg = "File'" & fileName & "' may be opened for modification" ShowMessage msg, msg, msdMessageCenterPriorityInfo Else msg = "File'" & fileName & "' can be opened read-only" ShowMessage msg, msg, msdMessageCenterPriorityWarning End If Exit Sub err_Main: ReportError PROC_NAME, MODULE_NAME End Sub' --------------------------------------------------------------------- ' 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 fileName 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, fileName)) Then Dim dimension As String If (threeD) Then dimension = "3D" Else dimension = "2D" End If Select Case format Case msdDesignFileFormatV7 msg = "'" & fileName & "' is a " & dimension & " V7 DGN file" Case msdDesignFileFormatV8 msg = "'" & fileName & "' is a " & dimension & " V8 DGN file" Case msdDesignFileFormatDWG msg = "'" & fileName & "' is a DWG file" Case msdDesignFileFormatDXF msg = "'" & fileName & "' is a DXF file" End Select ShowMessage msg, msg, msdMessageCenterPriorityInfo CanMicroStationOpen = True Else msg = "'" & fileName & "' is not a MicroStation design file" ShowMessage msg, msg, msdMessageCenterPriorityWarning End If Exit Function err_CanMicroStationOpen: ReportError PROC_NAME, MODULE_NAME End Function' --------------------------------------------------------------------- ' 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' --------------------------------------------------------------------- ' 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