Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

If Check_File is true.

66 views
Skip to first unread message

Kim Hawker

unread,
Apr 21, 2022, 9:35:24 PM4/21/22
to
I cannot figure what is wrong here. it all used to work. Now when I run similar code I get UN-expected results.

I know the file is there, I've checked.

I follow it line by line by pressing the F8 key, when it gets to the
Public Function Check_File(sPath As String) As Boolean

file check it shows true.
but then goes on down to show me what it's checking and it says
"Spath = Photo3.jpg" so then it comes back it sends the message
msgbox "File is not here"

**********************************************
Thisone = “Photo1.jpg”
If Check_File(App.Path & "\testfolder\") & thisone = True Then
MsgBox "This file is here"
else
msgbox "File is not here"
End If
***********************************************
Public Function Check_File(sPath As String) As Boolean
If Dir$(sPath) <> "" Then
Check_File = True
Else
Check_File = False
End If

MsgBox "sPath = " & Dir$(sPath) 'sPath
Spath = Photo3.jpg
Message has been deleted

Kim Hawker

unread,
Apr 22, 2022, 12:08:12 AM4/22/22
to
I found the problem.

From this If Check_File(App.Path & "\testfolder\") & thisone = True Then

To this If Check_File(App.Path & "\testfolder\" & thisone )= True Then

It works.


ObiWan

unread,
Apr 22, 2022, 9:00:26 AM4/22/22
to
:: On Thu, 21 Apr 2022 18:35:22 -0700 (PDT)
:: (microsoft.public.vb.general.discussion)
:: <f9fb1614-045d-44e7...@googlegroups.com>
:: Kim Hawker <hawke...@gmail.com> wrote:

> I cannot figure what is wrong here. it all used to work. Now when I
> run similar code I get UN-expected results.

Kim, I'm happy you found the "typo" and fixed it, but please allow me
to ask you a question

> Public Function Check_File(sPath As String) As Boolean
> If Dir$(sPath) <> "" Then
> Check_File = True
> Else
> Check_File = False
> End If

now, the above uses the "Dir$()", fine, but what if there's a folder
(notice a FOLDER, not a file) called "Photo3.jpg" in the path you're
checking ? In such a case your function will tell you that "a file"
exists while that isn't a file at all; my suggestion is to use some
code like the following

Public Function Check_File(ByVal sPathName As String) As Boolean
Dim vAttr As VbFileAttribute

On Local Error Resume Next
CheckFile = False
Err.Clear

vAttr = GetAttr(sPathName)
If Err.Number <> 0 Then
Err.Clear
Exit Function
End If
If (vAttr And vbDirectory) Then
Exit Function
End If
CheckFile = True
End Function

it will be faster than the "Dir" and, if the specified pathname points
to a directory it will correctly return "false"






Wendelin Uez

unread,
Apr 22, 2022, 11:20:22 AM4/22/22
to

simply try

If Check_File(App.Path & "\testfolder\" & thisone) = True Then

or even

If Check_File(App.Path & "\testfolder\" & thisone) Then


instead of

Kim Hawker

unread,
Apr 24, 2022, 2:54:36 AM4/24/22
to
On Friday, April 22, 2022 at 8:00:26 AM UTC-5, ObiWan wrote:

> Public Function Check_File(ByVal sPathName As String) As Boolean
> Dim vAttr As VbFileAttribute
>
> On Local Error Resume Next
> CheckFile = False
> Err.Clear
>
> vAttr = GetAttr(sPathName)
> If Err.Number <> 0 Then
> Err.Clear
> Exit Function
> End If
> If (vAttr And vbDirectory) Then
> Exit Function
> End If
> CheckFile = True
> End Function
>
> it will be faster than the "Dir" and, if the specified pathname points
> to a directory it will correctly return "false"

Thank you ObiWan, I love having a choice of coding versus one way. Plus this sounds like it might be a smarter way to code. Very nice of you.

Kim Hawker

unread,
Apr 24, 2022, 3:00:48 AM4/24/22
to
On Friday, April 22, 2022 at 10:20:22 AM UTC-5, Wendelin Uez wrote:
> simply try
> If Check_File(App.Path & "\testfolder\" & thisone) = True Then
> or even
>
> If Check_File(App.Path & "\testfolder\" & thisone) Then

Thank you Wendelin Uez,
For showing more ways of coding for a similar outcome. Yo u have been a big help. Gives me some pause to consider.

Mayayana

unread,
Apr 24, 2022, 7:50:46 AM4/24/22
to
"Kim Hawker" <hawke...@gmail.com> wrote

| Thank you ObiWan, I love having a choice of coding versus one way. Plus
this sounds like it might be a smarter way to code. Very nice of you.

You can also make it more compact, without unnecessary redundancy:

Public Function FolderExists(ByVal sPath As String) As Boolean
On Error Resume Next
FolderExists = (GetAttr(sPath) And vbDirectory) = vbDirectory
Err.Clear
End Function


Kim Hawker

unread,
Apr 24, 2022, 10:46:31 AM4/24/22
to
On Sunday, April 24, 2022 at 6:50:46 AM UTC-5, Mayayana wrote:


> Public Function FolderExists(ByVal sPath As String) As Boolean
> On Error Resume Next
> FolderExists = (GetAttr(sPath) And vbDirectory) = vbDirectory
> Err.Clear
> End Function

How would one call it? Use it?

Mayayana

unread,
Apr 24, 2022, 12:26:02 PM4/24/22
to
"Kim Hawker" <hawke...@gmail.com> wrote

| > Public Function FolderExists(ByVal sPath As String) As Boolean
| > On Error Resume Next
| > FolderExists = (GetAttr(sPath) And vbDirectory) = vbDirectory
| > Err.Clear
| > End Function
|
| How would one call it? Use it?

If FolderExists("C:\Windows\Desktop") = True Then...

It's basically the same as Obiwan's version, just more compact.
"And", in this case, is a bit comparison. vbDirectory is 16. GetAttr
gets all attributes of the file system object. Say, for example, that
the folder in question has the archive bit set (32) and the hidden
bit (2). GetAttr then returns 50. In binary that's 110010 16 in
binary is 10000. So the 16 bit is set in both values. Thus,
GetAttr And vbDirectory = 16, which is vbDirectory. If it's a file,
the 16 bit won't be set, so "GetAttr And vbDirectory" will return 0.
If there's no folder, the error will be trapped and the comparison
will still return false. 0 <> 16.


MikeD

unread,
Apr 24, 2022, 1:07:43 PM4/24/22
to
Except that the original request was for a FileExists and you provided a
FolderExists. :)

Mike

Kim Hawker

unread,
Apr 24, 2022, 2:16:46 PM4/24/22
to
On Sunday, April 24, 2022 at 11:26:02 AM UTC-5, Mayayana wrote:

> It's basically the same as Obiwan's version, just more compact.
> "And", in this case, is a bit comparison. vbDirectory is 16. GetAttr
> gets all attributes of the file system object. Say, for example, that
> the folder in question has the archive bit set (32) and the hidden
> bit (2). GetAttr then returns 50. In binary that's 110010 16 in
> binary is 10000. So the 16 bit is set in both values. Thus,
> GetAttr And vbDirectory = 16, which is vbDirectory. If it's a file,
> the 16 bit won't be set, so "GetAttr And vbDirectory" will return 0.
> If there's no folder, the error will be trapped and the comparison
> will still return false. 0 <> 16.

Awesome, Thank you Mayayana, for another time I know I’ll be wanting to know if a FOLDER exist versus a file. So thank you for your efforts.

Mayayana

unread,
Apr 24, 2022, 5:19:44 PM4/24/22
to
"MikeD" <nob...@nowhere.edu> wrote


| Except that the original request was for a FileExists and you provided a
| FolderExists. :)
|

Woops. Sorry to Kim. I wasn't paying attention. I saw
Obiwan's code using vbDirectory, while still fueling up
on morning coffee, and just ran with it.


ObiWan

unread,
Apr 26, 2022, 10:02:20 AM4/26/22
to
:: On Sun, 24 Apr 2022 07:50:55 -0400
:: (microsoft.public.vb.general.discussion)
:: <t43dik$klt$1...@dont-email.me>
Public Function FileExists(ByVal sPath As String) As Boolean
On Error Resume Next
FileExists = IIf((GetAttr(sPath) And vbDirectory) = vbDirectory, False, True)
Err.Clear
End Function

:-)


Ulrich Möller

unread,
May 15, 2022, 4:34:22 PM5/15/22
to
A slightly simplified variant:

Public Function FileExists(ByVal FileName As String) As Boolean
    ' Returns TRUE if the file exists
    On Error Resume Next
    FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
    On Error GoTo 0
End Function


Ulrich


ObiWan

unread,
May 16, 2022, 3:25:10 AM5/16/22
to
:: On Sun, 15 May 2022 22:34:19 +0200
:: (microsoft.public.vb.general.discussion)
:: <t5ro4b$tlg$1...@dont-email.me>
:: Ulrich Möller <knob...@arcor.de> wrote:

> Public Function FileExists(ByVal FileName As String) As Boolean
>     ' Returns TRUE if the file exists
>     On Error Resume Next
>     FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or
> vbVolume)) On Error GoTo 0
> End Function

Public Function FileExists(ByVal sPath As String) As Boolean
On Error Resume Next
 FileExists = Not CBool(GetAttr(sPath) And (vbDirectory Or vbVolume))
 Err.Clear
End Function

there's no need for the "on error goto 0", just clear the error code so
that it won't be "dirty" when the function terminates, other than that,
the "vbVolume" is a good idea, since it will take care of the case when
the code passes just "C:" to the function


Wendelin Uez

unread,
May 16, 2022, 5:25:00 AM5/16/22
to
> A slightly simplified variant:
>
> Public Function FileExists(ByVal FileName As String) As Boolean
> ' Returns TRUE if the file exists
> On Error Resume Next
> FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
> On Error GoTo 0
> End Function


and if speed is all you need pass Filename by reference rather than by value
which first copies the filename string (not only its address) inclusive
conversion without any practical benefit, and additionally remove conversion
of a boolean expression into a boolean variable, the result of a boolean
expression "<integer> AND <Iinteger> is already boolean (represented in an
integer):

FileExists = Not ( GetAttr(FileName) And (vbDirectory Or vbVolume) )


Jim Mack

unread,
May 16, 2022, 9:23:38 AM5/16/22
to
Nice to see competition for efficient code (-:

While it's true for numerics that ByVal makes a copy, in the case of
strings it doesn't. It just dereferences the handle into a pointer
("taking the value" of a variable is deref-ing a pointer; deref-ing a
pointer to a pointer, what a BSTR is, leaves a pointer). And no W-->A
conversion is needed for internal functions. So in this case it makes no
practical difference, it's just unnecessary.

The compiler will ignore the explicit CBool since there's an implicit
one, as you note. IMO it's never a bad idea to be explicit in casting
and other cases, since it tells others (and future you) that you
understand the implications of what you're writing. And the compiler is
quite smart.

--

Ulrich Möller

unread,
May 16, 2022, 9:37:29 AM5/16/22
to
Hallo Wendelin,

Am 16.05.2022 um 11:24 schrieb Wendelin Uez:
>> A slightly simplified variant:
>>
>> Public Function FileExists(ByVal FileName As String) As Boolean
>>  ' Returns TRUE if the file exists
>>  On Error Resume Next
>>  FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
>>  On Error GoTo 0
>> End Function
>
>
> and if speed is all you need pass Filename by reference rather than by
> value which first copies the filename string (not only its address) 
> inclusive conversion without any practical benefit,
Byval was intentionally chosen here to indicate that the passed value
will not be changed.

> and additionally remove conversion of a boolean expression into a
> boolean variable, the result of a boolean expression "<integer> AND
> <Iinteger> is already boolean (represented in an integer):
>
"Integer and integer" does not necessarily result in a Boolean value.
Here a bitwise operation is performed - and that is not the same!
Therefore the explicit type conversion to indicate that.

Ulrich

Ulrich Möller

unread,
May 16, 2022, 9:50:51 AM5/16/22
to
Hallo Wendelin,

Am 16.05.2022 um 11:24 schrieb Wendelin Uez:
>>  FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
> FileExists =  Not ( GetAttr(FileName) And (vbDirectory Or vbVolume) )
>

By the way:
these two lines are not identical!

E.g. there is
? not(16)
-17 --> is interpreted as true
? not cbool(16)
False --> not true, but correct.

Ulrich


Mayayana

unread,
May 16, 2022, 10:31:39 AM5/16/22
to
"Jim Mack" <no-ub...@mdxi.com> wrote

| While it's true for numerics that ByVal makes a copy, in the case of
| strings it doesn't.

Option Explicit
Dim s1 As String

Private Sub Command1_Click()
s1 = "okay"
op2 s1
Debug.Print s1
op1 s1
Debug.Print s1
End Sub

Private Sub op1(ByRef sref As String)
sref = "woops"
End Sub

Private Sub op2(ByVal sval As String)
sval = "woops"
End Sub



Jim Mack

unread,
May 16, 2022, 1:15:52 PM5/16/22
to
I stand corrected. I just did a small test to confirm that a real copy
is made, and it wasn't just a case of the language protecting an IN
parameter.

My experience with this is exclusively from writing assembler functions
that take BSTR via a typelib. In such cases I get a handle (BSTR*) or a
pointer (BSTR) but no copy is made. I never tried to modify the incoming
string directly but I'm sure they resolved to the same memory.

--
Jim

Wendelin Uez

unread,
May 16, 2022, 1:31:46 PM5/16/22
to
> "Integer and integer" does not necessarily result in a Boolean value. Here
> a bitwise operation is performed - and that is not the same! Therefore the
> explicit type conversion to indicate that.

VB6 stores boolean values as integers, there are no intrinsic Booleans:
DIM B As Boolean
Debug.Print LenB(B) -> 2

For interpretation "If <value> Then ..." only one bit is evaluated, while
"If Integer1 = Integer2 Then ..." evaluates all bits.


Wendelin Uez

unread,
May 16, 2022, 4:17:12 PM5/16/22
to
>> FileExists = Not CBool(GetAttr(FileName) And (vbDirectory Or vbVolume))
> FileExists = Not ( GetAttr(FileName) And (vbDirectory Or vbVolume) )

> By the way:
> these two lines are not identical!

that's why I omitted CBool() and compared attribute and bitmasks directly
before negotiating the result




> E.g. there is
> ? not(16)
> -17 --> is interpreted as true
> ? not cbool(16)
> False --> not true, but correct.


Yeah, "do not go to the left" is not the opposit of "go to the left", too
:-)

cBool(16) returns the integer representation for TRUE, the integer value
of -1, which has very few to do with the origin value 16, so "not cBool(16)"
returns the value for NOT TRUE and that is FALSE, represented by the integer
value of zero, because cBool eliminates all other bits

while

"not 16" simply inverts the first bit of the bit sequence representing 16,
that means all other bits of the original value remain existent and are not
nulled out by the cBool function, so the remaining bits return -17





Ulrich Möller

unread,
May 16, 2022, 4:26:09 PM5/16/22
to
"With the interpretation "If <value> Then ..." only one bit is evaluated"

This is not correct. Only the value 0 is interpreted as FALSE, all other
values <> 0, i.e. any set bit, are evaluated as TRUE.

Greetings
Ulrich

ObiWan

unread,
May 17, 2022, 6:12:21 AM5/17/22
to
:: On Tue, 26 Apr 2022 16:02:17 +0200
:: (microsoft.public.vb.general.discussion)
:: <20220426160...@mvps.org>
:: ObiWan <obi...@mvps.org> wrote:

> Public Function FileExists(ByVal sPath As String) As Boolean
> On Error Resume Next
> FileExists = IIf((GetAttr(sPath) And vbDirectory) = vbDirectory,
> False, True) Err.Clear
> End Function

Otherwise, if using an API is allowed

https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathfileexistsa

the "air code" would be something like this

Private Declare Function PathFileExistsA Lib "shlwapi.dll" _
(ByVal sPathName As String) As Long

Public Function FileExists(ByVal sPathName As String) As Boolean
FileExists = PathFileExistsA(sPathName)
End Function

and the above won't require any error handling

ObiWan

unread,
May 17, 2022, 6:17:43 AM5/17/22
to
:: On Tue, 17 May 2022 12:12:18 +0200
:: (microsoft.public.vb.general.discussion)
:: <20220517121...@mvps.org>
just found the version which Randy wrote time ago

http://vbnet.mvps.org/index.html?code/fileapi/pathfileexists.htm


Wendelin Uez

unread,
May 18, 2022, 3:27:40 AM5/18/22
to

> "With the interpretation "If <value> Then ..." only one bit is evaluated"
>
> This is not correct. Only the value 0 is interpreted as FALSE, all other
> values <> 0, i.e. any set bit, are evaluated as TRUE.



For Interpreting integers as boolean you have to use cBool conversion else
you run into heavy problems..

I learned above too, but simply enter you VB6 direct output window and
enter:this example, using any integer 1..32768, not zero

?4=true
->false

?4=false
-> false, too

woops! I guess you didn't expect that.

Then try

?cBool(4)=true
->true

?cBool(4)=false
-> false

That shows what you wrote above is true for "is interpreted by cBool" -
not for "interpreted by VB6 in all cases".

That's why I never use such abbreviations like
Function XXX() as boolean
XXX = dllfunction(...)
End Function

ObiWan

unread,
May 18, 2022, 3:46:05 AM5/18/22
to
:: On Tue, 17 May 2022 17:58:49 +0200
:: (microsoft.public.vb.general.discussion)
:: <t62759$oqf$1...@dont-email.me>
:: "Wendelin Uez" <wu...@online.de> wrote:

> That's why I never use such abbreviations like
>
> Function XXX() as boolean
> XXX = dllfunction(...)
> End Function


the above will work, if dllfunction returns 0 then XXX will return
false, if otherwise dllfunction returns a value different from 0 then
XXX will return true, VB does a cast internally and returns a boolean





Ulrich Möller

unread,
May 19, 2022, 4:45:16 AM5/19/22
to
Hello Wendelin,
I think this is where the parser is misleading us a bit, because it
could interpret this expression as an assignment, and this has no result
value to evaluate.

Here is also a nice example of why I keep pointing out that you should
not put =TRUE or =FALSE in an if condition. This can lead to errors that
are difficult to find.

v = 4
if v = true then debug.Print "True!" else debug.Print "False!"
False!
if v then debug.Print "True!" else debug.Print "False!"
True!

v = cbool(4)
if v = true then debug.Print "True!" else debug.Print "False!"
True!
if v  then debug.Print "True!" else debug.Print "False!"
True!

The second case we already had with the FileExists and GetAttr function
and why I used CBool there to make it clear.

Greetings
Ulrich

ObiWan

unread,
May 19, 2022, 4:51:46 AM5/19/22
to
:: On Thu, 19 May 2022 10:45:12 +0200
:: (microsoft.public.vb.general.discussion)
:: <t6502p$om6$1...@dont-email.me>
:: Ulrich Möller <knob...@arcor.de> wrote:

> > Function XXX() as boolean
> > XXX = dllfunction(...)
> > End Function

> I think this is where the parser is misleading us a bit, because it
> could interpret this expression as an assignment, and this has no
> result value to evaluate.

agreed, and then, we may use a slightly different approach

Function SomeFunc() As Boolean
SomeFunc = (DLLfunction() <> 0)
End Function

:D

Ulrich Möller

unread,
May 19, 2022, 6:27:46 AM5/19/22
to
this should then be clear for the parser.

Full ACK!

Randy (birchr)

unread,
Dec 14, 2022, 2:17:28 AM12/14/22
to
On Sunday, April 24, 2022 at 3:00:48 a.m. UTC-4, Kim Hawker wrote:
> On Friday, April 22, 2022 at 10:20:22 AM UTC-5, Wendelin Uez wrote:
> > simply try
> > If Check_File(App.Path & "\testfolder\" & thisone) = True Then
> > or even
> >
> > If Check_File(App.Path & "\testfolder\" & thisone) Then
> Thank you Wendelin Uez,
> For showing more ways of coding for a similar outcome. Yo u have been a big help. Gives me some pause to consider.

http://vbnet.mvps.org/index.html?code/fileapi/fileexists.htm

R
0 new messages