How to check if a path exisits

John Sh

Member
Local time
Today, 13:05
Joined
Feb 8, 2021
Messages
493
I have the following code to check for the existence, or not, of a backup directory with three possible paths.
Path "H:\" is a network path that may, or may not, be connected. If it is not connected I get "Bad file name or number" error.
Is there a way to check if the path exists other than DIR()
NOTE. The "pathX" string variables are predefined as public.
Code:
Public Sub setPathways()
    pathA = "H:\"
GetPath:
    If Dir(pathA & "Herbarium Data\Backup", vbDirectory) = "" Then
        pathA = IIf(pathA = "H:\", "G:\", "N:\")
        goto getPath
    End If
    pathB = pathA & "Backup\Backup_" & strLogin & "_"
    pathCol = pathA & "Barry_Collier\Collier_Collection\"
    pathLyn = pathA & "LYNDA\"
    pathJpg = pathA & "Herbarium Database Storage\HERBARIUM DATABASE\DMHN COLLECTION DIGITAL SPECIMEN IMAGES\"
End Sub
 
Use FileSystemObject - see this reference:


By navigating the documentation based on the tree view to the left, you can find the FSO method called FolderExists which gives you a TRUE/FALSE result based on whether the named folder actually exists.

The link I gave you includes the way to late-bind the creation of an FSO - and you only need one of them in your code. If you start playing with other objects returned via FSO, you might need multiples of those other objects - but you only need one FSO.
 
Code:
Public Sub setPathways()
Dim arrDrives
dim sResult As String
arrDrives = Array("H:\", "G:\", "N:\")
For i = 0 To 2
    PathA = arrDrives(i)
    If Len(Dir(pathA & & "Herbarium Data\Backup", vbDirectory))  <> 0
        Exit For
    Else
        Path = ""
    End If
Next
If Len(pathA) <> 0 Then
    pathB = pathA & "Backup\Backup_" & strLogin & "_"
    pathCol = pathA & "Barry_Collier\Collier_Collection\"
    pathLyn = pathA & "LYNDA\"
    pathJpg = pathA & "Herbarium Database Storage\HERBARIUM DATABASE\DMHN COLLECTION DIGITAL SPECIMEN IMAGES\"
End If
End Sub
 
Thanks all.
I put in an error trap as below. works fine.
Code:
Public Sub setPathways()
    On Error GoTo error
    pathA = "H:\"
GetPath:
    If Dir(pathA & "Herbarium Data\Backup", vbDirectory) = "" Then
        pathA = IIf(pathA = "H:\", "G:\", "N:\")
        GoTo GetPath
    End If
    pathB = pathA & "Backup\Backup_" & strLogin & "_"
    pathCol = pathA & "Barry_Collier\Collier_Collection\"
    pathLyn = pathA & "LYNDA\"
    pathJpg = pathA & "Herbarium Database Storage\HERBARIUM DATABASE\DMHN COLLECTION DIGITAL SPECIMEN IMAGES\"
    Exit Sub
error:
    pathA = IIf(pathA = "H:\", "G:\", "N:\")
    GoTo GetPath
End Sub
 
Actually, it is technically NOT fine. Your ON ERROR path terminates with a GOTO label when the syntax for error trap dismissal SHOULD be a RESUME label. For some cases you might get away with it, but by taking the wrong exit, it is possible for you to remain in Error-trap context after you return from the sub. (At least, it is possible by strict interpretation of the syntax.) Staying in error trap context blocks further errors, which is not generally a good idea.

Since you say it seems to be working, maybe you don't want to change anything. But if you ever get a situation where it looks like you missed taking a trap you SHOULD have taken, then you ran afoul of improper trap dismissal.
 
Did you try the FileSystemObject approach?
 
Actually, it is technically NOT fine. Your ON ERROR path terminates with a GOTO label when the syntax for error trap dismissal SHOULD be a RESUME label. For some cases you might get away with it, but by taking the wrong exit, it is possible for you to remain in Error-trap context after you return from the sub. (At least, it is possible by strict interpretation of the syntax.) Staying in error trap context blocks further errors, which is not generally a good idea.

Since you say it seems to be working, maybe you don't want to change anything. But if you ever get a situation where it looks like you missed taking a trap you SHOULD have taken, then you ran afoul of improper trap dismissal.
Thanks Doc_Man.
So the Resume label exits the error trap, where the Goto leaves it open if I'm reading you correctly.
I have changed the goto to resume.
 
So the Resume label exits the error trap, where the Goto leaves it open if I'm reading you correctly.
Absolutely correct!

It's a small thing and in theory CAN work the other way - but then there comes a time when it doesn't work right. You see, an error trap cannot be interrupted by another error trap and then resumed, so as long as you remain in trap context, a second trap has to wait. Code can run just fine in that context though most authorities suggest the fastest possible dismissal of the trap, usually to allow proper handling of future errors.

The reason that it probably worked for you this time is that you have a very short run of code followed by an END SUB. Your implied loop is very short, 3 iterations and done. That won't take a long time, and besides, the operations involved are very simple and thus unlikely to trip a trap, so it is probably OK. But if that had involved a complex long-running loop, it would be decidedly NOT OK.

Since the error trap is in a low-level subroutine, its context is bound to that subroutine. The END SUB would remove the internal flags related to trap handling and would implicitly dismiss the trap context. But as long as you are in that sub and stay in trap context, you run at risk. RESUME as a syntax element exists to do a GOTO and dismiss the trap at the same time.

Here is the REAL danger... IF you have a trap and fail to properly dismiss the context (i.e. use the GOTO instead of the RESUME), another trap CAN occur - but I said that traps cannot be interrupted and then resumed when already in trap context. What would happen instead is that the second trap would abort the subroutine and the error code would be passed up to the caller of that now-aborted routine to see if IT has a trap handler. I.e. the subroutine would abort and clear itself from the call stack. There would be no returning to it after a RESUME. In that case, the error would be seriously misleading as to where it happened. Talk about a real BEAST to analyze!
 
I'm curious as to the need for this procedure.
It appears that the paths are those of mapped drives.
Is this something that would be resolved by using a UNC path?
 
Just a note

Testing a file on a drive that exists is very quick
Testing whether a drive exists at all using Dir() seems to take a long while to resolve when it doesn't exist.
I don't know whether it's different in your case with different code, or whether it still takes a long while to return a false result.
 
Absolutely correct!

It's a small thing and in theory CAN work the other way - but then there comes a time when it doesn't work right. You see, an error trap cannot be interrupted by another error trap and then resumed, so as long as you remain in trap context, a second trap has to wait. Code can run just fine in that context though most authorities suggest the fastest possible dismissal of the trap, usually to allow proper handling of future errors.

The reason that it probably worked for you this time is that you have a very short run of code followed by an END SUB. Your implied loop is very short, 3 iterations and done. That won't take a long time, and besides, the operations involved are very simple and thus unlikely to trip a trap, so it is probably OK. But if that had involved a complex long-running loop, it would be decidedly NOT OK.

Since the error trap is in a low-level subroutine, its context is bound to that subroutine. The END SUB would remove the internal flags related to trap handling and would implicitly dismiss the trap context. But as long as you are in that sub and stay in trap context, you run at risk. RESUME as a syntax element exists to do a GOTO and dismiss the trap at the same time.

Here is the REAL danger... IF you have a trap and fail to properly dismiss the context (i.e. use the GOTO instead of the RESUME), another trap CAN occur - but I said that traps cannot be interrupted and then resumed when already in trap context. What would happen instead is that the second trap would abort the subroutine and the error code would be passed up to the caller of that now-aborted routine to see if IT has a trap handler. I.e. the subroutine would abort and clear itself from the call stack. There would be no returning to it after a RESUME. In that case, the error would be seriously misleading as to where it happened. Talk about a real BEAST to analyze!
Many thanks Doc_Man. Very informative.
Having had no formal training in vba, and only a little bit in Java, I consider myself as a bit above a beginner and am learning on the fly.
As a general rule I do try to write short code sections. I find them easier to debug and more easily integrated than longer, more convoluted code.
The time, effort and expertise available on this forum has been my salvation on many an occasion.
My heartfelt thanks goes out to all who have contributed.
John
 
Last edited:
I'm curious as to the need for this procedure.
It appears that the paths are those of mapped drives.
Is this something that would be resolved by using a UNC path?
The two drives "N:\" and "G:\" are the same external drive's location on two different computers. That is I have an external drive that is used in two locations. The "H\" drive is a university network drive that is mapped as "H" on four computers at various locations. "H:\" is the working drive where the split files reside. The external drive has the build files on it. When working from home, I may, or may not, be connected to the university's network, hence the possible error.
 
Just a note

Testing a file on a drive that exists is very quick
Testing whether a drive exists at all using Dir() seems to take a long while to resolve when it doesn't exist.
I don't know whether it's different in your case with different code, or whether it still takes a long while to return a false result.
Not having put a timer on it, the error message is, to all intents, instant. There is no appreciable delay.
 
Not having put a timer on it, the error message is, to all intents, instant. There is no appreciable delay.
We had a drive that was going off line or something, and trying to read the drive took about the same time as a whole disk file search, before it returned an error.
 
Didnt see if you tried fso at all.

Could be as simple as
Code:
    Dim fso As New FileSystemObject

    If fso.DriveExists("H:") Then
        'do something
    ElseIf fso.DriveExists("N:") Then
        'do something
    ElseIf fso.DriveExists("G:") Then
        'do something
    Else
        MsgBox "Not Found"
    End If
 
Last edited:
Didnt see if you tried fso at all.

Could be as simple as
Code:
    Dim fso As New FileSystemObject

    If fso.DriveExists("H:") Then
        'do something
    ElseIf fso.DriveExists("N:") Then
        'do something
    ElseIf fso.DriveExists("G:") Then
        'do something
    Else
        MsgBox "Not Found"
    End If
Not on this occasion, although I have used the fso system for other parts of this project. The error trap that I listed, with the mod that Doc_Man suggested, is simple and works as expected. I could see no advantage in swapping one working solution for another.
I thank you for your interest and input.
John
 
I would imagine avoiding a reliance on trapping errors would be a major advantage.
I tried the fso construct and it fails.
Because drive "H:" is mapped on my system, the fso finds it even when I am not connected. I need "H:" to be the first check as it has the split files for the live data and the users would be at a loss if the wrong drive is selected..
Changing the checking order would work in some instances but not all.
Using the error trap consistently gives the correct result.
I am happy to try other methods, if they exist, but for now the error trap seems to be the way to go.
 

Users who are viewing this thread

Back
Top Bottom